Gwion coverage report


Directory: src/
File: src/parse/scan0.c
Date: 2023-01-30 18:32:28
Exec Total Coverage
Lines: 342 421 81.2%
Functions: 34 40 85.0%
Branches: 218 320 68.1%

Line Branch Exec Source
1 #include "gwion_util.h"
2 #include "gwion_ast.h"
3 #include "gwion_env.h"
4 #include "vm.h"
5 #include "traverse.h"
6 #include "template.h"
7 #include "parse.h"
8 #include "gwion.h"
9 #include "object.h"
10 #include "instr.h"
11 #include "operator.h"
12 #include "import.h"
13 #include "spread.h"
14 #include "emit.h"
15
16 12967 static inline void add_type(const Env env, const Nspc nspc, const Type t) {
17 12967 nspc_add_type_front(nspc, insert_symbol(t->name), t);
18 12967 }
19
20 19810 ANN static inline m_bool scan0_defined(const Env env, const Symbol s,
21 const loc_t pos) {
22
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 19807 times.
19810 if (nspc_lookup_type1(env->curr, s))
23 3 ERR_B(pos, _("type '%s' already defined"), s_name(s));
24 19807 return already_defined(env, s, pos);
25 }
26
27 6826 ANN static Arg_List fptr_arg_list(const Env env, const Fptr_Def fptr) {
28
4/4
✓ Branch 0 taken 6791 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 6764 times.
6826 if(env->class_def && !GET_FLAG(fptr->base, static)) {
29 27 Arg arg = { .td = type2td(env->gwion, env->class_def, fptr->base->td->pos) };
30 27 const uint32_t len = mp_vector_len(fptr->base->args);
31 27 Arg_List args = new_mp_vector(env->gwion->mp, Arg, len + 1);
32 27 mp_vector_set(args, Arg, 0, arg);
33
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 27 times.
45 for(uint32_t i = 0; i < len; i++) {
34 18 Arg *base = mp_vector_at(fptr->base->args, Arg, i);
35 18 Arg arg = { .td = cpy_type_decl(env->gwion->mp, base->td) };
36 18 mp_vector_set(args, Arg, i+1, arg);
37 }
38 27 return args;
39
2/2
✓ Branch 0 taken 6775 times.
✓ Branch 1 taken 24 times.
6799 } else if(fptr->base->args)
40 6775 return cpy_arg_list(env->gwion->mp, fptr->base->args);
41 24 return NULL;
42 }
43
44 12987 ANN static inline m_bool scan0_global(const Env env, const ae_flag flag,
45 const loc_t loc) {
46
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 12982 times.
12987 CHECK_BB(env_storage(env, flag, loc));
47 12982 const bool global = (flag & ae_flag_global) == ae_flag_global;
48
2/2
✓ Branch 0 taken 12975 times.
✓ Branch 1 taken 7 times.
12982 if (!global) return global;
49
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (!env->class_def) {
50 7 env_push_global(env);
51
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (env->context) env->context->global = true;
52 7 return GW_OK;
53 }
54 ERR_B(loc, _("can't declare as global in class def"))
55 }
56
57 6829 ANN m_bool scan0_fptr_def(const Env env, const Fptr_Def fptr) {
58 6829 const loc_t loc = fptr->base->td->pos;
59
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6826 times.
6829 CHECK_BB(env_access(env, fptr->base->flag, loc));
60
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6826 times.
6826 CHECK_BB(scan0_defined(env, fptr->base->xid, loc));
61 6826 const Arg_List args = fptr_arg_list(env, fptr);
62 6826 Func_Base *const fbase = new_func_base(env->gwion->mp, cpy_type_decl(env->gwion->mp, fptr->base->td),
63 6826 insert_symbol("func"), args, ae_flag_static | ae_flag_private, loc);
64 6826 const Func_Def fdef = new_func_def(env->gwion->mp, fbase, NULL);
65 6826 Ast body = new_mp_vector(env->gwion->mp, Section, 1);
66 6826 mp_vector_set(body, Section, 0, MK_SECTION(func, func_def, fdef));
67 6826 Type_Decl* td = new_type_decl(env->gwion->mp, insert_symbol(env->gwion->type[et_closure]->name), loc);
68 6826 const Class_Def cdef = new_class_def(env->gwion->mp, ae_flag_final, fptr->base->xid, td, body, loc);
69
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6824 times.
6826 if(GET_FLAG(fptr->base, global)) {
70 2 SET_FLAG(cdef, global);
71 2 UNSET_FLAG(fptr->base, global);
72 }
73
2/2
✓ Branch 0 taken 4079 times.
✓ Branch 1 taken 2747 times.
6826 if(fptr->base->tmpl) {
74 4079 fbase->tmpl = cpy_tmpl(env->gwion->mp, fptr->base->tmpl);
75
2/2
✓ Branch 0 taken 4067 times.
✓ Branch 1 taken 12 times.
4079 if(!fptr->base->tmpl->call)
76 4067 cdef->base.tmpl = cpy_tmpl(env->gwion->mp, fptr->base->tmpl);
77 }
78 6826 fptr->cdef = cdef;
79 6826 return scan0_class_def(env, cdef);
80 }
81
82 static OP_CHECK(opck_implicit_similar) {
83 const struct Implicit *imp = (struct Implicit *)data;
84 return imp->e->type;
85 }
86
87 static OP_CHECK(opck_contract_similar) {
88 const Exp_Cast *cast = (Exp_Cast *)data;
89 if(tflag(exp_self(cast)->type, tflag_contract)) {
90 struct Implicit imp = { .t=exp_self(cast)->type, .e=cast->exp};
91 struct Op_Import opi = {
92 .op = insert_symbol("@implicit"), .lhs = cast->exp->type, .rhs = exp_self(cast)->type, .data=(m_uint)&imp };
93 CHECK_NN(op_check(env, &opi));
94 }
95 return opck_similar_cast(env, data);
96 }
97
98 15 ANN static void scan0_implicit_similar(const Env env, const Type lhs,
99 const Type rhs) {
100 15 struct Op_Func opfunc = {.ck = opck_similar_cast};
101 15 struct Op_Import opi = {
102 15 .op = insert_symbol("$"), .lhs = lhs, .rhs = rhs, .func = &opfunc};
103 15 add_op(env->gwion, &opi);
104 15 opi.lhs = rhs;
105 15 opi.rhs = lhs;
106 15 add_op(env->gwion, &opi);
107 15 opfunc.ck = opck_implicit_similar;
108 15 opi.op = insert_symbol("@implicit");
109 15 add_op(env->gwion, &opi);
110 15 }
111
112 3 ANN static void scan0_explicit_distinct(const Env env, const Type lhs,
113 const Type rhs) {
114 3 struct Op_Func opfunc = {.ck = opck_similar_cast};
115
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if(tflag(rhs, tflag_contract)) {
116 3 opfunc.ck = opck_contract_similar;
117 3 opfunc.em = opem_contract_similar;
118 }
119 3 struct Op_Import opi = {
120 3 .op = insert_symbol("$"), .lhs = lhs, .rhs = rhs, .func = &opfunc};
121 3 add_op(env->gwion, &opi);
122 3 opi.lhs = rhs;
123 3 opi.rhs = lhs;
124 3 add_op(env->gwion, &opi);
125 3 }
126
127 11 ANN static void typedef_simple(const Env env, const Type_Def tdef,
128 const Type base) {
129 11 const Type t = new_type(env->gwion->mp, s_name(tdef->xid), base);
130 11 t->size = base->size;
131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 const Nspc nspc = (!env->class_def && GET_FLAG(tdef->ext, global))
132 ? env->global_nspc
133
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
21 : env->curr;
134 11 add_type(env, nspc, t);
135 11 tdef->type = t;
136
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
11 if (base->nspc) {
137 5 t->nspc = new_nspc(env->gwion->mp, t->name);
138 5 t->nspc->parent = base->nspc;
139 }
140 11 t->flag = tdef->ext->flag;
141
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
11 if (tdef->ext->array && !tdef->ext->array->exp) {
142 3 set_tflag(t, tflag_empty);
143 3 SET_FLAG(t, abstract);
144
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 } else if(tflag(base, tflag_union))
145 set_tflag(t, tflag_union);
146 11 }
147
148 7 ANN static m_bool typedef_complex(const Env env, const Type_Def tdef,
149 const Type base) {
150
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 const ae_flag flag = base->info->cdef ? base->info->cdef->flag : 0;
151 7 const Class_Def cdef = new_class_def(env->gwion->mp, flag, tdef->xid,
152 7 cpy_type_decl(env->gwion->mp, tdef->ext),
153 7 NULL, tdef->ext->pos);
154 7 const bool final = GET_FLAG(base, final);
155
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if(final) UNSET_FLAG(base, final);
156
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 CHECK_BB(scan0_class_def(env, cdef));
157 7 tdef->type = cdef->base.type;
158 7 cdef->base.tmpl = tdef->tmpl; // check cpy
159 7 set_tflag(tdef->type, tflag_cdef);
160
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if(final) SET_FLAG(base, final);
161 7 return GW_OK;
162 }
163
164 22 ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) {
165
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 CHECK_BB(env_access(env, tdef->ext->flag, tdef->ext->pos));
166
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
22 DECL_OB(const Type, base, = known_type(env, tdef->ext));
167
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
20 CHECK_BB(scan0_defined(env, tdef->xid, tdef->ext->pos));
168
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 DECL_BB(const m_bool, global, = scan0_global(env, tdef->ext->flag, tdef->ext->pos));
169
6/6
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 4 times.
18 if (!tdef->ext->types && (!tdef->ext->array || !tdef->ext->array->exp))
170 11 typedef_simple(env, tdef, base);
171
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 else CHECK_BB(typedef_complex(env, tdef, base));
172 18 mk_class(env, tdef->type, tdef->pos);
173
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
18 if (tdef->when) set_tflag(tdef->type, tflag_contract);
174
4/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 3 times.
18 if (tdef->type != base && !tdef->distinct && !tdef->when)
175 15 scan0_implicit_similar(env, base, tdef->type);
176
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 15 times.
21 if (tdef->distinct || tdef->when) {
177
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (base->info->gack)
178 3 vmcode_addref(tdef->type->info->gack = base->info->gack);
179 3 set_tflag(tdef->type, tflag_distinct);
180 3 struct Op_Import opi = {.lhs = base, .rhs = tdef->type};
181 3 op_cpy(env, &opi);
182 3 scan0_explicit_distinct(env, base, tdef->type);
183 } else //if(tdef->ext->array)
184 15 set_tflag(tdef->type, tflag_typedef);
185
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if(tflag(base, tflag_ref)) {
186 set_tflag(tdef->type, tflag_ref);
187 set_tflag(tdef->type, tflag_infer);
188 }
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (global) env_pop(env, 0);
190 18 return GW_OK;
191 }
192
193 646 ANN static Type enum_type(const Env env, const Enum_Def edef) {
194 646 const Type t = type_copy(env->gwion->mp, env->gwion->type[et_enum]);
195 646 t->name = s_name(edef->xid);
196 646 t->info->parent = env->gwion->type[et_enum];
197 646 add_type(env, env->curr, t);
198 646 mk_class(env, t, edef->pos);
199 646 return t;
200 }
201
202 646 ANN m_bool scan0_enum_def(const Env env, const Enum_Def edef) {
203
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 646 times.
646 CHECK_BB(scan0_defined(env, edef->xid, edef->pos));
204
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 646 times.
646 DECL_BB(const m_bool, global, = scan0_global(env, edef->flag, edef->pos));
205 646 edef->type = enum_type(env, edef);
206 646 vector_init(&edef->values);
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 646 times.
646 if (global) env_pop(env, 0);
208 646 return GW_OK;
209 }
210
211 1284 ANN static Type union_type(const Env env, const Symbol s, const loc_t loc) {
212 1284 const m_str name = s_name(s);
213 1284 const Type t = new_type(env->gwion->mp, name, env->gwion->type[et_union]);
214 1284 t->nspc = new_nspc(env->gwion->mp, name);
215 1284 t->nspc->parent = env->curr;
216 1284 t->info->tuple = new_tupleform(env->gwion->mp, NULL); // ???
217 1284 set_tflag(t, tflag_union);
218 1284 add_type(env, env->curr, t);
219 1284 mk_class(env, t, loc);
220 1284 SET_FLAG(t, final);
221 1284 set_tflag(t, tflag_compound);
222
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1281 times.
1284 if (strncmp(t->name, "Option", 6)) SET_FLAG(t, abstract);
223 1284 return t;
224 }
225
226 1282 ANN static void union_tmpl(const Env env, const Union_Def udef) {
227
2/2
✓ Branch 1 taken 639 times.
✓ Branch 2 taken 643 times.
1282 if (tmpl_base(udef->tmpl)) {
228 639 const Union_Def u = cpy_union_def(env->gwion->mp, udef);
229 639 u->type = udef->type;
230 639 udef->type->info->udef = u;
231 639 set_tflag(u->type, tflag_tmpl);
232 639 set_tflag(u->type, tflag_udef);
233 }
234 1282 }
235
236 1287 ANN m_bool scan0_union_def(const Env env, const Union_Def udef) {
237
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1284 times.
1287 DECL_BB(const m_bool, global, = scan0_global(env, udef->flag, udef->pos));
238
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1284 times.
1284 CHECK_BB(scan0_defined(env, udef->xid, udef->pos));
239 1284 udef->type = union_type(env, udef->xid, udef->pos);
240
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1284 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1284 times.
1284 SET_ACCESS(udef, udef->type);
241
2/2
✓ Branch 0 taken 1282 times.
✓ Branch 1 taken 2 times.
1284 if (udef->tmpl) union_tmpl(env, udef);
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1284 times.
1284 if (global) env_pop(env, 0);
243 1284 set_tflag(udef->type, tflag_scan0);
244 1284 return GW_OK;
245 }
246
247 8474 ANN static inline void cdef_flag(const Class_Def cdef, const Type t) {
248
2/2
✓ Branch 0 taken 5458 times.
✓ Branch 1 taken 3016 times.
8474 if (cdef->base.tmpl) set_tflag(t, tflag_tmpl);
249
4/4
✓ Branch 0 taken 8234 times.
✓ Branch 1 taken 240 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 8228 times.
8474 if (cdef->base.ext && cdef->base.ext->array) set_tflag(t, tflag_typedef);
250 8474 }
251
252 4071 ANN static Type get_parent_base(const Env env, Type_Decl *td) {
253
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4068 times.
4071 DECL_OO(const Type, t, = known_type(env, td));
254 4068 Type owner = env->class_def;
255
2/2
✓ Branch 0 taken 4060 times.
✓ Branch 1 taken 4068 times.
8128 while (owner) {
256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4060 times.
4060 if (t == owner)
257 ERR_O(td->pos, _("'%s' as parent inside itself\n."), owner->name);
258 4060 owner = owner->info->value->from->owner_class;
259 }
260 4068 return t;
261 }
262
263 4170 ANN static inline Type scan0_final(const Env env, Type_Decl *td) {
264 4170 const Type t = known_type(env, td);
265
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4166 times.
4170 if(!t) ERR_O(td->pos, _("can't find parent class %s\n."), s_name(td->xid));
266 4166 return t;
267 }
268
269 8481 ANN static Type cdef_parent(const Env env, const Class_Def cdef) {
270
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 8451 times.
8481 if (cflag(cdef, cflag_struct)) return env->gwion->type[et_compound];
271
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 8241 times.
8451 if (!cdef->base.ext) return env->gwion->type[et_object];
272
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8235 times.
8241 Exp e = cdef->base.ext->array ? cdef->base.ext->array->exp : NULL;
273
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8241 times.
8247 while(e) {
274
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if(!is_prim_int(e))
275 ERR_O(e->pos, "non null array type extension must be literal");
276 6 e = e->next;
277 }
278
2/2
✓ Branch 1 taken 4071 times.
✓ Branch 2 taken 4170 times.
8241 if (tmpl_base(cdef->base.tmpl)) return get_parent_base(env, cdef->base.ext);
279 4170 const bool tmpl = !!cdef->base.tmpl;
280
2/2
✓ Branch 0 taken 1357 times.
✓ Branch 1 taken 2813 times.
4170 if (tmpl) template_push_types(env, cdef->base.tmpl);
281 4170 const Type t = scan0_final(env, cdef->base.ext);
282
2/2
✓ Branch 0 taken 1357 times.
✓ Branch 1 taken 2813 times.
4170 if (tmpl) nspc_pop_type(env->gwion->mp, env->curr);
283 4170 return t;
284 }
285
286 ANN static m_bool find_traits(const Env env, ID_List traits, const loc_t pos) {
287 for(uint32_t i = 0; i < traits->len; i++) {
288 Symbol xid = *mp_vector_at(traits, Symbol, i);
289 if (!nspc_lookup_trait1(env->curr, xid)) {
290 gwerr_basic(_("can't find trait"), NULL, NULL, env->name, pos, 0);
291 did_you_mean_trait(env->curr, s_name(xid));
292 env_set_error(env, true);
293 return GW_ERROR;
294 }
295 }
296 return GW_OK;
297 }
298
299 8482 ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
300
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 8481 times.
8482 CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos));
301
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 8474 times.
8481 DECL_OO(const Type, parent, = cdef_parent(env, cdef));
302
4/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 8467 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
8474 if(GET_FLAG(cdef, global) && isa(parent, env->gwion->type[et_closure]) < 0 && !type_global(env, parent)) {
303 gwerr_basic(_("parent type is not global"), NULL, NULL, env->name, cdef->base.ext ? cdef->base.ext->pos : cdef->base.pos, 0);
304 declared_here(parent->info->value);
305 env_set_error(env, true);
306 return NULL;
307 }
308
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8474 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
8474 if (cdef->traits) CHECK_BO(find_traits(env, cdef->traits, cdef->pos));
309 8474 const Type t = new_type(env->gwion->mp, s_name(cdef->base.xid), parent);
310
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 8444 times.
8474 if (cflag(cdef, cflag_struct)) {
311 30 t->size = 0;
312 30 set_tflag(t, tflag_struct);
313 8444 } else set_tflag(t, tflag_release);
314 8474 set_tflag(t, tflag_compound);
315 8474 t->info->tuple = new_tupleform(env->gwion->mp, parent);
316 8474 t->nspc = new_nspc(env->gwion->mp, t->name);
317 8474 t->nspc->parent = env->curr;
318 8474 t->info->cdef = cdef;
319 8474 t->flag |= cdef->flag;
320 8474 cdef_flag(cdef, t);
321 8474 return t;
322 }
323
324
325 7 ANN static m_bool _spread_tmpl(const Env env, const Type t, const Spread_Def spread) {
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(t->info->value->from->owner_class)
327 CHECK_BB(_spread_tmpl(env, t->info->value->from->owner_class, spread));
328 7 const Tmpl *tmpl = t->info->cdef->base.tmpl;
329
3/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 3 times.
7 if(!tmpl || !tmpl->call) return GW_OK;
330
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if(is_spread_tmpl(tmpl))
331
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 CHECK_BB(spread_ast(env, spread, tmpl));
332 2 return GW_OK;
333 }
334
335 9 ANN static m_bool spread_tmpl(const Env env, const Spread_Def spread) {
336
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 6 times.
9 if(env->class_def) CHECK_BB(_spread_tmpl(env, env->class_def, spread));
337
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if(!env->func) return GW_OK;
338 2 const Tmpl *tmpl = env->func->def->base->tmpl;
339
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if(!tmpl || !tmpl->call) return GW_OK;
340
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if(is_spread_tmpl(tmpl))
341
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_BB(spread_ast(env, spread, tmpl));
342 2 return GW_OK;
343 }
344
345 11 ANN static bool spreadable(const Env env) {
346 11 const Func f = env->func;
347
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
11 if(f && f->def->base->tmpl && is_spread_tmpl(f->def->base->tmpl))
348 2 return true;
349 9 Type t = env->class_def;
350
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 while(t) {
351 8 const Tmpl *tmpl = t->info->cdef->base.tmpl;
352
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
8 if(tmpl && is_spread_tmpl(tmpl))
353 7 return true;
354 1 t = t->info->value->from->owner_class;
355 }
356 2 return false;
357 }
358
359 761 ANN static m_bool scan0_stmt_list(const Env env, Stmt_List l) {
360
2/2
✓ Branch 0 taken 1802 times.
✓ Branch 1 taken 715 times.
2517 for(m_uint i = 0; i < l->len; i++) {
361 1802 const Stmt stmt = mp_vector_at(l, struct Stmt_, i);
362
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 1752 times.
1802 if (stmt->stmt_type == ae_stmt_pp) {
363
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 48 times.
50 if (stmt->d.stmt_pp.pp_type == ae_pp_include)
364 2 env->name = stmt->d.stmt_pp.data;
365
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 5 times.
48 else if (stmt->d.stmt_pp.pp_type == ae_pp_import)
366
1/2
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
43 CHECK_BB(plugin_ini(env->gwion, stmt->d.stmt_pp.data, stmt->pos));
367
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1741 times.
1752 } else if (stmt->stmt_type == ae_stmt_spread) {
368
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
11 if(!spreadable(env))
369 2 ERR_B(stmt->pos, "spread statement outside of variadic environment");
370
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 if(!env->context->extend)
371 6 env->context->extend = new_mp_vector(env->gwion->mp, Section, 0);
372
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 8 times.
9 CHECK_BB(spread_tmpl(env, &stmt->d.stmt_spread));
373 }
374 }
375 715 return GW_OK;
376 }
377
378 89442 ANN m_bool scan0_func_def(const Env env, const Func_Def fdef) {
379
2/2
✓ Branch 0 taken 714 times.
✓ Branch 1 taken 88728 times.
89442 const Ast old_extend = env->context ? env->context->extend : NULL;
380
4/4
✓ Branch 0 taken 24450 times.
✓ Branch 1 taken 64992 times.
✓ Branch 2 taken 24388 times.
✓ Branch 3 taken 62 times.
89442 if(!fdef->base->tmpl || !fdef->base->tmpl->call) return GW_OK;
381
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if(env->context) {
382
4/6
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 62 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 60 times.
62 if(fdef->base->tmpl && fdef->base->tmpl->call && is_spread_tmpl(fdef->base->tmpl)) {
383 2 struct Func_ fake = {.name = s_name(fdef->base->xid), .def = fdef }, *const former =
384 env->func;
385 2 env->func = &fake;
386
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if(!fdef->builtin && fdef->d.code)
387 2 scan0_stmt_list(env, fdef->d.code);
388
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(env->context->extend)
389 2 fdef->d.code = spread_func(env, fdef->d.code);
390 2 env->func = former;
391 2 env->context->extend = old_extend;
392 }}
393 62 return GW_OK;
394 }
395
396 ANN static m_bool scan0_extend_def(const Env env, const Extend_Def xdef) {
397 DECL_OB(const Type, t, = known_type(env, xdef->td));
398 if(type_global(env, t)) {
399 for(uint32_t i = 0; i < xdef->traits->len; i++) {
400 const Symbol xid = *mp_vector_at(xdef->traits, Symbol, i);
401 const Trait global = nspc_lookup_trait1(env->global_nspc, xid);
402 if(!global) {
403 const Trait trait = nspc_lookup_trait1(env->curr, xid);
404 gwerr_basic("trait should be declared global", NULL, NULL, trait->filename, trait->loc, 0);
405 gwerr_secondary("from the request ", env->name, xdef->td->pos);
406 env_set_error(env, true);
407 }
408 }
409 }
410 xdef->type = t;
411 return GW_OK;
412 }
413
414 ANN static m_bool _scan0_trait_def(const Env env, const Trait_Def pdef) {
415 CHECK_BB(scan0_defined(env, pdef->xid, pdef->pos));
416 DECL_BB(const m_bool, global, = scan0_global(env, pdef->flag, pdef->pos));
417 const Trait trait = new_trait(env->gwion->mp, pdef->pos);
418 trait->loc = pdef->pos;
419 trait->name = s_name(pdef->xid);
420 trait->filename = env->name;
421 nspc_add_trait(env->curr, pdef->xid, trait);
422 if(global) env_pop(env, 0);
423 Ast ast = pdef->body;
424 if(!ast) return GW_OK; // ???
425 for(m_uint i = 0; i < ast->len; i++) {
426 Section *section = mp_vector_at(ast, Section, i);
427 if (section->section_type == ae_section_func) {
428 const Func_Def fdef = section->d.func_def;
429 if (fdef->base->flag != ae_flag_none &&
430 fdef->base->flag != (ae_flag_none | ae_flag_abstract))
431 ERR_B(fdef->base->pos, "Trait function must be declared without qualifiers");
432 if (!trait->fun) trait->fun = new_mp_vector(env->gwion->mp, Func_Def, 0);
433 mp_vector_add(env->gwion->mp, &trait->fun, Func_Def, fdef);
434 }
435 }
436 return GW_OK;
437 }
438
439 ANN static m_bool scan0_trait_def(const Env env, const Trait_Def pdef) {
440 const Symbol s = pdef->xid;
441 const Trait exists = nspc_lookup_trait1(env->curr, s);
442 if (exists) {
443 gwerr_basic("trait already defined", NULL, NULL, env->name, pdef->pos, 0);
444 gwerr_secondary("defined here", env->name, exists->loc);
445 env_set_error(env, true);
446 return already_defined(env, s, pdef->pos);
447 }
448 if (pdef->traits) CHECK_BB(find_traits(env, pdef->traits, pdef->pos));
449 _scan0_trait_def(env, pdef);
450 return GW_OK;
451 }
452
453 2552 ANN m_bool scan0_prim_def(const Env env, const Prim_Def pdef) {
454 2552 const loc_t loc = pdef->loc;
455
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2552 times.
2552 CHECK_BB(env_access(env, pdef->flag, loc));
456
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2552 times.
2552 CHECK_BB(scan0_defined(env, pdef->name, loc));
457
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2552 times.
2552 DECL_BB(const m_bool, global, = scan0_global(env, pdef->flag, loc));
458 2552 const Type t = mk_primitive(env, s_name(pdef->name), pdef->size);
459 2552 add_type(env, env->curr, t);
460 2552 mk_class(env, t, pdef->loc);
461 2552 t->flag = pdef->flag;
462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2552 times.
2552 if(global) env_pop(env, 0);
463 2552 return GW_OK;
464 }
465
466 32618 HANDLE_SECTION_FUNC(scan0, m_bool, Env)
467
468 8482 ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
469
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8482 times.
8482 CHECK_BB(isres(env, cdef->base.xid, cdef->pos));
470
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8474 times.
8482 CHECK_OB((cdef->base.type = scan0_class_def_init(env, cdef)));
471 8474 cdef->base.type->info->traits = cdef->traits; // should we copy the traits?
472 8474 set_tflag(cdef->base.type, tflag_scan0);
473 8474 (void)mk_class(env, cdef->base.type, cdef->pos);
474 8474 add_type(env, cdef->base.type->info->value->from->owner, cdef->base.type);
475
2/2
✓ Branch 0 taken 8416 times.
✓ Branch 1 taken 58 times.
8474 const m_bool ret = cdef->body ? env_body(env, cdef, scan0_section) : GW_OK;
476 8474 return ret;
477 }
478
479 ANN Ast spread_class(const Env env, const Ast body);
480
481 3 static INSTR(StructAssign) {
482 3 memcpy(*(m_bit**)REG(-SZ_INT), REG((m_int)instr->m_val), instr->m_val2);
483 3 }
484
485 3 static OP_EMIT(opem_struct_assign) {
486 3 const Exp_Binary *bin = data;
487 3 const Type t = bin->lhs->type;
488 3 const Exp e = exp_self(bin);
489
490
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if(tflag(t, tflag_release)) {
491 const Instr release = emit_add_instr(emit, StructReleaseRegAddr);
492 release->m_val = -SZ_INT;
493 release->m_val2 = (m_uint)t;
494 }
495
496 3 const Instr instr = emit_add_instr(emit, StructAssign);
497 3 instr->m_val = -t->size - SZ_INT;
498 3 instr->m_val2 = t->size;
499 3 emit_struct_addref(emit, t, -SZ_INT, true); // add ref on lhs
500
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 if(exp_getvar(e)) {
501 2 emit_regmove(emit, -t->size);
502 2 const Instr instr = emit_add_instr(emit, Reg2Reg);
503 2 instr->m_val = -SZ_INT;
504 2 instr->m_val2 = t->size - SZ_INT;
505 1 } else emit_regmove(emit, -SZ_INT);
506 3 return GW_OK;
507 }
508
509 3 ANN static OP_CHECK(opck_struct_assign) {
510
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 CHECK_NN(opck_rassign(env, data));
511 3 Exp_Binary *bin = data;
512 3 bin->rhs->ref = bin->lhs;
513 3 return bin->lhs->type;
514 }
515
516 30 ANN static void scan0_struct_assign(const Env env, const Type t) {
517 30 struct Op_Func opfunc = {.ck = opck_struct_assign, .em = opem_struct_assign };
518 30 struct Op_Import opi = {
519 30 .op = insert_symbol(":=>"), .lhs = t, .rhs = t, .ret = t, .func = &opfunc};
520 30 add_op(env->gwion, &opi);
521 30 }
522
523 8484 ANN m_bool scan0_class_def(const Env env, const Class_Def c) {
524
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8482 times.
8484 DECL_BB(const m_bool, global, = scan0_global(env, c->flag, c->pos));
525
2/2
✓ Branch 0 taken 406 times.
✓ Branch 1 taken 8076 times.
8482 const Ast old_extend = env->context ? env->context->extend : NULL;
526
4/4
✓ Branch 1 taken 4394 times.
✓ Branch 2 taken 4088 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 4387 times.
8482 const int cpy = tmpl_base(c->base.tmpl) || GET_FLAG(c, global);
527
2/2
✓ Branch 0 taken 4095 times.
✓ Branch 1 taken 4387 times.
8482 const Class_Def cdef = !cpy ? c : cpy_class_def(env->gwion->mp, c);
528 8482 const m_bool ret = scan0_class_def_inner(env, cdef);
529
530
4/4
✓ Branch 0 taken 4095 times.
✓ Branch 1 taken 4387 times.
✓ Branch 2 taken 4092 times.
✓ Branch 3 taken 3 times.
8482 if (cpy && cdef->base.type) c->base.type = cdef->base.type;
531
2/2
✓ Branch 0 taken 406 times.
✓ Branch 1 taken 8076 times.
8482 if(env->context) {
532
4/4
✓ Branch 1 taken 356 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 354 times.
406 if(!tmpl_base(c->base.tmpl) && env->context->extend)
533 2 cdef->body = spread_class(env, cdef->body);
534 406 env->context->extend = old_extend;
535 }
536
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 8452 times.
8482 if(cflag(cdef, cflag_struct)) scan0_struct_assign(env, cdef->base.type);
537
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 8475 times.
8482 if (GET_FLAG(cdef, global)) env_pop(env, 0);
538 8482 return ret;
539 }
540
541 647 ANN m_bool scan0_ast(const Env env, Ast *ast) {
542 647 Ast a = *ast;
543
2/2
✓ Branch 0 taken 1075 times.
✓ Branch 1 taken 584 times.
1659 for(m_uint i = 0; i < a->len; i++) {
544 1075 Section * section = mp_vector_at(a, Section, i);
545
2/2
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 1012 times.
1075 CHECK_BB(scan0_section(env, section));
546 }
547 584 return GW_OK;
548 }
549