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 |
36 |
ANN static inline m_bool ensure_scan2(const Env env, const Type t) { |
|
17 |
72 |
struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan2_cdef, |
|
18 |
36 |
.scope=env->scope->depth, .flag=ae_flag_scan2 }; |
|
19 |
36 |
return envset_run(&es, t); |
|
20 |
} |
||
21 |
|||
22 |
21437 |
ANN static m_bool scan2_decl(const Env env, const Exp_Decl* decl) { |
|
23 |
21437 |
const Type t = get_type(decl->type); |
|
24 |
✓✓✓✓ |
21437 |
if(t->e->def && !GET_FLAG(t, scan2)) |
25 |
✗✓ | 30 |
CHECK_BB(ensure_scan2(env, t)) |
26 |
21437 |
Var_Decl_List list = decl->list; |
|
27 |
do { |
||
28 |
21445 |
const Var_Decl var = list->self; |
|
29 |
✓✓ | 21445 |
const Exp array = var->array ? var->array->exp : NULL; |
30 |
✓✓ | 21445 |
if(array) |
31 |
✗✓ | 35 |
CHECK_BB(scan2_exp(env, array)) |
32 |
21445 |
nspc_add_value(env->curr, var->xid, var->value); |
|
33 |
✓✓ | 21445 |
} while((list = list->next)); |
34 |
21437 |
return GW_OK; |
|
35 |
} |
||
36 |
|||
37 |
21437 |
ANN m_bool scan2_exp_decl(const Env env, const Exp_Decl* decl) { |
|
38 |
21437 |
const m_bool global = GET_FLAG(decl->td, global); |
|
39 |
✓✓ | 21437 |
const m_uint scope = !global ? env->scope->depth : env_push_global(env); |
40 |
21437 |
const m_bool ret = scan2_decl(env, decl); |
|
41 |
✓✓ | 21437 |
if(global) |
42 |
12 |
env_pop(env, scope); |
|
43 |
21437 |
return ret; |
|
44 |
} |
||
45 |
|||
46 |
16550 |
ANN static m_bool scan2_args(const Func_Def f) { |
|
47 |
16550 |
Arg_List list = f->base->args; |
|
48 |
do { |
||
49 |
23741 |
const Value v = list->var_decl->value; |
|
50 |
23741 |
v->from->offset = f->stack_depth; |
|
51 |
23741 |
f->stack_depth += v->type->size; |
|
52 |
✓✓ | 23741 |
} while((list = list->next)); |
53 |
16550 |
return GW_OK; |
|
54 |
} |
||
55 |
|||
56 |
42327 |
ANN static Value scan2_func_assign(const Env env, const Func_Def d, |
|
57 |
const Func f, const Value v) { |
||
58 |
42327 |
valuefrom(env, v->from); |
|
59 |
42327 |
SET_FLAG(v, func | ae_flag_const); |
|
60 |
✓✓ | 42327 |
if(!env->class_def) |
61 |
193 |
SET_FLAG(v, global); |
|
62 |
else { |
||
63 |
✓✓ | 42134 |
if(GET_FLAG(f, member)) |
64 |
41395 |
SET_FLAG(v, member); |
|
65 |
739 |
else SET_FLAG(v, static); |
|
66 |
✓✓✗✓ |
42134 |
SET_ACCESS(d, v) |
67 |
} |
||
68 |
42327 |
d->base->func = v->d.func_ref = f; |
|
69 |
42327 |
return f->value_ref = v; |
|
70 |
} |
||
71 |
|||
72 |
|||
73 |
71 |
ANN m_bool scan2_fptr_def(const Env env NUSED, const Fptr_Def fptr) { |
|
74 |
✓✓ | 71 |
if(!tmpl_base(fptr->base->tmpl)) { |
75 |
56 |
const Func_Def def = fptr->type->e->d.func->def; |
|
76 |
✓✓ | 56 |
if(def->base->args) { |
77 |
24 |
RET_NSPC(scan2_args(def)) |
|
78 |
} |
||
79 |
} else |
||
80 |
15 |
SET_FLAG(fptr->type, func); |
|
81 |
47 |
return GW_OK; |
|
82 |
} |
||
83 |
|||
84 |
731 |
ANN m_bool scan2_type_def(const Env env, const Type_Def tdef) { |
|
85 |
✓✓ | 731 |
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 |
2127 |
ANN static inline Value prim_value(const Env env, const Symbol s) { |
|
90 |
2127 |
const Value value = nspc_lookup_value1(env->curr, s); |
|
91 |
✓✓ | 2127 |
if(env->class_def) |
92 |
✓✓ | 401 |
return value ?: find_value(env->class_def, s); |
93 |
1726 |
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 |
4410 |
ANN static inline m_bool scan2_prim(const Env env, const Exp_Primary* prim) { |
|
105 |
✓✓✓✓ ✓✓ |
7737 |
if(prim->prim_type == ae_prim_hack || prim->prim_type == ae_prim_typeof || |
106 |
3327 |
prim->prim_type == ae_prim_interp) |
|
107 |
✗✓ | 1088 |
CHECK_BB(scan2_exp(env, prim->d.exp)) |
108 |
✓✓ | 3322 |
else if(prim->prim_type == ae_prim_id) { |
109 |
2127 |
const Value v = prim_value(env, prim->d.var); |
|
110 |
✓✓ | 2127 |
if(v) |
111 |
1504 |
SET_FLAG(v, used); |
|
112 |
✓✓✓✓ |
1195 |
} else if(prim->prim_type == ae_prim_array && prim->d.array->exp) |
113 |
22 |
return scan2_exp(env, prim->d.array->exp); |
|
114 |
✓✓ | 1173 |
else if(prim->prim_type == ae_prim_range) |
115 |
3 |
return scan2_range(env, prim->d.range); |
|
116 |
4385 |
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 |
1273 |
ANN static m_bool multi_decl(const Env env, const Exp e, const Symbol op) { |
|
130 |
✓✓ | 1273 |
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 |
1272 |
return GW_OK; |
|
136 |
} |
||
137 |
|||
138 |
637 |
ANN static inline m_bool scan2_exp_binary(const Env env, const Exp_Binary* bin) { |
|
139 |
✗✓ | 637 |
CHECK_BB(scan2_exp(env, bin->lhs)) |
140 |
✗✓ | 637 |
CHECK_BB(scan2_exp(env, bin->rhs)) |
141 |
✓✓ | 637 |
CHECK_BB(multi_decl(env, bin->lhs, bin->op)) |
142 |
636 |
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 |
33 |
return GW_OK; |
|
156 |
✗✓ | 519 |
CHECK_BB(scan2_exp(env, exp_call->func)) |
157 |
519 |
const Exp args = exp_call->args; |
|
158 |
✓✓ | 519 |
return args ? scan2_exp(env, args) : GW_OK; |
159 |
} |
||
160 |
|||
161 |
556 |
ANN static inline m_bool scan2_exp_dot(const Env env, const Exp_Dot* member) { |
|
162 |
556 |
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 |
✓✓✓✓ |
27842 |
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 |
✓✗✓✗ |
11 |
scan2_stmt_func(auto, Stmt_Auto,, !(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 |
✓✗✓✗ ✓✓✓✗ |
40 |
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 |
456 |
ANN static inline m_bool scan2_stmt_code(const Env env, const Stmt_Code stmt) { |
|
225 |
✓✓ | 456 |
if(stmt->stmt_list) |
226 |
393 |
{ RET_NSPC(scan2_stmt_list(env, stmt->stmt_list)) } |
|
227 |
63 |
return GW_OK; |
|
228 |
} |
||
229 |
|||
230 |
2500 |
ANN static inline m_bool scan2_stmt_exp(const Env env, const Stmt_Exp stmt) { |
|
231 |
✓✓ | 2500 |
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 |
#define scan2_stmt_pp dummy_func |
||
284 |
|||
285 |
DECL_STMT_FUNC(scan2, m_bool, Env) |
||
286 |
|||
287 |
2803 |
ANN static m_bool scan2_stmt(const Env env, const Stmt stmt) { |
|
288 |
2803 |
return scan2_stmt_func[stmt->stmt_type](env, &stmt->d); |
|
289 |
} |
||
290 |
|||
291 |
2636 |
ANN static m_bool scan2_stmt_list(const Env env, Stmt_List list) { |
|
292 |
✓✓ | 2636 |
do CHECK_BB(scan2_stmt(env, list->stmt)) |
293 |
✓✓ | 2634 |
while((list = list->next)); |
294 |
1104 |
return GW_OK; |
|
295 |
} |
||
296 |
|||
297 |
8638 |
ANN static m_bool scan2_func_def_overload(const Env env, const Func_Def f, const Value overload) { |
|
298 |
8638 |
const m_bool base = tmpl_base(f->base->tmpl); |
|
299 |
8638 |
const m_bool tmpl = GET_FLAG(overload, template); |
|
300 |
✓✓✗✓ |
8638 |
if(isa(overload->type, env->gwion->type[et_function]) < 0 || is_fptr(env->gwion, overload->type)) { |
301 |
✗✓ | 5 |
if(!GET_FLAG(f, typedef)) |
302 |
ERR_B(f->pos, _("function name '%s' is already used by another value"), overload->name) |
||
303 |
} |
||
304 |
✓✓✓✗ ✓✓✓✓ ✓✓ |
8638 |
if((!tmpl && base) || (tmpl && !base && !GET_FLAG(f, template))) |
305 |
1 |
ERR_B(f->pos, _("must overload template function with template")) |
|
306 |
8637 |
return GW_OK; |
|
307 |
} |
||
308 |
|||
309 |
42327 |
ANN static Func scan_new_func(const Env env, const Func_Def f, const m_str name) { |
|
310 |
42327 |
const Func func = new_func(env->gwion->mp, name, f); |
|
311 |
✓✓ | 42327 |
if(env->class_def) { |
312 |
✓✓ | 42134 |
if(GET_FLAG(env->class_def, template)) |
313 |
19 |
SET_FLAG(func, ref); |
|
314 |
✓✓ | 42134 |
if(!GET_FLAG(f, static)) |
315 |
41395 |
SET_FLAG(func, member); |
|
316 |
} |
||
317 |
42327 |
return func; |
|
318 |
} |
||
319 |
|||
320 |
42327 |
ANN static Type func_type(const Env env, const Func func) { |
|
321 |
✓✓ | 42327 |
const Type base = env->gwion->type[func->def->base->td ? et_function : et_lambda]; |
322 |
42327 |
const Type t = type_copy(env->gwion->mp, base); |
|
323 |
42327 |
t->xid = ++env->scope->type_xid; |
|
324 |
42327 |
t->e->parent = base; |
|
325 |
42327 |
t->name = func->name; |
|
326 |
42327 |
t->e->owner = env->curr; |
|
327 |
42327 |
t->e->owner_class = env->class_def; |
|
328 |
✓✓ | 42327 |
if(GET_FLAG(func, member)) |
329 |
41395 |
t->size += SZ_INT; |
|
330 |
42327 |
t->e->d.func = func; |
|
331 |
42327 |
return t; |
|
332 |
} |
||
333 |
|||
334 |
42327 |
ANN2(1,2) static Value func_value(const Env env, const Func f, |
|
335 |
const Value overload) { |
||
336 |
42327 |
const Type t = func_type(env, f); |
|
337 |
42327 |
const Value v = new_value(env->gwion->mp, t, t->name); |
|
338 |
42327 |
valuefrom(env, v->from); |
|
339 |
✗✓ | 42327 |
CHECK_OO(scan2_func_assign(env, f->def, f, v)) |
340 |
✓✓ | 42327 |
if(!overload) { |
341 |
33696 |
ADD_REF(v); |
|
342 |
33696 |
nspc_add_value_front(env->curr, f->def->base->xid, v); |
|
343 |
✓✗ | 8631 |
} else if(overload->d.func_ref) { |
344 |
8631 |
f->next = overload->d.func_ref->next; |
|
345 |
8631 |
overload->d.func_ref->next = f; |
|
346 |
} |
||
347 |
42327 |
return v; |
|
348 |
} |
||
349 |
|||
350 |
41968 |
ANN static m_bool scan2_func_def_builtin(MemPool p, const Func func, const m_str name) { |
|
351 |
41968 |
SET_FLAG(func, builtin); |
|
352 |
41968 |
SET_FLAG(func->value_ref, builtin); |
|
353 |
41968 |
func->code = new_vm_code(p, NULL, func->def->stack_depth, func->flag, name); |
|
354 |
41968 |
func->code->native_func = (m_uint)func->def->d.dl_func_ptr; |
|
355 |
41968 |
return GW_OK; |
|
356 |
} |
||
357 |
|||
358 |
64 |
ANN2(1, 2) static m_bool scan2_fdef_tmpl(const Env env, const Func_Def f, const Value overload) { |
|
359 |
64 |
const m_str name = s_name(f->base->xid); |
|
360 |
64 |
const Func func = scan_new_func(env, f, name); |
|
361 |
64 |
const Value value = func_value(env, func, overload); |
|
362 |
64 |
SET_FLAG(value, valid | ae_flag_template); |
|
363 |
64 |
SET_FLAG(value->type, func); // the only types with func flag, name could be better |
|
364 |
64 |
Type type = env->class_def; |
|
365 |
64 |
Nspc nspc = env->curr; |
|
366 |
64 |
uint i = 0; |
|
367 |
do { |
||
368 |
70 |
const Value v = nspc_lookup_value0(nspc, f->base->xid); |
|
369 |
✓✗ | 70 |
if(v) { |
370 |
70 |
Func ff = v->d.func_ref; |
|
371 |
✗✓ | 70 |
if(!ff)continue; |
372 |
do { |
||
373 |
✓✓ | 88 |
if(ff->def == f) { |
374 |
64 |
++i; |
|
375 |
64 |
continue; |
|
376 |
} |
||
377 |
✓✓ | 24 |
if(compat_func(ff->def, f) > 0) { |
378 |
✗✓ | 6 |
if(ff->value_ref->from->owner == env->curr) |
379 |
ERR_B(f->pos, "template function '%s' already defined with those arguments in this namespace", name) |
||
380 |
6 |
const Symbol sym = func_symbol(env, env->curr->name, name, |
|
381 |
"template", ff->vt_index); |
||
382 |
6 |
nspc_add_value(env->curr, sym, value); |
|
383 |
✓✗ | 6 |
if(!overload) { |
384 |
6 |
ADD_REF(value) |
|
385 |
6 |
nspc_add_value(env->curr, f->base->xid, value); |
|
386 |
} |
||
387 |
6 |
func->vt_index = ff->vt_index; |
|
388 |
6 |
return GW_OK; |
|
389 |
} |
||
390 |
✓✓✓✗ |
82 |
} while((ff = ff->next) && ++i); |
391 |
} |
||
392 |
✓✓✓✗ ✓✓ |
64 |
} while(type && (type = type->e->parent) && (nspc = type->nspc)); |
393 |
58 |
--i; |
|
394 |
58 |
const Symbol sym = func_symbol(env, env->curr->name, name, "template", i); |
|
395 |
58 |
nspc_add_value(env->curr, sym, value); |
|
396 |
✓✓ | 58 |
if(!overload) { |
397 |
49 |
ADD_REF(value) |
|
398 |
49 |
nspc_add_value(env->curr, f->base->xid, value); |
|
399 |
49 |
nspc_add_func(env->curr, f->base->xid, func); |
|
400 |
} else |
||
401 |
9 |
func->vt_index = ++overload->from->offset; |
|
402 |
✓✓ | 58 |
if(GET_FLAG(f, builtin)) { |
403 |
✗✓ | 5 |
CHECK_BB(scan2_func_def_builtin(env->gwion->mp, func, func->name)) |
404 |
5 |
SET_FLAG(func, builtin); |
|
405 |
5 |
SET_FLAG(value, builtin); |
|
406 |
} |
||
407 |
58 |
return GW_OK; |
|
408 |
} |
||
409 |
|||
410 |
24 |
ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f) { |
|
411 |
24 |
const m_str str = s_name(f->base->xid); |
|
412 |
✓✓ | 24 |
struct Op_Func opfunc = { .ck=strcmp(str, "@implicit") ? 0 : opck_usr_implicit }; |
413 |
48 |
struct Op_Import opi = { .ret=f->base->ret_type, .pos=f->pos, |
|
414 |
24 |
.data=(uintptr_t)f->base->func, .func=&opfunc }; |
|
415 |
24 |
func_operator(f, &opi); |
|
416 |
✗✓ | 24 |
CHECK_BB(add_op(env->gwion, &opi)) |
417 |
24 |
operator_set_func(&opi); |
|
418 |
24 |
return GW_OK; |
|
419 |
} |
||
420 |
|||
421 |
301 |
ANN static m_bool scan2_func_def_code(const Env env, const Func_Def f) { |
|
422 |
301 |
const Func former = env->func; |
|
423 |
301 |
env->func = f->base->func; |
|
424 |
✗✓ | 301 |
CHECK_BB(scan2_stmt_code(env, &f->d.code->d.stmt_code)) |
425 |
301 |
env->func = former; |
|
426 |
301 |
return GW_OK; |
|
427 |
} |
||
428 |
|||
429 |
42263 |
ANN static void scan2_func_def_flag(const Env env, const Func_Def f) { |
|
430 |
✓✓ | 42263 |
if(!GET_FLAG(f, builtin)) |
431 |
300 |
SET_FLAG(f->base->func, pure); |
|
432 |
✓✓ | 42263 |
if(f->base->xid == insert_symbol("@dtor")) |
433 |
6 |
SET_FLAG(env->class_def, dtor); |
|
434 |
42263 |
} |
|
435 |
|||
436 |
64 |
ANN static m_str func_tmpl_name(const Env env, const Func_Def f) { |
|
437 |
64 |
const m_str name = s_name(f->base->xid); |
|
438 |
struct Vector_ v; |
||
439 |
64 |
ID_List id = f->base->tmpl->list; |
|
440 |
64 |
m_uint tlen = 0; |
|
441 |
64 |
vector_init(&v); |
|
442 |
do { |
||
443 |
68 |
const Type t = nspc_lookup_type0(env->curr, id->xid); |
|
444 |
✗✓ | 68 |
if(!t)return NULL; |
445 |
68 |
vector_add(&v, (vtype)t); |
|
446 |
68 |
tlen += strlen(t->name); |
|
447 |
✓✓✓✗ |
68 |
} while((id = id->next) && ++tlen); |
448 |
64 |
char tmpl_name[tlen + 2]; |
|
449 |
64 |
m_str str = tmpl_name; |
|
450 |
✓✓ | 132 |
for(m_uint i = 0; i < vector_size(&v); ++i) { |
451 |
68 |
const m_str s = ((Type)vector_at(&v, i))->name; |
|
452 |
68 |
strcpy(str, s); |
|
453 |
68 |
str += strlen(s); |
|
454 |
✓✓ | 68 |
if(i + 1 < vector_size(&v)) |
455 |
4 |
*str++ = ','; |
|
456 |
} |
||
457 |
64 |
tmpl_name[tlen+1] = '\0'; |
|
458 |
64 |
vector_release(&v); |
|
459 |
64 |
const Symbol sym = func_symbol(env, env->curr->name, name, tmpl_name, (m_uint)f->base->tmpl->base); |
|
460 |
64 |
return s_name(sym); |
|
461 |
} |
||
462 |
|||
463 |
|||
464 |
42263 |
ANN2(1,2,4) static Value func_create(const Env env, const Func_Def f, |
|
465 |
const Value overload, const m_str name) { |
||
466 |
42263 |
const Func func = scan_new_func(env, f, name); |
|
467 |
42263 |
nspc_add_func(env->curr, insert_symbol(func->name), func); |
|
468 |
42263 |
const Value v = func_value(env, func, overload); |
|
469 |
42263 |
scan2_func_def_flag(env, f); |
|
470 |
✓✓ | 42263 |
if(GET_FLAG(f, builtin)) |
471 |
✗✓ | 41963 |
CHECK_BO(scan2_func_def_builtin(env->gwion->mp, func, func->name)) |
472 |
42263 |
nspc_add_value(env->curr, insert_symbol(func->name), v); |
|
473 |
42263 |
return v; |
|
474 |
} |
||
475 |
|||
476 |
42269 |
ANN2(1,2) static m_str func_name(const Env env, const Func_Def f, const Value v) { |
|
477 |
✓✓ | 42269 |
if(!f->base->tmpl) { |
478 |
✓✓ | 92959 |
const Symbol sym = func_symbol(env, env->curr->name, |
479 |
50759 |
s_name(f->base->xid), NULL, v ? ++v->from->offset : 0); |
|
480 |
42200 |
return s_name(sym); |
|
481 |
} |
||
482 |
✓✓ | 69 |
return f->base->func ? f->base->func->name : func_tmpl_name(env, f); |
483 |
} |
||
484 |
|||
485 |
42269 |
ANN2(1,2) m_bool scan2_fdef_std(const Env env, const Func_Def f, const Value overload) { |
|
486 |
42269 |
const m_str name = func_name(env, f, overload ?: NULL); |
|
487 |
✗✓ | 42269 |
if(!name)return GW_ERROR; |
488 |
42269 |
const Func base = f->base->func; |
|
489 |
✓✓ | 42269 |
if(!base) |
490 |
✗✓ | 42263 |
CHECK_OB(func_create(env, f, overload, name)) |
491 |
else |
||
492 |
6 |
f->base->func = base; |
|
493 |
✓✓ | 42269 |
if(f->base->args) |
494 |
✗✓ | 16526 |
CHECK_BB(scan2_args(f)) |
495 |
✓✓✓✓ |
42269 |
if(!GET_FLAG(f, builtin) && f->d.code) |
496 |
✗✓ | 301 |
CHECK_BB(scan2_func_def_code(env, f)) |
497 |
✓✓ | 42269 |
if(!base) { |
498 |
✓✓ | 42263 |
if(GET_FLAG(f, op)) |
499 |
✗✓ | 24 |
CHECK_BB(scan2_func_def_op(env, f)) |
500 |
42263 |
SET_FLAG(f->base->func->value_ref, valid); |
|
501 |
} |
||
502 |
42269 |
return GW_OK; |
|
503 |
} |
||
504 |
|||
505 |
42334 |
ANN m_bool scan2_fdef(const Env env, const Func_Def f) { |
|
506 |
42334 |
const Value overload = nspc_lookup_value2(env->curr, f->base->xid); // try0 |
|
507 |
✓✓ | 42334 |
if(overload) |
508 |
✓✓ | 8638 |
CHECK_BB(scan2_func_def_overload(env, f, overload)) |
509 |
✓✓ | 42333 |
return (!tmpl_base(f->base->tmpl) ? scan2_fdef_std : scan2_fdef_tmpl)(env, f, overload); |
510 |
} |
||
511 |
|||
512 |
__attribute__((returns_nonnull)) |
||
513 |
66 |
static ANN Func_Def scan2_cpy_fdef(const Env env, const Func_Def fdef) { |
|
514 |
66 |
const Func_Def f = cpy_func_def(env->gwion->mp, fdef); |
|
515 |
66 |
f->base->ret_type = fdef->base->ret_type; |
|
516 |
66 |
Arg_List a = f->base->args, b = fdef->base->args; |
|
517 |
✓✓ | 198 |
while(a) { |
518 |
66 |
a->var_decl->value = b->var_decl->value; |
|
519 |
66 |
a->type = b->type; |
|
520 |
66 |
a = a->next; |
|
521 |
66 |
b = b->next; |
|
522 |
} |
||
523 |
66 |
scan1_func_def(env, f); |
|
524 |
66 |
return f; |
|
525 |
} |
||
526 |
|||
527 |
42334 |
static inline int is_cpy(const Func_Def fdef) { |
|
528 |
✓✓✓✓ |
84732 |
return GET_FLAG(fdef, global) || |
529 |
✓✓ | 42465 |
(fdef->base->tmpl && !fdef->base->tmpl->call); |
530 |
} |
||
531 |
|||
532 |
42334 |
ANN m_bool scan2_func_def(const Env env, const Func_Def fdef) { |
|
533 |
✓✓ | 42334 |
if(GET_FLAG(fdef, global)) |
534 |
2 |
env->context->global = 1; |
|
535 |
84668 |
const Func_Def f = !is_cpy(fdef) ? |
|
536 |
✓✓ | 42334 |
fdef : scan2_cpy_fdef(env, fdef); |
537 |
✓✓ | 42334 |
const m_uint scope = !GET_FLAG(f, global) ? env->scope->depth : env_push_global(env); |
538 |
✓✓✓✓ ✓✗ |
42334 |
f->stack_depth = (env->class_def && !GET_FLAG(f, static) && !GET_FLAG(f, global)) ? SZ_INT : 0; |
539 |
✓✓ | 42334 |
if(GET_FLAG(f, variadic)) |
540 |
14 |
f->stack_depth += SZ_INT; |
|
541 |
42334 |
const m_bool ret = scanx_fdef(env, env, f, (_exp_func)scan2_fdef); |
|
542 |
✓✓ | 42334 |
if(GET_FLAG(f, global)) |
543 |
2 |
env_pop(env, scope); |
|
544 |
✓✓ | 42334 |
CHECK_BB(ret) |
545 |
42333 |
fdef->base->func = f->base->func; // only needed if 'is_cpy()' |
|
546 |
42333 |
return GW_OK; |
|
547 |
} |
||
548 |
|||
549 |
#define scan2_enum_def dummy_func |
||
550 |
1314 |
HANDLE_SECTION_FUNC(scan2, m_bool, Env) |
|
551 |
|||
552 |
67 |
ANN static m_bool scan2_parent(const Env env, const Class_Def cdef) { |
|
553 |
67 |
const Type parent = cdef->base.type->e->parent; |
|
554 |
✓✓✓✓ |
67 |
if(parent->e->def && !GET_FLAG(parent, scan2)) |
555 |
✗✓ | 6 |
CHECK_BB(ensure_scan2(env, parent)) |
556 |
✓✓ | 67 |
if(cdef->base.ext->array) |
557 |
✗✓ | 9 |
CHECK_BB(scan2_exp(env, cdef->base.ext->array->exp)) |
558 |
67 |
return GW_OK; |
|
559 |
} |
||
560 |
|||
561 |
67 |
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { |
|
562 |
✓✓✓✗ |
67 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
563 |
✗✓ | 24 |
CHECK_BB(template_push_types(env, cdef->base.tmpl)) |
564 |
67 |
const m_bool ret = scan2_parent(env, cdef); |
|
565 |
✓✓✓✗ |
67 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
566 |
24 |
nspc_pop_type(env->gwion->mp, env->curr); |
|
567 |
67 |
return ret; |
|
568 |
} |
||
569 |
|||
570 |
270 |
ANN m_bool scan2_class_def(const Env env, const Class_Def cdef) { |
|
571 |
✓✓ | 270 |
if(tmpl_base(cdef->base.tmpl)) |
572 |
19 |
return GW_OK; |
|
573 |
251 |
const Type t = cdef->base.type; |
|
574 |
✗✓ | 251 |
if(GET_FLAG(t, scan2))return GW_OK; |
575 |
✓✓✗✓ |
251 |
if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan2)) |
576 |
CHECK_BB(ensure_scan2(env, t->e->owner_class)) |
||
577 |
251 |
SET_FLAG(t, scan2); |
|
578 |
✓✓ | 251 |
if(cdef->base.ext) |
579 |
✗✓ | 67 |
CHECK_BB(cdef_parent(env, cdef)) |
580 |
✓✓ | 251 |
if(cdef->body) |
581 |
✗✓ | 209 |
CHECK_BB(env_body(env, cdef, scan2_section)) |
582 |
251 |
return GW_OK; |
|
583 |
} |
||
584 |
|||
585 |
946 |
ANN m_bool scan2_ast(const Env env, Ast ast) { |
|
586 |
✓✓ | 946 |
do CHECK_BB(scan2_section(env, ast->section)) |
587 |
✓✓ | 943 |
while((ast = ast->next)); |
588 |
552 |
return GW_OK; |
|
589 |
} |
Generated by: GCOVR (Version 4.2) |