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