GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#include "gwion_util.h" |
||
2 |
#include "gwion_ast.h" |
||
3 |
#include "gwion_env.h" |
||
4 |
#include "vm.h" |
||
5 |
#include "template.h" |
||
6 |
#include "traverse.h" |
||
7 |
#include "parse.h" |
||
8 |
#include "operator.h" |
||
9 |
#include "object.h" |
||
10 |
#include "instr.h" |
||
11 |
#include "import.h" |
||
12 |
|||
13 |
ANN static m_bool scan2_stmt(const Env, const Stmt); |
||
14 |
ANN static m_bool scan2_stmt_list(const Env, Stmt_List); |
||
15 |
|||
16 |
31 |
ANN static inline m_bool ensure_scan2(const Env env, const Type t) { |
|
17 |
62 |
struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan2_cdef, |
|
18 |
31 |
.scope=env->scope->depth, .flag=ae_flag_scan2 }; |
|
19 |
31 |
return envset_run(&es, t); |
|
20 |
} |
||
21 |
|||
22 |
21483 |
ANN static m_bool scan2_decl(const Env env, const Exp_Decl* decl) { |
|
23 |
21483 |
const Type t = get_type(decl->type); |
|
24 |
✓✓✓✓ |
21483 |
if(t->e->def && !GET_FLAG(t, scan2)) |
25 |
✗✓ | 25 |
CHECK_BB(ensure_scan2(env, t)) |
26 |
21483 |
Var_Decl_List list = decl->list; |
|
27 |
do { |
||
28 |
21492 |
const Var_Decl var = list->self; |
|
29 |
✓✓ | 21492 |
const Exp array = var->array ? var->array->exp : NULL; |
30 |
✓✓ | 21492 |
if(array) |
31 |
✗✓ | 37 |
CHECK_BB(scan2_exp(env, array)) |
32 |
21492 |
nspc_add_value(env->curr, var->xid, var->value); |
|
33 |
✓✓ | 21492 |
} while((list = list->next)); |
34 |
21483 |
return GW_OK; |
|
35 |
} |
||
36 |
|||
37 |
21483 |
ANN m_bool scan2_exp_decl(const Env env, const Exp_Decl* decl) { |
|
38 |
21483 |
const m_bool global = GET_FLAG(decl->td, global); |
|
39 |
✓✓ | 21483 |
const m_uint scope = !global ? env->scope->depth : env_push_global(env); |
40 |
21483 |
const m_bool ret = scan2_decl(env, decl); |
|
41 |
✓✓ | 21483 |
if(global) |
42 |
12 |
env_pop(env, scope); |
|
43 |
21483 |
return ret; |
|
44 |
} |
||
45 |
|||
46 |
16600 |
ANN static m_bool scan2_args(const Func_Def f) { |
|
47 |
16600 |
Arg_List list = f->base->args; |
|
48 |
do { |
||
49 |
23811 |
const Value v = list->var_decl->value; |
|
50 |
23811 |
v->from->offset = f->stack_depth; |
|
51 |
23811 |
f->stack_depth += v->type->size; |
|
52 |
✓✓ | 23811 |
} while((list = list->next)); |
53 |
16600 |
return GW_OK; |
|
54 |
} |
||
55 |
|||
56 |
42444 |
ANN static Value scan2_func_assign(const Env env, const Func_Def d, |
|
57 |
const Func f, const Value v) { |
||
58 |
42444 |
valuefrom(env, v->from); |
|
59 |
42444 |
SET_FLAG(v, func | ae_flag_const); |
|
60 |
✓✓ | 42444 |
if(!env->class_def) |
61 |
196 |
SET_FLAG(v, global); |
|
62 |
else { |
||
63 |
✓✓ | 42248 |
if(GET_FLAG(f, member)) |
64 |
41507 |
SET_FLAG(v, member); |
|
65 |
741 |
else SET_FLAG(v, static); |
|
66 |
✓✓✗✓ |
42248 |
SET_ACCESS(d->base, v) |
67 |
} |
||
68 |
42444 |
d->base->func = v->d.func_ref = f; |
|
69 |
42444 |
return f->value_ref = v; |
|
70 |
} |
||
71 |
|||
72 |
|||
73 |
75 |
ANN m_bool scan2_fptr_def(const Env env NUSED, const Fptr_Def fptr) { |
|
74 |
✓✓ | 75 |
if(!tmpl_base(fptr->base->tmpl)) { |
75 |
60 |
const Func_Def def = fptr->type->e->d.func->def; |
|
76 |
✓✓ | 60 |
if(def->base->args) { |
77 |
26 |
RET_NSPC(scan2_args(def)) |
|
78 |
} |
||
79 |
} else |
||
80 |
15 |
SET_FLAG(fptr->type, func); |
|
81 |
49 |
return GW_OK; |
|
82 |
} |
||
83 |
|||
84 |
733 |
ANN m_bool scan2_type_def(const Env env, const Type_Def tdef) { |
|
85 |
✓✓ | 733 |
if(!tdef->type->e->def) return GW_OK; |
86 |
✓✗ | 8 |
return !is_fptr(env->gwion, tdef->type) ? scan2_class_def(env, tdef->type->e->def) : GW_OK; |
87 |
} |
||
88 |
|||
89 |
2132 |
ANN static inline Value prim_value(const Env env, const Symbol s) { |
|
90 |
2132 |
const Value value = nspc_lookup_value1(env->curr, s); |
|
91 |
✓✓ | 2132 |
if(env->class_def) |
92 |
✓✓ | 401 |
return value ?: find_value(env->class_def, s); |
93 |
1731 |
return value; |
|
94 |
} |
||
95 |
|||
96 |
12 |
ANN static m_bool scan2_range(const Env env, Range *range) { |
|
97 |
✓✓ | 12 |
if(range->start) |
98 |
✗✓ | 11 |
CHECK_BB(scan2_exp(env, range->start)) |
99 |
✓✓ | 12 |
if(range->end) |
100 |
✗✓ | 8 |
CHECK_BB(scan2_exp(env, range->end)) |
101 |
12 |
return GW_OK; |
|
102 |
} |
||
103 |
|||
104 |
4421 |
ANN static inline m_bool scan2_prim(const Env env, const Exp_Primary* prim) { |
|
105 |
✓✓✓✓ ✓✓ |
7757 |
if(prim->prim_type == ae_prim_hack || prim->prim_type == ae_prim_typeof || |
106 |
3336 |
prim->prim_type == ae_prim_interp) |
|
107 |
✗✓ | 1088 |
CHECK_BB(scan2_exp(env, prim->d.exp)) |
108 |
✓✓ | 3333 |
else if(prim->prim_type == ae_prim_id) { |
109 |
2132 |
const Value v = prim_value(env, prim->d.var); |
|
110 |
✓✓ | 2132 |
if(v) |
111 |
1508 |
SET_FLAG(v, used); |
|
112 |
✓✓✓✓ |
1201 |
} else if(prim->prim_type == ae_prim_array && prim->d.array->exp) |
113 |
22 |
return scan2_exp(env, prim->d.array->exp); |
|
114 |
✓✓ | 1179 |
else if(prim->prim_type == ae_prim_range) |
115 |
3 |
return scan2_range(env, prim->d.range); |
|
116 |
4396 |
return GW_OK; |
|
117 |
} |
||
118 |
|||
119 |
30 |
ANN static inline m_bool scan2_exp_array(const Env env, const Exp_Array* array) { |
|
120 |
✗✓ | 30 |
CHECK_BB(scan2_exp(env, array->base)) |
121 |
30 |
return scan2_exp(env, array->array->exp); |
|
122 |
} |
||
123 |
|||
124 |
9 |
ANN static inline m_bool scan2_exp_slice(const Env env, const Exp_Slice* exp) { |
|
125 |
✗✓ | 9 |
CHECK_BB(scan2_exp(env, exp->base)) |
126 |
9 |
return scan2_range(env, exp->range); |
|
127 |
} |
||
128 |
|||
129 |
1283 |
ANN static m_bool multi_decl(const Env env, const Exp e, const Symbol op) { |
|
130 |
✓✓ | 1283 |
if(e->exp_type == ae_exp_decl) { |
131 |
✓✓ | 158 |
if(e->d.exp_decl.list->next) |
132 |
1 |
ERR_B(e->pos, _("cant '%s' from/to a multi-variable declaration."), s_name(op)) |
|
133 |
157 |
SET_FLAG(e->d.exp_decl.list->self->value, used); |
|
134 |
} |
||
135 |
1282 |
return GW_OK; |
|
136 |
} |
||
137 |
|||
138 |
642 |
ANN static inline m_bool scan2_exp_binary(const Env env, const Exp_Binary* bin) { |
|
139 |
✗✓ | 642 |
CHECK_BB(scan2_exp(env, bin->lhs)) |
140 |
✗✓ | 642 |
CHECK_BB(scan2_exp(env, bin->rhs)) |
141 |
✓✓ | 642 |
CHECK_BB(multi_decl(env, bin->lhs, bin->op)) |
142 |
641 |
return multi_decl(env, bin->rhs, bin->op); |
|
143 |
} |
||
144 |
|||
145 |
40 |
ANN static inline m_bool scan2_exp_cast(const Env env, const Exp_Cast* cast) { |
|
146 |
40 |
return scan2_exp(env, cast->exp); |
|
147 |
} |
||
148 |
|||
149 |
37 |
ANN static inline m_bool scan2_exp_post(const Env env, const Exp_Postfix* post) { |
|
150 |
37 |
return scan2_exp(env, post->exp); |
|
151 |
} |
||
152 |
|||
153 |
552 |
ANN static inline m_bool scan2_exp_call(const Env env, const Exp_Call* exp_call) { |
|
154 |
✓✓ | 552 |
if(exp_call->tmpl) |
155 |
32 |
return GW_OK; |
|
156 |
✗✓ | 520 |
CHECK_BB(scan2_exp(env, exp_call->func)) |
157 |
520 |
const Exp args = exp_call->args; |
|
158 |
✓✓ | 520 |
return args ? scan2_exp(env, args) : GW_OK; |
159 |
} |
||
160 |
|||
161 |
553 |
ANN static inline m_bool scan2_exp_dot(const Env env, const Exp_Dot* member) { |
|
162 |
553 |
return scan2_exp(env, member->base); |
|
163 |
} |
||
164 |
|||
165 |
10 |
ANN static inline m_bool scan2_exp_if(const Env env, const Exp_If* exp_if) { |
|
166 |
✗✓ | 10 |
CHECK_BB(scan2_exp(env, exp_if->cond)) |
167 |
✓✓✗✓ |
10 |
CHECK_BB(scan2_exp(env, exp_if->if_exp ?: exp_if->cond)) |
168 |
10 |
return scan2_exp(env, exp_if->else_exp); |
|
169 |
} |
||
170 |
|||
171 |
141 |
ANN static m_bool scan2_exp_unary(const Env env, const Exp_Unary * unary) { |
|
172 |
✓✓✓✓ ✓✓ |
141 |
if((unary->op == insert_symbol("spork") || unary->op == insert_symbol("fork")) && unary->code) { |
173 |
25 |
RET_NSPC(scan2_stmt(env, unary->code)) |
|
174 |
✓✓ | 116 |
} else if(unary->exp) |
175 |
91 |
return scan2_exp(env, unary->exp); |
|
176 |
25 |
return GW_OK; |
|
177 |
} |
||
178 |
|||
179 |
11 |
ANN static inline m_bool _scan2_stmt_match_case(const restrict Env env, const Stmt_Match stmt) { |
|
180 |
✗✓ | 11 |
CHECK_BB(scan2_exp(env, stmt->cond)) |
181 |
✓✓ | 11 |
if(stmt->when) |
182 |
✗✓ | 4 |
CHECK_BB(scan2_exp(env, stmt->when)) |
183 |
11 |
return scan2_stmt_list(env, stmt->list); |
|
184 |
} |
||
185 |
|||
186 |
11 |
ANN static inline m_bool scan2_stmt_match_case(const restrict Env env, const Stmt_Match stmt) { |
|
187 |
11 |
RET_NSPC(_scan2_stmt_match_case(env, stmt)) |
|
188 |
} |
||
189 |
|||
190 |
7 |
ANN static inline m_bool _scan2_stmt_match(const restrict Env env, const Stmt_Match stmt) { |
|
191 |
✓✓ | 7 |
if(stmt->where) |
192 |
✗✓ | 2 |
CHECK_BB(scan2_stmt(env, stmt->where)) |
193 |
7 |
Stmt_List list = stmt->list; |
|
194 |
✗✓ | 11 |
do CHECK_BB(scan2_stmt_match_case(env, &list->stmt->d.stmt_match)) |
195 |
✓✓ | 11 |
while((list = list->next)); |
196 |
7 |
return GW_OK; |
|
197 |
} |
||
198 |
|||
199 |
7 |
ANN static inline m_bool scan2_stmt_match(const restrict Env env, const Stmt_Match stmt) { |
|
200 |
✗✓ | 7 |
CHECK_BB(scan2_exp(env, stmt->cond)) |
201 |
7 |
RET_NSPC(_scan2_stmt_match(env, stmt)) |
|
202 |
} |
||
203 |
|||
204 |
#define scan2_exp_lambda dummy_func |
||
205 |
✓✓✓✓ |
27901 |
HANDLE_EXP_FUNC(scan2, m_bool, Env) |
206 |
|||
207 |
#define scan2_stmt_func(name, type, prolog, exp) describe_stmt_func(scan2, name, type, prolog, exp) |
||
208 |
✓✗✓✗ |
26 |
scan2_stmt_func(flow, Stmt_Flow,, !(scan2_exp(env, stmt->cond) < 0 || |
209 |
scan2_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
210 |
✓✗✓✗ |
10 |
scan2_stmt_func(varloop, Stmt_VarLoop,, !(scan2_exp(env, stmt->exp) < 0 || |
211 |
scan2_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
212 |
✓✗✓✗ ✓✓✓✗ ✓✗ |
11 |
scan2_stmt_func(for, Stmt_For,, !(scan2_stmt(env, stmt->c1) < 0 || |
213 |
scan2_stmt(env, stmt->c2) < 0 || |
||
214 |
(stmt->c3 && scan2_exp(env, stmt->c3) < 0) || |
||
215 |
scan2_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
216 |
✓✗✓✗ |
12 |
scan2_stmt_func(each, Stmt_Each,, !(scan2_exp(env, stmt->exp) < 0 || |
217 |
scan2_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
218 |
✓✗✓✗ |
8 |
scan2_stmt_func(loop, Stmt_Loop,, !(scan2_exp(env, stmt->cond) < 0 || |
219 |
scan2_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
220 |
✓✗✓✗ ✓✓✓✗ |
39 |
scan2_stmt_func(if, Stmt_If,, !(scan2_exp(env, stmt->cond) < 0 || |
221 |
scan2_stmt(env, stmt->if_body) < 0 || |
||
222 |
(stmt->else_body && scan2_stmt(env, stmt->else_body) < 0)) ? 1 : -1) |
||
223 |
|||
224 |
459 |
ANN static inline m_bool scan2_stmt_code(const Env env, const Stmt_Code stmt) { |
|
225 |
✓✓ | 459 |
if(stmt->stmt_list) |
226 |
396 |
{ RET_NSPC(scan2_stmt_list(env, stmt->stmt_list)) } |
|
227 |
63 |
return GW_OK; |
|
228 |
} |
||
229 |
|||
230 |
2494 |
ANN static inline m_bool scan2_stmt_exp(const Env env, const Stmt_Exp stmt) { |
|
231 |
✓✓ | 2494 |
return stmt->val ? scan2_exp(env, stmt->val) : 1; |
232 |
} |
||
233 |
|||
234 |
__attribute__((returns_nonnull)) |
||
235 |
8 |
ANN static Map scan2_label_map(const Env env) { |
|
236 |
8 |
Map m, label = env_label(env); |
|
237 |
✓✗ | 18 |
const m_uint* key = env->class_def && !env->func ? |
238 |
✓✓ | 10 |
(m_uint*)env->class_def : (m_uint*)env->func; |
239 |
✓✓ | 8 |
if(!label->ptr) |
240 |
7 |
map_init(label); |
|
241 |
✓✓ | 8 |
if(!(m = (Map)map_get(label, (vtype)key))) { |
242 |
7 |
m = new_map(env->gwion->mp); |
|
243 |
7 |
map_set(label, (vtype)key, (vtype)m); |
|
244 |
} |
||
245 |
8 |
return m; |
|
246 |
} |
||
247 |
|||
248 |
15 |
ANN static m_bool scan2_stmt_jump(const Env env, const Stmt_Jump stmt) { |
|
249 |
✓✓ | 15 |
if(stmt->is_label) { |
250 |
8 |
const Map m = scan2_label_map(env); |
|
251 |
✓✓ | 8 |
if(map_get(m, (vtype)stmt->name)) |
252 |
1 |
ERR_B(stmt_self(stmt)->pos, _("label '%s' already defined"), s_name(stmt->name)) |
|
253 |
7 |
map_set(m, (vtype)stmt->name, (vtype)stmt); |
|
254 |
7 |
vector_init(&stmt->data.v); |
|
255 |
} |
||
256 |
14 |
return GW_OK; |
|
257 |
} |
||
258 |
|||
259 |
18 |
ANN static m_bool scan2_union_decl(const Env env, const Decl_List list) { |
|
260 |
18 |
Decl_List l = list; |
|
261 |
✗✓ | 34 |
do CHECK_BB(scan2_exp_decl(env, &l->self->d.exp_decl)) |
262 |
// do CHECK_BB(scan2_exp(env, l->self)) |
||
263 |
✓✓ | 34 |
while((l = l->next)); |
264 |
18 |
return GW_OK; |
|
265 |
} |
||
266 |
|||
267 |
22 |
ANN m_bool scan2_union_def(const Env env, const Union_Def udef) { |
|
268 |
✓✓ | 22 |
if(tmpl_base(udef->tmpl)) |
269 |
4 |
return GW_OK; |
|
270 |
18 |
const m_uint scope = union_push(env, udef); |
|
271 |
18 |
const m_bool ret = scan2_union_decl(env, udef->l); |
|
272 |
18 |
union_pop(env, udef, scope); |
|
273 |
18 |
union_flag(udef, ae_flag_scan2); |
|
274 |
18 |
return ret; |
|
275 |
} |
||
276 |
|||
277 |
|||
278 |
#define scan2_stmt_while scan2_stmt_flow |
||
279 |
#define scan2_stmt_until scan2_stmt_flow |
||
280 |
#define scan2_stmt_continue (void*)dummy_func |
||
281 |
#define scan2_stmt_break (void*)dummy_func |
||
282 |
#define scan2_stmt_return scan2_stmt_exp |
||
283 |
|||
284 |
4 |
ANN static m_bool scan2_stmt_pp(const Env env, const Stmt_PP stmt) { |
|
285 |
✓✓ | 4 |
if(stmt->pp_type == ae_pp_include) |
286 |
3 |
env->name = stmt->data; |
|
287 |
4 |
return GW_OK; |
|
288 |
} |
||
289 |
|||
290 |
DECL_STMT_FUNC(scan2, m_bool, Env) |
||
291 |
|||
292 |
2800 |
ANN static m_bool scan2_stmt(const Env env, const Stmt stmt) { |
|
293 |
2800 |
return scan2_stmt_func[stmt->stmt_type](env, &stmt->d); |
|
294 |
} |
||
295 |
|||
296 |
2633 |
ANN static m_bool scan2_stmt_list(const Env env, Stmt_List list) { |
|
297 |
✓✓ | 2633 |
do CHECK_BB(scan2_stmt(env, list->stmt)) |
298 |
✓✓ | 2631 |
while((list = list->next)); |
299 |
1103 |
return GW_OK; |
|
300 |
} |
||
301 |
|||
302 |
8664 |
ANN static m_bool scan2_func_def_overload(const Env env, const Func_Def f, const Value overload) { |
|
303 |
8664 |
const m_bool base = tmpl_base(f->base->tmpl); |
|
304 |
8664 |
const m_bool tmpl = GET_FLAG(overload, template); |
|
305 |
✓✓✗✓ |
8664 |
if(isa(overload->type, env->gwion->type[et_function]) < 0 || is_fptr(env->gwion, overload->type)) { |
306 |
✗✓ | 5 |
if(!GET_FLAG(f->base, typedef)) |
307 |
ERR_B(f->pos, _("function name '%s' is already used by another value"), overload->name) |
||
308 |
} |
||
309 |
✓✓✓✗ ✓✓✓✓ ✓✓ |
8664 |
if((!tmpl && base) || (tmpl && !base && !GET_FLAG(f->base, template))) |
310 |
1 |
ERR_B(f->pos, _("must overload template function with template")) |
|
311 |
8663 |
return GW_OK; |
|
312 |
} |
||
313 |
|||
314 |
42444 |
ANN static Func scan_new_func(const Env env, const Func_Def f, const m_str name) { |
|
315 |
42444 |
const Func func = new_func(env->gwion->mp, name, f); |
|
316 |
✓✓ | 42444 |
if(env->class_def) { |
317 |
✓✓ | 42248 |
if(GET_FLAG(env->class_def, template)) |
318 |
15 |
SET_FLAG(func, ref); |
|
319 |
✓✓ | 42248 |
if(!GET_FLAG(f->base, static)) |
320 |
41507 |
SET_FLAG(func, member); |
|
321 |
} |
||
322 |
42444 |
return func; |
|
323 |
} |
||
324 |
|||
325 |
42444 |
ANN static Type func_type(const Env env, const Func func) { |
|
326 |
✓✓ | 42444 |
const Type base = env->gwion->type[func->def->base->td ? et_function : et_lambda]; |
327 |
42444 |
const Type t = type_copy(env->gwion->mp, base); |
|
328 |
42444 |
t->xid = ++env->scope->type_xid; |
|
329 |
42444 |
t->e->parent = base; |
|
330 |
42444 |
t->name = func->name; |
|
331 |
42444 |
t->e->owner = env->curr; |
|
332 |
42444 |
t->e->owner_class = env->class_def; |
|
333 |
✓✓ | 42444 |
if(GET_FLAG(func, member)) |
334 |
41507 |
t->size += SZ_INT; |
|
335 |
42444 |
t->e->d.func = func; |
|
336 |
42444 |
return t; |
|
337 |
} |
||
338 |
|||
339 |
42444 |
ANN2(1,2) static Value func_value(const Env env, const Func f, |
|
340 |
const Value overload) { |
||
341 |
42444 |
const Type t = func_type(env, f); |
|
342 |
42444 |
const Value v = new_value(env->gwion->mp, t, t->name); |
|
343 |
42444 |
valuefrom(env, v->from); |
|
344 |
✗✓ | 42444 |
CHECK_OO(scan2_func_assign(env, f->def, f, v)) |
345 |
✓✓ | 42444 |
if(!overload) { |
346 |
33787 |
ADD_REF(v); |
|
347 |
33787 |
nspc_add_value_front(env->curr, f->def->base->xid, v); |
|
348 |
✓✗ | 8657 |
} else if(overload->d.func_ref) { |
349 |
8657 |
f->next = overload->d.func_ref->next; |
|
350 |
8657 |
overload->d.func_ref->next = f; |
|
351 |
} |
||
352 |
42444 |
return v; |
|
353 |
} |
||
354 |
|||
355 |
42082 |
ANN static m_bool scan2_func_def_builtin(MemPool p, const Func func, const m_str name) { |
|
356 |
42082 |
SET_FLAG(func, builtin); |
|
357 |
42082 |
SET_FLAG(func->value_ref, builtin); |
|
358 |
42082 |
func->code = new_vm_code(p, NULL, func->def->stack_depth, func->flag, name); |
|
359 |
42082 |
func->code->native_func = (m_uint)func->def->d.dl_func_ptr; |
|
360 |
42082 |
return GW_OK; |
|
361 |
} |
||
362 |
|||
363 |
61 |
ANN2(1, 2) static m_bool scan2_fdef_tmpl(const Env env, const Func_Def f, const Value overload) { |
|
364 |
61 |
const m_str name = s_name(f->base->xid); |
|
365 |
61 |
const Func func = scan_new_func(env, f, name); |
|
366 |
61 |
const Value value = func_value(env, func, overload); |
|
367 |
61 |
SET_FLAG(value, valid | ae_flag_template); |
|
368 |
61 |
SET_FLAG(value->type, func); // the only types with func flag, name could be better |
|
369 |
61 |
Type type = env->class_def; |
|
370 |
61 |
Nspc nspc = env->curr; |
|
371 |
61 |
uint i = 0; |
|
372 |
do { |
||
373 |
67 |
const Value v = nspc_lookup_value0(nspc, f->base->xid); |
|
374 |
✓✗ | 67 |
if(v) { |
375 |
67 |
Func ff = v->d.func_ref; |
|
376 |
✗✓ | 67 |
if(!ff)continue; |
377 |
do { |
||
378 |
✓✓ | 85 |
if(ff->def == f) { |
379 |
61 |
++i; |
|
380 |
61 |
continue; |
|
381 |
} |
||
382 |
✓✓ | 24 |
if(compat_func(ff->def, f) > 0) { |
383 |
✗✓ | 6 |
if(ff->value_ref->from->owner == env->curr) |
384 |
ERR_B(f->pos, "template function '%s' already defined with those arguments in this namespace", name) |
||
385 |
6 |
const Symbol sym = func_symbol(env, env->curr->name, name, |
|
386 |
"template", ff->vt_index); |
||
387 |
6 |
nspc_add_value(env->curr, sym, value); |
|
388 |
✓✗ | 6 |
if(!overload) { |
389 |
6 |
ADD_REF(value) |
|
390 |
6 |
nspc_add_value(env->curr, f->base->xid, value); |
|
391 |
} |
||
392 |
6 |
func->vt_index = ff->vt_index; |
|
393 |
6 |
return GW_OK; |
|
394 |
} |
||
395 |
✓✓✓✗ |
79 |
} while((ff = ff->next) && ++i); |
396 |
} |
||
397 |
✓✓✓✗ ✓✓ |
61 |
} while(type && (type = type->e->parent) && (nspc = type->nspc)); |
398 |
55 |
--i; |
|
399 |
55 |
const Symbol sym = func_symbol(env, env->curr->name, name, "template", i); |
|
400 |
55 |
nspc_add_value(env->curr, sym, value); |
|
401 |
✓✓ | 55 |
if(!overload) { |
402 |
46 |
ADD_REF(value) |
|
403 |
46 |
nspc_add_value(env->curr, f->base->xid, value); |
|
404 |
46 |
nspc_add_func(env->curr, f->base->xid, func); |
|
405 |
} else |
||
406 |
9 |
func->vt_index = ++overload->from->offset; |
|
407 |
✓✓ | 55 |
if(GET_FLAG(f->base, builtin)) { |
408 |
✗✓ | 2 |
CHECK_BB(scan2_func_def_builtin(env->gwion->mp, func, func->name)) |
409 |
2 |
SET_FLAG(func, builtin); |
|
410 |
2 |
SET_FLAG(value, builtin); |
|
411 |
} |
||
412 |
55 |
return GW_OK; |
|
413 |
} |
||
414 |
|||
415 |
24 |
ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f) { |
|
416 |
24 |
const m_str str = s_name(f->base->xid); |
|
417 |
✓✓ | 24 |
struct Op_Func opfunc = { .ck=strcmp(str, "@implicit") ? 0 : opck_usr_implicit }; |
418 |
48 |
struct Op_Import opi = { .ret=f->base->ret_type, .pos=f->pos, |
|
419 |
24 |
.data=(uintptr_t)f->base->func, .func=&opfunc }; |
|
420 |
24 |
func_operator(f, &opi); |
|
421 |
✗✓ | 24 |
CHECK_BB(add_op(env->gwion, &opi)) |
422 |
24 |
operator_set_func(&opi); |
|
423 |
24 |
return GW_OK; |
|
424 |
} |
||
425 |
|||
426 |
304 |
ANN static m_bool scan2_func_def_code(const Env env, const Func_Def f) { |
|
427 |
304 |
const Func former = env->func; |
|
428 |
304 |
env->func = f->base->func; |
|
429 |
✗✓ | 304 |
CHECK_BB(scan2_stmt_code(env, &f->d.code->d.stmt_code)) |
430 |
304 |
env->func = former; |
|
431 |
304 |
return GW_OK; |
|
432 |
} |
||
433 |
|||
434 |
42383 |
ANN static void scan2_func_def_flag(const Env env, const Func_Def f) { |
|
435 |
✓✓ | 42383 |
if(!GET_FLAG(f->base, builtin)) |
436 |
303 |
SET_FLAG(f->base->func, pure); |
|
437 |
✓✓ | 42383 |
if(f->base->xid == insert_symbol("@dtor")) |
438 |
6 |
SET_FLAG(env->class_def, dtor); |
|
439 |
42383 |
} |
|
440 |
|||
441 |
66 |
ANN static m_str func_tmpl_name(const Env env, const Func_Def f) { |
|
442 |
66 |
const m_str name = s_name(f->base->xid); |
|
443 |
struct Vector_ v; |
||
444 |
66 |
ID_List id = f->base->tmpl->list; |
|
445 |
66 |
m_uint tlen = 0; |
|
446 |
66 |
vector_init(&v); |
|
447 |
do { |
||
448 |
70 |
const Type t = nspc_lookup_type0(env->curr, id->xid); |
|
449 |
✗✓ | 70 |
if(!t)return NULL; |
450 |
70 |
vector_add(&v, (vtype)t); |
|
451 |
70 |
tlen += strlen(t->name); |
|
452 |
✓✓✓✗ |
70 |
} while((id = id->next) && ++tlen); |
453 |
66 |
char tmpl_name[tlen + 2]; |
|
454 |
66 |
m_str str = tmpl_name; |
|
455 |
✓✓ | 136 |
for(m_uint i = 0; i < vector_size(&v); ++i) { |
456 |
70 |
const m_str s = ((Type)vector_at(&v, i))->name; |
|
457 |
70 |
strcpy(str, s); |
|
458 |
70 |
str += strlen(s); |
|
459 |
✓✓ | 70 |
if(i + 1 < vector_size(&v)) |
460 |
4 |
*str++ = ','; |
|
461 |
} |
||
462 |
66 |
tmpl_name[tlen+1] = '\0'; |
|
463 |
66 |
vector_release(&v); |
|
464 |
66 |
const Symbol sym = func_symbol(env, env->curr->name, name, tmpl_name, (m_uint)f->base->tmpl->base); |
|
465 |
66 |
return s_name(sym); |
|
466 |
} |
||
467 |
|||
468 |
|||
469 |
42383 |
ANN2(1,2,4) static Value func_create(const Env env, const Func_Def f, |
|
470 |
const Value overload, const m_str name) { |
||
471 |
42383 |
const Func func = scan_new_func(env, f, name); |
|
472 |
42383 |
nspc_add_func(env->curr, insert_symbol(func->name), func); |
|
473 |
42383 |
const Value v = func_value(env, func, overload); |
|
474 |
42383 |
scan2_func_def_flag(env, f); |
|
475 |
✓✓ | 42383 |
if(GET_FLAG(f->base, builtin)) |
476 |
✗✓ | 42080 |
CHECK_BO(scan2_func_def_builtin(env->gwion->mp, func, func->name)) |
477 |
42383 |
nspc_add_value(env->curr, insert_symbol(func->name), v); |
|
478 |
42383 |
return v; |
|
479 |
} |
||
480 |
|||
481 |
42389 |
ANN2(1,2) static m_str func_name(const Env env, const Func_Def f, const Value v) { |
|
482 |
✓✓ | 42389 |
if(!f->base->tmpl) { |
483 |
✓✓ | 93219 |
const Symbol sym = func_symbol(env, env->curr->name, |
484 |
50901 |
s_name(f->base->xid), NULL, v ? ++v->from->offset : 0); |
|
485 |
42318 |
return s_name(sym); |
|
486 |
} |
||
487 |
✓✓ | 71 |
return f->base->func ? f->base->func->name : func_tmpl_name(env, f); |
488 |
} |
||
489 |
|||
490 |
42389 |
ANN2(1,2) m_bool scan2_fdef_std(const Env env, const Func_Def f, const Value overload) { |
|
491 |
42389 |
const m_str name = func_name(env, f, overload ?: NULL); |
|
492 |
✗✓ | 42389 |
if(!name)return GW_ERROR; |
493 |
42389 |
const Func base = f->base->func; |
|
494 |
✓✓ | 42389 |
if(!base) |
495 |
✗✓ | 42383 |
CHECK_OB(func_create(env, f, overload, name)) |
496 |
else |
||
497 |
6 |
f->base->func = base; |
|
498 |
✓✓ | 42389 |
if(f->base->args) |
499 |
✗✓ | 16574 |
CHECK_BB(scan2_args(f)) |
500 |
✓✓✓✓ |
42389 |
if(!GET_FLAG(f->base, builtin) && f->d.code) |
501 |
✗✓ | 304 |
CHECK_BB(scan2_func_def_code(env, f)) |
502 |
✓✓ | 42389 |
if(!base) { |
503 |
✓✓ | 42383 |
if(GET_FLAG(f->base, op)) |
504 |
✗✓ | 24 |
CHECK_BB(scan2_func_def_op(env, f)) |
505 |
42383 |
SET_FLAG(f->base->func->value_ref, valid); |
|
506 |
} |
||
507 |
42389 |
return GW_OK; |
|
508 |
} |
||
509 |
|||
510 |
42451 |
ANN m_bool scan2_fdef(const Env env, const Func_Def f) { |
|
511 |
42451 |
const Value overload = nspc_lookup_value2(env->curr, f->base->xid); // try0 |
|
512 |
✓✓ | 42451 |
if(overload) |
513 |
✓✓ | 8664 |
CHECK_BB(scan2_func_def_overload(env, f, overload)) |
514 |
✓✓ | 42450 |
return (!tmpl_base(f->base->tmpl) ? scan2_fdef_std : scan2_fdef_tmpl)(env, f, overload); |
515 |
} |
||
516 |
|||
517 |
__attribute__((returns_nonnull)) |
||
518 |
63 |
static ANN Func_Def scan2_cpy_fdef(const Env env, const Func_Def fdef) { |
|
519 |
63 |
const Func_Def f = cpy_func_def(env->gwion->mp, fdef); |
|
520 |
63 |
f->base->ret_type = fdef->base->ret_type; |
|
521 |
63 |
Arg_List a = f->base->args, b = fdef->base->args; |
|
522 |
✓✓ | 192 |
while(a) { |
523 |
66 |
a->var_decl->value = b->var_decl->value; |
|
524 |
66 |
a->type = b->type; |
|
525 |
66 |
a = a->next; |
|
526 |
66 |
b = b->next; |
|
527 |
} |
||
528 |
63 |
scan1_func_def(env, f); |
|
529 |
63 |
return f; |
|
530 |
} |
||
531 |
|||
532 |
42451 |
static inline int is_cpy(const Func_Def fdef) { |
|
533 |
✓✓✓✓ |
84963 |
return GET_FLAG(fdef->base, global) || |
534 |
✓✓ | 42581 |
(fdef->base->tmpl && !fdef->base->tmpl->call); |
535 |
} |
||
536 |
|||
537 |
42451 |
ANN m_bool scan2_func_def(const Env env, const Func_Def fdef) { |
|
538 |
✓✓ | 42451 |
if(GET_FLAG(fdef->base, global)) |
539 |
2 |
env->context->global = 1; |
|
540 |
84902 |
const Func_Def f = !is_cpy(fdef) ? |
|
541 |
✓✓ | 42451 |
fdef : scan2_cpy_fdef(env, fdef); |
542 |
✓✓ | 42451 |
const m_uint scope = !GET_FLAG(f->base, global) ? env->scope->depth : env_push_global(env); |
543 |
✓✓✓✓ ✓✗ |
42451 |
f->stack_depth = (env->class_def && !GET_FLAG(f->base, static) && !GET_FLAG(f->base, global)) ? SZ_INT : 0; |
544 |
✓✓ | 42451 |
if(GET_FLAG(f->base, variadic)) |
545 |
14 |
f->stack_depth += SZ_INT; |
|
546 |
42451 |
const m_bool ret = scanx_fdef(env, env, f, (_exp_func)scan2_fdef); |
|
547 |
✓✓ | 42451 |
if(GET_FLAG(f->base, global)) |
548 |
2 |
env_pop(env, scope); |
|
549 |
✓✓ | 42451 |
CHECK_BB(ret) |
550 |
42450 |
fdef->base->func = f->base->func; // only needed if 'is_cpy()' |
|
551 |
42450 |
return GW_OK; |
|
552 |
} |
||
553 |
|||
554 |
#define scan2_enum_def dummy_func |
||
555 |
1308 |
HANDLE_SECTION_FUNC(scan2, m_bool, Env) |
|
556 |
|||
557 |
64 |
ANN static m_bool scan2_parent(const Env env, const Class_Def cdef) { |
|
558 |
64 |
const Type parent = cdef->base.type->e->parent; |
|
559 |
✓✓✓✓ |
64 |
if(parent->e->def && !GET_FLAG(parent, scan2)) |
560 |
✗✓ | 6 |
CHECK_BB(ensure_scan2(env, parent)) |
561 |
✓✓ | 64 |
if(cdef->base.ext->array) |
562 |
✗✓ | 9 |
CHECK_BB(scan2_exp(env, cdef->base.ext->array->exp)) |
563 |
64 |
return GW_OK; |
|
564 |
} |
||
565 |
|||
566 |
64 |
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { |
|
567 |
✓✓✓✗ |
64 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
568 |
✗✓ | 21 |
CHECK_BB(template_push_types(env, cdef->base.tmpl)) |
569 |
64 |
const m_bool ret = scan2_parent(env, cdef); |
|
570 |
✓✓✓✗ |
64 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
571 |
21 |
nspc_pop_type(env->gwion->mp, env->curr); |
|
572 |
64 |
return ret; |
|
573 |
} |
||
574 |
|||
575 |
264 |
ANN m_bool scan2_class_def(const Env env, const Class_Def cdef) { |
|
576 |
✓✓ | 264 |
if(tmpl_base(cdef->base.tmpl)) |
577 |
18 |
return GW_OK; |
|
578 |
246 |
const Type t = cdef->base.type; |
|
579 |
✗✓ | 246 |
if(GET_FLAG(t, scan2))return GW_OK; |
580 |
✓✓✗✓ |
246 |
if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan2)) |
581 |
CHECK_BB(ensure_scan2(env, t->e->owner_class)) |
||
582 |
246 |
SET_FLAG(t, scan2); |
|
583 |
✓✓ | 246 |
if(cdef->base.ext) |
584 |
✗✓ | 64 |
CHECK_BB(cdef_parent(env, cdef)) |
585 |
✓✓ | 246 |
if(cdef->body) |
586 |
✗✓ | 204 |
CHECK_BB(env_body(env, cdef, scan2_section)) |
587 |
246 |
return GW_OK; |
|
588 |
} |
||
589 |
|||
590 |
949 |
ANN m_bool scan2_ast(const Env env, Ast ast) { |
|
591 |
✓✓ | 949 |
do CHECK_BB(scan2_section(env, ast->section)) |
592 |
✓✓ | 946 |
while((ast = ast->next)); |
593 |
555 |
return GW_OK; |
|
594 |
} |
Generated by: GCOVR (Version 4.2) |