Gwion coverage report


Directory: src/
File: src/lib/object_op.c
Date: 2023-01-30 18:32:28
Exec Total Coverage
Lines: 254 288 88.2%
Functions: 23 26 88.5%
Branches: 141 200 70.5%

Line Branch Exec Source
1
2 #include "gwion_util.h"
3 #include "gwion_ast.h"
4 #include "gwion_env.h"
5 #include "vm.h"
6 #include "gwion.h"
7 #include "instr.h"
8 #include "object.h"
9 #include "operator.h"
10 #include "import.h"
11 #include "emit.h"
12 #include "traverse.h"
13 #include "template.h"
14 #include "parse.h"
15 #include "gwi.h"
16 #include "tmpl_info.h"
17
18 #undef insert_symbol
19
20 #define describe_logical(name, op) \
21 static INSTR(name##Object) { \
22 POP_REG(shred, SZ_INT); \
23 const M_Object lhs = *(M_Object *)REG(-SZ_INT); \
24 const M_Object rhs = *(M_Object *)REG(0); \
25 *(m_uint *)REG(-SZ_INT) = (lhs op rhs); \
26 }
27
28 describe_logical(Eq, ==) describe_logical(Neq, !=);
29
30 25 static OP_CHECK(opck_object_at) {
31 25 const Exp_Binary *bin = (Exp_Binary *)data;
32
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 24 times.
25 if (opck_rassign(env, data) == env->gwion->type[et_error])
33 1 return env->gwion->type[et_error];
34
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 7 times.
24 if (bin->rhs->exp_type == ae_exp_decl) {
35 17 Var_Decl vd = bin->rhs->d.exp_decl.vd;
36 17 SET_FLAG(vd.value, late);
37 }
38 24 exp_setvar(bin->rhs, 1);
39
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 CHECK_BO(isa(bin->lhs->type, bin->rhs->type));
40 24 bin->rhs->ref = bin->lhs;
41 24 return bin->rhs->type;
42 }
43
44 9 static OP_CHECK(opck_object_instance) {
45 9 Exp_Binary *bin = (Exp_Binary*)data;
46 9 Exp rhs = bin->rhs;
47
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (rhs->exp_type != ae_exp_decl)
48 2 return NULL;
49
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (rhs->d.exp_decl.td->array)
50 return NULL;
51 7 Exp lhs = bin->lhs;
52 7 Exp e = exp_self(bin);
53 7 Exp_Decl *const decl = &e->d.exp_decl;
54 7 e->exp_type = ae_exp_decl;
55 7 decl->td = cpy_type_decl(env->gwion->mp, rhs->d.exp_decl.td);
56 7 decl->vd = rhs->d.exp_decl.vd;
57 7 decl->type = rhs->type;
58 7 decl->args = lhs;
59 7 free_exp(env->gwion->mp, rhs);
60
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 CHECK_ON(check_exp(env, e));
61 return e->type;
62 }
63
64 ANN void unset_local(const Emitter emit, void *const l);
65 24 static OP_EMIT(opem_object_at) {
66 24 const Exp_Binary *bin = (Exp_Binary *)data;
67
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if(!bin->rhs->data) {
68 24 const Instr addref = emit_add_instr(emit, RegAddRef);
69 24 addref->m_val = -SZ_INT * 2;
70 } else if(bin->rhs->data != (void*)-1)
71 unset_local(emit, bin->rhs->data);
72
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 17 times.
24 if (bin->rhs->exp_type != ae_exp_decl)
73 7 (void)emit_add_instr(emit, ObjectAssign);
74 else
75 17 (void)emit_add_instr(emit, Assign);
76 24 return GW_OK;
77 }
78
79 4 static OP_CHECK(opck_object_cast) {
80 4 const Exp_Cast *cast = (Exp_Cast *)data;
81 4 const Type to = known_type(env, cast->td);
82
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (isa(cast->exp->type, to) < 0) {
83
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (isa(to, cast->exp->type) > 0)
84 ERR_N(exp_self(cast)->pos, _("can't upcast '%s' to '%s'"),
85 cast->exp->type->name, to->name);
86 3 ERR_N(exp_self(cast)->pos, _("can't cast '%s' to '%s'"),
87 cast->exp->type->name, to->name);
88 }
89 1 return exp_self(cast)->type;
90 }
91
92 ANN /*static*/ Type scan_class(const Env env, const Type t,
93 const Type_Decl *td);
94
95 2734 static OP_CHECK(opck_struct_scan) {
96 2734 struct TemplateScan *ts = (struct TemplateScan *)data;
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2734 times.
2734 if(ts->t->info->cdef->base.tmpl->call) return ts->t;
98
2/2
✓ Branch 1 taken 2733 times.
✓ Branch 2 taken 1 times.
2734 return scan_class(env, ts->t, ts->td) ?: env->gwion->type[et_error];
99 }
100
101 32 ANN static void emit_dot_static_data(const Emitter emit, const Value v,
102 const bool emit_addr) {
103 32 const m_uint size = v->type->size;
104 32 const m_uint data = (m_uint)(v->from->owner->class_data + v->from->offset);
105 32 emit_dotstatic(emit, data, size, emit_addr);
106 32 }
107
108 32 ANN static void emit_dot_static_import_data(const Emitter emit, const Value v,
109 const bool emit_addr) {
110
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (vflag(v, vflag_builtin) /*&& GET_FLAG(v, const)*/) {
111 const m_uint size = v->type->size;
112 emit_regpushimm(emit, (m_uint)v->d.ptr, size, emit_addr);
113 32 } else emit_dot_static_data(emit, v, emit_addr);
114 32 }
115
116 20 ANN static void emit_dottmpl(const Emitter emit, const Func f) {
117 20 const Instr instr = emit_add_instr(emit, DotTmpl);
118 20 instr->m_val = (m_uint)f->def;
119 20 struct dottmpl_ *dt = mp_malloc(emit->gwion->mp, dottmpl);
120 20 dt->nspc = emit->env->curr;
121 20 dt->type = emit->env->class_def;
122 20 dt->tmpl_name = tl2str(emit->gwion, f->def->base->tmpl->call, f->def->base->pos);
123 20 instr->m_val2 = (m_uint)dt;
124 20 }
125
126 235 ANN static void emit_member_func(const Emitter emit, const Exp_Dot *member) {
127 235 const Exp self = exp_self(member);
128 235 const Func f = self->type->info->func;
129
130
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 228 times.
235 if(is_new(f->def)) {
131
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if(f != emit->env->func) emit_pushfunc(emit, f);
132 7 return;
133 }
134
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 208 times.
228 if (f->def->base->tmpl) {
135
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if(self->is_call) emit_dottmpl(emit, f);
136 else {
137 if(vflag(f->value_ref, vflag_member))
138 emit_regmove(emit, -SZ_INT);
139 emit_pushimm(emit, (m_uint)f);
140 return;
141 }
142
2/2
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 131 times.
208 } else if (is_static_call(emit->gwion, exp_self(member))) {
143
5/6
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 61 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
77 if (self->is_call && f == emit->env->func && !is_new(f->def)) return;
144
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 61 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 14 times.
76 if(!self->is_call && vflag(f->value_ref, vflag_member)) emit_regmove(emit, -SZ_INT);
145 76 return emit_pushfunc(emit, f);
146 } else {
147
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 129 times.
131 if (tflag(member->base->type, tflag_struct))
148 2 return emit_pushfunc(emit, f);
149 129 const Instr instr = emit_add_instr(emit, DotFunc);
150 129 instr->m_val = f->def->vt_index;
151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 129 times.
129 if (!vflag(f->value_ref, vflag_member))
152 instr->m_val2 = -SZ_INT;
153 else {
154
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 27 times.
129 if(self->is_call) emit_regmove(emit, SZ_INT);
155 27 else instr->m_val2 = -SZ_INT;
156 }
157 }
158 149 return;
159 }
160
161 88 ANN static inline void emit_member(const Emitter emit, const Value v,
162 const uint emit_addr) {
163 88 const m_uint size = v->type->size;
164 88 emit_dotmember(emit, v->from->offset, size, emit_addr);
165 88 }
166
167 34 ANN static inline void emit_struct_data(const Emitter emit, const Value v,
168 const bool emit_addr) {
169 34 emit_structmember(emit, v->from->offset, v->type->size, emit_addr);
170
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
34 if (!emit_addr) emit_regmove(emit, v->type->size - SZ_INT);
171 34 }
172
173 ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v,
174 const loc_t pos);
175
176 467 ANN static inline Value get_value(const Env env, const Exp_Dot *member,
177 const Type t) {
178 467 const Value value = find_value(t, member->xid);
179
2/2
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 11 times.
467 if (value)
180 456 return value;
181
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
11 if (env->func && env->func->def->base->values)
182 2 return upvalues_lookup(env->func->def->base->values, member->xid);
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if(t->info->values)
184 return (Value)scope_lookup1(t->info->values, (m_uint)member->xid);
185 9 return NULL;
186 }
187
188 458 ANN static m_bool member_access(const Env env, const Exp exp, const Value value) {
189
4/4
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 318 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 127 times.
458 if (!env->class_def || isa(env->class_def, value->from->owner_class) < 0) {
190
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 327 times.
331 if (GET_FLAG(value, private)) {
191 4 gwerr_basic("invalid variable access", "is private", NULL, env->name,
192 exp->pos, 0);
193 4 env_error_footer(env);
194 4 defined_here(value);
195 4 env_set_error(env, true);
196
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 325 times.
327 } else if (GET_FLAG(value, protect))
197 2 exp_setprot(exp, 1);
198 }
199 458 return GW_OK;
200 }
201
202 467 OP_CHECK(opck_object_dot) {
203 467 Exp_Dot *const member = (Exp_Dot *)data;
204 467 Exp self = exp_self(member);
205 467 const m_str str = s_name(member->xid);
206 467 const m_bool base_static = is_class(env->gwion, member->base->type);
207 467 const Type the_base =
208
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 402 times.
467 base_static ? _class_base(member->base->type) : member->base->type;
209 467 const Value value = get_value(env, member, the_base);
210
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 458 times.
467 if (!value) {
211 9 const Value v = nspc_lookup_value1(env->curr, member->xid);
212
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if(v) {
213
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (self->is_call) {
214
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1 if (is_func(env->gwion, v->type) && (!v->from->owner_class || isa(the_base, v->from->owner_class) > 0)) // is_callable needs type
215 1 return v->type;
216 }
217 }
218 8 env_err(env, self->pos, _("class '%s' has no member '%s'"),
219 the_base->name, str);
220
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 if (member->base->type->nspc) did_you_mean_type(the_base, str);
221 8 return env->gwion->type[et_error];
222 }
223
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 458 times.
458 CHECK_BN(not_from_owner_class(env, the_base, value, self->pos));
224
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 458 times.
458 CHECK_BN(member_access(env, self, value));
225
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 394 times.
✓ Branch 3 taken 63 times.
✓ Branch 4 taken 1 times.
458 if ((base_static && vflag(value, vflag_member)) ||
226
3/4
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 331 times.
457 (value->from->owner_class != env->class_def && isa(value->from->owner_class, env->class_def) > 0))
227 1 ERR_N(self->pos,
228 _("cannot access member '%s.%s' without object instance..."),
229 the_base->name, str);
230
2/2
✓ Branch 0 taken 298 times.
✓ Branch 1 taken 159 times.
457 if (GET_FLAG(value, const)) exp_setmeta(self, true);
231 457 return value->type;
232 }
233
234 389 ANN static Type member_type(const Gwion gwion, const Type base) {
235 389 const Type t = actual_type(gwion, base);
236
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 385 times.
389 return !tflag(t, tflag_ref) ? t: (Type)vector_front(&t->info->tuple->contains);
237 }
238
239 389 OP_EMIT(opem_object_dot) {
240 389 const Exp_Dot *member = (Exp_Dot *)data;
241 389 const Type t_base = member_type(emit->gwion, member->base->type);
242 389 const Value value = find_value(t_base, member->xid);
243 // if(!tflag(t_base, tflag_emit) /*&& emit->env->class_def != t_base*/)
244 // ensure_emit(emit, t_base);
245
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 389 times.
389 if (is_class(emit->gwion, value->type)) {
246 emit_pushimm(emit, (m_uint)value->type);
247 return GW_OK;
248 }
249
4/4
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 351 times.
✓ Branch 3 taken 35 times.
✓ Branch 4 taken 3 times.
389 if (tflag(t_base, tflag_struct) && !GET_FLAG(value, static)) {
250 35 exp_setvar(member->base, true);
251
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
35 CHECK_BB(emit_exp(emit, member->base));
252 }
253
4/4
✓ Branch 1 taken 335 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 332 times.
724 if (!is_class(emit->gwion, member->base->type) &&
254
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
338 (vflag(value, vflag_member) ||
255 3 (is_func(emit->gwion, exp_self(member)->type)))) {
256
2/2
✓ Branch 1 taken 297 times.
✓ Branch 2 taken 36 times.
333 if (!tflag(t_base, tflag_struct))
257
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 297 times.
297 CHECK_BB(emit_exp(emit, member->base));
258 }
259
4/4
✓ Branch 2 taken 253 times.
✓ Branch 3 taken 136 times.
✓ Branch 4 taken 235 times.
✓ Branch 5 taken 18 times.
642 if (is_func(emit->gwion, exp_self(member)->type) &&
260 253 !fflag(exp_self(member)->type->info->func, fflag_fptr))
261 235 emit_member_func(emit, member);
262
2/2
✓ Branch 1 taken 122 times.
✓ Branch 2 taken 32 times.
154 else if (vflag(value, vflag_member)) {
263
2/2
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 34 times.
122 if (!tflag(t_base, tflag_struct))
264 88 emit_member(emit, value, exp_getvar(exp_self(member)));
265 else
266 34 emit_struct_data(emit, value, exp_getvar(exp_self(member)));
267
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 } else if (GET_FLAG(value, static))
268 32 emit_dot_static_import_data(emit, value, exp_getvar(exp_self(member)));
269 else exit(3); //emit_pushimm(emit, (m_uint)value->type);
270
4/4
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 337 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 2 times.
441 if(isa(value->type, emit->gwion->type[et_object]) > 0 &&
271 52 !exp_getvar(exp_self(member)) &&
272
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
50 (GET_FLAG(value, static) || GET_FLAG(value, late)))
273 9 emit_fast_except(emit, value->from, exp_self(member)->pos);
274 389 return GW_OK;
275 }
276
277 16 ANN static m_bool scantmpl_class_def(const Env env, struct tmpl_info *info) {
278 16 const Class_Def c = info->base->info->cdef;
279 16 const Class_Def cdef = new_class_def(
280 16 env->gwion->mp, c->flag, info->name,
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 c->base.ext ? cpy_type_decl(env->gwion->mp, c->base.ext) : NULL,
282 NULL, c->pos);
283
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 if(c->body) cdef->body = cpy_ast(env->gwion->mp, c->body);
284 16 cdef->cflag = c->cflag;
285 16 cdef->base.tmpl = mk_tmpl(env, c->base.tmpl, info->td->types);
286 16 const m_bool ret = scan0_class_def(env, cdef);
287
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if ((info->ret = cdef->base.type)) {
288 16 info->ret->info->cdef = cdef;
289 16 set_tflag(info->ret, tflag_cdef);
290 } else
291 free_class_def(env->gwion->mp, cdef);
292 16 return ret;
293 }
294
295 643 ANN static m_bool scantmpl_union_def(const Env env, struct tmpl_info *info) {
296 643 const Union_Def u = info->base->info->udef;
297 1286 const Union_Def udef = new_union_def(
298 643 env->gwion->mp, cpy_union_list(env->gwion->mp, u->l), u->pos);
299 643 udef->xid = info->name;
300 643 udef->tmpl = mk_tmpl(env, u->tmpl, info->td->types);
301 // resolve the template here
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 643 times.
643 if (GET_FLAG(info->base, global)) SET_FLAG(udef, global);
303 643 const m_bool ret = scan0_union_def(env, udef);
304
1/2
✓ Branch 0 taken 643 times.
✗ Branch 1 not taken.
643 if (udef->type) {
305 643 udef->type->info->udef = udef; // mark as udef
306 643 info->ret = udef->type; // is info->ret necessary?
307 643 set_tflag(info->ret, tflag_udef);
308 } else
309 free_union_def(env->gwion->mp, udef);
310 643 return ret;
311 }
312
313 659 ANN static Type _scan_class(const Env env, struct tmpl_info *info) {
314
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 643 times.
659 if (info->base->info->parent != env->gwion->type[et_union])
315
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 15 times.
16 CHECK_BO(scantmpl_class_def(env, info));
316 else
317
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 643 times.
643 CHECK_BO(scantmpl_union_def(env, info));
318 658 return info->ret;
319 }
320
321 2734 ANN Type scan_class(const Env env, const Type t, const Type_Decl *td) {
322 2734 struct tmpl_info info = {
323 2734 .base = t, .td = td, .list = t->info->cdef->base.tmpl->list};
324 2734 const Type exists = tmpl_exists(env, &info);
325
3/4
✓ Branch 0 taken 2075 times.
✓ Branch 1 taken 659 times.
✓ Branch 2 taken 2075 times.
✗ Branch 3 not taken.
2734 if (exists) return exists != env->gwion->type[et_error] ? exists : NULL;
326 659 struct EnvSet es = {.env = env,
327 .data = env,
328 .func = (_exp_func)scan0_cdef,
329 659 .scope = env->scope->depth,
330 .flag = tflag_check};
331 659 const Type owner = t->info->value->from->owner_class;
332
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 659 times.
659 CHECK_BO(envset_pushv(&es, t->info->value));
333
5/6
✓ Branch 0 taken 658 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 657 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
659 const bool local = !owner && !tmpl_global(env, td->types) && from_global_nspc(env, env->curr);
334
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 659 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
659 if(local && env->context) env_push(env, NULL, env->context->nspc);
335 659 const Type ret = _scan_class(env, &info);
336
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 659 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
659 if(local && env->context)env_pop(env, es.scope);
337 659 envset_pop(&es, owner);
338 659 return ret;
339 }
340
341 1 static OP_EMIT(opem_not_object) {
342 1 const Vector v = &emit->code->instr;
343 1 const Instr back = (Instr)vector_back(v);
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (back->opcode == eGWOP_EXCEPT) {
345 back->opcode = eIntNot;
346 return GW_OK;
347
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 } else if (back->opcode == eOP_MAX && back->execute == fast_except) {
348 back->opcode = eIntNot;
349 return GW_OK;
350 }
351 1 const Instr instr = emit_add_instr(emit, RegSetImm);
352 1 instr->m_val2 = -SZ_INT;
353 1 return GW_OK;
354 }
355
356 static OP_EMIT(opem_uncond_object) {
357 const Vector v = &emit->code->instr;
358 if(vector_size(v) >= 2) {
359 const Instr back = (Instr)vector_at(v, vector_size(v) -2);
360 if (back->opcode == eGWOP_EXCEPT || (back->opcode == eOP_MAX && back->execute == fast_except)) {
361 free_instr(emit->gwion, back);
362 vector_rem(v, vector_size(v) - 2);
363 }
364 }
365 emit_add_instr(emit, BranchNeqInt);
366 return GW_OK;
367 }
368
369 1 static OP_EMIT(opem_cond_object) {
370 1 const Vector v = &emit->code->instr;
371
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if(vector_size(v) >= 2) {
372 1 const Instr back = (Instr)vector_at(v, vector_size(v) -2);
373
2/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (back->opcode == eGWOP_EXCEPT || (back->opcode == eOP_MAX && back->execute == fast_except)) {
374 free_instr(emit->gwion, back);
375 vector_rem(v, vector_size(v) - 2);
376 }
377 }
378 1 emit_add_instr(emit, BranchEqInt);
379 1 return GW_OK;
380 }
381
382 638 GWION_IMPORT(object_op) {
383 638 const Type t_error = gwi_mk_type(gwi, "@error", 0, NULL);
384 638 gwi->gwion->type[et_error] = t_error;
385 638 GWI_BB(gwi_set_global_type(gwi, t_error, et_error))
386 638 GWI_BB(gwi_oper_ini(gwi, "Object", "Object", NULL))
387 638 GWI_BB(gwi_oper_add(gwi, opck_object_at))
388 638 GWI_BB(gwi_oper_emi(gwi, opem_object_at))
389 638 GWI_BB(gwi_oper_end(gwi, ":=>", NULL))
390 638 GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@Compound", NULL))
391 638 GWI_BB(gwi_oper_add(gwi, opck_object_instance))
392 638 GWI_BB(gwi_oper_end(gwi, "=>", NULL))
393 638 GWI_BB(gwi_oper_ini(gwi, "Object", "Object", "bool"))
394 638 GWI_BB(gwi_oper_end(gwi, "==", EqObject))
395 638 GWI_BB(gwi_oper_end(gwi, "!=", NeqObject))
396 638 GWI_BB(gwi_oper_add(gwi, opck_object_cast))
397 638 GWI_BB(gwi_oper_end(gwi, "$", NULL))
398 638 GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool"))
399 638 GWI_BB(gwi_oper_emi(gwi, opem_uncond_object))
400 638 GWI_BB(gwi_oper_end(gwi, "@unconditional", NULL))
401 638 GWI_BB(gwi_oper_emi(gwi, opem_cond_object))
402 638 GWI_BB(gwi_oper_end(gwi, "@conditional", NULL))
403 638 GWI_BB(gwi_oper_add(gwi, opck_unary_meta2))
404 638 GWI_BB(gwi_oper_emi(gwi, opem_not_object))
405 638 GWI_BB(gwi_oper_end(gwi, "!", NULL))
406 638 GWI_BB(gwi_oper_ini(gwi, "@Compound", NULL, NULL))
407 638 GWI_BB(gwi_oper_add(gwi, opck_struct_scan))
408 638 GWI_BB(gwi_oper_end(gwi, "class", NULL))
409 638 return GW_OK;
410 }
411