Line | Branch | Exec | Source |
---|---|---|---|
1 | #include <ctype.h> | ||
2 | #include "gwion_util.h" | ||
3 | #include "gwion_ast.h" | ||
4 | #include "gwion_env.h" | ||
5 | #include "vm.h" | ||
6 | #include "instr.h" | ||
7 | #include "traverse.h" | ||
8 | #include "template.h" | ||
9 | #include "gwion.h" | ||
10 | #include "object.h" | ||
11 | #include "operator.h" | ||
12 | #include "import.h" | ||
13 | #include "parse.h" | ||
14 | #include "match.h" | ||
15 | #include "specialid.h" | ||
16 | #include "tmp_resolve.h" | ||
17 | #include "partial.h" | ||
18 | #include "spread.h" | ||
19 | #include "array.h" | ||
20 | |||
21 | ANN m_bool check_stmt_list(const Env env, Stmt_List list); | ||
22 | ANN m_bool check_class_def(const Env env, const Class_Def class_def); | ||
23 | |||
24 | 109 | ANN static Type check_internal(const Env env, const Symbol sym, const Exp e, | |
25 | const Type t) { | ||
26 | 109 | struct Implicit imp = {.e = e, .t = t, .pos = e->pos}; | |
27 | 109 | struct Op_Import opi = {.op = sym, | |
28 | 109 | .lhs = e->type, | |
29 | .rhs = t, | ||
30 | 109 | .data = (uintptr_t)&imp, | |
31 | .pos = e->pos}; | ||
32 | 109 | return op_check(env, &opi); | |
33 | } | ||
34 | |||
35 | 160 | ANN m_bool check_implicit(const Env env, const Exp e, const Type t) { | |
36 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 115 times.
|
160 | if (e->type == t) return GW_OK; |
37 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 109 times.
|
115 | if (isa(e->type, t) > 0) return GW_OK; |
38 | 109 | const Symbol sym = insert_symbol("@implicit"); | |
39 |
2/2✓ Branch 1 taken 33 times.
✓ Branch 2 taken 76 times.
|
109 | return (e->cast_to = check_internal(env, sym, e, t)) ? GW_OK : GW_ERROR; |
40 | } | ||
41 | |||
42 | 45 | ANN m_bool check_subscripts(Env env, const Array_Sub array, | |
43 | const m_bool is_decl) { | ||
44 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
|
45 | CHECK_OB(check_exp(env, array->exp)); |
45 | 45 | m_uint depth = 0; | |
46 | 45 | Exp e = array->exp; | |
47 | do { | ||
48 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 28 times.
|
59 | if (is_decl) { |
49 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 30 times.
|
31 | if(check_implicit(env, e, env->gwion->type[et_int]) < 0) |
50 | 1 | ERR_B(array->exp->pos, _("invalid array declaration index type.")) | |
51 | } | ||
52 |
3/4✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 44 times.
|
58 | } while (++depth && (e = e->next)); |
53 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 43 times.
|
44 | if (depth != array->depth) |
54 | 1 | ERR_B(array->exp->pos, _("invalid array access expression.")) | |
55 | 43 | return GW_OK; | |
56 | } | ||
57 | |||
58 | 2708 | ANN static inline m_bool check_exp_decl_parent(const Env env, | |
59 | const Var_Decl *var) { | ||
60 | 2708 | const Value value = find_value(env->class_def->info->parent, var->xid); | |
61 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2707 times.
|
2708 | if (value) { |
62 | 1 | env_err(env, var->pos, _("Value defined in parent class")); | |
63 | 1 | defined_here(value); | |
64 | 1 | return GW_ERROR; | |
65 | } | ||
66 | 2707 | return GW_OK; | |
67 | } | ||
68 | |||
69 | 3363 | ANN static m_uint get_decl_size(const Env env, const Value v) { | |
70 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 3363 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
3363 | if(safe_tflag(env->class_def, tflag_packed) && v->type->actual_size) |
71 | ✗ | return v->type->actual_size; | |
72 | 3363 | return v->type->size; | |
73 | |||
74 | } | ||
75 | |||
76 | #define describe_check_decl(a, b, flag) \ | ||
77 | ANN static inline void decl_##a(const Env env, const Value v) { \ | ||
78 | const Nspc nspc = env->curr; \ | ||
79 | flag; \ | ||
80 | v->from->offset = nspc->b; \ | ||
81 | nspc->b += get_decl_size(env, v); \ | ||
82 | } | ||
83 | |||
84 | 2695 | describe_check_decl(member, offset, v->vflag |= vflag_member); | |
85 | 668 | describe_check_decl(static, class_data_size, SET_FLAG(v, static)); | |
86 | |||
87 | 19093 | ANN static void var_effects(const Env env, const Type t, const Symbol sym, const loc_t loc) { | |
88 |
2/2✓ Branch 0 taken 6990 times.
✓ Branch 1 taken 12103 times.
|
19093 | if (t->info->parent) var_effects(env, t->info->parent, sym, loc); |
89 |
2/2✓ Branch 1 taken 16362 times.
✓ Branch 2 taken 2731 times.
|
19093 | if(!tflag(t, tflag_ctor)) return; |
90 | 2731 | const Value ctor = nspc_lookup_value0(t->nspc, sym); | |
91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2731 times.
|
2731 | if(!ctor) return; // bit sus |
92 | 2731 | const Func f = ctor->d.func_ref; | |
93 | 2731 | const Vector v = &f->def->base->effects; | |
94 |
2/2✓ Branch 0 taken 2730 times.
✓ Branch 1 taken 1 times.
|
2731 | if(!v->ptr) return; |
95 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
|
2 | for (m_uint i = 0; i < vector_size(v); i++) |
96 | 1 | env_add_effect(env, (Symbol)vector_at(v, i), loc); | |
97 | } | ||
98 | |||
99 | 12104 | ANN static m_bool check_var(const Env env, const Var_Decl *var) { | |
100 |
5/6✓ Branch 0 taken 2711 times.
✓ Branch 1 taken 9393 times.
✓ Branch 2 taken 2708 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 2708 times.
✗ Branch 5 not taken.
|
12104 | if (env->class_def && !env->scope->depth && env->class_def->info->parent) |
101 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2707 times.
|
2708 | CHECK_BB(check_exp_decl_parent(env, var)); |
102 | 12103 | var_effects(env, var->value->type, insert_symbol("@ctor"), var->pos); | |
103 | 12103 | return GW_OK; | |
104 | } | ||
105 | |||
106 | 12103 | ANN static m_bool check_var_td(const Env env, const Var_Decl *var, | |
107 | Type_Decl *const td) { | ||
108 | 12103 | const Value v = var->value; | |
109 |
2/2✓ Branch 0 taken 2710 times.
✓ Branch 1 taken 9393 times.
|
12103 | if (env->class_def) { |
110 |
2/2✓ Branch 1 taken 2695 times.
✓ Branch 2 taken 15 times.
|
2710 | if (vflag(v, vflag_member)) { |
111 | 2695 | decl_member(env, v); | |
112 |
1/2✓ Branch 0 taken 2695 times.
✗ Branch 1 not taken.
|
2695 | if (env->class_def->info->tuple) tuple_info(env, v); |
113 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
|
15 | } else if (GET_FLAG(td, static)) |
114 | 12 | decl_static(env, v); | |
115 | } | ||
116 | 12103 | return GW_OK; | |
117 | } | ||
118 | |||
119 | 12104 | ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) { | |
120 | 12104 | const Var_Decl *vd = &decl->vd; | |
121 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 12103 times.
|
12104 | CHECK_BB(check_var(env, vd)); |
122 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12103 times.
|
12103 | CHECK_BB(check_var_td(env, vd, decl->td)); |
123 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 12087 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
12103 | if (decl->td->array && decl->td->array->exp) { |
124 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 15 times.
|
16 | CHECK_BB(check_subscripts(env, decl->td->array, true)); |
125 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (GET_FLAG(array_base(decl->type), abstract)) |
126 | ✗ | CHECK_BB(check_array_instance(env, decl->td, decl->args)); | |
127 | } | ||
128 | 12102 | valid_value(env, vd->xid, vd->value); | |
129 | // set_vflag(var->value, vflag_used)); | ||
130 | 12102 | return GW_OK; | |
131 | } | ||
132 | |||
133 | 12107 | ANN /*static inline*/ m_bool ensure_check(const Env env, const Type t) { | |
134 |
6/6✓ Branch 1 taken 43 times.
✓ Branch 2 taken 12064 times.
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 11 times.
✓ Branch 7 taken 28 times.
✓ Branch 8 taken 4 times.
|
12107 | if (tflag(t, tflag_check) || !(tflag(t, tflag_cdef) || tflag(t, tflag_udef))) |
135 | 12092 | return GW_OK; | |
136 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 11 times.
|
15 | if(!tflag(t, tflag_tmpl)) return GW_OK; |
137 | 11 | struct EnvSet es = {.env = env, | |
138 | .data = env, | ||
139 | .func = (_exp_func)check_cdef, | ||
140 | 11 | .scope = env->scope->depth, | |
141 | .flag = tflag_check}; | ||
142 | 11 | return envset_run(&es, t); | |
143 | } | ||
144 | |||
145 | 4194 | ANN m_bool ensure_traverse(const Env env, const Type t) { | |
146 |
6/6✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4190 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 1 times.
|
4194 | if (tflag(t, tflag_check) || !(tflag(t, tflag_cdef) || tflag(t, tflag_udef))) |
147 | 4192 | return GW_OK; | |
148 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
|
2 | if(!tflag(t, tflag_tmpl)) return GW_OK; |
149 | 1 | struct EnvSet es = {.env = env, | |
150 | .data = env, | ||
151 | .func = (_exp_func)traverse_cdef, | ||
152 | 1 | .scope = env->scope->depth, | |
153 | .flag = tflag_check}; | ||
154 | 1 | return envset_run(&es, t); | |
155 | } | ||
156 | |||
157 | 12107 | ANN static inline m_bool inferable(const Env env, const Type t, | |
158 | const loc_t pos) { | ||
159 |
2/2✓ Branch 1 taken 12104 times.
✓ Branch 2 taken 3 times.
|
12107 | if (!tflag(t, tflag_infer)) return GW_OK; |
160 | 3 | ERR_B(pos, _("can't infer type.")) | |
161 | } | ||
162 | |||
163 | 12114 | ANN Type check_exp_decl(const Env env, Exp_Decl *const decl) { | |
164 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 12098 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
12114 | if (decl->td->array && decl->td->array->exp) |
165 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | CHECK_OO(check_exp(env, decl->td->array->exp)); |
166 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 12103 times.
|
12114 | if (decl->args) { |
167 | 11 | const Exp e = new_exp_unary2(env->gwion->mp, insert_symbol("new"), cpy_type_decl(env->gwion->mp, decl->td), decl->args, decl->td->pos); | |
168 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 4 times.
|
11 | CHECK_OO(check_exp(env, e)); |
169 | 4 | decl->args = e; | |
170 | 4 | e->ref = exp_self(decl); | |
171 | } | ||
172 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 12098 times.
|
12107 | if (decl->td->xid == insert_symbol("auto")) { // should be better |
173 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | CHECK_BO(scan1_exp(env, exp_self(decl))); |
174 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | CHECK_BO(scan2_exp(env, exp_self(decl))); |
175 | } | ||
176 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12107 times.
|
12107 | if (!decl->type) ERR_O(decl->td->pos, _("can't find type")); |
177 | { | ||
178 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12107 times.
|
12107 | CHECK_BO(ensure_check(env, decl->type)); |
179 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 12104 times.
|
12107 | if(inferable(env, decl->type, decl->td->pos) < 0) { |
180 |
5/8✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
3 | if(!tflag(decl->type, tflag_check) && decl->type->ref > 1 && env->class_def && !env->scope->depth) |
181 | 1 | type_remref(decl->type, env->gwion); | |
182 | 3 | return NULL; | |
183 | } | ||
184 | } | ||
185 | 12104 | const m_bool global = GET_FLAG(decl->td, global); | |
186 |
2/2✓ Branch 0 taken 12099 times.
✓ Branch 1 taken 5 times.
|
12104 | const m_uint scope = !global ? env->scope->depth : env_push_global(env); |
187 | 12104 | const m_bool ret = check_decl(env, decl); | |
188 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 12099 times.
|
12104 | if (global) { |
189 | 5 | env_pop(env, scope); | |
190 | 5 | set_vflag(decl->vd.value, vflag_direct); | |
191 | } | ||
192 | 12104 | env_weight(env, 1 + isa(decl->type, env->gwion->type[et_object]) > 0); | |
193 |
2/2✓ Branch 0 taken 12102 times.
✓ Branch 1 taken 2 times.
|
12104 | return ret > 0 ? decl->vd.value->type : NULL; |
194 | } | ||
195 | |||
196 | 65 | ANN static m_bool check_collection(const Env env, Type type, const Exp e, | |
197 | 65 | const loc_t loc) { | |
198 | 65 | const Type common = find_common_anc(e->type, type); | |
199 |
2/2✓ Branch 0 taken 59 times.
✓ Branch 1 taken 6 times.
|
65 | if (common) return GW_OK; |
200 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
|
6 | if (check_implicit(env, e, type) > 0) return GW_OK; |
201 | |||
202 | 3 | char fst[20 + strlen(type->name)]; | |
203 | 3 | sprintf(fst, "expected `{+/}%s{0}`", type->name); | |
204 | 3 | gwerr_basic(_("literal contains incompatible types"), fst, "the first element determines the type", env->name, | |
205 | loc, 0); | ||
206 | // suggested fix: rewrite int 2 as float 2.0" | ||
207 | 3 | char sec[16 + strlen(e->type->name)]; | |
208 | 3 | sprintf(sec, "got `{+/}%s{0}`", e->type->name); | |
209 | 3 | gwerr_secondary(sec, env->name, e->pos); | |
210 | 3 | return GW_ERROR; | |
211 | } | ||
212 | |||
213 | 20 | ANN static inline Type prim_array_match(const Env env, Exp e) { | |
214 | 20 | const Type type = e->type; | |
215 | 20 | bool err = false; | |
216 | 20 | const loc_t loc = e->pos; | |
217 | do | ||
218 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 49 times.
|
51 | if (check_collection(env, type, e, loc) < 0) err = true; |
219 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 20 times.
|
51 | while ((e = e->next)); |
220 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
|
20 | if (!err) return array_type(env, array_base_simple(type), type->array_depth + 1); |
221 | 2 | env_set_error(env, true); | |
222 | 2 | return NULL; | |
223 | } | ||
224 | |||
225 | 23 | ANN static Type check_prim_array(const Env env, const Array_Sub *data) { | |
226 | 23 | const Array_Sub array = *data; | |
227 | 23 | const Exp e = array->exp; | |
228 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 22 times.
|
23 | if (!e) |
229 | 1 | ERR_O(prim_pos(data), _("must provide values/expressions for array [...]")) | |
230 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
|
22 | CHECK_OO(check_exp(env, e)); |
231 | 20 | env_weight(env, 1); | |
232 | 20 | return array->type = prim_array_match(env, e); | |
233 | } | ||
234 | |||
235 | 12 | ANN static m_bool check_range(const Env env, Range *range) { | |
236 |
3/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
|
12 | if (range->start) CHECK_OB(check_exp(env, range->start)); |
237 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
|
12 | if (range->end) CHECK_OB(check_exp(env, range->end)); |
238 |
4/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 4 times.
|
12 | if (range->start && range->end) { |
239 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
|
7 | if (isa(range->end->type, range->start->type) < 0) |
240 | 1 | ERR_B(range->start->pos, _("range types do not match")) | |
241 | } | ||
242 | 11 | return GW_OK; | |
243 | } | ||
244 | |||
245 | 3 | ANN static Type check_prim_range(const Env env, Range **data) { | |
246 | 3 | Range *range = *data; | |
247 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
|
3 | CHECK_BO(check_range(env, range)); |
248 | 2 | env_weight(env, 1); | |
249 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | const Exp e = range->start ?: range->end; |
250 | assert(e); | ||
251 | 2 | const Symbol sym = insert_symbol("[:]"); | |
252 | 4 | struct Op_Import opi = {.op = sym, | |
253 | 2 | .lhs = e->type, | |
254 | .pos = e->pos, | ||
255 | 2 | .data = (uintptr_t)prim_exp(data)}; | |
256 | 2 | return op_check(env, &opi); | |
257 | } | ||
258 | |||
259 | 3 | ANN static Type check_prim_dict(const Env env, Exp *data) { | |
260 | 3 | const Exp base = *data; | |
261 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | CHECK_OO(check_exp(env, base)); |
262 | 3 | const Type key = base->type; | |
263 | 3 | const Type val = base->next->type; | |
264 | 3 | bool err = false; | |
265 | 3 | const loc_t loc = base->pos; | |
266 | 3 | Exp e = base; | |
267 | 3 | env_weight(env, 1); | |
268 | do { | ||
269 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | if (check_collection(env, key, e, loc) < 0) err = true; |
270 | 7 | e = e->next; | |
271 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
|
7 | if (check_collection(env, val, e, loc) < 0) err = true; |
272 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
|
7 | } while ((e = e->next)); |
273 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if (!err) return dict_type(env->gwion, key, val, base->pos); |
274 | 1 | env_set_error(env, true); return NULL; | |
275 | } | ||
276 | |||
277 | 575 | ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, | |
278 | const loc_t pos) { | ||
279 |
2/4✓ Branch 0 taken 575 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 575 times.
|
575 | if (!v->from->owner_class || isa(t, v->from->owner_class) < 0) { |
280 | ✗ | if(!is_class(env->gwion, v->type)) | |
281 | ✗ | ERR_B(pos, _("'%s' from owner namespace '%s' used in '%s'."), v->name, | |
282 | v->from->owner ? v->from->owner->name : "?", t->name) | ||
283 | } | ||
284 | 575 | return GW_OK; | |
285 | } | ||
286 | |||
287 | 1351 | ANN static inline Value get_value(const Env env, const Symbol sym) { | |
288 | 1351 | const Value value = nspc_lookup_value1(env->curr, sym); | |
289 |
2/2✓ Branch 0 taken 1330 times.
✓ Branch 1 taken 21 times.
|
1351 | if(value) { |
290 |
4/4✓ Branch 0 taken 117 times.
✓ Branch 1 taken 1213 times.
✓ Branch 2 taken 115 times.
✓ Branch 3 taken 2 times.
|
1330 | if (!value->from->owner_class || isa(env->class_def, value->from->owner_class) > 0) |
291 | 1328 | return value; | |
292 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if(env->class_def) { |
293 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (isa(env->class_def, value->from->owner_class) > 0 || value == env->class_def->info->value) |
294 | ✗ | return value; | |
295 | |||
296 | } | ||
297 | } | ||
298 |
4/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 4 times.
|
23 | if (env->func && env->func->def->base->values) { |
299 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | DECL_OO(const Value, v, = upvalues_lookup(env->func->def->base->values, sym)); |
300 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | if(fbflag(env->func->def->base, fbflag_lambda)) |
301 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | CHECK_OO(not_upvalue(env, v)); |
302 | 8 | return v; | |
303 | } | ||
304 | 15 | return NULL; | |
305 | } | ||
306 | |||
307 | 3 | ANN static inline bool is_value_global(const Env env, const Value v) { | |
308 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if(GET_FLAG(v, global)) return true; |
309 | ✗ | return from_global_nspc(env, v->from->owner); | |
310 | } | ||
311 | |||
312 | 1351 | ANN static Value check_non_res_value(const Env env, const Symbol *data) { | |
313 | 1351 | const Symbol var = *data; | |
314 | 1351 | const Value value = get_value(env, var); | |
315 |
2/2✓ Branch 0 taken 223 times.
✓ Branch 1 taken 1128 times.
|
1351 | if (env->class_def) { |
316 |
2/2✓ Branch 0 taken 220 times.
✓ Branch 1 taken 3 times.
|
223 | if (value) { |
317 |
2/2✓ Branch 0 taken 117 times.
✓ Branch 1 taken 103 times.
|
220 | if(value->from->owner_class) |
318 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 117 times.
|
117 | CHECK_BO(not_from_owner_class(env, |
319 | env->class_def, value, prim_pos(data))); | ||
320 | } | ||
321 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 220 times.
|
223 | const Value v = value ?: find_value(env->class_def, var); |
322 |
2/2✓ Branch 0 taken 221 times.
✓ Branch 1 taken 2 times.
|
223 | if (v) { |
323 |
5/6✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 196 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 23 times.
|
246 | if (env->func && GET_FLAG(env->func->def->base, static) && |
324 | 25 | vflag(v, vflag_member)) | |
325 | 2 | ERR_O(prim_pos(data), | |
326 | _("non-static member '%s' used from static function."), | ||
327 | s_name(var)) | ||
328 | } | ||
329 | 221 | return v; | |
330 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1128 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1128 | } else if (SAFE_FLAG(env->class_def, global) || |
331 |
4/4✓ Branch 0 taken 224 times.
✓ Branch 1 taken 904 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 220 times.
|
1128 | (env->func && GET_FLAG(env->func->def->base, global))) { |
332 |
3/6✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
4 | if (!value || !(is_value_global(env, value) || vflag(value, vflag_arg))) |
333 | 1 | ERR_O(prim_pos(data), | |
334 | _("non-global variable '%s' used from global function/class."), | ||
335 | s_name(var)) | ||
336 |
4/4✓ Branch 0 taken 220 times.
✓ Branch 1 taken 904 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 214 times.
|
1124 | } else if(env->func && fbflag(env->func->def->base, fbflag_locale)) { |
337 |
3/6✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
6 | if(!is_func(env->gwion, value->type) && value->from->owner && !from_global_nspc(env, value->from->owner)) // is_callable |
338 | ✗ | ERR_O(prim_pos(data), _("invalid variable access from locale definition")); | |
339 | } | ||
340 | 1127 | return value; | |
341 | } | ||
342 | |||
343 | 467 | ANN static Type check_dot(const Env env, const Exp_Dot *member) { | |
344 | 934 | struct Op_Import opi = {.op = insert_symbol("."), | |
345 | 467 | .lhs = member->base->type, | |
346 | 467 | .data = (uintptr_t)member, | |
347 | 467 | .pos = exp_self(member)->pos}; | |
348 | 467 | env_weight(env, 1); | |
349 | 467 | return op_check(env, &opi); | |
350 | } | ||
351 | |||
352 | 15 | ANN static m_bool check_upvalue(const Env env, const Exp_Primary *prim, const Value v) { | |
353 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | if(not_upvalue(env, v)) |
354 | 15 | return GW_OK; | |
355 | ✗ | gwerr_basic(_("value not in lambda scope"), NULL, NULL, env->name, exp_self(prim)->pos, 4242); | |
356 | ✗ | declared_here(v); | |
357 | ✗ | gw_err("{-}hint:{0} try adding it to capture list"); | |
358 | ✗ | env_set_error(env, true); | |
359 | ✗ | return GW_ERROR; | |
360 | } | ||
361 | |||
362 | 116 | ANN static Type prim_owned(const Env env, const Symbol *data) { | |
363 | 116 | const Exp exp = exp_self(prim_exp(data)); | |
364 | 116 | const Value v = exp->d.prim.value; | |
365 |
3/4✓ Branch 1 taken 4 times.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
116 | if(is_class(env->gwion, v->type) && env->class_def == v->type->info->base_type) // write it better |
366 | ✗ | return v->type->info->base_type; | |
367 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 100 times.
|
116 | const m_str name = !GET_FLAG(v, static) ? "this" : v->from->owner_class->name; |
368 | const Exp base = | ||
369 | 116 | new_prim_id(env->gwion->mp, insert_symbol(name), prim_pos(data)); | |
370 | 116 | exp_setuse(base, 1); | |
371 | 116 | exp->exp_type = ae_exp_dot; | |
372 | 116 | exp->d.exp_dot.base = base; | |
373 | 116 | exp->d.exp_dot.xid = *data; | |
374 | 116 | return check_exp(env, exp); | |
375 | } | ||
376 | |||
377 | 1351 | ANN static Type prim_id_non_res(const Env env, const Symbol *data) { | |
378 | 1351 | const Symbol sym = *data; | |
379 | 1351 | const Value v = check_non_res_value(env, data); | |
380 |
6/8✓ Branch 0 taken 1335 times.
✓ Branch 1 taken 16 times.
✓ Branch 3 taken 1335 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 769 times.
✓ Branch 6 taken 566 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 769 times.
|
1351 | if (!v || !vflag(v, vflag_valid) || (v->from->ctx && v->from->ctx->error)) { |
381 | 16 | const m_str name = s_name(*data); | |
382 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
16 | if (!isalpha(*name) && *name != '_') { |
383 | 3 | prim_self(data)->value = env->gwion->type[et_op]->info->value; | |
384 | 3 | return env->gwion->type[et_op]; | |
385 | } | ||
386 |
3/6✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
13 | if (env->func && fbflag(env->func->def->base, fbflag_lambda) && env->func->def->base->values) { |
387 | ✗ | const Value v = upvalues_lookup(env->func->def->base->values, sym); | |
388 | ✗ | if(v) { | |
389 | ✗ | CHECK_BO(check_upvalue(env, prim_self(data), v)); | |
390 | ✗ | return v->type; | |
391 | } | ||
392 | } | ||
393 | 13 | gwerr_basic(_("Invalid variable"), _("not legit at this point."), NULL, | |
394 | 13 | env->name, prim_pos(data), 0); | |
395 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | did_you_mean_nspc(v ? v->from->owner : env->curr, s_name(sym)); |
396 | 13 | env_set_error(env, true); | |
397 | 13 | return NULL; | |
398 | } | ||
399 | 1335 | prim_self(data)->value = v; | |
400 |
2/2✓ Branch 0 taken 116 times.
✓ Branch 1 taken 1219 times.
|
1335 | if (v->from->owner_class) return prim_owned(env, data); |
401 |
2/2✓ Branch 0 taken 392 times.
✓ Branch 1 taken 827 times.
|
1219 | if (GET_FLAG(v, const)) exp_setmeta(prim_exp(data), 1); |
402 | |||
403 |
4/4✓ Branch 0 taken 326 times.
✓ Branch 1 taken 893 times.
✓ Branch 2 taken 299 times.
✓ Branch 3 taken 27 times.
|
1219 | if (env->func && strcmp(env->func->name, "in spork")) { |
404 | // if(vflag(v, vflag_fglobal) /*&& !vflag(v, vflag_builtin) */&& !is_func(env->gwion, v->type)) { | ||
405 |
8/8✓ Branch 0 taken 276 times.
✓ Branch 1 taken 23 times.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 239 times.
✓ Branch 6 taken 40 times.
✓ Branch 7 taken 20 times.
✓ Branch 9 taken 9 times.
✓ Branch 10 taken 31 times.
|
299 | if((GET_FLAG(v, global) || vflag(v, vflag_fglobal)) && !vflag(v, vflag_builtin) && !is_func(env->gwion, v->type)) { |
406 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
|
9 | if(!env->func->_wait) |
407 | 7 | env->func->_wait = new_mp_vector(env->gwion->mp, Value, 0); | |
408 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
|
9 | if (!v->used_by) { |
409 | 6 | v->used_by = new_mp_vector(env->gwion->mp, Func, 1); | |
410 | 6 | mp_vector_set(v->used_by, Func, 0, env->func); | |
411 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | mp_vector_add(env->gwion->mp, &env->func->_wait, Value, v); |
412 | } else { | ||
413 | 3 | bool found = false; | |
414 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
|
5 | for(uint32_t i = 0; i < v->used_by->len; i++) { |
415 | 3 | const Func f = *mp_vector_at(v->used_by, Func, i); | |
416 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if(f == env->func) { |
417 | 1 | found = true; | |
418 | 1 | break; | |
419 | } | ||
420 | } | ||
421 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if(!found) { |
422 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | mp_vector_add(env->gwion->mp, &v->used_by, Func, env->func); |
423 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | mp_vector_add(env->gwion->mp, &env->func->_wait, Value, v); |
424 | } | ||
425 | } | ||
426 | } | ||
427 | |||
428 |
4/4✓ Branch 0 taken 227 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 218 times.
|
299 | if (!GET_FLAG(v, const) && v->from->owner) |
429 | 9 | unset_fflag(env->func, fflag_pure); | |
430 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 284 times.
|
299 | if (fbflag(env->func->def->base, fbflag_lambda)) |
431 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
|
15 | CHECK_BO(check_upvalue(env, prim_self(data), v)); |
432 | } | ||
433 | // set_vflag(v->vflag, vflag_used); | ||
434 | 1219 | return v->type; | |
435 | } | ||
436 | |||
437 | 325 | ANN Type check_prim_str(const Env env, const struct AstString *data) { | |
438 |
2/2✓ Branch 1 taken 323 times.
✓ Branch 2 taken 2 times.
|
325 | if (!prim_self(data)->value) |
439 | 323 | prim_self(data)->value = global_string(env, data->data, prim_pos(data)); | |
440 | 325 | exp_setmeta(prim_exp(data), true); | |
441 | 325 | return env->gwion->type[et_string]; // prim->value | |
442 | } | ||
443 | |||
444 | 1734 | ANN static Type check_prim_id(const Env env, const Symbol *data) { | |
445 | 1734 | struct SpecialId_ *spid = specialid_get(env->gwion, *data); | |
446 |
2/2✓ Branch 0 taken 383 times.
✓ Branch 1 taken 1351 times.
|
1734 | if (spid) return specialid_type(env, spid, prim_self(data)); |
447 | 1351 | return prim_id_non_res(env, data); | |
448 | } | ||
449 | |||
450 | 3 | ANN static Type check_prim_perform(const Env env, const Symbol *data) { | |
451 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if(*data) env_add_effect(env, *data, prim_pos(data)); |
452 | ✗ | else if(!env->scope->in_try) | |
453 | ✗ | ERR_O(prim_pos(data), "`rethrow` outside try/handle statement"); | |
454 | 3 | env_weight(env, 1); | |
455 | 3 | return env->gwion->type[et_void]; | |
456 | } | ||
457 | |||
458 | 739 | ANN static Type check_prim_interp(const Env env, const Exp *exp) { | |
459 |
2/2✓ Branch 1 taken 32 times.
✓ Branch 2 taken 707 times.
|
739 | CHECK_OO(check_exp(env, *exp)); |
460 | 707 | env_weight(env, 1); | |
461 | 707 | return env->gwion->type[et_string]; | |
462 | } | ||
463 | |||
464 | 720 | ANN static Type check_prim_hack(const Env env, const Exp *data) { | |
465 |
2/2✓ Branch 0 taken 219 times.
✓ Branch 1 taken 501 times.
|
720 | if (env->func) unset_fflag(env->func, fflag_pure); |
466 |
2/2✓ Branch 1 taken 32 times.
✓ Branch 2 taken 688 times.
|
720 | CHECK_OO(check_prim_interp(env, data)); |
467 | 688 | env_weight(env, 1); | |
468 | 688 | return env->gwion->type[et_gack]; | |
469 | } | ||
470 | |||
471 | 4 | ANN static Type check_prim_locale(const Env env, const Symbol *data NUSED) { | |
472 | 4 | exp_setmeta(prim_exp(data), true); | |
473 | 4 | return env->gwion->type[et_float]; | |
474 | } | ||
475 | |||
476 | #define describe_prim_xxx(name, type) \ | ||
477 | ANN static Type check_prim_##name(const Env env NUSED, \ | ||
478 | const union prim_data *data NUSED) { \ | ||
479 | return type; \ | ||
480 | } | ||
481 | |||
482 | 564 | describe_prim_xxx(num, env->gwion->type[et_int]); | |
483 | 22 | describe_prim_xxx(char, env->gwion->type[et_char]); | |
484 | 72 | describe_prim_xxx(float, env->gwion->type[et_float]); | |
485 | 9 | describe_prim_xxx(nil, env->gwion->type[et_void]); | |
486 | |||
487 | DECL_PRIM_FUNC(check, Type, Env); | ||
488 | |||
489 | 3501 | ANN static Type check_prim(const Env env, Exp_Primary *prim) { | |
490 | 3501 | return exp_self(prim)->type = check_prim_func[prim->prim_type](env, &prim->d); | |
491 | } | ||
492 | |||
493 | 21 | ANN Type check_array_access(const Env env, const Array_Sub array) { | |
494 | 21 | const Symbol sym = insert_symbol("[]"); | |
495 | 21 | struct Op_Import opi = {.op = sym, | |
496 | 21 | .lhs = array->exp->type, | |
497 | 21 | .rhs = array->type, | |
498 | 21 | .pos = array->exp->pos, | |
499 | 21 | .data = (uintptr_t)array}; | |
500 | 21 | return op_check(env, &opi); | |
501 | } | ||
502 | |||
503 | 23 | static ANN Type check_exp_array(const Env env, const Exp_Array *array) { | |
504 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 22 times.
|
23 | CHECK_OO((array->array->type = check_exp(env, array->base))); |
505 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 21 times.
|
22 | CHECK_BO(check_subscripts(env, array->array, 0)); |
506 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 18 times.
|
21 | if(exp_getmeta(array->base)) exp_setmeta(exp_self(array), true); |
507 | 21 | return check_array_access(env, array->array); | |
508 | } | ||
509 | |||
510 | 9 | static ANN Type check_exp_slice(const Env env, const Exp_Slice *range) { | |
511 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
9 | CHECK_OO(check_exp(env, range->base)); |
512 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
9 | CHECK_BO(check_range(env, range->range)); |
513 | 9 | env_weight(env, 1); | |
514 | 9 | const Symbol sym = insert_symbol("[:]"); | |
515 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
|
9 | const Exp e = range->range->start ?: range->range->end; |
516 | assert(e); | ||
517 | 18 | struct Op_Import opi = {.op = sym, | |
518 | 9 | .lhs = e->type, | |
519 | 9 | .rhs = range->base->type, | |
520 | .pos = e->pos, | ||
521 | 9 | .data = (uintptr_t)exp_self(range)}; | |
522 | 9 | return op_check(env, &opi); | |
523 | } | ||
524 | |||
525 | // get the type of the function | ||
526 | // without the mangling | ||
527 | ✗ | ANN static inline Type type_list_base_func(const Type type) { | |
528 | ✗ | const Nspc owner = type->info->value->from->owner; | |
529 | ✗ | const Symbol xid = type->info->func->def->base->xid; | |
530 | ✗ | return nspc_lookup_type0(owner, xid); | |
531 | } | ||
532 | |||
533 | 43 | ANN static inline Type type_list_base(const Gwion gwion, const Type type) { | |
534 |
1/2✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
|
43 | return !(is_func(gwion, type)) ? type : type_list_base_func(type); |
535 | } | ||
536 | |||
537 | 43 | ANN static Type_Decl* mk_td(const Env env, Type_Decl *td, | |
538 | const Type type, const loc_t pos) { | ||
539 | 43 | const Type base = type_list_base(env->gwion, type); | |
540 | 86 | const Type t = !td->array ? | |
541 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | base : array_type(env, base, td->array->depth); |
542 | 43 | return type2td(env->gwion, t, pos); | |
543 | } | ||
544 | |||
545 | 49 | ANN static Type tmpl_arg_match(const Env env, const Symbol xid, const Symbol tgt, const Type t) { | |
546 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 6 times.
|
49 | if (xid == tgt) return t; |
547 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if(!tflag(t, tflag_cdef)) return NULL; |
548 | ✗ | const uint32_t len = mp_vector_len(t->info->cdef->base.tmpl->list); | |
549 | ✗ | for(uint32_t i = 0; i < len; i++) { | |
550 | ✗ | Specialized *spec = mp_vector_at(t->info->cdef->base.tmpl->list, Specialized, i); | |
551 | ✗ | const Type base = nspc_lookup_type1(t->nspc, spec->xid); | |
552 | ✗ | const Type t = tmpl_arg_match(env, xid, spec->xid, base); | |
553 | ✗ | if(t) return t; | |
554 | } | ||
555 | ✗ | return NULL; | |
556 | } | ||
557 | |||
558 | ANN2(1, 2) | ||
559 | 735 | static Func find_func_match_actual(const Env env, const Func f, const Exp exp, | |
560 | const bool implicit, const bool specific) { | ||
561 | 735 | Func func = f; | |
562 | do { | ||
563 | 836 | Exp e = exp; | |
564 | 836 | Arg_List args = func->def->base->args; | |
565 | 836 | m_uint i = 0; | |
566 | 836 | const m_uint args_len = mp_vector_len(args); | |
567 |
2/2✓ Branch 0 taken 762 times.
✓ Branch 1 taken 471 times.
|
1233 | while (e) { |
568 | 762 | e->cast_to = NULL; | |
569 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 758 times.
|
762 | if (!e->type) // investigate |
570 | 4 | return NULL; | |
571 |
2/2✓ Branch 0 taken 612 times.
✓ Branch 1 taken 146 times.
|
758 | Arg *arg = i < args_len ? mp_vector_at(args, Arg, i++) : NULL; |
572 |
2/2✓ Branch 0 taken 146 times.
✓ Branch 1 taken 612 times.
|
758 | if (!arg) { |
573 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 121 times.
|
146 | CHECK_OO(func->next); |
574 | 121 | return find_func_match_actual(env, func->next, exp, implicit, | |
575 | specific); | ||
576 | } | ||
577 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 612 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
612 | if (tflag(e->type, tflag_ref) && isa(e->type, arg->type) > 0) { |
578 | ✗ | if(!e->cast_to)e->cast_to = arg->type; | |
579 | } | ||
580 | |||
581 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 612 times.
|
612 | if (arg->type == env->gwion->type[et_auto]) { |
582 | ✗ | const Type owner = func->value_ref->from->owner_class; | |
583 | ✗ | if (owner) CHECK_BO(template_push(env, owner)); | |
584 | ✗ | arg->type = known_type(env, arg->td); | |
585 | ✗ | if (owner) nspc_pop_type(env->gwion->mp, env->curr); | |
586 | ✗ | CHECK_OO(arg->type); | |
587 | } | ||
588 | |||
589 |
2/2✓ Branch 1 taken 215 times.
✓ Branch 2 taken 397 times.
|
612 | if (!func_match_inner(env, e, arg->type, implicit, specific)) break; |
590 | 397 | e = e->next; | |
591 | } | ||
592 |
4/4✓ Branch 0 taken 471 times.
✓ Branch 1 taken 215 times.
✓ Branch 2 taken 401 times.
✓ Branch 3 taken 70 times.
|
686 | if (!e && args_len == i) return func; |
593 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 184 times.
|
285 | } while ((func = func->next)); |
594 | 184 | return NULL; | |
595 | } | ||
596 | |||
597 | ANN static Type check_exp_call(const Env env, Exp_Call *exp); | ||
598 | |||
599 | 2 | ANN static Func call2ufcs(const Env env, Exp_Call *call, const Value v) { | |
600 | 2 | const Exp this = call->func->d.exp_dot.base; | |
601 | 2 | this->next = call->args; | |
602 | 2 | call->args = this; | |
603 | 2 | call->func->type = v->type; | |
604 | 2 | call->func->d.prim.value = v; | |
605 | 2 | call->func->d.prim.d.var = call->func->d.exp_dot.xid; | |
606 | 2 | call->func->exp_type = ae_exp_primary; | |
607 | 2 | call->func->d.prim.prim_type = ae_prim_id; | |
608 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | CHECK_OO(check_exp_call(env, call)); |
609 | 2 | return call->func->type->info->func; | |
610 | } | ||
611 | |||
612 | 37 | ANN static Func ufcs(const Env env, const Func up, Exp_Call *const call) { | |
613 | 37 | const Value v = nspc_lookup_value1(env->curr, up->def->base->xid); | |
614 |
5/6✓ Branch 0 taken 19 times.
✓ Branch 1 taken 18 times.
✓ Branch 3 taken 19 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 18 times.
|
37 | if (v && is_func(env->gwion, v->type) && !v->from->owner_class) // is_callable |
615 | 1 | return call2ufcs(env, call, v); | |
616 | 36 | return NULL; | |
617 | } | ||
618 | |||
619 | 447 | ANN Func find_func_match(const Env env, const Func up, Exp_Call *const call) { | |
620 | Func func; | ||
621 | 447 | const Exp exp = call->args; | |
622 | 447 | const Exp args = | |
623 |
4/4✓ Branch 0 taken 254 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 246 times.
✓ Branch 3 taken 8 times.
|
447 | (exp && isa(exp->type, env->gwion->type[et_void]) < 0) ? exp : NULL; |
624 |
4/4✓ Branch 1 taken 75 times.
✓ Branch 2 taken 372 times.
✓ Branch 3 taken 46 times.
✓ Branch 4 taken 29 times.
|
522 | if ((func = find_func_match_actual(env, up, args, false, true)) || |
625 |
1/2✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
|
121 | (func = find_func_match_actual(env, up, args, true, true)) || |
626 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
|
92 | (func = find_func_match_actual(env, up, args, false, true)) || |
627 | 46 | (func = find_func_match_actual(env, up, args, true, false))) | |
628 | 401 | return func; | |
629 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | return call->func->exp_type == ae_exp_dot && up->value_ref->from->owner_class |
630 | 37 | ? ufcs(env, up, call) | |
631 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 9 times.
|
83 | : NULL; |
632 | } | ||
633 | |||
634 | 43 | ANN m_bool check_traverse_fdef(const Env env, const Func_Def fdef) { | |
635 | 43 | struct Vector_ v = {}; | |
636 | 43 | const m_uint scope = env->scope->depth; | |
637 | 43 | env->scope->depth = 0; | |
638 | 43 | vector_init(&v); | |
639 | 43 | const Vector w = (Vector)&env->curr->info->value->ptr; | |
640 | 43 | m_uint i = vector_size(w); | |
641 |
2/2✓ Branch 2 taken 11 times.
✓ Branch 3 taken 43 times.
|
54 | while (i-- > 1) vector_add(&v, vector_at(w, i)); |
642 | 43 | VLEN(w) = 1; | |
643 | 43 | const m_bool ret = traverse_func_def(env, fdef); | |
644 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 2 taken 43 times.
|
54 | for (m_uint i = vector_size(&v) + 1; --i;) |
645 | 11 | vector_add(w, vector_at(&v, i - 1)); | |
646 | 43 | vector_release(&v); | |
647 | 43 | env->scope->depth = scope; | |
648 | 43 | return ret; | |
649 | } | ||
650 | |||
651 | 29444 | ANN static m_bool check_func_args(const Env env, Arg_List args) { | |
652 |
2/2✓ Branch 0 taken 36612 times.
✓ Branch 1 taken 29443 times.
|
66055 | for(uint32_t i = 0; i < args->len; i++) { |
653 | 36612 | Arg *arg = mp_vector_at(args, Arg, i); | |
654 | 36612 | const Var_Decl *decl = &arg->var_decl; | |
655 | 36612 | const Value v = decl->value; | |
656 |
4/4✓ Branch 0 taken 36574 times.
✓ Branch 1 taken 38 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 36573 times.
|
36612 | if(decl->xid) CHECK_BB(already_defined(env, decl->xid, decl->pos)); |
657 | 36611 | valid_value(env, decl->xid, v); | |
658 | } | ||
659 | 29443 | return GW_OK; | |
660 | } | ||
661 | |||
662 | #define next_arg(type) \ | ||
663 | ANN static inline type next_arg_##type(const type e) { \ | ||
664 | const type next = e->next; \ | ||
665 | if (next) gw_err(", "); \ | ||
666 | return next; \ | ||
667 | } | ||
668 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
|
10 | next_arg(Exp) |
669 | //next_arg(Arg_List); | ||
670 | |||
671 | 7 | ANN static void print_current_args(Exp e) { | |
672 | 7 | gw_err(_("and not\n ")); | |
673 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | do gw_err(" {G}%s{0}", e->type ? e->type->name : "<Unknown>"); |
674 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
|
10 | while ((e = next_arg_Exp(e))); |
675 | 7 | gw_err("\n"); | |
676 | 7 | } | |
677 | |||
678 | ANN2(1) | ||
679 | 17 | static void function_alternative(const Env env, const Type t, const Exp args, | |
680 | const loc_t pos) { | ||
681 |
3/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 9 times.
|
17 | if (env->context && env->context->error) // needed for ufcs |
682 | 8 | return; | |
683 | 9 | gwerr_basic("Argument type mismatch", "call site", | |
684 | 9 | "valid alternatives:", env->name, pos, 0); | |
685 | 9 | const bool is_closure = isa(t, env->gwion->type[et_closure]) < 0; | |
686 | 9 | Func up = is_closure | |
687 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
|
9 | ? t->info->func : closure_def(t)->base->func; |
688 | 10 | do print_signature(up); | |
689 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
|
10 | while ((up = up->next)); |
690 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
|
9 | if (args) |
691 | 7 | print_current_args(args); | |
692 | else | ||
693 | 2 | gw_err(_("and not:\n {G}void{0}\n")); | |
694 | 9 | env_set_error(env, true); | |
695 | } | ||
696 | |||
697 | 41 | ANN static Func get_template_func(const Env env, Exp_Call *const func, | |
698 | const Value v) { | ||
699 | 41 | const Func f = find_template_match(env, v, func); | |
700 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
|
41 | if (f) { |
701 | 39 | Tmpl *tmpl = new_tmpl_call(env->gwion->mp, func->tmpl->call); | |
702 | 78 | tmpl->list = v->d.func_ref | |
703 | 39 | ? v->d.func_ref->def->base->tmpl->list | |
704 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | : func->func->type->info->func->def->base->tmpl->list; |
705 | 39 | ((Exp_Call *)func)->tmpl = tmpl; | |
706 | 39 | func->func->type = f->value_ref->type; | |
707 | 39 | return f; | |
708 | } | ||
709 | 2 | ((Exp_Call *)func)->tmpl = NULL; | |
710 | assert(exp_self(func)); | ||
711 | 2 | ERR_O(exp_self(func)->pos, | |
712 | _("function is a template for which automatic type inference is not fully implemented")); | ||
713 | } | ||
714 | |||
715 | ✗ | ANN static Func predefined_func(const Env env, const Value v, Exp_Call *exp, | |
716 | const Tmpl *tm) { | ||
717 | ✗ | Tmpl tmpl = {.call = tm->call}; | |
718 | ✗ | exp->tmpl = &tmpl; | |
719 | ✗ | DECL_OO(const Func, func, = get_template_func(env, exp, v)); | |
720 | ✗ | return v->d.func_ref = func; | |
721 | } | ||
722 | |||
723 | ✗ | ANN static Type check_predefined(const Env env, Exp_Call *exp, const Value v, | |
724 | const Tmpl *tm, const Func_Def fdef) { | ||
725 | ✗ | DECL_OO(const Func, func, | |
726 | = v->d.func_ref ?: predefined_func(env, v, exp, tm)); | ||
727 | ✗ | if (!fdef->base->ret_type) { // template fptr | |
728 | ✗ | struct EnvSet es = {.env = env, | |
729 | .data = env, | ||
730 | .func = (_exp_func)check_cdef, | ||
731 | ✗ | .scope = env->scope->depth, | |
732 | .flag = tflag_check}; | ||
733 | ✗ | CHECK_BO(envset_pushv(&es, v)); | |
734 | ✗ | func->def->base->fbflag |= fbflag_internal; | |
735 | ✗ | const m_bool ret = check_traverse_fdef(env, func->def); | |
736 | ✗ | envset_pop(&es, v->from->owner_class); | |
737 | ✗ | CHECK_BO(ret); | |
738 | } | ||
739 | ✗ | exp->func->type = func->value_ref->type; | |
740 | ✗ | return func->def->base->ret_type; | |
741 | } | ||
742 | |||
743 | 43 | ANN static Type_List check_template_args(const Env env, Exp_Call *exp, | |
744 | const Tmpl *tm, const Func_Def fdef) { | ||
745 | 43 | Specialized_List sl = tm->list; | |
746 | 43 | const bool spread = is_spread_tmpl(fdef->base->tmpl); | |
747 | 43 | const uint32_t len = sl->len - spread; | |
748 | 43 | Type_List tl = new_mp_vector(env->gwion->mp, Type_Decl*, len); | |
749 | 43 | m_uint args_number = 0; | |
750 | |||
751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | if(exp->other) { |
752 | ✗ | for(uint32_t i = 0; i < len; i++) { | |
753 | ✗ | Specialized *spec = mp_vector_at(sl, Specialized, i); | |
754 | ✗ | if (tmpl_arg_match(env, spec->xid, fdef->base->td->xid, fdef->base->ret_type)) { | |
755 | ✗ | CHECK_OO(check_exp(env, exp->other)); | |
756 | ✗ | if(!is_func(env->gwion, exp->other->type)) { | |
757 | ✗ | Type_Decl *td = type2td(env->gwion, exp->other->type, fdef->base->td->pos); | |
758 | ✗ | mp_vector_set(tl, Type_Decl*, 0, td); | |
759 | } else { | ||
760 | ✗ | Func func = exp->other->type->info->func; | |
761 | do { | ||
762 | ✗ | if(mp_vector_len(func->def->base->args) == 1) { | |
763 | ✗ | Arg *arg = mp_vector_at(func->def->base->args, Arg, 0); | |
764 | ✗ | Type_Decl *td = cpy_type_decl(env->gwion->mp, arg->td); | |
765 | ✗ | mp_vector_set(tl, Type_Decl*, 0, td); | |
766 | ✗ | break; | |
767 | } | ||
768 | ✗ | } while((func = func->next)); | |
769 | } | ||
770 | ✗ | ++args_number; | |
771 | ✗ | break; | |
772 | } | ||
773 | } | ||
774 | } | ||
775 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 43 times.
|
89 | for(uint32_t i = 0; i < len; i++) { |
776 | 46 | Specialized *spec = mp_vector_at(sl, Specialized, i); | |
777 | 46 | Arg_List args = fdef->base->args; | |
778 | 46 | const uint32_t args_len = mp_vector_len(args); | |
779 | 46 | Exp template_arg = exp->args; | |
780 | 46 | uint32_t count = 0; | |
781 |
3/4✓ Branch 0 taken 49 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
|
52 | while (count < args_len && template_arg) { |
782 | 49 | Arg *arg = mp_vector_at(args, Arg, count); | |
783 |
2/2✓ Branch 1 taken 43 times.
✓ Branch 2 taken 6 times.
|
49 | if (tmpl_arg_match(env, spec->xid, arg->td->xid, template_arg->type)) { |
784 | 43 | mp_vector_set(tl, Type_Decl*, args_number, | |
785 | mk_td(env, arg->td, template_arg->type, fdef->base->pos)); | ||
786 | 43 | ++args_number; | |
787 | 43 | break; | |
788 | } | ||
789 | 6 | count++; | |
790 | 6 | template_arg = template_arg->next; | |
791 | } | ||
792 | } | ||
793 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
|
43 | if (args_number < len) //TODO: free type_list |
794 | 2 | ERR_O(exp->func->pos, _("not able to infer types for template call.")) | |
795 | |||
796 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 39 times.
|
41 | if(spread) { |
797 | 2 | Exp e = exp->args; | |
798 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if(fdef->base->args) |
799 | ✗ | for(uint32_t i = 0; i < fdef->base->args->len && e; i++) e = e->next; | |
800 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | while(e) { |
801 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | mp_vector_add(env->gwion->mp, &tl, Type_Decl*, type2td(env->gwion, e->type, e->pos)); |
802 | 2 | e = e->next; | |
803 | } | ||
804 | } | ||
805 | 41 | return tl; | |
806 | } | ||
807 | |||
808 | 43 | ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) { | |
809 | 43 | /*const */Type t = exp->func->type; | |
810 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | if(isa(t, env->gwion->type[et_closure]) > 0) { |
811 | ✗ | const Func_Def fdef = closure_def(t); | |
812 | ✗ | t = fdef->base->func->value_ref->type; | |
813 | } | ||
814 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
|
43 | DECL_OO(const Value, value, = type_value(env->gwion, t)); |
815 | 43 | const Func_Def fdef = | |
816 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | value->d.func_ref ? value->d.func_ref->def : t->info->func->def; |
817 | 43 | Tmpl *tm = fdef->base->tmpl; | |
818 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
43 | if (tm->call) return check_predefined(env, exp, value, tm, fdef); |
819 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 41 times.
|
43 | DECL_OO(const Type_List, tl, = check_template_args(env, exp, tm, fdef)); |
820 | 41 | Tmpl tmpl = {.call = tl}; | |
821 | 41 | ((Exp_Call *)exp)->tmpl = &tmpl; | |
822 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 39 times.
|
41 | DECL_OO(const Func, func, = get_template_func(env, exp, value)); |
823 | 39 | return func->def->base->ret_type != env->gwion->type[et_auto] ? | |
824 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 1 times.
|
39 | func->def->base->ret_type : exp->func->d.exp_dot.base->type; |
825 | } | ||
826 | |||
827 | ANN Type upvalue_type(const Env env, Capture *cap); | ||
828 | |||
829 | 9 | ANN static m_bool lambda_args_ref(const Env env, Exp_Call *const call) { | |
830 | 9 | Exp e = call->args; | |
831 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
9 | CHECK_OB(check_exp(env, e)); |
832 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
10 | do if(tflag(e->type, tflag_ref) && !safe_tflag(exp_self(e)->cast_to, tflag_ref)) |
833 | ✗ | exp_setvar(e, true); | |
834 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
|
10 | while((e = e->next)); |
835 | 9 | return GW_OK; | |
836 | } | ||
837 | |||
838 | 1 | ANN2(1) static m_bool lambda_append_args(const Env env, Exp_Call *const call, const Exp add) { | |
839 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(!add) return GW_ERROR; |
840 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (call->args) { |
841 | ✗ | Exp e = call->args; | |
842 | ✗ | while(e->next) e = e->next; | |
843 | ✗ | e->next = add; | |
844 | 1 | } else call->args = add; | |
845 | 1 | return traverse_exp(env, add); | |
846 | } | ||
847 | |||
848 | 1 | ANN static Exp check_lambda_captures(const Env env, const Func_Def fdef) { | |
849 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if(!fdef->base->args) |
850 | 1 | fdef->base->args = new_mp_vector(env->gwion->mp, Arg, 0); | |
851 | 1 | Exp args = NULL, tmp; | |
852 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | for(uint32_t i = 0; i < fdef->captures->len; i++) { |
853 | 1 | Capture *const cap = mp_vector_at(fdef->captures, Capture, i); | |
854 | 1 | const Type t = upvalue_type(env, cap); | |
855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(!t) { |
856 | ✗ | if(args) free_exp(env->gwion->mp, args); | |
857 | ✗ | return NULL; | |
858 | } | ||
859 | 2 | Arg arg = { | |
860 | 1 | .td = type2td(env->gwion, t, cap->pos), | |
861 | 1 | .var_decl = { .xid = cap->xid } | |
862 | }; | ||
863 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | mp_vector_add(env->gwion->mp, &fdef->base->args, Arg, arg); |
864 | 1 | const Exp exp = new_prim_id(env->gwion->mp, cap->xid, cap->pos); | |
865 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(args) tmp = tmp->next = exp; |
866 | 1 | else args = tmp = exp; | |
867 | } | ||
868 | 1 | free_mp_vector(env->gwion->mp, Capture, fdef->captures); | |
869 | 1 | fdef->captures = NULL; | |
870 | 1 | return args; | |
871 | } | ||
872 | |||
873 | 14 | ANN static Type check_lambda_call(const Env env, Exp_Call *const exp) { | |
874 | 14 | const Func_Def fdef = exp->func->d.exp_lambda.def; | |
875 | 14 | const bool captures = !!fdef->captures; | |
876 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
|
14 | if (exp->args) CHECK_BO(lambda_args_ref(env, exp)); |
877 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
|
14 | const Exp _args = !captures ? NULL : check_lambda_captures(env, fdef); |
878 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
14 | if(captures) CHECK_BO(lambda_append_args(env, exp, _args)); |
879 | 14 | Exp_Lambda *l = &exp->func->d.exp_lambda; | |
880 | 14 | Arg_List args = l->def->base->args; | |
881 | 14 | Exp e = exp->args; | |
882 |
4/4✓ Branch 0 taken 21 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 13 times.
|
25 | for(uint32_t i = 0; i < (args ? args->len : 0); i++) { |
883 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
|
12 | if(!e) |
884 | 1 | ERR_O(exp_self(exp)->pos, _("argument number does not match for lambda")) | |
885 | 11 | Arg *arg = mp_vector_at(args, Arg, i); | |
886 | 11 | arg->type = e->type; | |
887 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | if(is_class(env->gwion, arg->type)) |
888 | ✗ | type_addref(arg->type); | |
889 | 11 | e = e->next; | |
890 | } | ||
891 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if(e) |
892 | ✗ | ERR_O(exp_self(exp)->pos, _("argument number does not match for lambda")) | |
893 | 13 | Upvalues upvalues = { .values = env->curr->info->value}; | |
894 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
13 | if(env->func && env->func->def->base->values) |
895 | ✗ | upvalues.parent = env->func->def->base->values; | |
896 | 13 | l->def->base->values = &upvalues; | |
897 | 13 | const m_bool ret = traverse_func_def(env, l->def); | |
898 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (l->def->base->func) { |
899 | 13 | free_scope(env->gwion->mp, env->curr->info->value); | |
900 | 13 | env->curr->info->value = l->def->base->values->values; | |
901 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
|
13 | if (env->class_def) set_vflag(l->def->base->func->value_ref, vflag_member); |
902 | 13 | exp->func->type = l->def->base->func->value_ref->type; | |
903 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
|
13 | if (!l->def->base->ret_type) |
904 | 7 | l->def->base->ret_type = env->gwion->type[et_void]; | |
905 | } | ||
906 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | return ret > 0 ? l->def->base->ret_type : NULL; |
907 | } | ||
908 | |||
909 | 458 | ANN m_bool func_check(const Env env, Exp_Call *const exp) { | |
910 | 458 | exp->func->is_call = true; | |
911 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 450 times.
|
458 | CHECK_OB(check_exp(env, exp->func)); |
912 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 448 times.
|
450 | if (exp->func->exp_type == ae_exp_decl) |
913 | 2 | ERR_B(exp->func->pos, _("Can't call late function pointer at declaration " | |
914 | "site. did you meant to use `:=>`?")) | ||
915 | 448 | const Type t = actual_type(env->gwion, exp->func->type); | |
916 |
4/4✓ Branch 1 taken 386 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 220 times.
✓ Branch 4 taken 166 times.
|
448 | if (is_func(env->gwion, t) && exp->func->exp_type == ae_exp_dot && // is_callable |
917 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 219 times.
|
220 | !t->info->value->from->owner_class) { |
918 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1 | if (exp->args) CHECK_OB(check_exp(env, exp->args)); |
919 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | return call2ufcs(env, exp, t->info->func->value_ref) ? GW_OK : GW_ERROR; |
920 | } | ||
921 | 447 | const Exp e = exp_self(exp); | |
922 | 447 | struct Op_Import opi = {.op = insert_symbol("@func_check"), | |
923 | .rhs = t, | ||
924 | .pos = e->pos, | ||
925 | 447 | .data = (uintptr_t)e}; | |
926 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 443 times.
|
447 | if(op_get(env, &opi)) |
927 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
|
4 | CHECK_OB(op_check(env, &opi)); |
928 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 444 times.
|
446 | if (e->exp_type != ae_exp_call) return 0; |
929 |
1/2✓ Branch 0 taken 444 times.
✗ Branch 1 not taken.
|
444 | return e->type != env->gwion->type[et_error] ? GW_OK : GW_ERROR; |
930 | } | ||
931 | |||
932 | 395 | ANN void call_add_effect(const Env env, const Func func, const loc_t pos) { | |
933 |
3/4✓ Branch 0 taken 384 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 384 times.
|
395 | if (func != env->func && func->def->base->effects.ptr) { |
934 | ✗ | const Vector v = &func->def->base->effects; | |
935 | ✗ | for (m_uint i = 0; i < vector_size(v); i++) | |
936 | ✗ | env_add_effect(env, (Symbol)vector_at(v, i), pos); | |
937 | } | ||
938 | 395 | } | |
939 | |||
940 | 435 | ANN Type call_type(const Env env, Exp_Call *const exp) { | |
941 | 435 | const Type t = exp->func->type; | |
942 |
2/2✓ Branch 1 taken 360 times.
✓ Branch 2 taken 75 times.
|
435 | if (is_func(env->gwion, t)) return t; |
943 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 6 times.
|
75 | if(isa(exp->func->type, env->gwion->type[et_closure]) > 0) |
944 | 69 | return closure_def(t)->base->func->value_ref->type; | |
945 |
3/4✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
6 | if(is_class(env->gwion, t) && tflag(t->info->base_type, tflag_struct)) { |
946 | 4 | const Value v = nspc_lookup_value0(t->info->base_type->nspc, insert_symbol("new")); | |
947 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if(v) return exp->func->type = v->type; |
948 | } | ||
949 | 6 | struct Op_Import opi = {.op = insert_symbol("call_type"), | |
950 | 2 | .rhs = actual_type(env->gwion, exp->func->type), | |
951 | 2 | .data = (uintptr_t)exp, | |
952 | 2 | .pos = exp_self(exp)->pos}; | |
953 | 2 | return op_check(env, &opi); | |
954 | } | ||
955 | |||
956 | 1 | ANN static inline bool is_super(const Exp func) { | |
957 | 2 | return func->exp_type == ae_exp_primary && | |
958 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | func->d.prim.prim_type == ae_prim_id && |
959 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | !strcmp(s_name(func->d.prim.d.var), "super"); |
960 | } | ||
961 | |||
962 | 347 | ANN static Type call_return(const Env env, Exp_Call *const exp, | |
963 | const Func func) { | ||
964 | 347 | const Value v = func->value_ref; | |
965 | 347 | exp->func->type = v->type; | |
966 | 347 | call_add_effect(env, func, exp->func->pos); | |
967 |
2/2✓ Branch 0 taken 330 times.
✓ Branch 1 taken 17 times.
|
347 | if(func->def->base->ret_type != env->gwion->type[et_auto]) |
968 | 330 | return func->def->base->ret_type; | |
969 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 9 times.
|
17 | if(tflag(v->from->owner_class, tflag_struct)) |
970 | 8 | return v->from->owner_class; | |
971 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
|
9 | if(exp->func->exp_type == ae_exp_dot) |
972 | 8 | return exp->func->d.exp_dot.base->type; | |
973 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if(is_super(exp->func)) |
974 | 1 | return exp->func->type; | |
975 | ✗ | return NULL; | |
976 | } | ||
977 | |||
978 | 435 | ANN Type _check_exp_call1(const Env env, Exp_Call *const exp) { | |
979 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 433 times.
|
435 | DECL_OO(const Type, t, = call_type(env, exp)); |
980 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 431 times.
|
433 | if (t == env->gwion->type[et_op]) return check_op_call(env, exp); |
981 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 417 times.
|
431 | if (!t->info->func) // TODO: effects? |
982 | 14 | return check_lambda_call(env, exp); | |
983 |
2/2✓ Branch 0 taken 224 times.
✓ Branch 1 taken 193 times.
|
417 | if (exp->args) { |
984 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 224 times.
|
224 | CHECK_OO(check_exp(env, exp->args)); |
985 | 224 | Exp e = exp->args; | |
986 | 300 | do exp_setuse(e, true); | |
987 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 224 times.
|
300 | while((e = e->next)); |
988 | } | ||
989 |
2/2✓ Branch 1 taken 43 times.
✓ Branch 2 taken 374 times.
|
417 | if (tflag(t, tflag_ftmpl)) |
990 | 43 | return check_exp_call_template(env, (Exp_Call *)exp); // TODO: effects? | |
991 | 374 | const Func func = find_func_match(env, t->info->func, exp); | |
992 |
2/2✓ Branch 0 taken 347 times.
✓ Branch 1 taken 27 times.
|
374 | if (func) return call_return(env, exp, func); |
993 | 27 | return exp->func->exp_type != ae_exp_lambda | |
994 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | ? NULL : partial_type(env, exp); |
995 | } | ||
996 | |||
997 | 418 | ANN static Type check_static(const Env env, const Exp e) { | |
998 | 418 | const Type t = e->type; | |
999 |
2/2✓ Branch 1 taken 360 times.
✓ Branch 2 taken 58 times.
|
418 | if(unlikely(!is_func(env->gwion, t)) || |
1000 |
2/2✓ Branch 0 taken 344 times.
✓ Branch 1 taken 16 times.
|
360 | !t->info->func || |
1001 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 344 times.
|
344 | !GET_FLAG(t->info->func->def->base, abstract) || |
1002 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
418 | !is_static_call(env->gwion, e)) return t; |
1003 | ✗ | env_err(env, e->pos, "making a static call to an abstract function"); | |
1004 | ✗ | declared_here(t->info->value); | |
1005 | ✗ | return NULL; | |
1006 | } | ||
1007 | |||
1008 | 430 | ANN Type check_exp_call1(const Env env, Exp_Call *const exp) { | |
1009 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 420 times.
|
430 | DECL_BO(const m_bool, ret, = func_check(env, exp)); |
1010 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 418 times.
|
420 | if (!ret) return exp_self(exp)->type; |
1011 | 418 | const Type t = exp->func->type; | |
1012 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 418 times.
|
418 | CHECK_OO(check_static(env, exp->func)); |
1013 | 418 | const Type _ret = _check_exp_call1(env, exp); | |
1014 |
2/2✓ Branch 0 taken 385 times.
✓ Branch 1 taken 33 times.
|
418 | if(_ret) return _ret; |
1015 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 15 times.
|
33 | if(isa(exp->func->type, env->gwion->type[et_closure]) > 0) { |
1016 |
3/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
18 | if(exp->func->exp_type == ae_exp_dot && t->info->value->from->owner_class) { |
1017 | 17 | const Exp args = exp->args; | |
1018 | 17 | const Exp this_arg = cpy_exp(env->gwion->mp, exp->func->d.exp_dot.base); | |
1019 | 17 | this_arg->next = args; | |
1020 | 17 | exp->args = this_arg; | |
1021 | 17 | const Type t = _check_exp_call1(env, exp); | |
1022 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
|
17 | if(t) return t; |
1023 | } | ||
1024 | } | ||
1025 | 17 | function_alternative(env, exp->func->type, exp->args, exp->func->pos); | |
1026 | 17 | return NULL; | |
1027 | } | ||
1028 | |||
1029 | 629 | ANN static Type check_exp_binary(const Env env, const Exp_Binary *bin) { | |
1030 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 621 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
629 | if(bin->lhs->exp_type == ae_exp_call && !bin->lhs->d.exp_call.tmpl) { |
1031 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | CHECK_OO(check_exp(env, bin->lhs->d.exp_call.func)); |
1032 | // check is template? | ||
1033 | 8 | bin->lhs->d.exp_call.other = bin->rhs; | |
1034 | } | ||
1035 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 626 times.
|
629 | CHECK_OO(check_exp(env, bin->lhs)); |
1036 | 626 | const m_bool is_auto = //bin->op == insert_symbol(":=>") && | |
1037 |
2/2✓ Branch 0 taken 125 times.
✓ Branch 1 taken 501 times.
|
751 | bin->rhs->exp_type == ae_exp_decl && |
1038 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 117 times.
|
125 | bin->rhs->d.exp_decl.type == env->gwion->type[et_auto]; |
1039 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 618 times.
|
626 | if (is_auto) bin->rhs->d.exp_decl.type = bin->lhs->type; |
1040 | // allow foo => new C to mean new C(foo) | ||
1041 |
2/2✓ Branch 0 taken 140 times.
✓ Branch 1 taken 486 times.
|
626 | if(bin->op == insert_symbol("=>") && |
1042 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
140 | bin->rhs->exp_type == ae_exp_unary && bin->rhs->d.exp_unary.unary_type == unary_td && |
1043 | ✗ | !bin->rhs->d.exp_unary.ctor.td->array && | |
1044 | ✗ | !bin->rhs->d.exp_unary.ctor.exp) { | |
1045 | ✗ | Exp lhs = bin->lhs; | |
1046 | ✗ | Exp rhs = bin->rhs; | |
1047 | ✗ | Exp e = exp_self(bin); | |
1048 | ✗ | Exp_Unary *const unary = &e->d.exp_unary; | |
1049 | ✗ | e->exp_type = ae_exp_unary; | |
1050 | ✗ | unary->unary_type = unary_td; | |
1051 | ✗ | unary->op = insert_symbol("new"); | |
1052 | ✗ | unary->ctor.td = cpy_type_decl(env->gwion->mp, bin->rhs->d.exp_unary.ctor.td); | |
1053 | ✗ | unary->ctor.exp = lhs; | |
1054 | ✗ | free_exp(env->gwion->mp, rhs); | |
1055 | ✗ | return check_exp(env, e); | |
1056 | } | ||
1057 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 618 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
626 | if(bin->rhs->exp_type == ae_exp_call && !bin->rhs->d.exp_call.tmpl) |
1058 | 8 | bin->rhs->d.exp_call.other = bin->lhs; | |
1059 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 624 times.
|
626 | CHECK_OO(check_exp(env, bin->rhs)); |
1060 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 616 times.
|
624 | if (is_auto) { |
1061 | assert(bin->rhs->type == bin->lhs->type); | ||
1062 | 8 | set_vflag(bin->rhs->d.exp_decl.vd.value, vflag_assigned); | |
1063 | } | ||
1064 | 1248 | struct Op_Import opi = {.op = bin->op, | |
1065 | 624 | .lhs = bin->lhs->type, | |
1066 | 624 | .rhs = bin->rhs->type, | |
1067 | 624 | .data = (uintptr_t)bin, | |
1068 | 624 | .pos = exp_self(bin)->pos}; | |
1069 | 624 | exp_setuse(bin->lhs, 1); | |
1070 | 624 | exp_setuse(bin->rhs, 1); | |
1071 | 624 | const Type ret = op_check(env, &opi); | |
1072 |
5/6✓ Branch 0 taken 59 times.
✓ Branch 1 taken 565 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 57 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
|
624 | if (!ret && is_auto && exp_self(bin)->exp_type == ae_exp_binary) |
1073 | ✗ | bin->rhs->d.exp_decl.vd.value->type = env->gwion->type[et_auto]; | |
1074 | 624 | return ret; | |
1075 | } | ||
1076 | |||
1077 | 21 | ANN static Type check_exp_cast(const Env env, const Exp_Cast *cast) { | |
1078 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
|
21 | DECL_OO(const Type, t, = check_exp(env, cast->exp)); |
1079 |
2/2✓ Branch 2 taken 2 times.
✓ Branch 3 taken 19 times.
|
21 | CHECK_OO((exp_self(cast)->type = known_type(env, cast->td))); |
1080 | 57 | struct Op_Import opi = {.op = insert_symbol("$"), | |
1081 | .lhs = t, | ||
1082 | 19 | .rhs = exp_self(cast)->type, | |
1083 | 19 | .data = (uintptr_t)cast, | |
1084 | 19 | .pos = exp_self(cast)->pos}; | |
1085 | 19 | return op_check(env, &opi); | |
1086 | } | ||
1087 | |||
1088 | 31 | ANN static Type check_exp_post(const Env env, const Exp_Postfix *post) { | |
1089 | 93 | struct Op_Import opi = {.op = post->op, | |
1090 | 31 | .lhs = check_exp(env, post->exp), | |
1091 | 31 | .data = (uintptr_t)post, | |
1092 | 31 | .pos = exp_self(post)->pos}; | |
1093 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
|
31 | CHECK_OO(opi.lhs); |
1094 | 31 | exp_setuse(post->exp, 1); | |
1095 | 31 | const Type t = op_check(env, &opi); | |
1096 |
3/4✓ Branch 0 taken 29 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
|
31 | if (t && isa(t, env->gwion->type[et_object]) < 0) |
1097 | 29 | exp_setmeta(exp_self(post), 1); | |
1098 | 31 | return t; | |
1099 | } | ||
1100 | |||
1101 | 2 | ANN static m_bool predefined_call(const Env env, const Type t, | |
1102 | const loc_t pos) { | ||
1103 | const m_str str = | ||
1104 | 2 | tl2str(env->gwion, t->info->func->def->base->tmpl->call, pos); | |
1105 | 2 | env_err(env, pos, _("Type '%s' has '%s' as pre-defined types."), t->name, | |
1106 | str); | ||
1107 | 2 | free_mstr(env->gwion->mp, str); | |
1108 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (tflag(t, tflag_typedef)) { |
1109 | ✗ | gwerr_secondary("from definition:", env->name, | |
1110 | ✗ | t->info->func->def->base->pos); | |
1111 | } | ||
1112 | 2 | return GW_ERROR; | |
1113 | } | ||
1114 | |||
1115 | 409 | ANN2(1) static inline bool is_partial(const Env env, Exp exp) { | |
1116 |
2/2✓ Branch 0 taken 274 times.
✓ Branch 1 taken 402 times.
|
676 | while (exp) { |
1117 |
3/4✓ Branch 1 taken 267 times.
✓ Branch 2 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 267 times.
|
274 | if (is_hole(env, exp) || is_typed_hole(env, exp)) |
1118 | 7 | return true; | |
1119 | 267 | exp = exp->next; | |
1120 | } | ||
1121 | 402 | return false; | |
1122 | } | ||
1123 | |||
1124 | 3 | ANN static bool tl_match(const Env env, const Type_List tl0, const Type_List tl1) { | |
1125 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (tl0->len != tl1->len) return false; |
1126 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for(uint32_t i = 0; i < tl0->len; i++) { |
1127 | 3 | Type_Decl *td0 = *mp_vector_at(tl0, Type_Decl*, i); | |
1128 | 3 | Type_Decl *td1 = *mp_vector_at(tl1, Type_Decl*, i); | |
1129 |
2/2✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
|
3 | if(known_type(env, td0) != known_type(env, td1)) |
1130 | 2 | return false; | |
1131 | } | ||
1132 | 1 | return true; | |
1133 | } | ||
1134 | |||
1135 | 26 | ANN static Type check_exp_call_tmpl(const Env env, Exp_Call *exp, const Type t) { | |
1136 |
3/4✓ Branch 0 taken 19 times.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
|
26 | if (exp->args) CHECK_OO(check_exp(env, exp->args)); |
1137 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25 times.
|
26 | if (!t->info->func->def->base->tmpl) |
1138 | 1 | ERR_O(exp_self(exp)->pos, _("template call of non-template function.")) | |
1139 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 22 times.
|
25 | if (t->info->func->def->base->tmpl->call) { |
1140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (env->func == t->info->func) { |
1141 | ✗ | exp->func->type = env->func->value_ref->type; | |
1142 | ✗ | return env->func->def->base->ret_type; | |
1143 | } else { | ||
1144 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
|
3 | if(tl_match(env, t->info->func->def->base->tmpl->call, exp->tmpl->call)) |
1145 | 1 | return check_exp_call1(env, exp); | |
1146 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | CHECK_BO(predefined_call(env, t, exp_self(exp)->pos)); |
1147 | } | ||
1148 | } | ||
1149 | 22 | const Value v = type_value(env->gwion, t); | |
1150 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 14 times.
|
22 | DECL_OO(const Func, f, = find_template_match(env, v, exp)); |
1151 | 14 | exp->func->type = f->value_ref->type; | |
1152 | 14 | return f->def->base->ret_type; | |
1153 | } | ||
1154 | |||
1155 | 409 | ANN static Type check_exp_call(const Env env, Exp_Call *exp) { | |
1156 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 402 times.
|
409 | if (is_partial(env, exp->args)) { |
1157 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | CHECK_OO(check_exp(env, exp->func)); |
1158 | 7 | struct Op_Import opi = {.op = insert_symbol("@partial"), | |
1159 | 7 | .lhs = exp->func->type, | |
1160 | 7 | .pos = exp->func->pos, | |
1161 | 7 | .data = (uintptr_t)exp}; | |
1162 | 7 | return op_check(env, &opi); | |
1163 | } | ||
1164 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 374 times.
|
402 | if (exp->tmpl) { |
1165 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 27 times.
|
28 | DECL_BO(const m_bool, ret, = func_check(env, exp)); |
1166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (!ret) return exp_self(exp)->type; |
1167 | 27 | Type t = actual_type(env->gwion, exp->func->type); | |
1168 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 24 times.
|
27 | if(isa(exp->func->type, env->gwion->type[et_closure]) > 0) { |
1169 | 3 | t = typedef_base(t); | |
1170 | 3 | t = mp_vector_at(t->info->cdef->body, Section , 0)->d.func_def->base->func->value_ref->type; | |
1171 | } | ||
1172 | // check for closure and b ring it back | ||
1173 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 26 times.
|
27 | if (!is_func(env->gwion, t)) return check_exp_call1(env, exp); |
1174 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | if(!is_new(t->info->func->def)) |
1175 | 26 | return check_exp_call_tmpl(env, exp, t); | |
1176 | } | ||
1177 | 374 | return check_exp_call1(env, exp); | |
1178 | } | ||
1179 | |||
1180 | 130 | ANN static Type check_exp_unary(const Env env, const Exp_Unary *unary) { | |
1181 | 130 | const Type rhs = | |
1182 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 64 times.
|
130 | unary->unary_type == unary_exp ? check_exp(env, unary->exp) : NULL; |
1183 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 64 times.
|
130 | if (unary->unary_type == unary_exp) { |
1184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | CHECK_OO(rhs); |
1185 | 66 | exp_setuse(unary->exp, 1); | |
1186 | } | ||
1187 | 260 | struct Op_Import opi = {.op = unary->op, | |
1188 | .rhs = rhs, | ||
1189 | 130 | .data = (uintptr_t)unary, | |
1190 | 130 | .pos = exp_self(unary)->pos}; | |
1191 |
2/2✓ Branch 1 taken 16 times.
✓ Branch 2 taken 114 times.
|
130 | DECL_OO(const Type, ret, = op_check(env, &opi)); |
1192 | 114 | return ret; | |
1193 | } | ||
1194 | |||
1195 | 81 | ANN static Type _flow(const Env env, const Exp e, const m_bool b) { | |
1196 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
|
81 | DECL_OO(const Type, type, = check_exp(env, e)); |
1197 | 162 | struct Op_Import opi = { | |
1198 | 81 | .op = insert_symbol(b ? "@conditional" : "@unconditional"), | |
1199 | .rhs = type, | ||
1200 | .pos = e->pos, | ||
1201 |
2/2✓ Branch 0 taken 68 times.
✓ Branch 1 taken 13 times.
|
81 | .data = (uintptr_t)e}; |
1202 | 81 | return op_check(env, &opi); | |
1203 | } | ||
1204 | #define check_flow(emit, b) _flow(emit, b, 1) | ||
1205 | |||
1206 | 8 | ANN static Type check_exp_if(const Env env, Exp_If *const exp_if) { | |
1207 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 | if (!exp_if->if_exp) { |
1208 | 1 | const Exp e = exp_if->if_exp = cpy_exp(env->gwion->mp, exp_if->cond); | |
1209 | 1 | scan1_exp(env, e); | |
1210 | 1 | scan2_exp(env, e); | |
1211 | } | ||
1212 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | DECL_OO(const Type, cond, = check_flow(env, exp_if->cond)); |
1213 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | DECL_OO(const Type, if_exp, = check_exp(env, exp_if->if_exp)); |
1214 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | DECL_OO(const Type, else_exp, = check_exp(env, exp_if->else_exp)); |
1215 | |||
1216 | 8 | const uint meta = | |
1217 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
8 | exp_getmeta(exp_if->if_exp) || exp_getmeta(exp_if->else_exp); |
1218 | 8 | exp_setmeta(exp_self(exp_if), meta); | |
1219 | 8 | const Type ret = find_common_anc(if_exp, else_exp); | |
1220 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 | if (!ret) |
1221 | 1 | ERR_O(exp_self(exp_if)->pos, | |
1222 | _("incompatible types '%s' and '%s' in if expression..."), | ||
1223 | if_exp->name, else_exp->name) | ||
1224 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (isa(if_exp, else_exp) < 0) |
1225 | ✗ | ERR_O(exp_self(exp_if)->pos, _("condition type '%s' does not match '%s'"), | |
1226 | cond->name, ret->name) | ||
1227 | 7 | exp_setuse(exp_if->cond, true); | |
1228 | 7 | exp_setuse(exp_if->if_exp, true); | |
1229 | 7 | exp_setuse(exp_if->else_exp, true); | |
1230 | 7 | return ret; | |
1231 | } | ||
1232 | |||
1233 | 470 | ANN static Type check_exp_dot(const Env env, Exp_Dot *member) { | |
1234 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 467 times.
|
470 | CHECK_OO(check_exp(env, member->base)); |
1235 | 467 | return check_dot(env, member); | |
1236 | } | ||
1237 | |||
1238 | 17 | ANN m_bool check_type_def(const Env env, const Type_Def tdef) { | |
1239 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 14 times.
|
17 | if (tdef->when) { |
1240 | 3 | set_tflag(tdef->type, tflag_contract); | |
1241 | 3 | struct Var_Decl_ decl = { .xid = insert_symbol("self"), .pos = tdef->when->pos }; | |
1242 | 3 | Type_Decl *td = cpy_type_decl(env->gwion->mp, tdef->ext); | |
1243 | 3 | Arg_List args = new_mp_vector(env->gwion->mp, Arg, 1); | |
1244 | 3 | mp_vector_set(args, Arg, 0, ((Arg) { .td = td, .var_decl = decl })); | |
1245 | 6 | Func_Base *fb = new_func_base( | |
1246 | 3 | env->gwion->mp, type2td(env->gwion, tdef->type, tdef->pos), | |
1247 | 3 | insert_symbol("@implicit"), args, ae_flag_none, tdef->pos); | |
1248 | 3 | set_fbflag(fb, fbflag_op); | |
1249 | 3 | const Exp helper = new_prim_id(env->gwion->mp, insert_symbol("@predicate"), | |
1250 | 3 | tdef->when->pos); | |
1251 | 3 | const Exp when = tdef->when; | |
1252 | 3 | tdef->when = NULL; | |
1253 | 3 | when->next = helper; | |
1254 | 3 | Stmt_List code = new_mp_vector(env->gwion->mp, struct Stmt_, 2); | |
1255 | 3 | mp_vector_set(code, struct Stmt_, 0, | |
1256 | ((struct Stmt_) { | ||
1257 | .stmt_type = ae_stmt_exp, .d = { .stmt_exp = { .val = when }}, | ||
1258 | .pos = when->pos | ||
1259 | })); | ||
1260 | 3 | mp_vector_set(code, struct Stmt_, 1, | |
1261 | ((struct Stmt_) { | ||
1262 | .stmt_type = ae_stmt_exp, | ||
1263 | .pos = when->pos | ||
1264 | })); | ||
1265 | 3 | const Func_Def fdef = new_func_def(env->gwion->mp, fb, code); | |
1266 | 3 | tdef->when_def = fdef; | |
1267 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
4 | CHECK_BB(traverse_func_def(env, fdef)); |
1268 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (isa(when->type, env->gwion->type[et_bool]) < 0) { |
1269 | 1 | char explain[strlen(when->type->name) + 20]; | |
1270 | 1 | sprintf(explain, "found `{/+}%s{0}`", when->type->name); | |
1271 | 1 | gwerr_basic("Invalid `{/+}when{0}` predicate expression type", explain, | |
1272 | 1 | "use `{/+}bool{0}`", env->name, when->pos, 0); | |
1273 | 1 | char from[strlen(tdef->type->name) + 39]; | |
1274 | 1 | sprintf(from, "in `{/+}%s{0}` definition", tdef->type->name); | |
1275 | 1 | gwerr_secondary(from, env->name, tdef->pos); | |
1276 | 1 | env_set_error(env, true); | |
1277 | 1 | return GW_ERROR; | |
1278 | } | ||
1279 | // we handle the return after, so that we don't get *cant' use implicit | ||
1280 | // casting while defining it* | ||
1281 | 2 | const Exp ret_id = new_prim_id(env->gwion->mp, insert_symbol("self"), when->pos); | |
1282 | 2 | ret_id->d.prim.value = new_value(env, tdef->type, "self", tdef->pos); | |
1283 | 2 | struct Stmt_ ret = { | |
1284 | .stmt_type = ae_stmt_return, .d = { .stmt_exp = { .val = ret_id }}, | ||
1285 | .pos = when->pos | ||
1286 | }; | ||
1287 | 2 | mp_vector_set(fdef->d.code, struct Stmt_, 1, ret); | |
1288 | 2 | ret_id->type = tdef->type; | |
1289 | } | ||
1290 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 9 times.
|
16 | if (tflag(tdef->type, tflag_cdef)) |
1291 | 7 | return check_class_def(env, tdef->type->info->cdef); | |
1292 | 9 | else inherit(tdef->type); | |
1293 | 9 | return GW_OK; | |
1294 | } | ||
1295 | |||
1296 | 25 | ANN static Type check_exp_lambda(const Env env, const Exp_If *exp_if NUSED) { | |
1297 | 25 | return env->gwion->type[et_function]; | |
1298 | } | ||
1299 | |||
1300 | ✗ | ANN static Type check_exp_td(const Env env, Type_Decl **td) { | |
1301 | ✗ | DECL_OO(const Type, t, = known_type(env, *td)); | |
1302 | ✗ | if(t == env->gwion->type[et_class]) | |
1303 | ✗ | ERR_O(exp_self(td)->pos, "can't use {G+}Class{0} in type decl expression"); | |
1304 | ✗ | if (!is_func(env->gwion, t)) return type_class(env->gwion, t); | |
1305 | ✗ | return t; | |
1306 | } | ||
1307 | |||
1308 | DECL_EXP_FUNC(check, Type, Env) | ||
1309 | |||
1310 | 18939 | ANN Type check_exp(const Env env, const Exp exp) { | |
1311 | 18939 | Exp curr = exp; | |
1312 |
2/2✓ Branch 0 taken 16981 times.
✓ Branch 1 taken 1958 times.
|
18939 | if (!exp->type) { |
1313 | 16981 | env_weight(env, 1); | |
1314 | do { | ||
1315 |
2/2✓ Branch 1 taken 214 times.
✓ Branch 2 taken 17154 times.
|
17368 | CHECK_OO((curr->type = check_exp_func[curr->exp_type](env, &curr->d))); |
1316 |
6/6✓ Branch 0 taken 1889 times.
✓ Branch 1 taken 15265 times.
✓ Branch 3 taken 1859 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 160 times.
✓ Branch 6 taken 1699 times.
|
19013 | if (env->func && !is_class(env->gwion, curr->type) && |
1317 |
2/2✓ Branch 1 taken 52 times.
✓ Branch 2 taken 108 times.
|
2019 | is_func(env->gwion, curr->type) && |
1318 | 160 | !safe_fflag(curr->type->info->func, fflag_pure)) | |
1319 | 52 | unset_fflag(env->func, fflag_pure); | |
1320 |
2/2✓ Branch 0 taken 387 times.
✓ Branch 1 taken 16767 times.
|
17154 | } while ((curr = curr->next)); |
1321 | } | ||
1322 | 18725 | return exp->type; | |
1323 | } | ||
1324 | |||
1325 | 645 | ANN m_bool check_enum_def(const Env env, const Enum_Def edef) { | |
1326 | 645 | const m_uint scope = env_push_type(env, edef->type); | |
1327 | 645 | ID_List list = edef->list; | |
1328 |
2/2✓ Branch 0 taken 656 times.
✓ Branch 1 taken 645 times.
|
1301 | for(uint32_t i = 0; i < list->len; i++) { |
1329 | 656 | Symbol xid = *mp_vector_at(list, Symbol, i); | |
1330 | 656 | decl_static(env, nspc_lookup_value0(env->curr, xid)); | |
1331 | } | ||
1332 | 645 | env_pop(env, scope); | |
1333 | 645 | nspc_allocdata(env->gwion->mp, edef->type->nspc); | |
1334 | 645 | return GW_OK; | |
1335 | } | ||
1336 | |||
1337 | 132 | ANN static m_bool check_stmt_code(const Env env, const Stmt_Code stmt) { | |
1338 |
2/2✓ Branch 0 taken 131 times.
✓ Branch 1 taken 1 times.
|
132 | if (stmt->stmt_list) { RET_NSPC(check_stmt_list(env, stmt->stmt_list)) } |
1339 | 1 | return GW_OK; | |
1340 | } | ||
1341 | |||
1342 | 53 | ANN static inline m_bool _check_breaks(const Env env, const Stmt b) { | |
1343 | 53 | RET_NSPC(check_stmt(env, b))} | |
1344 | |||
1345 | 53 | ANN static m_bool check_breaks(const Env env, const Stmt a, const Stmt b) { | |
1346 | 53 | vector_add(&env->scope->breaks, (vtype)a); | |
1347 | 53 | const m_bool ret = _check_breaks(env, b); | |
1348 | 53 | vector_pop(&env->scope->breaks); | |
1349 | 53 | return ret; | |
1350 | } | ||
1351 | |||
1352 | 53 | ANN static m_bool check_conts(const Env env, const Stmt a, const Stmt b) { | |
1353 | 53 | vector_add(&env->scope->conts, (vtype)a); | |
1354 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 52 times.
|
53 | CHECK_BB(check_breaks(env, a, b)); |
1355 | 52 | vector_pop(&env->scope->conts); | |
1356 | 52 | return GW_OK; | |
1357 | } | ||
1358 | |||
1359 | 8 | ANN static inline m_bool for_empty(const Env env, const Stmt_For stmt) { | |
1360 |
3/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
|
8 | if (!stmt->c2 || !stmt->c2->d.stmt_exp.val) |
1361 | 1 | ERR_B(stmt_self(stmt)->pos, | |
1362 | _("empty for loop condition..." | ||
1363 | "...(note: explicitly use 'true' if it's the intent)" | ||
1364 | "...(e.g., 'for(; true;){{ /*...*/ }')")) | ||
1365 | 7 | return GW_OK; | |
1366 | } | ||
1367 | |||
1368 | 2 | ANN static void check_idx(const Env env, const Type base, struct EachIdx_ *const idx) { | |
1369 | 2 | idx->v = new_value(env, base, s_name(idx->sym), idx->pos); | |
1370 | 2 | valid_value(env, idx->sym, idx->v); | |
1371 | 2 | SET_FLAG(idx->v, const); | |
1372 | 2 | } | |
1373 | |||
1374 | /** sets for the key expression value | ||
1375 | with eg type *int* for an array or the *Key* type of a Dict **/ | ||
1376 | 1 | ANN static m_bool check_each_idx(const Env env, const Exp exp, struct EachIdx_ *const idx) { | |
1377 | 1 | struct Op_Import opi = { | |
1378 | 1 | .lhs = exp->type, | |
1379 | 1 | .op = insert_symbol("@each_idx"), | |
1380 | 1 | .data = (m_uint)exp, | |
1381 | .pos = idx->pos | ||
1382 | }; | ||
1383 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | DECL_OB(const Type, t, = op_check(env, &opi)); |
1384 | 1 | check_idx(env, t, idx); | |
1385 | 1 | return GW_OK; | |
1386 | } | ||
1387 | |||
1388 | /** return the base type for the foreach expression | ||
1389 | eg the base type of an array or the *Val* type of a Dict **/ | ||
1390 | 7 | ANN static Type check_each_val(const Env env, const Exp exp) { | |
1391 | 7 | struct Op_Import opi = { | |
1392 | 7 | .lhs = exp->type, | |
1393 | 7 | .op = insert_symbol("@each_val"), | |
1394 | 7 | .data = (m_uint)exp, | |
1395 | .pos = exp->pos | ||
1396 | }; | ||
1397 | 7 | return op_check(env, &opi); | |
1398 | } | ||
1399 | |||
1400 | 9 | ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) { | |
1401 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7 times.
|
9 | CHECK_OB(check_exp(env, stmt->exp)); |
1402 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
|
7 | if (stmt->idx) |
1403 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | CHECK_BB(check_each_idx(env, stmt->exp, stmt->idx)); |
1404 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | DECL_OB(const Type, ret, = check_each_val(env, stmt->exp)); |
1405 | 7 | stmt->v = new_value(env, ret, s_name(stmt->sym), stmt->vpos); | |
1406 | 7 | valid_value(env, stmt->sym, stmt->v); | |
1407 | 7 | return check_conts(env, stmt_self(stmt), stmt->body); | |
1408 | } | ||
1409 | |||
1410 | 8 | ANN static m_bool do_stmt_repeat(const Env env, const Stmt_Loop stmt) { | |
1411 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 | if (stmt->idx) check_idx(env, env->gwion->type[et_int], stmt->idx); |
1412 | 8 | return check_conts(env, stmt_self(stmt), stmt->body); | |
1413 | } | ||
1414 | |||
1415 | 9 | ANN static inline m_bool repeat_type(const Env env, const Exp e) { | |
1416 | 9 | const Type t_int = env->gwion->type[et_int]; | |
1417 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 8 times.
|
9 | if (check_implicit(env, e, t_int) < 0) { |
1418 | 1 | char explain[40 + strlen(e->type->name)]; | |
1419 | 1 | sprintf(explain, "expected `{/+}int{0}`, got `{/+}%s{0}`", e->type->name); | |
1420 | 1 | gwerr_basic(_("invalid repeat condition type"), explain, | |
1421 | 1 | _("use an integer or cast to int if possible"), env->name, | |
1422 | e->pos, 0); | ||
1423 | 1 | env_set_error(env, true); | |
1424 | 1 | return GW_ERROR; | |
1425 | } | ||
1426 | 8 | return GW_OK; | |
1427 | } | ||
1428 | |||
1429 | #define stmt_func_xxx(name, type, prolog, exp) \ | ||
1430 | describe_stmt_func(check, name, type, prolog, exp) | ||
1431 |
5/8✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 33 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 25 times.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
|
33 | stmt_func_xxx(if, Stmt_If,, !(!check_flow(env, stmt->cond) || |
1432 | check_stmt(env, stmt->if_body) < 0 || | ||
1433 | (stmt->else_body && check_stmt(env, stmt->else_body) < 0)) ? 1 : -1) | ||
1434 |
5/8✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 14 times.
✓ Branch 9 taken 32 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 32 times.
✗ Branch 14 not taken.
|
32 | stmt_func_xxx(flow, Stmt_Flow, env_inline_mult(env, 1.5), |
1435 | !(!check_exp(env, stmt->cond) || | ||
1436 | !_flow(env, stmt->cond, !stmt->is_do ? | ||
1437 | stmt_self(stmt)->stmt_type == ae_stmt_while : | ||
1438 | stmt_self(stmt)->stmt_type != ae_stmt_while) || | ||
1439 | check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1) | ||
1440 |
9/12✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 1 times.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 1 times.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 6 times.
✗ Branch 18 not taken.
|
8 | stmt_func_xxx(for, Stmt_For, env_inline_mult(env, 1.5), !( |
1441 | for_empty(env, stmt) < 0 || | ||
1442 | check_stmt(env, stmt->c1) < 0 || | ||
1443 | !check_flow(env, stmt->c2->d.stmt_exp.val) || | ||
1444 | (stmt->c3 && !check_exp(env, stmt->c3)) || | ||
1445 | check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1) | ||
1446 |
4/6✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 1 times.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
|
9 | stmt_func_xxx(loop, Stmt_Loop, env_inline_mult(env, 1.5); check_idx(env, stmt->idx), !(!check_exp(env, stmt->cond) || |
1447 | repeat_type(env, stmt->cond) < 0 || | ||
1448 | do_stmt_repeat(env, stmt) < 0) ? 1 : -1) | ||
1449 | 9 | stmt_func_xxx(each, Stmt_Each, env_inline_mult(env, 1.5), do_stmt_each(env, stmt)) | |
1450 | |||
1451 | 83 | ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) { | |
1452 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 82 times.
|
83 | if (is_new(env->func->def)) { |
1453 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if(stmt->val) |
1454 | 1 | ERR_B(stmt_self(stmt)->pos, | |
1455 | _("'return' statement inside constructor function should have no expression")) | ||
1456 | ✗ | return GW_OK; | |
1457 | } | ||
1458 |
3/4✓ Branch 0 taken 79 times.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
|
82 | DECL_OB(const Type, ret_type, |
1459 | = stmt->val ? check_exp(env, stmt->val) : env->gwion->type[et_void]); | ||
1460 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 76 times.
|
82 | if (!env->func->def->base->ret_type) { |
1461 | 6 | env->func->def->base->ret_type = ret_type; | |
1462 | 6 | return GW_OK; | |
1463 | } | ||
1464 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 7 times.
|
76 | if (isa(ret_type, env->func->def->base->ret_type) > 0) return GW_OK; |
1465 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | if (tflag(ret_type, tflag_noret)) |
1466 | ✗ | ERR_B(stmt->val->pos, _("Can't use type `{+G}%s{+G}` for return"), | |
1467 | ret_type->name); | ||
1468 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
|
7 | if (stmt->val) { |
1469 | 6 | Arg *arg = mp_vector_at(env->func->def->base->args, Arg, 0); | |
1470 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
|
6 | if (env->func->def->base->xid == insert_symbol("@implicit") && |
1471 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | ret_type == arg->type) |
1472 | 1 | ERR_B(stmt_self(stmt)->pos, | |
1473 | _("can't use implicit casting while defining it")) | ||
1474 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
|
5 | if (check_implicit(env, stmt->val, env->func->def->base->ret_type) > 0) |
1475 | 4 | return GW_OK; | |
1476 | 1 | ERR_B(stmt_self(stmt)->pos, | |
1477 | _("invalid return type: got '%s', expected '%s'"), ret_type->name, | ||
1478 | env->func->def->base->ret_type->name) | ||
1479 | } | ||
1480 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (isa(env->func->def->base->ret_type, env->gwion->type[et_void]) > 0) |
1481 | ✗ | return GW_OK; | |
1482 | 1 | ERR_B(stmt_self(stmt)->pos, _("missing value for return statement")) | |
1483 | } | ||
1484 | |||
1485 | #define describe_check_stmt_stack(stack, name) \ | ||
1486 | ANN static m_bool check_stmt_##name(const Env env, const Stmt stmt) { \ | ||
1487 | if (!vector_size(&env->scope->stack)) \ | ||
1488 | ERR_B(stmt->pos, _("'" #name "' found outside of for/while/until...")) \ | ||
1489 | return GW_OK; \ | ||
1490 | } | ||
1491 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 9 times.
|
10 | describe_check_stmt_stack(conts, continue); |
1492 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 12 times.
|
13 | describe_check_stmt_stack(breaks, break); |
1493 | |||
1494 | 1277 | ANN m_bool check_union_def(const Env env NUSED, const Union_Def udef) { | |
1495 |
2/2✓ Branch 1 taken 1276 times.
✓ Branch 2 taken 1 times.
|
1277 | if (tmpl_base(udef->tmpl)) // there's a func for this |
1496 | 1276 | return GW_OK; | |
1497 | 1 | set_tflag(udef->type, tflag_check); | |
1498 | 1 | return GW_OK; | |
1499 | } | ||
1500 | |||
1501 | 1853 | ANN static m_bool check_stmt_exp(const Env env, const Stmt_Exp stmt) { | |
1502 |
2/2✓ Branch 0 taken 1840 times.
✓ Branch 1 taken 13 times.
|
1853 | if(stmt->val) { |
1503 |
2/2✓ Branch 1 taken 136 times.
✓ Branch 2 taken 1704 times.
|
1840 | CHECK_OB(check_exp(env, stmt->val)); |
1504 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1703 times.
|
1704 | if(stmt->val->exp_type == ae_exp_lambda) { |
1505 | 1 | const loc_t loc = stmt->val->d.exp_lambda.def->base->pos; | |
1506 | 1 | env_warn(env, loc, _("Partial application not used")); | |
1507 | } | ||
1508 | } | ||
1509 |
3/4✓ Branch 0 taken 1704 times.
✓ Branch 1 taken 13 times.
✓ Branch 3 taken 1704 times.
✗ Branch 4 not taken.
|
1717 | return stmt->val ? check_exp(env, stmt->val) ? 1 : -1 : 1; |
1510 | } | ||
1511 | |||
1512 | 2 | ANN static Value match_value(const Env env, const Type base, | |
1513 | const Exp_Primary *prim) { | ||
1514 | 2 | const Symbol sym = prim->d.var; | |
1515 | 2 | const Value v = new_value(env, base, s_name(sym), prim_pos(prim)); | |
1516 | // valuefrom? | ||
1517 | 2 | valid_value(env, sym, v); | |
1518 | 2 | return v; | |
1519 | } | ||
1520 | |||
1521 | 16 | ANN Symbol case_basic_op(const Env env, const Type base, const Exp e) { | |
1522 | 16 | const Symbol _op = insert_symbol("=="); | |
1523 | 16 | struct Op_Import opi = {.op = _op, | |
1524 | .lhs = base, | ||
1525 | 16 | .rhs = e->type, | |
1526 | .data = (uintptr_t)NULL, | ||
1527 | .pos = e->pos}; | ||
1528 | 16 | return op_get(env, &opi) | |
1529 | 8 | ? insert_symbol("==") | |
1530 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
24 | : insert_symbol("?="); |
1531 | } | ||
1532 | |||
1533 | 11 | ANN static Symbol case_op(const Env env, const Type base, const Exp e) { | |
1534 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | if (e->exp_type == ae_exp_primary) { |
1535 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
|
11 | if (e->d.prim.prim_type == ae_prim_id) { |
1536 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (e->d.prim.d.var == insert_symbol("_")) return NULL; |
1537 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (!nspc_lookup_value1(env->curr, e->d.prim.d.var)) { |
1538 | 2 | e->d.prim.value = match_value(env, base, &e->d.prim); | |
1539 | 2 | return NULL; | |
1540 | } | ||
1541 | } | ||
1542 | ✗ | } else if (isa(base, env->gwion->type[et_union]) > 0 && | |
1543 | ✗ | e->exp_type == ae_exp_call) { | |
1544 | ✗ | const Exp func = e->d.exp_call.func; | |
1545 | ✗ | if (func->d.prim.prim_type == ae_prim_id) { | |
1546 | ✗ | const Value v = find_value(base, func->d.prim.d.var); | |
1547 | ✗ | if (v) { | |
1548 | ✗ | e->type = v->type; | |
1549 | ✗ | case_op(env, v->type, e->d.exp_call.args); | |
1550 | ✗ | e->d.exp_call.args->type = v->type; | |
1551 | ✗ | return NULL; | |
1552 | } | ||
1553 | } | ||
1554 | } | ||
1555 | 8 | return case_basic_op(env, base, e); | |
1556 | } | ||
1557 | |||
1558 | 11 | ANN static m_bool match_case_exp(const Env env, Exp e) { | |
1559 | 11 | Exp last = e; | |
1560 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 2 taken 11 times.
|
22 | for (m_uint i = 0; i < vector_size(&env->scope->match->cond); e = e->next, ++i) { |
1561 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (!e) ERR_B(last->pos, _("no enough to match")) |
1562 | 11 | last = e; | |
1563 | 11 | const Exp base = (Exp)vector_at(&env->scope->match->cond, i); | |
1564 | 11 | const Symbol op = case_op(env, base->type, e); | |
1565 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
|
11 | if (op) { |
1566 | 8 | const Exp next = e->next; | |
1567 | 8 | e->next = NULL; | |
1568 | 8 | const Type t = check_exp(env, e); | |
1569 | 8 | e->next = next; | |
1570 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | CHECK_OB(t); |
1571 | 8 | Exp_Binary bin = {.lhs = cpy_exp(env->gwion->mp, base), .rhs = cpy_exp(env->gwion->mp, e), .op = op}; | |
1572 | 8 | struct Exp_ ebin = {.d = {.exp_binary = bin}, .exp_type = ae_exp_binary, .pos = e->pos }; | |
1573 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | CHECK_BB(traverse_exp(env, &ebin)); |
1574 | 8 | const Type ret = ebin.type; | |
1575 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if(ebin.exp_type == ae_exp_binary) { |
1576 | ✗ | free_exp(env->gwion->mp, bin.lhs); | |
1577 | ✗ | free_exp(env->gwion->mp, bin.rhs); | |
1578 | } | ||
1579 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | CHECK_OB(ret); |
1580 | } | ||
1581 | } | ||
1582 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
|
11 | if (e) ERR_B(e->pos, _("too many expression to match")) |
1583 | 10 | return GW_OK; | |
1584 | } | ||
1585 | |||
1586 | 11 | ANN static m_bool _check_stmt_case(const Env env, const Stmt_Match stmt) { | |
1587 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
|
11 | CHECK_BB(match_case_exp(env, stmt->cond)); |
1588 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
10 | if (stmt->when) CHECK_OB(check_flow(env, stmt->when)); |
1589 | 10 | return check_stmt_list(env, stmt->list); | |
1590 | } | ||
1591 | |||
1592 | 11 | ANN static m_bool check_stmt_case(const Env env, const Stmt_Match stmt) { | |
1593 | 11 | RET_NSPC(_check_stmt_case(env, stmt))} | |
1594 | |||
1595 | 7 | ANN static m_bool case_loop(const Env env, const Stmt_Match stmt) { | |
1596 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
|
17 | for(m_uint i = 0; i < stmt->list->len; i++) { |
1597 | 11 | const Stmt s = mp_vector_at(stmt->list, struct Stmt_, i); | |
1598 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
|
11 | CHECK_BB(check_stmt_case(env, &s->d.stmt_match)); |
1599 | } | ||
1600 | 6 | return GW_OK; | |
1601 | } | ||
1602 | |||
1603 | 3 | ANN static inline m_bool check_handler(const restrict Env env, | |
1604 | const Handler *handler) { | ||
1605 | 3 | RET_NSPC(check_stmt(env, handler->stmt)); | |
1606 | } | ||
1607 | |||
1608 | 3 | ANN static inline m_bool check_handler_list(const restrict Env env, | |
1609 | const Handler_List handlers) { | ||
1610 | 3 | const bool in_try = env->scope->in_try; | |
1611 | 3 | env->scope->in_try = true; | |
1612 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for(uint32_t i = 0; i < handlers->len; i++) { |
1613 | 3 | Handler *handler = mp_vector_at(handlers, Handler, i); | |
1614 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | CHECK_BB(check_handler(env, handler)); |
1615 | } | ||
1616 | 3 | env->scope->in_try = in_try; | |
1617 | 3 | return GW_OK; | |
1618 | } | ||
1619 | |||
1620 | ✗ | ANN static inline bool find_handler(const Handler_List handlers, const Symbol xid) { | |
1621 | ✗ | for(uint32_t i = 0; i < handlers->len; i++) { | |
1622 | ✗ | Handler *handler = mp_vector_at(handlers, Handler, i); | |
1623 | ✗ | if(xid == handler->xid) return true; | |
1624 | ✗ | if(!handler->xid) return true; | |
1625 | } | ||
1626 | ✗ | return false; | |
1627 | } | ||
1628 | |||
1629 | 3 | ANN static inline m_bool check_stmt_try_start(const restrict Env env, | |
1630 | const Stmt_Try stmt) { | ||
1631 | 3 | RET_NSPC(check_stmt(env, stmt->stmt)) | |
1632 | } | ||
1633 | |||
1634 | 3 | ANN static inline m_bool check_stmt_try(const restrict Env env, const Stmt_Try stmt) { | |
1635 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | CHECK_BB(check_handler_list(env, stmt->handler)); |
1636 | 3 | vector_add(&env->scope->effects, 0); | |
1637 | 3 | const m_bool ret = check_stmt_try_start(env, stmt); | |
1638 | 3 | MP_Vector *const v = (MP_Vector*)vector_pop(&env->scope->effects); | |
1639 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (v) { |
1640 | ✗ | for (m_uint i = 0; i < v->len; i++) { | |
1641 | ✗ | struct ScopeEffect *eff = mp_vector_at(v, struct ScopeEffect, i); | |
1642 | ✗ | bool found = find_handler(stmt->handler, eff->sym); | |
1643 | ✗ | if (!found) env_add_effect(env, eff->sym, eff->pos); | |
1644 | } | ||
1645 | ✗ | free_mp_vector(env->gwion->mp, struct ScopeEffect, v); | |
1646 | } | ||
1647 | 3 | return ret; | |
1648 | } | ||
1649 | |||
1650 | 7 | ANN static m_bool _check_stmt_match(const Env env, const Stmt_Match stmt) { | |
1651 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | CHECK_OB(check_exp(env, stmt->cond)); |
1652 | 7 | MATCH_INI(env->scope) | |
1653 | 7 | const m_bool ret = case_loop(env, stmt); | |
1654 | 7 | MATCH_END(env->scope) | |
1655 | 7 | return ret; | |
1656 | } | ||
1657 | |||
1658 | 7 | ANN static inline m_bool handle_where(const Env env, const Stmt_Match stmt) { | |
1659 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
7 | if (stmt->where) CHECK_BB(check_stmt(env, stmt->where)); |
1660 | 7 | RET_NSPC(_check_stmt_match(env, stmt)) | |
1661 | } | ||
1662 | |||
1663 | 7 | ANN static m_bool check_stmt_match(const Env env, const Stmt_Match stmt) { | |
1664 | 7 | RET_NSPC(handle_where(env, stmt)) | |
1665 | } | ||
1666 | |||
1667 | #define check_stmt_while check_stmt_flow | ||
1668 | #define check_stmt_until check_stmt_flow | ||
1669 | |||
1670 | 8 | ANN static m_bool check_stmt_pp(const Env env, const Stmt_PP stmt) { | |
1671 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
|
8 | if (stmt->pp_type == ae_pp_include) env->name = stmt->data; |
1672 | // check for memoization | ||
1673 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
6 | else if (env->func && stmt->pp_type == ae_pp_pragma && |
1674 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | !strncmp(stmt->data, "memoize", strlen("memoize"))) |
1675 | 1 | env->func->memoize = strtol(stmt->data + 7, NULL, 10); | |
1676 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | else if(stmt->pp_type == ae_pp_locale) { |
1677 | 2 | const loc_t loc = stmt_self(stmt)->pos; | |
1678 | 2 | const Exp id = new_prim_id(env->gwion->mp, stmt->xid, loc); | |
1679 | 2 | const Exp arg = new_prim_id(env->gwion->mp, insert_symbol("_"), loc); | |
1680 | 2 | arg->next = stmt->exp; | |
1681 | 2 | const Exp call = new_exp_call(env->gwion->mp, id, arg, loc); | |
1682 | 2 | stmt->exp = call; | |
1683 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | CHECK_BB(traverse_exp(env, id)); |
1684 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | CHECK_OB(partial_type(env, &call->d.exp_call)); |
1685 | } | ||
1686 | 8 | return GW_OK; | |
1687 | } | ||
1688 | |||
1689 | ✗ | ANN static m_bool check_stmt_defer(const Env env, const Stmt_Defer stmt) { | |
1690 | ✗ | return check_stmt(env, stmt->stmt); | |
1691 | } | ||
1692 | |||
1693 | #define check_stmt_retry dummy_func | ||
1694 | #define check_stmt_spread dummy_func | ||
1695 | DECL_STMT_FUNC(check, m_bool, Env) | ||
1696 | |||
1697 | 2201 | ANN m_bool check_stmt(const Env env, const Stmt stmt) { | |
1698 | 2201 | return check_stmt_func[stmt->stmt_type](env, &stmt->d); | |
1699 | } | ||
1700 | |||
1701 | 2445 | ANN m_bool check_stmt_list(const Env env, Stmt_List l) { | |
1702 |
2/2✓ Branch 0 taken 2093 times.
✓ Branch 1 taken 2298 times.
|
4391 | for(m_uint i = 0; i < l->len; i++) { |
1703 | 2093 | const Stmt s = mp_vector_at(l, struct Stmt_, i); | |
1704 |
2/2✓ Branch 1 taken 147 times.
✓ Branch 2 taken 1946 times.
|
2093 | CHECK_BB(check_stmt(env, s)); |
1705 | } | ||
1706 | 2298 | return GW_OK; | |
1707 | } | ||
1708 | |||
1709 | 5148 | ANN static m_bool check_signature_match(const Env env, const Func_Def fdef, | |
1710 | const Func parent) { | ||
1711 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5147 times.
|
5148 | if (GET_FLAG(parent->def->base, final)) |
1712 | 1 | ERR_B(fdef->base->td->pos, _("can't override final function '%s'\n"), | |
1713 | parent->name) | ||
1714 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5145 times.
|
5147 | if (GET_FLAG(parent->def->base, static) != GET_FLAG(fdef->base, static)) { |
1715 | 2 | const m_str c_name = fdef->base->func->value_ref->from->owner_class->name; | |
1716 | 2 | const m_str p_name = parent->value_ref->from->owner_class->name; | |
1717 | 2 | const m_str f_name = s_name(fdef->base->xid); | |
1718 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | ERR_B(fdef->base->td->pos, |
1719 | _("function '%s.%s' ressembles '%s.%s' but cannot override...\n" | ||
1720 | " ...(reason: '%s.%s' is declared as 'static')"), | ||
1721 | c_name, f_name, p_name, c_name, | ||
1722 | GET_FLAG(fdef->base, static) ? c_name : p_name, f_name) | ||
1723 | } | ||
1724 |
3/4✓ Branch 0 taken 5135 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 5135 times.
✗ Branch 3 not taken.
|
5145 | if(fdef->base->tmpl || isa(fdef->base->ret_type, parent->def->base->ret_type) > 0) |
1725 | 5145 | return GW_OK; | |
1726 | ✗ | gwerr_basic_from("invalid overriding", NULL, NULL, fdef->base->func->value_ref->from, 0); | |
1727 | ✗ | gwerr_secondary_from("does not match", parent->value_ref->from); | |
1728 | ✗ | env_set_error(env, true); | |
1729 | ✗ | return GW_ERROR; | |
1730 | } | ||
1731 | |||
1732 | 5148 | ANN static m_bool parent_match_actual(const Env env, | |
1733 | const restrict Func_Def fdef, | ||
1734 | const restrict Func func) { | ||
1735 | 5148 | Func parent_func = func; | |
1736 | do { | ||
1737 |
3/4✓ Branch 0 taken 5163 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 5148 times.
✓ Branch 4 taken 15 times.
|
5163 | if (parent_func->def->base && compat_func(fdef, parent_func->def) > 0) { |
1738 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5145 times.
|
5148 | CHECK_BB(check_signature_match(env, fdef, parent_func)); |
1739 |
2/2✓ Branch 0 taken 5135 times.
✓ Branch 1 taken 10 times.
|
5145 | if (!fdef->base->tmpl) { |
1740 | 5135 | fdef->vt_index = parent_func->def->vt_index; | |
1741 | 5135 | vector_set(&env->curr->vtable, fdef->vt_index, | |
1742 | 5135 | (vtype)fdef->base->func); | |
1743 | } | ||
1744 | 5145 | return GW_OK; | |
1745 | } | ||
1746 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | } while ((parent_func = parent_func->next)); |
1747 | ✗ | return 0; | |
1748 | } | ||
1749 | |||
1750 | 72020 | ANN static m_bool check_parent_match(const Env env, const Func_Def fdef) { | |
1751 | 72020 | const Func func = fdef->base->func; | |
1752 | 72020 | const Type parent = env->class_def->info->parent; | |
1753 |
2/2✓ Branch 0 taken 9415 times.
✓ Branch 1 taken 62605 times.
|
72020 | if (!env->curr->vtable.ptr) vector_init(&env->curr->vtable); |
1754 |
1/2✓ Branch 0 taken 72020 times.
✗ Branch 1 not taken.
|
72020 | if (parent) { |
1755 | 72020 | const Value v = find_value(parent, fdef->base->xid); | |
1756 |
4/4✓ Branch 0 taken 5151 times.
✓ Branch 1 taken 66869 times.
✓ Branch 3 taken 5148 times.
✓ Branch 4 taken 3 times.
|
72020 | if (v && is_func(env->gwion, v->type)) { |
1757 | 5148 | const m_bool match = parent_match_actual(env, fdef, v->d.func_ref); | |
1758 |
1/2✓ Branch 0 taken 5148 times.
✗ Branch 1 not taken.
|
5148 | if (match) return match; |
1759 | } | ||
1760 | } | ||
1761 | 66872 | func->def->vt_index = vector_size(&env->curr->vtable); | |
1762 | 66872 | vector_add(&env->curr->vtable, (vtype)func); | |
1763 | 66872 | return GW_OK; | |
1764 | } | ||
1765 | |||
1766 | 77 | ANN static inline Func get_overload(const Env env, const Func_Def fdef, | |
1767 | const m_uint i) { | ||
1768 | const Symbol sym = | ||
1769 | 77 | func_symbol(env, env->curr->name, s_name(fdef->base->xid), NULL, i); | |
1770 | 77 | return nspc_lookup_func1(env->curr, sym); | |
1771 | } | ||
1772 | |||
1773 | 20 | ANN static m_bool check_func_overload(const Env env, const Func_Def fdef) { | |
1774 | 20 | const Value v = fdef->base->func->value_ref; | |
1775 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 19 times.
|
63 | for (m_uint i = 0; i <= v->from->offset; ++i) { |
1776 | 44 | const Func f1 = get_overload(env, fdef, i); | |
1777 |
3/4✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 43 times.
|
76 | for (m_uint j = i + 1; f1 && j <= v->from->offset; ++j) { |
1778 | 33 | const Func f2 = get_overload(env, fdef, j); | |
1779 |
4/6✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
34 | if (f2 && compat_func(f1->def, f2->def) > 0 && |
1780 | 1 | fbflag(f1->def->base, fbflag_op) == | |
1781 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | fbflag(f2->def->base, fbflag_op) && |
1782 | 1 | fbflag(f1->def->base, fbflag_unary) == | |
1783 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | fbflag(f2->def->base, fbflag_unary) && |
1784 | 1 | fbflag(f1->def->base, fbflag_postfix) == | |
1785 | 1 | fbflag(f2->def->base, fbflag_postfix)) | |
1786 | 1 | ERR_B(f2->def->base->pos, | |
1787 | _("global function '%s' already defined" | ||
1788 | " for those arguments"), | ||
1789 | s_name(fdef->base->xid)) | ||
1790 | } | ||
1791 | } | ||
1792 | 19 | return GW_OK; | |
1793 | } | ||
1794 | |||
1795 | 1 | ANN static bool check_effect_overload(const Vector base, const Func override) { | |
1796 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!base->ptr) return true; |
1797 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!override->def->base->effects.ptr) return false; |
1798 | ✗ | const Vector v = &override->def->base->effects; | |
1799 | ✗ | for (m_uint i = 0; i < vector_size(v); i++) { | |
1800 | ✗ | if (vector_find(base, vector_at(v, i)) == -1) return false; | |
1801 | } | ||
1802 | ✗ | return true; | |
1803 | } | ||
1804 | |||
1805 | 66519 | ANN static m_bool check_func_def_override(const Env env, const Func_Def fdef, | |
1806 | Value *ov) { | ||
1807 | 66519 | const Func func = fdef->base->func; | |
1808 |
3/4✓ Branch 0 taken 61893 times.
✓ Branch 1 taken 4626 times.
✓ Branch 2 taken 61893 times.
✗ Branch 3 not taken.
|
66519 | if (env->class_def && env->class_def->info->parent) { |
1809 | const Value override = | ||
1810 | 61893 | find_value(env->class_def->info->parent, fdef->base->xid); | |
1811 |
3/4✓ Branch 0 taken 5144 times.
✓ Branch 1 taken 56749 times.
✓ Branch 2 taken 5144 times.
✗ Branch 3 not taken.
|
61893 | if (override && override->from->owner_class && |
1812 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5141 times.
|
5144 | !is_func(env->gwion, override->type)) |
1813 | 3 | ERR_B(fdef->base->pos, | |
1814 | _("function name '%s' conflicts with previously defined value...\n" | ||
1815 | " from super class '%s'..."), | ||
1816 | s_name(fdef->base->xid), override->from->owner_class->name) | ||
1817 | 61890 | *ov = override; | |
1818 | } | ||
1819 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 66496 times.
|
66516 | if (func->value_ref->from->offset && |
1820 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | (!fdef->base->tmpl /*|| !fdef->base->tmpl->base*/)) |
1821 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 19 times.
|
20 | CHECK_BB(check_func_overload(env, fdef)); |
1822 | 66515 | return GW_OK; | |
1823 | } | ||
1824 | |||
1825 | 1817 | ANN static m_bool check_fdef_effects(const Env env, const Func_Def fdef) { | |
1826 | 1817 | MP_Vector *v = (MP_Vector*)vector_back(&env->scope->effects); | |
1827 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1814 times.
|
1817 | if (v) { |
1828 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (fdef->base->xid == insert_symbol("@dtor")) |
1829 | ✗ | ERR_B(fdef->base->pos, _("can't use effects in destructors")); | |
1830 | 3 | const Vector base = &fdef->base->effects; | |
1831 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!base->ptr) vector_init(base); |
1832 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (uint32_t i = 0; i < v->len; i++) { |
1833 | 3 | struct ScopeEffect *eff = mp_vector_at(v, struct ScopeEffect, i); | |
1834 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if(vector_find(base, (m_uint)eff->sym) == -1) |
1835 | 3 | vector_add(base, (m_uint)eff->sym); | |
1836 | } | ||
1837 | 3 | free_mp_vector(env->gwion->mp, struct ScopeEffect, v); | |
1838 | } | ||
1839 | 1817 | return GW_OK; | |
1840 | } | ||
1841 | |||
1842 | 66515 | ANN m_bool check_fdef(const Env env, const Func_Def fdef) { | |
1843 |
4/4✓ Branch 0 taken 29444 times.
✓ Branch 1 taken 37071 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 29443 times.
|
66515 | if (fdef->base->args) CHECK_BB(check_func_args(env, fdef->base->args)); |
1844 |
2/2✓ Branch 0 taken 61946 times.
✓ Branch 1 taken 4568 times.
|
66514 | if(fdef->builtin) return GW_OK; |
1845 |
3/4✓ Branch 0 taken 1817 times.
✓ Branch 1 taken 2751 times.
✓ Branch 2 taken 1817 times.
✗ Branch 3 not taken.
|
4568 | if (fdef->d.code && fdef->d.code) { |
1846 | 1817 | const bool ctor = is_ctor(fdef); | |
1847 |
2/2✓ Branch 0 taken 273 times.
✓ Branch 1 taken 1544 times.
|
1817 | if(!ctor) { |
1848 | 273 | env->scope->depth++; | |
1849 | 273 | nspc_push_value(env->gwion->mp, env->curr); | |
1850 | } | ||
1851 | 1817 | const m_bool ret = check_stmt_list(env, fdef->d.code); | |
1852 |
2/2✓ Branch 0 taken 273 times.
✓ Branch 1 taken 1544 times.
|
1817 | if(!ctor) { |
1853 | 273 | nspc_pop_value(env->gwion->mp, env->curr); | |
1854 | 273 | env->scope->depth--; | |
1855 | } | ||
1856 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1817 times.
|
1817 | CHECK_BB(check_fdef_effects(env, fdef)); |
1857 | 1817 | return ret; | |
1858 | } | ||
1859 | 2751 | return GW_OK; | |
1860 | } | ||
1861 | |||
1862 | 1362 | ANN static m_bool check_ctor(const Env env, const Func func) { | |
1863 |
4/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1353 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 2 times.
|
1362 | if(!func->def->builtin && !GET_FLAG(func, const)) { |
1864 | 7 | const Type_Decl *td = env->class_def->info->cdef->base.ext; | |
1865 | ✗ | const m_uint depth = !td || !td->array | |
1866 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | ? 1 : td->array->exp->d.prim.d.num; |
1867 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if(depth) { // check if size is 0 |
1868 | 7 | const Type parent = env->class_def->info->parent; | |
1869 | 7 | const Value v = nspc_lookup_value0(parent->nspc, insert_symbol("new")); | |
1870 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
7 | if(v && !GET_FLAG(v->d.func_ref->def->base, abstract)) |
1871 | ✗ | ERR_B(func->def->base->pos, "missing call to parent constructor"); | |
1872 | } | ||
1873 | } | ||
1874 | |||
1875 | 1362 | return GW_OK; | |
1876 | } | ||
1877 | |||
1878 | 76675 | ANN m_bool _check_func_def(const Env env, const Func_Def f) { | |
1879 |
4/4✓ Branch 1 taken 10153 times.
✓ Branch 2 taken 66522 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 10152 times.
|
76675 | if (tmpl_base(f->base->tmpl) && fbflag(f->base, fbflag_op)) return GW_OK; |
1880 | 76674 | const Func func = f->base->func; | |
1881 | 76674 | const Func_Def fdef = func->def; | |
1882 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 76674 times.
|
76674 | if(fflag(func, fflag_valid))return GW_OK; |
1883 | 76674 | set_fflag(func, fflag_valid); | |
1884 | assert(func == fdef->base->func); | ||
1885 |
4/4✓ Branch 0 taken 72025 times.
✓ Branch 1 taken 4649 times.
✓ Branch 3 taken 72020 times.
✓ Branch 4 taken 5 times.
|
76674 | if (env->class_def && !fbflag(func->def->base, fbflag_lambda)) |
1886 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 72017 times.
|
72020 | CHECK_BB(check_parent_match(env, fdef)); |
1887 |
2/2✓ Branch 1 taken 10152 times.
✓ Branch 2 taken 66519 times.
|
76671 | if (tmpl_base(fdef->base->tmpl)) return GW_OK; |
1888 | 66519 | Value override = NULL; | |
1889 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 66515 times.
|
66519 | CHECK_BB(check_func_def_override(env, fdef, &override)); |
1890 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66513 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66515 times.
|
66515 | DECL_BB(const m_int, scope, = GET_FLAG(fdef->base, global) |
1891 | ? env_push_global(env) | ||
1892 | : env->scope->depth); | ||
1893 | 66515 | const Func former = env->func; | |
1894 | 66515 | env->func = func; | |
1895 | 66515 | nspc_push_value(env->gwion->mp, env->curr); | |
1896 | 66515 | struct Op_Import opi = {}; | |
1897 |
2/2✓ Branch 1 taken 18 times.
✓ Branch 2 taken 66497 times.
|
66515 | if (fbflag(fdef->base, fbflag_op)) { |
1898 | 18 | func_operator(f, &opi); | |
1899 | 18 | operator_suspend(env->curr, &opi); | |
1900 | } | ||
1901 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66515 times.
|
66515 | if(fdef->captures) { |
1902 | ✗ | uint32_t offset = fdef->stack_depth; | |
1903 | ✗ | for(uint32_t i = 0; i < fdef->captures->len; i++) { | |
1904 | ✗ | Capture *cap = mp_vector_at(fdef->captures, Capture, i); | |
1905 | ✗ | valid_value(env, cap->xid, cap->temp); | |
1906 | ✗ | cap->temp->from->offset = offset; | |
1907 | ✗ | offset += cap->temp->type->size; | |
1908 | } | ||
1909 | } | ||
1910 | 66515 | vector_add(&env->scope->effects, 0); | |
1911 | 66515 | const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)check_fdef); | |
1912 | 66515 | vector_pop(&env->scope->effects); | |
1913 |
2/2✓ Branch 1 taken 18 times.
✓ Branch 2 taken 66497 times.
|
66515 | if (fbflag(fdef->base, fbflag_op)) operator_resume(&opi); |
1914 | 66515 | nspc_pop_value(env->gwion->mp, env->curr); | |
1915 | 66515 | env->func = former; | |
1916 |
2/2✓ Branch 0 taken 66485 times.
✓ Branch 1 taken 30 times.
|
66515 | if (ret > 0) { |
1917 |
4/4✓ Branch 0 taken 61869 times.
✓ Branch 1 taken 4616 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 61867 times.
|
66485 | if (env->class_def && fdef->base->effects.ptr && |
1918 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | (override && |
1919 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | !check_effect_overload(&fdef->base->effects, override->d.func_ref))) |
1920 | 1 | ERR_B(fdef->base->pos, _("too much effects in override."), | |
1921 | s_name(fdef->base->xid)) | ||
1922 |
4/4✓ Branch 0 taken 1370 times.
✓ Branch 1 taken 65114 times.
✓ Branch 3 taken 1362 times.
✓ Branch 4 taken 8 times.
|
66484 | if(is_new(f) && !tflag(env->class_def, tflag_struct)) |
1923 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1362 times.
|
1362 | CHECK_BB(check_ctor(env, func)); |
1924 | } | ||
1925 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66512 times.
|
66514 | if (GET_FLAG(fdef->base, global)) env_pop(env, scope); |
1926 |
2/2✓ Branch 0 taken 61889 times.
✓ Branch 1 taken 4625 times.
|
66514 | if (func->value_ref->from->owner_class) |
1927 | 61889 | func->inline_mult += 3; | |
1928 | else | ||
1929 | 4625 | func->inline_mult += 4; | |
1930 | 66514 | return ret; | |
1931 | } | ||
1932 | |||
1933 | 76675 | ANN m_bool check_func_def(const Env env, const Func_Def fdef) { | |
1934 | 76675 | const uint16_t depth = env->scope->depth; | |
1935 | 76675 | env->scope->depth = 0; | |
1936 | 76675 | const m_bool ret = _check_func_def(env, fdef); | |
1937 | 76675 | env->scope->depth = depth; | |
1938 | 76675 | return ret; | |
1939 | } | ||
1940 | |||
1941 | ANN bool check_trait_requests(const Env env, const Type t, const ID_List list, const ValueFrom *from); | ||
1942 | ✗ | ANN static m_bool check_extend_def(const Env env, const Extend_Def xdef) { | |
1943 | ✗ | const Type t = xdef->type; | |
1944 | ✗ | ValueFrom from = { .filename = env->name, .loc=xdef->td->pos, .ctx=env->context, | |
1945 | ✗ | .owner = env->curr, .owner_class = env->class_def | |
1946 | }; | ||
1947 | ✗ | const bool ret = check_trait_requests(env, t, xdef->traits, &from); | |
1948 | ✗ | if(ret) { | |
1949 | ✗ | if(!t->info->traits) { | |
1950 | ✗ | t->info->traits = new_mp_vector(env->gwion->mp, Symbol, xdef->traits->len); | |
1951 | ✗ | for(uint32_t i = 0; i < xdef->traits->len; i++) { | |
1952 | ✗ | const Symbol sym = *mp_vector_at(t->info->traits, Symbol, i); | |
1953 | ✗ | mp_vector_set(t->info->traits, Symbol, i, sym); | |
1954 | } | ||
1955 | } else { | ||
1956 | ✗ | for(uint32_t i = 0; i < xdef->traits->len; i++) { | |
1957 | ✗ | const Symbol sym = *mp_vector_at(t->info->traits, Symbol, i); | |
1958 | ✗ | mp_vector_add(env->gwion->mp, &t->info->traits, Symbol, sym); | |
1959 | } | ||
1960 | } | ||
1961 | ✗ | return GW_OK; | |
1962 | } | ||
1963 | ✗ | return GW_ERROR; | |
1964 | } | ||
1965 | |||
1966 | ✗ | ANN static m_bool _check_trait_def(const Env env, const Trait_Def pdef) { | |
1967 | ✗ | const Trait trait = nspc_lookup_trait1(env->curr, pdef->xid); | |
1968 | ✗ | Ast ast = pdef->body; | |
1969 | ✗ | if(!ast) return GW_OK; | |
1970 | ✗ | for(m_uint i = 0; i < ast->len; i++) { | |
1971 | ✗ | Section * section = mp_vector_at(ast, Section, i); | |
1972 | // we should traverse the funcs here also | ||
1973 | ✗ | if (section->section_type == ae_section_stmt) { | |
1974 | ✗ | Stmt_List l = section->d.stmt_list; | |
1975 | ✗ | for(m_uint i = 0; i < l->len; i++) { | |
1976 | ✗ | const Stmt stmt = mp_vector_at(l, struct Stmt_, i); | |
1977 | ✗ | if (stmt->stmt_type == ae_stmt_exp) { | |
1978 | ✗ | CHECK_BB(traverse_exp(env, stmt->d.stmt_exp.val)); | |
1979 | ✗ | Var_Decl vd = stmt->d.stmt_exp.val->d.exp_decl.vd; | |
1980 | ✗ | const Value value = vd.value; | |
1981 | ✗ | valuefrom(env, value->from); | |
1982 | ✗ | if (!trait->var) | |
1983 | ✗ | trait->var = new_mp_vector(env->gwion->mp, Value, 0); | |
1984 | ✗ | mp_vector_add(env->gwion->mp, &trait->var, Value, value); | |
1985 | } | ||
1986 | } | ||
1987 | } | ||
1988 | } | ||
1989 | ✗ | return GW_OK; | |
1990 | } | ||
1991 | |||
1992 | ✗ | ANN static m_bool check_trait_def(const Env env, const Trait_Def pdef) { | |
1993 | ✗ | RET_NSPC(_check_trait_def(env, pdef)); | |
1994 | } | ||
1995 | |||
1996 | 6808 | ANN m_bool check_fptr_def(const Env env, const Fptr_Def fptr) { | |
1997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6808 times.
|
6808 | if(GET_FLAG(fptr->cdef, global)) env_push_global(env); |
1998 | 6808 | const m_bool ret = check_class_def(env, fptr->cdef); | |
1999 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6808 times.
|
6808 | if(GET_FLAG(fptr->cdef, global)) env_pop(env, 0); |
2000 | 6808 | return ret; | |
2001 | } | ||
2002 | |||
2003 | #define check_prim_def dummy_func | ||
2004 | 29636 | HANDLE_SECTION_FUNC(check, m_bool, Env) | |
2005 | |||
2006 | 4151 | ANN static m_bool check_parent(const Env env, const Class_Def cdef) { | |
2007 | 4151 | const Type parent = cdef->base.type->info->parent; | |
2008 | 4151 | const Type_Decl *td = cdef->base.ext; | |
2009 |
3/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4146 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
4151 | if (td->array && td->array->exp) |
2010 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
|
5 | CHECK_BB(check_subscripts(env, td->array, 1)); |
2011 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4151 times.
|
4151 | CHECK_BB(ensure_traverse(env, parent)); |
2012 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4144 times.
|
4151 | if(GET_FLAG(parent, abstract)) |
2013 | 7 | SET_FLAG(cdef->base.type, abstract); | |
2014 | 4151 | return GW_OK; | |
2015 | } | ||
2016 | |||
2017 | 4151 | ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { | |
2018 | 4151 | const bool tmpl = !!cdef->base.tmpl; | |
2019 |
3/4✓ Branch 0 taken 1357 times.
✓ Branch 1 taken 2794 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1357 times.
|
4151 | if (tmpl) CHECK_BB(template_push_types(env, cdef->base.tmpl)); |
2020 | 4151 | const m_bool ret = check_parent(env, cdef); | |
2021 |
2/2✓ Branch 0 taken 1357 times.
✓ Branch 1 taken 2794 times.
|
4151 | if (tmpl) nspc_pop_type(env->gwion->mp, env->curr); |
2022 | 4151 | return ret; | |
2023 | } | ||
2024 | |||
2025 | 4298 | ANN m_bool check_abstract(const Env env, const Class_Def cdef) { | |
2026 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 4281 times.
|
4298 | if (!cdef->base.type->nspc->vtable.ptr) return GW_OK; |
2027 | 4281 | bool err = false; | |
2028 |
2/2✓ Branch 1 taken 27596 times.
✓ Branch 2 taken 4281 times.
|
31877 | for (m_uint i = 0; i < vector_size(&cdef->base.type->nspc->vtable); ++i) { |
2029 | 27596 | const Func f = (Func)vector_at(&cdef->base.type->nspc->vtable, i); | |
2030 |
4/6✓ Branch 0 taken 27596 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27596 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 27593 times.
|
27596 | if (f && f->def->base && GET_FLAG(f->def->base, abstract)) { |
2031 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if (!err) { |
2032 | 2 | err = true; | |
2033 | 2 | gwerr_basic(_("missing function definition"), | |
2034 | _("must be declared 'abstract'"), | ||
2035 | _("provide an implementation for the following:"), | ||
2036 | 2 | env->name, cdef->pos, 0); | |
2037 | } | ||
2038 | 3 | ValueFrom *from = f->value_ref->from; | |
2039 | 3 | gwerr_secondary_from("implementation missing", from); | |
2040 | 3 | env_set_error(env, true); | |
2041 | } | ||
2042 | } | ||
2043 |
2/2✓ Branch 0 taken 4279 times.
✓ Branch 1 taken 2 times.
|
4281 | return !err ? GW_OK : GW_ERROR; |
2044 | } | ||
2045 | /* | ||
2046 | ANN static inline void ctor_effects(const Env env) { | ||
2047 | const Vector v = &env->scope->effects; | ||
2048 | MP_Vector *const w = (MP_Vector*)vector_back(v); | ||
2049 | if (!w) return; | ||
2050 | vector_init(&env->class_def->effects); | ||
2051 | for (uint32_t j = 0; j < w->len; j++) { | ||
2052 | struct ScopeEffect *eff = mp_vector_at(w, struct ScopeEffect, j); | ||
2053 | vector_add(&env->class_def->effects, (m_uint)eff->sym); | ||
2054 | } | ||
2055 | free_mp_vector(env->gwion->mp, struct ScopeEffect, w); | ||
2056 | vector_pop(v); | ||
2057 | } | ||
2058 | */ | ||
2059 | 28785 | ANN static m_bool check_body(const Env env, Section *const section) { | |
2060 | 28785 | const m_bool ret = check_section(env, section); | |
2061 | // ctor_effects(env); | ||
2062 | 28785 | return ret; | |
2063 | } | ||
2064 | |||
2065 | 4241 | ANN static bool class_def_has_body(Ast ast) { | |
2066 | 4241 | const Section *section = mp_vector_at(ast, Section, 0); | |
2067 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4241 times.
|
4241 | if(section->section_type != ae_section_func) return false; |
2068 | 4241 | Func_Def f = section->d.func_def; | |
2069 |
2/2✓ Branch 0 taken 2748 times.
✓ Branch 1 taken 1493 times.
|
4241 | if(strcmp(s_name(f->base->xid), "@ctor"))return false; |
2070 | 1493 | Stmt_List l = f->d.code; | |
2071 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 1418 times.
|
1538 | for(m_uint i = 0; i < l->len; i++) { |
2072 | 120 | const Stmt stmt = mp_vector_at(l, struct Stmt_, i); | |
2073 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
|
120 | if (stmt->stmt_type == ae_stmt_pp) continue; |
2074 |
2/2✓ Branch 0 taken 111 times.
✓ Branch 1 taken 9 times.
|
120 | if (stmt->stmt_type == ae_stmt_exp) { |
2075 | 111 | const Exp exp = stmt->d.stmt_exp.val; | |
2076 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 108 times.
|
113 | if (!exp) continue; |
2077 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 63 times.
|
129 | if (exp->exp_type != ae_exp_decl) return true; |
2078 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 61 times.
|
63 | if (GET_FLAG(exp->d.exp_decl.td, late)) continue; |
2079 | 61 | Var_Decl vd = exp->d.exp_decl.vd; | |
2080 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | if (GET_FLAG(vd.value, late)) continue; |
2081 |
2/2✓ Branch 1 taken 21 times.
✓ Branch 2 taken 40 times.
|
61 | if (tflag(vd.value->type, tflag_compound)) |
2082 | 21 | return true; | |
2083 | 9 | } else return true; | |
2084 | } | ||
2085 | 1418 | return false; | |
2086 | } | ||
2087 | |||
2088 | 332 | ANN static inline bool type_is_recurs(const Type t, const Type tgt) { | |
2089 |
4/8✓ Branch 0 taken 331 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 331 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 331 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
332 | return isa(tgt, t) > 0 || isa(t, tgt) > 0 || (tgt->info->tuple && vector_find(&tgt->info->tuple->contains, (m_uint)t) > -1); |
2090 | } | ||
2091 | |||
2092 | ANN static m_bool recursive_type_base(const Env env, const Type t); | ||
2093 | ANN static bool recursive_type(const Env env, const Type t, const Type tgt); | ||
2094 | 332 | ANN static bool recursive_value(const Env env, const Type t, const Value v) { | |
2095 | 332 | const Type tgt = array_base(v->type); | |
2096 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 331 times.
|
332 | if(type_is_recurs(t, tgt)) { |
2097 | 1 | env_err(env, v->from->loc, _("recursive type")); | |
2098 | 1 | env_set_error(env, false); | |
2099 | 1 | gwerr_secondary("in class", t->name, t->info->cdef->base.pos); | |
2100 | |||
2101 | 2 | const Type first = tgt->info->value->from->loc.first.line < t->info->value->from->loc.first.line ? | |
2102 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | v->type : t; |
2103 | 2 | const Type second = tgt->info->value->from->loc.first.line > t->info->value->from->loc.first.line ? | |
2104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | v->type : t; |
2105 | |||
2106 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(first != second) { |
2107 | ✗ | const Map m1 = &first->info->value->from->owner->info->type->map; | |
2108 | ✗ | map_remove(m1, (m_uint)insert_symbol(first->name)); | |
2109 | ✗ | const Map m2 = &second->info->value->from->owner->info->type->map; | |
2110 | ✗ | map_remove(m2, (m_uint)insert_symbol(second->name)); | |
2111 | ✗ | if(first->ref > 2) | |
2112 | ✗ | type_remref(first, env->gwion); | |
2113 | ✗ | if(second->ref > 2) | |
2114 | ✗ | type_remref(second, env->gwion); | |
2115 | ✗ | if(v->from->owner_class->ref > 2) | |
2116 | ✗ | type_remref(v->from->owner_class, env->gwion); | |
2117 | ✗ | if(t->ref > 2) | |
2118 | ✗ | type_remref(t, env->gwion); | |
2119 | } | ||
2120 | 1 | set_tflag(t, tflag_infer); | |
2121 | 1 | set_tflag(tgt, tflag_infer); | |
2122 | 1 | unset_tflag(t, tflag_check); | |
2123 | 1 | unset_tflag(tgt, tflag_check); | |
2124 | 1 | return true; | |
2125 | } | ||
2126 | |||
2127 |
2/12✓ Branch 0 taken 331 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 331 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
331 | if(t != tgt && v->type->nspc && (!GET_FLAG(v, late) || vflag(v, vflag_assigned)) && strncmp(tgt->name, "Option:[", 8) && |
2128 | ✗ | tflag(tgt, tflag_compound)) | |
2129 | ✗ | return recursive_type(env, t, tgt); | |
2130 | |||
2131 | 331 | return false; | |
2132 | } | ||
2133 | |||
2134 | 34 | ANN static bool recursive_type(const Env env, const Type t, const Type tgt) { | |
2135 | Value v; | ||
2136 | 34 | struct scope_iter inner = {tgt->nspc->info->value, 0, 0}; | |
2137 | 34 | bool error = false; | |
2138 |
2/2✓ Branch 1 taken 332 times.
✓ Branch 2 taken 34 times.
|
366 | while (scope_iter(&inner, &v) > 0) { |
2139 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 332 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 332 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 331 times.
|
332 | if((!GET_FLAG(v, late) || vflag(v, vflag_assigned)) && v->type != tgt && recursive_value(env, t, v)) { |
2140 | 1 | error = true; | |
2141 | } | ||
2142 | } | ||
2143 | 34 | return error; | |
2144 | } | ||
2145 | |||
2146 | 4298 | ANN static m_bool recursive_type_base(const Env env, const Type t) { | |
2147 | Value value; | ||
2148 | 4298 | bool error = false; | |
2149 | 4298 | struct scope_iter iter = {t->nspc->info->value, 0, 0}; | |
2150 |
2/2✓ Branch 1 taken 50826 times.
✓ Branch 2 taken 4298 times.
|
55124 | while (scope_iter(&iter, &value) > 0) { |
2151 |
2/2✓ Branch 1 taken 50787 times.
✓ Branch 2 taken 39 times.
|
50826 | if (!tflag(value->type, tflag_compound)) continue; |
2152 |
4/6✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 35 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
|
39 | if (value->type->nspc && (!GET_FLAG(value, late) || vflag(value, vflag_assigned))) { |
2153 |
4/4✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 33 times.
|
35 | if(value->type == t || recursive_type(env, t, value->type)) { |
2154 | 2 | env_err(env, value->from->loc, _("recursive type")); | |
2155 | 2 | gw_err("use {+G}late{0} on one (or more) of the variables?\n"); | |
2156 | 2 | error = true; | |
2157 | } | ||
2158 | } | ||
2159 | } | ||
2160 | 4298 | return error; | |
2161 | } | ||
2162 | |||
2163 | ANN bool check_trait_requests(const Env env, const Type t, const ID_List list, const ValueFrom *from); | ||
2164 | 4330 | ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) { | |
2165 | 4330 | const Type t = cdef->base.type; | |
2166 |
3/4✓ Branch 0 taken 4151 times.
✓ Branch 1 taken 179 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4151 times.
|
4330 | if (cdef->base.ext) CHECK_BB(cdef_parent(env, cdef)); |
2167 |
2/2✓ Branch 1 taken 4304 times.
✓ Branch 2 taken 26 times.
|
4330 | if (!tflag(t, tflag_struct)) inherit(t); |
2168 |
2/2✓ Branch 0 taken 4297 times.
✓ Branch 1 taken 33 times.
|
4330 | if (cdef->body) { |
2169 |
2/2✓ Branch 1 taken 30 times.
✓ Branch 2 taken 4267 times.
|
4297 | CHECK_BB(env_body(env, cdef, check_body)); |
2170 |
4/4✓ Branch 1 taken 4241 times.
✓ Branch 2 taken 26 times.
✓ Branch 4 taken 75 times.
✓ Branch 5 taken 4166 times.
|
4267 | if (cflag(cdef, cflag_struct) || class_def_has_body(cdef->body)) |
2171 | // if (class_def_has_body(cdef->body)) | ||
2172 | 101 | set_tflag(t, tflag_ctor); | |
2173 | } | ||
2174 |
4/4✓ Branch 0 taken 4298 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4296 times.
|
4300 | if (!GET_FLAG(cdef, abstract)) CHECK_BB(check_abstract(env, cdef)); |
2175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4298 times.
|
4298 | if (cdef->traits) { |
2176 | ✗ | ID_List list = cdef->traits; | |
2177 | ✗ | if (!check_trait_requests(env, t, list, t->info->value->from)) { | |
2178 | ✗ | env->class_def = t; | |
2179 | ✗ | env_error_footer(env); | |
2180 | ✗ | env_set_error(env, true); | |
2181 | ✗ | return GW_ERROR; | |
2182 | } | ||
2183 | } | ||
2184 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4298 times.
|
4298 | CHECK_BB(recursive_type_base(env, t)); |
2185 | 4298 | nspc_allocdata(env->gwion->mp, t->nspc); | |
2186 | 4298 | return GW_OK; | |
2187 | } | ||
2188 | |||
2189 | 8401 | ANN m_bool check_class_def(const Env env, const Class_Def cdef) { | |
2190 |
2/2✓ Branch 1 taken 4071 times.
✓ Branch 2 taken 4330 times.
|
8401 | if (tmpl_base(cdef->base.tmpl)) return GW_OK; |
2191 | 4330 | const Type t = cdef->base.type; | |
2192 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4330 times.
|
4330 | if (tflag(t, tflag_check)) return GW_OK; |
2193 | 4330 | set_tflag(t, tflag_check); | |
2194 | 4330 | return _check_class_def(env, t->info->cdef); | |
2195 | } | ||
2196 | |||
2197 | 350 | ANN static inline void check_unhandled(const Env env) { | |
2198 | 350 | const Vector v = &env->scope->effects; | |
2199 | 350 | MP_Vector *const w = (MP_Vector*)vector_back(v); | |
2200 |
2/2✓ Branch 0 taken 349 times.
✓ Branch 1 taken 1 times.
|
350 | if(!w) return; |
2201 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | for (m_uint j = 0; j < w->len; j++) { |
2202 | 1 | struct ScopeEffect *eff = mp_vector_at(w, struct ScopeEffect, j); | |
2203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(s_name(eff->sym)[0] == '!') |
2204 | ✗ | continue; | |
2205 | 1 | gwerr_secondary("Unhandled effect", env->name, eff->pos); | |
2206 | 1 | env_set_error(env, false); | |
2207 | } | ||
2208 | 1 | free_mp_vector(env->gwion->mp, struct ScopeEffect, w); | |
2209 | 1 | vector_pop(v); | |
2210 | } | ||
2211 | |||
2212 | ✗ | ANN static void check_extend(const Env env, Ast ast) { | |
2213 | ✗ | for(m_uint i = 0; i < ast->len; i++) { | |
2214 | ✗ | Section * section = mp_vector_at(ast, Section, i); | |
2215 | ✗ | (void)check_section(env, section); | |
2216 | ✗ | mp_vector_add(env->gwion->mp, &env->context->tree, Section, *section); | |
2217 | } | ||
2218 | ✗ | free_mp_vector(env->gwion->mp, Section, env->context->extend); | |
2219 | ✗ | env->context->extend = NULL; | |
2220 | } | ||
2221 | |||
2222 | 508 | ANN m_bool check_ast(const Env env, Ast *ast) { | |
2223 | 508 | Ast a = *ast; | |
2224 |
2/2✓ Branch 0 taken 851 times.
✓ Branch 1 taken 350 times.
|
1201 | for(m_uint i = 0; i < a->len; i++) { |
2225 | 851 | Section * section = mp_vector_at(a, Section, i); | |
2226 |
2/2✓ Branch 1 taken 158 times.
✓ Branch 2 taken 693 times.
|
851 | CHECK_BB(check_section(env, section)); |
2227 | } | ||
2228 |
1/2✓ Branch 1 taken 350 times.
✗ Branch 2 not taken.
|
350 | if(vector_size(&env->scope->effects)) check_unhandled(env); |
2229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 350 times.
|
350 | if(env->context->extend) check_extend(env, env->context->extend); |
2230 | 350 | return GW_OK; | |
2231 | } | ||
2232 |