GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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 "traverse.h" |
||
7 |
#include "template.h" |
||
8 |
#include "parse.h" |
||
9 |
|||
10 |
ANN static m_bool scan1_stmt_list(const Env env, Stmt_List list); |
||
11 |
ANN static m_bool scan1_stmt(const Env env, Stmt stmt); |
||
12 |
|||
13 |
11599 |
ANN static inline m_bool type_cyclic(const Env env, const Type t, const Type_Decl *td) { |
|
14 |
11599 |
Type owner = env->class_def; |
|
15 |
do { |
||
16 |
11610 |
Type parent = t; |
|
17 |
✓✓ | 43481 |
while(parent) { |
18 |
✓✓ | 20262 |
if(parent == owner) |
19 |
1 |
ERR_B(td_pos(td), _("%s declared inside %s"), t->name, owner->name); |
|
20 |
20261 |
parent = parent->e->parent; |
|
21 |
} |
||
22 |
✓✓ | 11609 |
} while((owner = owner->e->owner_class)); |
23 |
11598 |
return GW_OK; |
|
24 |
} |
||
25 |
|||
26 |
34 |
ANN static inline m_bool ensure_scan1(const Env env, const Type t) { |
|
27 |
68 |
struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan1_cdef, |
|
28 |
34 |
.scope=env->scope->depth, .flag=ae_flag_scan1 }; |
|
29 |
34 |
return envset_run(&es, t); |
|
30 |
} |
||
31 |
|||
32 |
45241 |
ANN static Type scan1_type(const Env env, Type_Decl* td) { |
|
33 |
✓✓ | 45241 |
DECL_OO(const Type, type, = known_type(env, td)) |
34 |
45217 |
const Type t = get_type(type); |
|
35 |
✓✓✓✓ ✓✓ |
45217 |
if(!env->func && env->class_def && !GET_FLAG(td, ref)) |
36 |
✓✓ | 11599 |
CHECK_BO(type_cyclic(env, t, td)) |
37 |
✓✓✓✓ |
45216 |
if(!GET_FLAG(t, scan1) && t->e->def) |
38 |
✗✓ | 28 |
CHECK_BO(ensure_scan1(env, t)) |
39 |
45216 |
return type; |
|
40 |
} |
||
41 |
|||
42 |
45181 |
ANN static Type void_type(const Env env, Type_Decl* td) { |
|
43 |
✓✓ | 45181 |
DECL_OO(const Type, type, = scan1_type(env, td)) |
44 |
✓✓ | 45158 |
if(type->size) |
45 |
45155 |
return type; |
|
46 |
3 |
ERR_O(td_pos(td), _("cannot declare variables of size '0' (i.e. 'void')...")) |
|
47 |
} |
||
48 |
|||
49 |
21457 |
ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) { |
|
50 |
✓✓ | 21457 |
if(decl->type) |
51 |
21 |
return decl->type; |
|
52 |
✓✓ | 21436 |
DECL_OO(const Type ,t, = void_type(env, decl->td)) |
53 |
✓✓✗✓ |
21416 |
if(decl->td->xid == insert_symbol("auto") && decl->type) |
54 |
return decl->type; |
||
55 |
✓✓✓✓ ✓✓ |
21416 |
if(!env->scope->depth && env->class_def && !GET_FLAG(decl->td, static)) |
56 |
11550 |
SET_FLAG(decl->td, member); |
|
57 |
✓✓✓✗ |
21416 |
if(GET_FLAG(t, private) && t->e->owner != env->curr) |
58 |
1 |
ERR_O(exp_self(decl)->pos, _("can't use private type %s"), t->name) |
|
59 |
✓✓✗✓ ✗✗ |
21415 |
if(GET_FLAG(t, protect) && (!env->class_def || isa(t, env->class_def) < 0)) |
60 |
1 |
ERR_O(exp_self(decl)->pos, _("can't use protected type %s"), t->name) |
|
61 |
21414 |
return decl->type = t; |
|
62 |
} |
||
63 |
|||
64 |
21441 |
static inline m_bool scan1_defined(const Env env, const Var_Decl var) { |
|
65 |
✓✓ | 21441 |
if(var->value) // from a `typeof` declaration |
66 |
21 |
return GW_OK; |
|
67 |
✓✓✓✓ ✓✓ |
21420 |
if(((!env->class_def || env->scope->depth) ? nspc_lookup_value1 : nspc_lookup_value2)(env->curr, var->xid)) |
68 |
3 |
ERR_B(var->pos, _("variable %s has already been defined in the same scope..."), |
|
69 |
s_name(var->xid)) |
||
70 |
21417 |
return GW_OK; |
|
71 |
} |
||
72 |
|||
73 |
21433 |
ANN static m_bool scan1_decl(const Env env, const Exp_Decl* decl) { |
|
74 |
21433 |
Var_Decl_List list = decl->list; |
|
75 |
do { |
||
76 |
21441 |
const Var_Decl var = list->self; |
|
77 |
✗✓ | 21441 |
CHECK_BB(isres(env, var->xid, exp_self(decl)->pos)) |
78 |
21441 |
Type t = decl->type; |
|
79 |
✓✓ | 21441 |
CHECK_BB(scan1_defined(env, var)) |
80 |
✓✓ | 21438 |
if(var->array) { |
81 |
✓✓ | 44 |
if(var->array->exp) { |
82 |
✓✓ | 36 |
if(GET_FLAG(decl->td, ref)) |
83 |
1 |
ERR_B(var->array->exp->pos, _("ref array must not have array expression.\n" |
|
84 |
"e.g: int @my_array[];\nnot: int @my_array[2];")) |
||
85 |
✗✓ | 35 |
CHECK_BB(scan1_exp(env, var->array->exp)) |
86 |
} |
||
87 |
43 |
t = array_type(env, decl->type, var->array->depth); |
|
88 |
✓✓✓✓ |
21394 |
} else if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref)) { |
89 |
✗✓ | 1 |
if(decl->td->xid == insert_symbol("auto")) |
90 |
SET_FLAG(decl->td, ref); |
||
91 |
else |
||
92 |
1 |
ERR_B(exp_self(decl)->pos, _("Type '%s' is abstract, declare as ref. (use @)"), t->name) |
|
93 |
} |
||
94 |
✓✓ | 21436 |
const Value v = var->value = var->value ?: new_value(env->gwion->mp, t, s_name(var->xid)); |
95 |
✓✓✓✓ ✓✓ |
21436 |
if(SAFE_FLAG(env->class_def, struct) && !GET_FLAG(decl->td, static)) { |
96 |
22 |
v->from->offset = env->class_def->size; |
|
97 |
22 |
env->class_def->size += t->size; |
|
98 |
} |
||
99 |
21436 |
nspc_add_value(env->curr, var->xid, v); |
|
100 |
21436 |
v->flag = decl->td->flag; |
|
101 |
21436 |
v->type = t; |
|
102 |
✓✓✓✓ |
21436 |
if(var->array && !var->array->exp) |
103 |
8 |
SET_FLAG(v, ref); |
|
104 |
✓✓ | 21436 |
if(env->class_def) { |
105 |
✓✗ | 11587 |
if(env->class_def->e->tuple) |
106 |
11587 |
tuple_contains(env, v); |
|
107 |
✓✓ | 9849 |
} else if(!env->scope->depth) |
108 |
9660 |
SET_FLAG(v, global); |
|
109 |
21436 |
v->d.ptr = var->addr; |
|
110 |
✓✓ | 21436 |
if(GET_FLAG(decl->td, global)) |
111 |
6 |
SET_FLAG(v, abstract); |
|
112 |
✓✓ | 21436 |
if(!env->scope->depth) |
113 |
21239 |
valuefrom(env, v->from); |
|
114 |
✓✓ | 21436 |
} while((list = list->next)); |
115 |
21428 |
((Exp_Decl*)decl)->type = decl->list->self->value->type; |
|
116 |
21428 |
return GW_OK; |
|
117 |
} |
||
118 |
|||
119 |
19 |
ANN int is_global(const Nspc nspc, Nspc global) { |
|
120 |
✓✓ | 19 |
do if(nspc == global) |
121 |
6 |
return 1; |
|
122 |
✓✓ | 13 |
while((global = global->parent)); |
123 |
2 |
return 0; |
|
124 |
} |
||
125 |
|||
126 |
21461 |
ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) { |
|
127 |
✓✓ | 21461 |
CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos)) |
128 |
21457 |
((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl); |
|
129 |
✓✓ | 21457 |
CHECK_OB(decl->type) |
130 |
✗✓ | 21435 |
if(GET_FLAG(decl->type, const)) |
131 |
exp_setmeta(exp_self(decl), 1); |
||
132 |
21435 |
const m_bool global = GET_FLAG(decl->td, global); |
|
133 |
✓✓ | 21435 |
if(global) { |
134 |
✓✓ | 8 |
if(env->context) |
135 |
7 |
env->context->global = 1; |
|
136 |
✓✓ | 8 |
if(!is_global(decl->type->e->owner, env->global_nspc)) |
137 |
2 |
ERR_B(exp_self(decl)->pos, _("type '%s' is not global"), decl->type->name) |
|
138 |
} |
||
139 |
✓✓ | 21433 |
const m_uint scope = !global ? env->scope->depth : env_push_global(env); |
140 |
21433 |
const m_bool ret = scan1_decl(env, decl); |
|
141 |
✓✓ | 21433 |
if(global) |
142 |
6 |
env_pop(env, scope); |
|
143 |
21433 |
return ret; |
|
144 |
} |
||
145 |
|||
146 |
795 |
ANN static inline int opiscall(const Symbol sym) { |
|
147 |
795 |
const m_str opname = s_name(sym); |
|
148 |
✓✓✓✓ ✓✓ |
907 |
return (opname[0] == '@' || opname[0] == '$') && |
149 |
✗✓ | 215 |
(isalpha(opname[1]) || opname[1] == '_'); |
150 |
} |
||
151 |
|||
152 |
3 |
ANN static inline Exp sym2func(const Env env, const Symbol sym, const loc_t pos) { |
|
153 |
3 |
MemPool mp = env->gwion->mp; |
|
154 |
3 |
const m_str name = s_name(sym); |
|
155 |
3 |
return new_prim_id(mp, insert_symbol(name + 1), loc_cpy(mp, pos)); |
|
156 |
} |
||
157 |
|||
158 |
1 |
ANN static void binary_args(const Exp_Binary* bin) { |
|
159 |
1 |
Exp arg = bin->lhs; |
|
160 |
✗✓ | 2 |
while(arg->next) |
161 |
arg = arg->next; |
||
162 |
1 |
arg->next = bin->rhs; |
|
163 |
1 |
} |
|
164 |
|||
165 |
3 |
ANN static m_bool exp2call(const Env env, const Exp e, const Symbol sym, const Exp args) { |
|
166 |
3 |
e->exp_type = ae_exp_call; |
|
167 |
3 |
e->d.exp_call.func = sym2func(env, sym, e->pos); |
|
168 |
3 |
e->d.exp_call.args = args; |
|
169 |
3 |
return scan1_exp(env, e); |
|
170 |
} |
||
171 |
|||
172 |
1 |
ANN static m_bool binary2call(const Env env, const Exp_Binary* bin) { |
|
173 |
1 |
binary_args(bin); |
|
174 |
1 |
return exp2call(env, exp_self(bin), bin->op, bin->lhs); |
|
175 |
} |
||
176 |
|||
177 |
639 |
ANN static inline m_bool scan1_exp_binary(const Env env, const Exp_Binary* bin) { |
|
178 |
✓✓ | 639 |
if(opiscall(bin->op)) |
179 |
1 |
return binary2call(env, bin); |
|
180 |
✗✓ | 638 |
CHECK_BB(scan1_exp(env, bin->lhs)) |
181 |
638 |
return scan1_exp(env, bin->rhs); |
|
182 |
} |
||
183 |
|||
184 |
12 |
ANN static m_bool scan1_range(const Env env, Range *range) { |
|
185 |
✓✓ | 12 |
if(range->start) |
186 |
✗✓ | 11 |
CHECK_BB(scan1_exp(env, range->start)) |
187 |
✓✓ | 12 |
if(range->end) |
188 |
✗✓ | 8 |
CHECK_BB(scan1_exp(env, range->end)) |
189 |
12 |
return GW_OK; |
|
190 |
} |
||
191 |
|||
192 |
4412 |
ANN static inline m_bool scan1_prim(const Env env, const Exp_Primary* prim) { |
|
193 |
✓✓✓✓ ✓✓ |
7740 |
if(prim->prim_type == ae_prim_hack || prim->prim_type == ae_prim_typeof || |
194 |
3328 |
prim->prim_type == ae_prim_interp) |
|
195 |
1089 |
return scan1_exp(env, prim->d.exp); |
|
196 |
✓✓✓✓ |
3323 |
if(prim->prim_type == ae_prim_array && prim->d.array->exp) |
197 |
22 |
return scan1_exp(env, prim->d.array->exp); |
|
198 |
✓✓ | 3301 |
if(prim->prim_type == ae_prim_range) |
199 |
3 |
return scan1_range(env, prim->d.range); |
|
200 |
3298 |
return GW_OK; |
|
201 |
} |
||
202 |
|||
203 |
30 |
ANN static inline m_bool scan1_exp_array(const Env env, const Exp_Array* array) { |
|
204 |
✗✓ | 30 |
CHECK_BB(scan1_exp(env, array->base)) |
205 |
30 |
return scan1_exp(env, array->array->exp); |
|
206 |
} |
||
207 |
|||
208 |
9 |
ANN static inline m_bool scan1_exp_slice(const Env env, const Exp_Slice* range) { |
|
209 |
✗✓ | 9 |
CHECK_BB(scan1_exp(env, range->base)) |
210 |
9 |
return scan1_range(env, range->range); |
|
211 |
} |
||
212 |
|||
213 |
40 |
ANN static inline m_bool scan1_exp_cast(const Env env, const Exp_Cast* cast) { |
|
214 |
40 |
return scan1_exp(env, cast->exp); |
|
215 |
} |
||
216 |
|||
217 |
39 |
ANN static m_bool scan1_exp_post(const Env env, const Exp_Postfix* post) { |
|
218 |
✓✓ | 39 |
if(opiscall(post->op)) { |
219 |
1 |
return exp2call(env, exp_self(post), post->op, post->exp); |
|
220 |
} |
||
221 |
✗✓ | 38 |
CHECK_BB(scan1_exp(env, post->exp)) |
222 |
38 |
const m_str access = exp_access(post->exp); |
|
223 |
✓✓ | 38 |
if(!access) |
224 |
37 |
return GW_OK; |
|
225 |
1 |
ERR_B(post->exp->pos, _("post operator '%s' cannot be used" |
|
226 |
" on %s data-type..."), s_name(post->op), access); |
||
227 |
} |
||
228 |
|||
229 |
553 |
ANN static m_bool scan1_exp_call(const Env env, const Exp_Call* exp_call) { |
|
230 |
✓✓ | 553 |
if(exp_call->tmpl) |
231 |
32 |
return GW_OK; |
|
232 |
✓✓ | 521 |
CHECK_BB(scan1_exp(env, exp_call->func)) |
233 |
520 |
const Exp args = exp_call->args; |
|
234 |
✓✓ | 520 |
return args ? scan1_exp(env, args) : GW_OK; |
235 |
} |
||
236 |
|||
237 |
555 |
ANN static inline m_bool scan1_exp_dot(const Env env, const Exp_Dot* member) { |
|
238 |
✓✓ | 555 |
if(member->base->next) |
239 |
1 |
ERR_B(member->base->pos, _("can't use multiple expression" |
|
240 |
" in dot member base expression")) |
||
241 |
554 |
return scan1_exp(env, member->base); |
|
242 |
} |
||
243 |
|||
244 |
10 |
ANN static m_bool scan1_exp_if(const Env env, const Exp_If* exp_if) { |
|
245 |
✗✓ | 10 |
CHECK_BB(scan1_exp(env, exp_if->cond)) |
246 |
✓✓✗✓ |
10 |
CHECK_BB(scan1_exp(env, exp_if->if_exp ?: exp_if->cond)) |
247 |
10 |
return scan1_exp(env, exp_if->else_exp); |
|
248 |
} |
||
249 |
|||
250 |
142 |
ANN static inline m_bool scan1_exp_unary(const restrict Env env, const Exp_Unary *unary) { |
|
251 |
✓✓✓✓ ✓✓ |
142 |
if((unary->op == insert_symbol("spork") || unary->op == insert_symbol("fork")) && unary->code) |
252 |
25 |
{ RET_NSPC(scan1_stmt(env, unary->code)) } |
|
253 |
✓✓ | 117 |
else if(opiscall(unary->op)) { |
254 |
1 |
return exp2call(env, exp_self(unary), unary->op, unary->exp); |
|
255 |
} |
||
256 |
✓✓ | 116 |
return unary->exp ? scan1_exp(env, unary->exp) : GW_OK; |
257 |
} |
||
258 |
|||
259 |
#define scan1_exp_lambda dummy_func |
||
260 |
✓✓✓✓ |
27907 |
HANDLE_EXP_FUNC(scan1, m_bool, Env) |
261 |
|||
262 |
11 |
ANN static inline m_bool _scan1_stmt_match_case(const restrict Env env, const Stmt_Match stmt) { |
|
263 |
✗✓ | 11 |
CHECK_BB(scan1_exp(env, stmt->cond)) |
264 |
✓✓ | 11 |
if(stmt->when) |
265 |
✗✓ | 4 |
CHECK_BB(scan1_exp(env, stmt->when)) |
266 |
11 |
return scan1_stmt_list(env, stmt->list); |
|
267 |
} |
||
268 |
|||
269 |
11 |
ANN static inline m_bool scan1_stmt_match_case(const restrict Env env, const Stmt_Match stmt) { |
|
270 |
11 |
RET_NSPC(_scan1_stmt_match_case(env, stmt)) |
|
271 |
} |
||
272 |
|||
273 |
7 |
ANN static inline m_bool _scan1_stmt_match(const restrict Env env, const Stmt_Match stmt) { |
|
274 |
✓✓ | 7 |
if(stmt->where) |
275 |
✗✓ | 2 |
CHECK_BB(scan1_stmt(env, stmt->where)) |
276 |
7 |
Stmt_List list = stmt->list; |
|
277 |
✗✓ | 11 |
do CHECK_BB(scan1_stmt_match_case(env, &list->stmt->d.stmt_match)) |
278 |
✓✓ | 11 |
while((list = list->next)); |
279 |
7 |
return GW_OK; |
|
280 |
} |
||
281 |
|||
282 |
7 |
ANN static inline m_bool scan1_stmt_match(const restrict Env env, const Stmt_Match stmt) { |
|
283 |
✗✓ | 7 |
CHECK_BB(scan1_exp(env, stmt->cond)) |
284 |
7 |
RET_NSPC(_scan1_stmt_match(env, stmt)) |
|
285 |
} |
||
286 |
|||
287 |
#define describe_ret_nspc(name, type, prolog, exp) describe_stmt_func(scan1, name, type, prolog, exp) |
||
288 |
✓✗✓✗ |
26 |
describe_ret_nspc(flow, Stmt_Flow,, !(scan1_exp(env, stmt->cond) < 0 || |
289 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
290 |
✓✗✓✗ |
10 |
describe_ret_nspc(varloop, Stmt_VarLoop,, !(scan1_exp(env, stmt->exp) < 0 || |
291 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
292 |
✓✗✓✗ ✓✓✓✗ ✓✗ |
11 |
describe_ret_nspc(for, Stmt_For,, !(scan1_stmt(env, stmt->c1) < 0 || |
293 |
scan1_stmt(env, stmt->c2) < 0 || |
||
294 |
(stmt->c3 && scan1_exp(env, stmt->c3) < 0) || |
||
295 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
296 |
✓✗✓✗ |
11 |
describe_ret_nspc(auto, Stmt_Auto,, !(scan1_exp(env, stmt->exp) < 0 || |
297 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
298 |
✓✗✓✗ |
8 |
describe_ret_nspc(loop, Stmt_Loop,, !(scan1_exp(env, stmt->cond) < 0 || |
299 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
300 |
✓✗✓✗ ✓✓✓✗ |
39 |
describe_ret_nspc(if, Stmt_If,, !(scan1_exp(env, stmt->cond) < 0 || |
301 |
scan1_stmt(env, stmt->if_body) < 0 || |
||
302 |
(stmt->else_body && scan1_stmt(env, stmt->else_body) < 0)) ? 1 : -1) |
||
303 |
|||
304 |
157 |
ANN static inline m_bool scan1_stmt_code(const Env env, const Stmt_Code stmt) { |
|
305 |
✓✓ | 157 |
if(stmt->stmt_list) |
306 |
153 |
{ RET_NSPC(scan1_stmt_list(env, stmt->stmt_list)) } |
|
307 |
4 |
return GW_OK; |
|
308 |
} |
||
309 |
|||
310 |
2524 |
ANN static inline m_bool scan1_stmt_exp(const Env env, const Stmt_Exp stmt) { |
|
311 |
✓✓ | 2524 |
return stmt->val ? scan1_exp(env, stmt->val) : 1; |
312 |
} |
||
313 |
|||
314 |
722 |
ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) { |
|
315 |
722 |
ID_List list = edef->list; |
|
316 |
do { |
||
317 |
✗✓ | 1478 |
CHECK_BB(already_defined(env, list->xid, edef->pos)) |
318 |
1478 |
const Value v = new_value(env->gwion->mp, edef->t, s_name(list->xid)); |
|
319 |
1478 |
valuefrom(env, v->from); |
|
320 |
✓✓ | 1478 |
if(env->class_def) { |
321 |
28 |
SET_FLAG(v, static); |
|
322 |
✓✓✗✓ |
28 |
SET_ACCESS(edef, v) |
323 |
✓✓✗✓ |
28 |
SET_ACCESS(edef, edef->t) |
324 |
} |
||
325 |
1478 |
SET_FLAG(v, const | ae_flag_enum | ae_flag_valid); |
|
326 |
1478 |
nspc_add_value(edef->t->e->owner, list->xid, v); |
|
327 |
1478 |
vector_add(&edef->values, (vtype)v); |
|
328 |
✓✓ | 1478 |
} while((list = list->next)); |
329 |
722 |
return GW_OK; |
|
330 |
} |
||
331 |
|||
332 |
23744 |
ANN static Value arg_value(const Env env, const Arg_List list) { |
|
333 |
23744 |
const Var_Decl var = list->var_decl; |
|
334 |
✓✓ | 23744 |
const Value v = new_value(env->gwion->mp, list->type, var->xid ? s_name(var->xid) : (m_str)__func__); |
335 |
✓✓ | 23744 |
if(var->array) |
336 |
8 |
v->type = list->type = array_type(env, list->type, var->array->depth); |
|
337 |
✓✓ | 23744 |
if(list->td) |
338 |
23739 |
v->flag = list->td->flag | ae_flag_abstract; |
|
339 |
23744 |
return v; |
|
340 |
} |
||
341 |
|||
342 |
23751 |
ANN static m_bool scan1_args(const Env env, Arg_List list) { |
|
343 |
do { |
||
344 |
23751 |
const Var_Decl var = list->var_decl; |
|
345 |
✓✓ | 23751 |
if(var->xid) |
346 |
✓✓ | 23747 |
CHECK_BB(isres(env, var->xid, var->pos)) |
347 |
✓✓ | 23750 |
if(list->td) |
348 |
✓✓ | 23745 |
CHECK_OB((list->type = void_type(env, list->td))) |
349 |
23744 |
var->value = arg_value(env, list); |
|
350 |
23744 |
nspc_add_value(env->curr, var->xid, var->value); |
|
351 |
✓✓ | 23744 |
} while((list = list->next)); |
352 |
16551 |
return GW_OK; |
|
353 |
} |
||
354 |
|||
355 |
139 |
ANN static m_bool _scan1_fdef_base_tmpl(const Env env, Func_Base *base) { |
|
356 |
139 |
ID_List id = base->tmpl->list; |
|
357 |
149 |
do nspc_add_type(env->curr, id->xid, env->gwion->type[et_undefined]); |
|
358 |
✓✓ | 149 |
while((id = id->next)); |
359 |
✓✓ | 139 |
CHECK_OB((base->ret_type = known_type(env, base->td))) |
360 |
✓✓ | 138 |
if(base->args) { |
361 |
92 |
Arg_List arg = base->args; |
|
362 |
✓✓ | 136 |
do CHECK_OB(known_type(env, arg->td)) |
363 |
✓✓ | 135 |
while((arg = arg->next)); |
364 |
} |
||
365 |
137 |
return GW_OK; |
|
366 |
} |
||
367 |
|||
368 |
139 |
ANN static m_bool scan1_fdef_base_tmpl(const Env env, Func_Base *base) { |
|
369 |
139 |
nspc_push_type(env->gwion->mp, env->curr); |
|
370 |
139 |
const m_bool ret = _scan1_fdef_base_tmpl(env, base); |
|
371 |
139 |
nspc_pop_type(env->gwion->mp, env->curr); |
|
372 |
139 |
return ret; |
|
373 |
} |
||
374 |
|||
375 |
76 |
ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) { |
|
376 |
✓✓ | 76 |
if(tmpl_base(fptr->base->tmpl)) |
377 |
16 |
return scan1_fdef_base_tmpl(env, fptr->base); |
|
378 |
✗✓ | 60 |
if(!fptr->base->func) { |
379 |
fptr->base->func = nspc_lookup_value0(env->curr, fptr->base->xid)->d.func_ref; |
||
380 |
fptr->type = nspc_lookup_type0(env->curr, fptr->base->xid); |
||
381 |
} |
||
382 |
60 |
const Func_Def fdef = fptr->base->func->def; |
|
383 |
✓✓ | 60 |
CHECK_OB((fdef->base->ret_type = scan1_type(env, fdef->base->td))) |
384 |
✓✓ | 58 |
if(!fdef->base->args) |
385 |
32 |
return GW_OK; |
|
386 |
26 |
RET_NSPC(scan1_args(env, fdef->base->args)) |
|
387 |
} |
||
388 |
|||
389 |
732 |
ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) { |
|
390 |
✗✓ | 732 |
if(!tdef->type) |
391 |
tdef->type = nspc_lookup_type0(env->curr, tdef->xid); |
||
392 |
✓✓ | 732 |
if(!tdef->type->e->def)return GW_OK; |
393 |
✓✗ | 8 |
return !is_fptr(env->gwion, tdef->type) ? scan1_cdef(env, tdef->type->e->def) : GW_OK; |
394 |
} |
||
395 |
|||
396 |
37 |
ANN static m_bool scan1_union_def_action(const Env env, const Union_Def udef, |
|
397 |
const Decl_List l) { |
||
398 |
37 |
const Exp_Decl decl = l->self->d.exp_decl; |
|
399 |
37 |
SET_FLAG(decl.td, valid | udef->flag); |
|
400 |
37 |
const m_bool global = GET_FLAG(udef, global); |
|
401 |
✓✓ | 37 |
if(global) |
402 |
6 |
UNSET_FLAG(decl.td, global); |
|
403 |
✓✓ | 37 |
if(GET_FLAG(udef, member)) |
404 |
3 |
SET_FLAG(decl.td, member); |
|
405 |
✓✓ | 34 |
else if(GET_FLAG(udef, static)) |
406 |
4 |
SET_FLAG(decl.td, static); |
|
407 |
✓✓ | 37 |
CHECK_BB(scan1_exp(env, l->self)) |
408 |
|||
409 |
35 |
Var_Decl_List list = decl.list; |
|
410 |
35 |
do ADD_REF(list->self->value) |
|
411 |
✗✓ | 35 |
while((list = list->next)); |
412 |
|||
413 |
✓✓ | 35 |
if(global) |
414 |
6 |
SET_FLAG(decl.td, global); |
|
415 |
35 |
return GW_OK; |
|
416 |
} |
||
417 |
|||
418 |
37 |
ANN static inline m_bool scan1_union_def_inner_loop(const Env env, const Union_Def udef, Decl_List l) { |
|
419 |
✓✓ | 37 |
do CHECK_BB(scan1_union_def_action(env, udef, l)) |
420 |
✓✓ | 35 |
while((l = l->next)); |
421 |
18 |
return GW_OK; |
|
422 |
} |
||
423 |
|||
424 |
20 |
ANN static m_bool scan1_union_def_inner(const Env env, const Union_Def udef) { |
|
425 |
✓✓✓✗ |
20 |
if(udef->tmpl && udef->tmpl->call) |
426 |
✗✓ | 3 |
CHECK_BB(template_push_types(env, udef->tmpl)) |
427 |
20 |
const m_bool ret = scan1_union_def_inner_loop(env, udef, udef->l); |
|
428 |
✓✓✓✗ |
20 |
if(udef->tmpl && udef->tmpl->call) |
429 |
3 |
nspc_pop_type(env->gwion->mp, env->curr); |
|
430 |
20 |
return ret; |
|
431 |
} |
||
432 |
|||
433 |
24 |
ANN m_bool scan1_union_def(const Env env, const Union_Def udef) { |
|
434 |
✓✓ | 24 |
if(tmpl_base(udef->tmpl)) |
435 |
4 |
return GW_OK; |
|
436 |
20 |
const m_uint scope = union_push(env, udef); |
|
437 |
✓✓✓✓ |
20 |
if(udef->xid || udef->type_xid) { |
438 |
12 |
UNSET_FLAG(udef, private); |
|
439 |
12 |
UNSET_FLAG(udef, protect); |
|
440 |
} |
||
441 |
20 |
const m_bool ret = scan1_union_def_inner(env, udef); |
|
442 |
20 |
union_pop(env, udef, scope); |
|
443 |
20 |
union_flag(udef, ae_flag_scan1); |
|
444 |
20 |
return ret; |
|
445 |
} |
||
446 |
|||
447 |
#define scan1_stmt_while scan1_stmt_flow |
||
448 |
#define scan1_stmt_until scan1_stmt_flow |
||
449 |
#define scan1_stmt_continue (void*)dummy_func |
||
450 |
#define scan1_stmt_break (void*)dummy_func |
||
451 |
#define scan1_stmt_jump (void*)dummy_func |
||
452 |
#define scan1_stmt_return scan1_stmt_exp |
||
453 |
#define scan1_stmt_pp (void*)dummy_func |
||
454 |
DECL_STMT_FUNC(scan1, m_bool, Env) |
||
455 |
|||
456 |
2828 |
ANN static inline m_bool scan1_stmt(const Env env, const Stmt stmt) { |
|
457 |
2828 |
return scan1_stmt_func[stmt->stmt_type](env, &stmt->d); |
|
458 |
} |
||
459 |
|||
460 |
2662 |
ANN static m_bool scan1_stmt_list(const Env env, Stmt_List l) { |
|
461 |
do { |
||
462 |
✓✓ | 2662 |
CHECK_BB(scan1_stmt(env, l->stmt)) |
463 |
✓✓ | 2628 |
if(l->next) { |
464 |
✓✓ | 1530 |
if(l->stmt->stmt_type != ae_stmt_return) { |
465 |
✓✓✓✓ |
2875 |
if(l->next->stmt->stmt_type == ae_stmt_exp && |
466 |
1346 |
!l->next->stmt->d.stmt_exp.val) { |
|
467 |
4 |
Stmt_List next = l->next; |
|
468 |
4 |
l->next = l->next->next; |
|
469 |
4 |
next->next = NULL; |
|
470 |
4 |
free_stmt_list(env->gwion->mp, next); |
|
471 |
} |
||
472 |
} else { |
||
473 |
1 |
Stmt_List tmp = l->next; |
|
474 |
1 |
l->next = NULL; |
|
475 |
1 |
free_stmt_list(env->gwion->mp, tmp); |
|
476 |
} |
||
477 |
} |
||
478 |
✓✓ | 2628 |
} while((l = l->next)); |
479 |
1103 |
return GW_OK; |
|
480 |
} |
||
481 |
|||
482 |
11 |
ANN static m_bool class_internal(const Env env, const Func_Base *base) { |
|
483 |
✓✓ | 11 |
if(!env->class_def) |
484 |
1 |
ERR_B(td_pos(base->td), _("'%s' must be in class def!!"), s_name(base->xid)) |
|
485 |
✓✓ | 10 |
if(base->args) |
486 |
1 |
ERR_B(td_pos(base->td), _("'%s' must not have args"), s_name(base->xid)) |
|
487 |
✓✓ | 9 |
if(base->ret_type != env->gwion->type[et_void]) |
488 |
1 |
ERR_B(td_pos(base->td), _("'%s' must return 'void'"), s_name(base->xid)) |
|
489 |
8 |
return GW_OK; |
|
490 |
} |
||
491 |
|||
492 |
6 |
ANN static inline m_bool scan_internal_arg(const Env env, const Func_Base *base) { |
|
493 |
✓✗✓✓ |
6 |
if(base->args && !base->args->next) |
494 |
5 |
return GW_OK; |
|
495 |
1 |
ERR_B(td_pos(base->td), _("'%s' must have one (and only one) argument"), s_name(base->xid)) |
|
496 |
} |
||
497 |
|||
498 |
3 |
ANN static inline m_bool scan_internal_int(const Env env, const Func_Base *base) { |
|
499 |
✗✓ | 3 |
CHECK_BB(scan_internal_arg(env, base)) |
500 |
✓✓ | 3 |
if(isa(base->ret_type, env->gwion->type[et_int]) > 0) |
501 |
2 |
return GW_OK; |
|
502 |
1 |
ERR_B(td_pos(base->td), _("'%s' must return 'int'"), s_name(base->xid)) |
|
503 |
} |
||
504 |
|||
505 |
22 |
ANN static m_bool scan_internal(const Env env, const Func_Base *base) { |
|
506 |
22 |
const Symbol op = base->xid; |
|
507 |
✓✓✓✓ |
22 |
if(op == insert_symbol("@dtor") || op == insert_symbol("@gack")) |
508 |
11 |
return class_internal(env, base); |
|
509 |
✓✓ | 11 |
if(op == insert_symbol("@implicit")) |
510 |
3 |
return scan_internal_arg(env, base); |
|
511 |
✓✓✓✓ |
14 |
if(op == insert_symbol("@conditionnal") || |
512 |
6 |
op == insert_symbol("@unconditionnal")) |
|
513 |
3 |
return scan_internal_int(env, base); |
|
514 |
5 |
return GW_OK; |
|
515 |
} |
||
516 |
|||
517 |
230 |
ANN static m_bool scan1_fdef_args(const Env env, Arg_List list) { |
|
518 |
do { |
||
519 |
230 |
Nspc nspc = env->curr; |
|
520 |
✗✓ | 1025 |
do if(nspc_lookup_value0(nspc, list->var_decl->xid)) |
521 |
ERR_B(list->var_decl->pos, _("argument '%s' shadows a previuosly defined variable"), |
||
522 |
s_name(list->var_decl->xid)) |
||
523 |
✓✓ | 1025 |
while((nspc = nspc->parent)); |
524 |
✓✓ | 230 |
} while((list = list->next)); |
525 |
171 |
return GW_OK; |
|
526 |
} |
||
527 |
|||
528 |
42277 |
ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) { |
|
529 |
✓✓ | 42277 |
if(fdef->base->args) { |
530 |
✓✓ | 16532 |
if(!GET_FLAG(fdef, builtin)) |
531 |
✗✓ | 171 |
CHECK_BB(scan1_fdef_args(env, fdef->base->args)) |
532 |
✓✓ | 16532 |
CHECK_BB(scan1_args(env, fdef->base->args)) |
533 |
} |
||
534 |
✓✓✓✓ ✓✓ |
42272 |
if(!GET_FLAG(fdef, builtin) && fdef->d.code && fdef->d.code->d.stmt_code.stmt_list) |
535 |
✓✓ | 245 |
CHECK_BB(scan1_stmt_list(env, fdef->d.code->d.stmt_code.stmt_list)) |
536 |
42271 |
return GW_OK; |
|
537 |
} |
||
538 |
|||
539 |
42283 |
ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) { |
|
540 |
✓✓ | 42283 |
if(fdef->base->td) |
541 |
✓✓ | 42275 |
CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td))) |
542 |
✓✓ | 42282 |
if(GET_FLAG(fdef, typedef)) |
543 |
✓✓ | 22 |
CHECK_BB(scan_internal(env, fdef->base)) |
544 |
✓✓✓✓ |
42260 |
else if(GET_FLAG(fdef, op) && env->class_def) |
545 |
2 |
SET_FLAG(fdef, static); |
|
546 |
42277 |
RET_NSPC(scan1_fbody(env, fdef)) |
|
547 |
return GW_OK; |
||
548 |
} |
||
549 |
|||
550 |
42410 |
ANN static inline m_bool scan1_fdef_defined(const Env env, const Func_Def fdef) { |
|
551 |
42410 |
const Value v = nspc_lookup_value1(env->curr, fdef->base->xid); |
|
552 |
✓✓ | 42410 |
if(!v) |
553 |
33789 |
return GW_OK; |
|
554 |
✓✓ | 8621 |
if(isa(actual_type(env->gwion, v->type), env->gwion->type[et_function]) > 0) |
555 |
8620 |
return GW_OK; |
|
556 |
1 |
ERR_B(fdef->pos, _("function '%s' has already been defined in the same scope..."), |
|
557 |
s_name(fdef->base->xid)) |
||
558 |
} |
||
559 |
|||
560 |
42413 |
ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) { |
|
561 |
✓✓ | 42413 |
if(fdef->base->td) |
562 |
✓✓ | 42405 |
CHECK_BB(env_storage(env, fdef->flag, td_pos(fdef->base->td))) |
563 |
✓✓ | 42410 |
CHECK_BB(scan1_fdef_defined(env, fdef)) |
564 |
✓✓ | 42409 |
if(tmpl_base(fdef->base->tmpl)) |
565 |
123 |
return scan1_fdef_base_tmpl(env, fdef->base); |
|
566 |
42286 |
struct Func_ fake = { .name=s_name(fdef->base->xid) }, *const former = env->func; |
|
567 |
42286 |
env->func = &fake; |
|
568 |
42286 |
++env->scope->depth; |
|
569 |
42286 |
const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)scan1_fdef); |
|
570 |
42286 |
--env->scope->depth; |
|
571 |
42286 |
env->func = former; |
|
572 |
42286 |
return ret; |
|
573 |
} |
||
574 |
|||
575 |
1380 |
HANDLE_SECTION_FUNC(scan1, m_bool, Env) |
|
576 |
|||
577 |
70 |
ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) { |
|
578 |
70 |
const Type parent = known_type(env, tdef->ext); |
|
579 |
✗✓ | 70 |
CHECK_OO((tdef->type->e->parent = parent)); |
580 |
70 |
Type t = parent; |
|
581 |
✗✓ | 245 |
do if(tdef->type == t) |
582 |
ERR_O(td_pos(tdef->ext), _("recursive (%s <= %s) class declaration."), tdef->type->name, t->name) |
||
583 |
✓✓ | 245 |
while((t = t->e->parent)); |
584 |
70 |
return parent; |
|
585 |
} |
||
586 |
|||
587 |
70 |
ANN static m_bool scan1_parent(const Env env, const Class_Def cdef) { |
|
588 |
70 |
const loc_t pos = td_pos(cdef->base.ext); |
|
589 |
✓✓ | 70 |
if(cdef->base.ext->array) |
590 |
✗✓ | 9 |
CHECK_BB(scan1_exp(env, cdef->base.ext->array->exp)) |
591 |
✗✓ | 70 |
DECL_OB(const Type , parent, = scan1_get_parent(env, &cdef->base)) |
592 |
✓✓ | 70 |
if(isa(parent, env->gwion->type[et_object]) < 0) |
593 |
1 |
ERR_B(pos, _("cannot extend primitive type '%s'"), parent->name) |
|
594 |
✓✓✓✓ |
69 |
if(parent->e->def && !GET_FLAG(parent, scan1)) |
595 |
✗✓ | 6 |
CHECK_BB(ensure_scan1(env, parent)) |
596 |
✓✓ | 69 |
if(type_ref(parent)) |
597 |
1 |
ERR_B(pos, _("can't use ref type in class extend")) |
|
598 |
✓✓ | 68 |
if(GET_FLAG(parent, nonnull)) |
599 |
1 |
ERR_B(pos, _("can't use nonnull type in class extend")) |
|
600 |
67 |
return GW_OK; |
|
601 |
} |
||
602 |
|||
603 |
70 |
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { |
|
604 |
✓✓✓✗ |
70 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
605 |
✗✓ | 22 |
CHECK_BB(template_push_types(env, cdef->base.tmpl)) |
606 |
70 |
const m_bool ret = scan1_parent(env, cdef); |
|
607 |
✓✓✓✗ |
70 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
608 |
22 |
nspc_pop_type(env->gwion->mp, env->curr); |
|
609 |
70 |
return ret; |
|
610 |
} |
||
611 |
|||
612 |
289 |
ANN m_bool scan1_class_def(const Env env, const Class_Def cdef) { |
|
613 |
✓✓ | 289 |
if(tmpl_base(cdef->base.tmpl)) |
614 |
22 |
return GW_OK; |
|
615 |
267 |
const Type t = cdef->base.type; |
|
616 |
✓✓ | 267 |
if(GET_FLAG(t, scan1)) |
617 |
2 |
return GW_OK; |
|
618 |
265 |
SET_FLAG(t, scan1); |
|
619 |
✓✓✗✓ |
265 |
if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan1)) |
620 |
CHECK_BB(ensure_scan1(env, t->e->owner_class)) |
||
621 |
265 |
SET_FLAG(cdef->base.type, scan1); |
|
622 |
✓✓ | 265 |
if(cdef->base.ext) |
623 |
✓✓ | 70 |
CHECK_BB(cdef_parent(env, cdef)) |
624 |
✓✓ | 262 |
if(cdef->body) |
625 |
✓✓ | 216 |
CHECK_BB(env_body(env, cdef, scan1_section)) |
626 |
256 |
return GW_OK; |
|
627 |
} |
||
628 |
|||
629 |
1009 |
ANN m_bool scan1_ast(const Env env, Ast ast) { |
|
630 |
✓✓ | 1009 |
do CHECK_BB(scan1_section(env, ast->section)) |
631 |
✓✓ | 957 |
while((ast = ast->next)); |
632 |
553 |
return GW_OK; |
|
633 |
} |
Generated by: GCOVR (Version 4.2) |