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