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 |
11615 |
ANN static inline m_bool type_cyclic(const Env env, const Type t, const Type_Decl *td) { |
|
14 |
11615 |
Type owner = env->class_def; |
|
15 |
do { |
||
16 |
11626 |
Type parent = t; |
|
17 |
✓✓ | 43541 |
while(parent) { |
18 |
✓✓ | 20290 |
if(parent == owner) |
19 |
1 |
ERR_B(td_pos(td), _("%s declared inside %s"), t->name, owner->name); |
|
20 |
20289 |
parent = parent->e->parent; |
|
21 |
} |
||
22 |
✓✓ | 11625 |
} while((owner = owner->e->owner_class)); |
23 |
11614 |
return GW_OK; |
|
24 |
} |
||
25 |
|||
26 |
35 |
ANN static inline m_bool ensure_scan1(const Env env, const Type t) { |
|
27 |
70 |
struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan1_cdef, |
|
28 |
35 |
.scope=env->scope->depth, .flag=ae_flag_scan1 }; |
|
29 |
35 |
return envset_run(&es, t); |
|
30 |
} |
||
31 |
|||
32 |
45313 |
ANN static Type scan1_type(const Env env, Type_Decl* td) { |
|
33 |
✓✓ | 45313 |
DECL_OO(const Type, type, = known_type(env, td)) |
34 |
45290 |
const Type t = get_type(type); |
|
35 |
✓✓✓✓ ✓✓ |
45290 |
if(!env->func && env->class_def && !GET_FLAG(td, ref)) |
36 |
✓✓ | 11615 |
CHECK_BO(type_cyclic(env, t, td)) |
37 |
✓✓✓✓ |
45289 |
if(!GET_FLAG(t, scan1) && t->e->def) |
38 |
✗✓ | 29 |
CHECK_BO(ensure_scan1(env, t)) |
39 |
45289 |
return type; |
|
40 |
} |
||
41 |
|||
42 |
45249 |
ANN static Type void_type(const Env env, Type_Decl* td) { |
|
43 |
✓✓ | 45249 |
DECL_OO(const Type, type, = scan1_type(env, td)) |
44 |
✓✓ | 45227 |
if(type->size) |
45 |
45224 |
return type; |
|
46 |
3 |
ERR_O(td_pos(td), _("cannot declare variables of size '0' (i.e. 'void')...")) |
|
47 |
} |
||
48 |
|||
49 |
21488 |
ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) { |
|
50 |
✓✓ | 21488 |
if(decl->type) |
51 |
21 |
return decl->type; |
|
52 |
✓✓ | 21467 |
DECL_OO(const Type ,t, = void_type(env, decl->td)) |
53 |
✓✓✗✓ |
21448 |
if(decl->td->xid == insert_symbol("auto") && decl->type) |
54 |
return decl->type; |
||
55 |
✓✓✓✓ ✓✓ |
21448 |
if(!env->scope->depth && env->class_def && !GET_FLAG(decl->td, static)) |
56 |
11566 |
SET_FLAG(decl->td, member); |
|
57 |
✓✓✓✗ |
21448 |
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 |
✓✓✗✓ ✗✗ |
21447 |
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 |
21446 |
return decl->type = t; |
|
62 |
} |
||
63 |
|||
64 |
21474 |
static inline m_bool scan1_defined(const Env env, const Var_Decl var) { |
|
65 |
✓✓ | 21474 |
if(var->value) // from a `typeof` declaration |
66 |
21 |
return GW_OK; |
|
67 |
✓✓✓✓ ✓✓ |
21453 |
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 |
21450 |
return GW_OK; |
|
71 |
} |
||
72 |
|||
73 |
21465 |
ANN static m_bool scan1_decl(const Env env, const Exp_Decl* decl) { |
|
74 |
21465 |
Var_Decl_List list = decl->list; |
|
75 |
do { |
||
76 |
21474 |
const Var_Decl var = list->self; |
|
77 |
✗✓ | 21474 |
CHECK_BB(isres(env, var->xid, exp_self(decl)->pos)) |
78 |
21474 |
Type t = decl->type; |
|
79 |
✓✓ | 21474 |
CHECK_BB(scan1_defined(env, var)) |
80 |
✓✓ | 21471 |
if(var->array) { |
81 |
✓✓ | 46 |
if(var->array->exp) { |
82 |
✓✓ | 38 |
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 |
✗✓ | 37 |
CHECK_BB(scan1_exp(env, var->array->exp)) |
86 |
} |
||
87 |
45 |
t = array_type(env, decl->type, var->array->depth); |
|
88 |
✓✓✓✓ |
21425 |
} 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 |
✓✓ | 21469 |
const Value v = var->value = var->value ?: new_value(env->gwion->mp, t, s_name(var->xid)); |
95 |
✓✓✓✓ ✓✓ |
21469 |
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 |
21469 |
nspc_add_value(env->curr, var->xid, v); |
|
100 |
21469 |
v->flag = decl->td->flag; |
|
101 |
21469 |
v->type = t; |
|
102 |
✓✓✓✓ |
21469 |
if(var->array && !var->array->exp) |
103 |
8 |
SET_FLAG(v, ref); |
|
104 |
✓✓ | 21469 |
if(env->class_def) { |
105 |
✓✗ | 11603 |
if(env->class_def->e->tuple) |
106 |
11603 |
tuple_contains(env, v); |
|
107 |
✓✓ | 9866 |
} else if(!env->scope->depth) |
108 |
9677 |
SET_FLAG(v, global); |
|
109 |
21469 |
v->d.ptr = var->addr; |
|
110 |
✓✓ | 21469 |
if(GET_FLAG(decl->td, global)) |
111 |
6 |
SET_FLAG(v, abstract); |
|
112 |
✓✓ | 21469 |
if(!env->scope->depth) |
113 |
21272 |
valuefrom(env, v->from); |
|
114 |
✓✓ | 21469 |
} while((list = list->next)); |
115 |
21460 |
((Exp_Decl*)decl)->type = decl->list->self->value->type; |
|
116 |
21460 |
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 |
21492 |
ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) { |
|
127 |
✓✓ | 21492 |
CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos)) |
128 |
21488 |
((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl); |
|
129 |
✓✓ | 21488 |
CHECK_OB(decl->type) |
130 |
✗✓ | 21467 |
if(GET_FLAG(decl->type, const)) |
131 |
exp_setmeta(exp_self(decl), 1); |
||
132 |
21467 |
const m_bool global = GET_FLAG(decl->td, global); |
|
133 |
✓✓ | 21467 |
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 |
✓✓ | 21465 |
const m_uint scope = !global ? env->scope->depth : env_push_global(env); |
140 |
21465 |
const m_bool ret = scan1_decl(env, decl); |
|
141 |
✓✓ | 21465 |
if(global) |
142 |
6 |
env_pop(env, scope); |
|
143 |
21465 |
return ret; |
|
144 |
} |
||
145 |
|||
146 |
799 |
ANN static inline int opiscall(const Symbol sym) { |
|
147 |
799 |
const m_str opname = s_name(sym); |
|
148 |
✓✓✓✓ ✓✓ |
911 |
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 |
643 |
ANN static inline m_bool scan1_exp_binary(const Env env, const Exp_Binary* bin) { |
|
178 |
✓✓ | 643 |
if(opiscall(bin->op)) |
179 |
1 |
return binary2call(env, bin); |
|
180 |
✗✓ | 642 |
CHECK_BB(scan1_exp(env, bin->lhs)) |
181 |
642 |
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 |
4432 |
ANN static inline m_bool scan1_prim(const Env env, const Exp_Primary* prim) { |
|
193 |
✓✓✓✓ ✓✓ |
7774 |
if(prim->prim_type == ae_prim_hack || prim->prim_type == ae_prim_typeof || |
194 |
3342 |
prim->prim_type == ae_prim_interp) |
|
195 |
1093 |
return scan1_exp(env, prim->d.exp); |
|
196 |
✓✓✓✓ |
3339 |
if(prim->prim_type == ae_prim_array && prim->d.array->exp) |
197 |
22 |
return scan1_exp(env, prim->d.array->exp); |
|
198 |
✓✓ | 3317 |
if(prim->prim_type == ae_prim_range) |
199 |
3 |
return scan1_range(env, prim->d.range); |
|
200 |
3314 |
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 |
✓✓✓✓ |
27962 |
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 |
✓✗✓✗ |
12 |
describe_ret_nspc(each, Stmt_Each,, !(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 |
2535 |
ANN static inline m_bool scan1_stmt_exp(const Env env, const Stmt_Exp stmt) { |
|
311 |
✓✓ | 2535 |
return stmt->val ? scan1_exp(env, stmt->val) : 1; |
312 |
} |
||
313 |
|||
314 |
723 |
ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) { |
|
315 |
723 |
ID_List list = edef->list; |
|
316 |
do { |
||
317 |
✗✓ | 1480 |
CHECK_BB(already_defined(env, list->xid, edef->pos)) |
318 |
1480 |
const Value v = new_value(env->gwion->mp, edef->t, s_name(list->xid)); |
|
319 |
1480 |
valuefrom(env, v->from); |
|
320 |
✓✓ | 1480 |
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 |
1480 |
SET_FLAG(v, const | ae_flag_enum | ae_flag_valid); |
|
326 |
1480 |
nspc_add_value(edef->t->e->owner, list->xid, v); |
|
327 |
1480 |
vector_add(&edef->values, (vtype)v); |
|
328 |
✓✓ | 1480 |
} while((list = list->next)); |
329 |
723 |
return GW_OK; |
|
330 |
} |
||
331 |
|||
332 |
23781 |
ANN static Value arg_value(const Env env, const Arg_List list) { |
|
333 |
23781 |
const Var_Decl var = list->var_decl; |
|
334 |
✓✓ | 23781 |
const Value v = new_value(env->gwion->mp, list->type, var->xid ? s_name(var->xid) : (m_str)__func__); |
335 |
✓✓ | 23781 |
if(var->array) |
336 |
8 |
v->type = list->type = array_type(env, list->type, var->array->depth); |
|
337 |
✓✓ | 23781 |
if(list->td) |
338 |
23776 |
v->flag = list->td->flag | ae_flag_abstract; |
|
339 |
23781 |
return v; |
|
340 |
} |
||
341 |
|||
342 |
23788 |
ANN static m_bool scan1_args(const Env env, Arg_List list) { |
|
343 |
do { |
||
344 |
23788 |
const Var_Decl var = list->var_decl; |
|
345 |
✓✓ | 23788 |
if(var->xid) |
346 |
✓✓ | 23782 |
CHECK_BB(isres(env, var->xid, var->pos)) |
347 |
✓✓ | 23787 |
if(list->td) |
348 |
✓✓ | 23782 |
CHECK_OB((list->type = void_type(env, list->td))) |
349 |
23781 |
var->value = arg_value(env, list); |
|
350 |
23781 |
nspc_add_value(env->curr, var->xid, var->value); |
|
351 |
✓✓ | 23781 |
} while((list = list->next)); |
352 |
16578 |
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 |
80 |
ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) { |
|
376 |
✓✓ | 80 |
if(tmpl_base(fptr->base->tmpl)) |
377 |
16 |
return scan1_fdef_base_tmpl(env, fptr->base); |
|
378 |
✗✓ | 64 |
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 |
64 |
const Func_Def fdef = fptr->base->func->def; |
|
383 |
✓✓ | 64 |
CHECK_OB((fdef->base->ret_type = scan1_type(env, fdef->base->td))) |
384 |
✓✓ | 62 |
if(!fdef->base->args) |
385 |
34 |
return GW_OK; |
|
386 |
28 |
RET_NSPC(scan1_args(env, fdef->base->args)) |
|
387 |
} |
||
388 |
|||
389 |
733 |
ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) { |
|
390 |
✗✓ | 733 |
if(!tdef->type) |
391 |
tdef->type = nspc_lookup_type0(env->curr, tdef->xid); |
||
392 |
✓✓ | 733 |
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 |
|||
454 |
4 |
ANN static m_bool scan1_stmt_pp(const Env env, const Stmt_PP stmt) { |
|
455 |
✓✓ | 4 |
if(stmt->pp_type == ae_pp_include) |
456 |
3 |
env->name = stmt->data; |
|
457 |
4 |
return GW_OK; |
|
458 |
} |
||
459 |
|||
460 |
DECL_STMT_FUNC(scan1, m_bool, Env) |
||
461 |
|||
462 |
2843 |
ANN static inline m_bool scan1_stmt(const Env env, const Stmt stmt) { |
|
463 |
2843 |
return scan1_stmt_func[stmt->stmt_type](env, &stmt->d); |
|
464 |
} |
||
465 |
|||
466 |
2676 |
ANN static m_bool scan1_stmt_list(const Env env, Stmt_List l) { |
|
467 |
do { |
||
468 |
✓✓ | 2676 |
CHECK_BB(scan1_stmt(env, l->stmt)) |
469 |
✓✓ | 2643 |
if(l->next) { |
470 |
✓✓ | 1537 |
if(l->stmt->stmt_type != ae_stmt_return) { |
471 |
✓✓✓✓ |
2887 |
if(l->next->stmt->stmt_type == ae_stmt_exp && |
472 |
1351 |
!l->next->stmt->d.stmt_exp.val) { |
|
473 |
4 |
Stmt_List next = l->next; |
|
474 |
4 |
l->next = l->next->next; |
|
475 |
4 |
next->next = NULL; |
|
476 |
4 |
free_stmt_list(env->gwion->mp, next); |
|
477 |
} |
||
478 |
} else { |
||
479 |
1 |
Stmt_List tmp = l->next; |
|
480 |
1 |
l->next = NULL; |
|
481 |
1 |
free_stmt_list(env->gwion->mp, tmp); |
|
482 |
} |
||
483 |
} |
||
484 |
✓✓ | 2643 |
} while((l = l->next)); |
485 |
1111 |
return GW_OK; |
|
486 |
} |
||
487 |
|||
488 |
11 |
ANN static m_bool class_internal(const Env env, const Func_Base *base) { |
|
489 |
✓✓ | 11 |
if(!env->class_def) |
490 |
1 |
ERR_B(td_pos(base->td), _("'%s' must be in class def!!"), s_name(base->xid)) |
|
491 |
✓✓ | 10 |
if(base->args) |
492 |
1 |
ERR_B(td_pos(base->td), _("'%s' must not have args"), s_name(base->xid)) |
|
493 |
✓✓ | 9 |
if(base->ret_type != env->gwion->type[et_void]) |
494 |
1 |
ERR_B(td_pos(base->td), _("'%s' must return 'void'"), s_name(base->xid)) |
|
495 |
8 |
return GW_OK; |
|
496 |
} |
||
497 |
|||
498 |
6 |
ANN static inline m_bool scan_internal_arg(const Env env, const Func_Base *base) { |
|
499 |
✓✗✓✓ |
6 |
if(base->args && !base->args->next) |
500 |
5 |
return GW_OK; |
|
501 |
1 |
ERR_B(td_pos(base->td), _("'%s' must have one (and only one) argument"), s_name(base->xid)) |
|
502 |
} |
||
503 |
|||
504 |
3 |
ANN static inline m_bool scan_internal_int(const Env env, const Func_Base *base) { |
|
505 |
✗✓ | 3 |
CHECK_BB(scan_internal_arg(env, base)) |
506 |
✓✓ | 3 |
if(isa(base->ret_type, env->gwion->type[et_int]) > 0) |
507 |
2 |
return GW_OK; |
|
508 |
1 |
ERR_B(td_pos(base->td), _("'%s' must return 'int'"), s_name(base->xid)) |
|
509 |
} |
||
510 |
|||
511 |
22 |
ANN static m_bool scan_internal(const Env env, const Func_Base *base) { |
|
512 |
22 |
const Symbol op = base->xid; |
|
513 |
✓✓✓✓ |
22 |
if(op == insert_symbol("@dtor") || op == insert_symbol("@gack")) |
514 |
11 |
return class_internal(env, base); |
|
515 |
✓✓ | 11 |
if(op == insert_symbol("@implicit")) |
516 |
3 |
return scan_internal_arg(env, base); |
|
517 |
✓✓✓✓ |
14 |
if(op == insert_symbol("@conditionnal") || |
518 |
6 |
op == insert_symbol("@unconditionnal")) |
|
519 |
3 |
return scan_internal_int(env, base); |
|
520 |
5 |
return GW_OK; |
|
521 |
} |
||
522 |
|||
523 |
232 |
ANN static m_bool scan1_fdef_args(const Env env, Arg_List list) { |
|
524 |
do { |
||
525 |
232 |
Nspc nspc = env->curr; |
|
526 |
✗✓ | 1033 |
do if(nspc_lookup_value0(nspc, list->var_decl->xid)) |
527 |
ERR_B(list->var_decl->pos, _("argument '%s' shadows a previuosly defined variable"), |
||
528 |
s_name(list->var_decl->xid)) |
||
529 |
✓✓ | 1033 |
while((nspc = nspc->parent)); |
530 |
✓✓ | 232 |
} while((list = list->next)); |
531 |
173 |
return GW_OK; |
|
532 |
} |
||
533 |
|||
534 |
42339 |
ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) { |
|
535 |
✓✓ | 42339 |
if(fdef->base->args) { |
536 |
✓✓ | 16557 |
if(!GET_FLAG(fdef->base, builtin)) |
537 |
✗✓ | 173 |
CHECK_BB(scan1_fdef_args(env, fdef->base->args)) |
538 |
✓✓ | 16557 |
CHECK_BB(scan1_args(env, fdef->base->args)) |
539 |
} |
||
540 |
✓✓✓✓ ✓✓ |
42334 |
if(!GET_FLAG(fdef->base, builtin) && fdef->d.code && fdef->d.code->d.stmt_code.stmt_list) |
541 |
✓✓ | 248 |
CHECK_BB(scan1_stmt_list(env, fdef->d.code->d.stmt_code.stmt_list)) |
542 |
42333 |
return GW_OK; |
|
543 |
} |
||
544 |
|||
545 |
42345 |
ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) { |
|
546 |
✓✓ | 42345 |
if(fdef->base->td) |
547 |
✓✓ | 42337 |
CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td))) |
548 |
✓✓ | 42344 |
if(GET_FLAG(fdef->base, typedef)) |
549 |
✓✓ | 22 |
CHECK_BB(scan_internal(env, fdef->base)) |
550 |
✓✓✓✓ |
42322 |
else if(GET_FLAG(fdef->base, op) && env->class_def) |
551 |
2 |
SET_FLAG(fdef->base, static); |
|
552 |
42339 |
RET_NSPC(scan1_fbody(env, fdef)) |
|
553 |
return GW_OK; |
||
554 |
} |
||
555 |
|||
556 |
42472 |
ANN static inline m_bool scan1_fdef_defined(const Env env, const Func_Def fdef) { |
|
557 |
42472 |
const Value v = nspc_lookup_value1(env->curr, fdef->base->xid); |
|
558 |
✓✓ | 42472 |
if(!v) |
559 |
33836 |
return GW_OK; |
|
560 |
✓✓ | 8636 |
if(isa(actual_type(env->gwion, v->type), env->gwion->type[et_function]) > 0) |
561 |
8635 |
return GW_OK; |
|
562 |
1 |
ERR_B(fdef->pos, _("function '%s' has already been defined in the same scope..."), |
|
563 |
s_name(fdef->base->xid)) |
||
564 |
} |
||
565 |
|||
566 |
42475 |
ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) { |
|
567 |
✓✓ | 42475 |
if(fdef->base->td) |
568 |
✓✓ | 42467 |
CHECK_BB(env_storage(env, fdef->base->flag, td_pos(fdef->base->td))) |
569 |
✓✓ | 42472 |
CHECK_BB(scan1_fdef_defined(env, fdef)) |
570 |
✓✓ | 42471 |
if(tmpl_base(fdef->base->tmpl)) |
571 |
123 |
return scan1_fdef_base_tmpl(env, fdef->base); |
|
572 |
42348 |
struct Func_ fake = { .name=s_name(fdef->base->xid) }, *const former = env->func; |
|
573 |
42348 |
env->func = &fake; |
|
574 |
42348 |
++env->scope->depth; |
|
575 |
42348 |
const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)scan1_fdef); |
|
576 |
42348 |
--env->scope->depth; |
|
577 |
42348 |
env->func = former; |
|
578 |
42348 |
return ret; |
|
579 |
} |
||
580 |
|||
581 |
1385 |
HANDLE_SECTION_FUNC(scan1, m_bool, Env) |
|
582 |
|||
583 |
70 |
ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) { |
|
584 |
70 |
const Type parent = known_type(env, tdef->ext); |
|
585 |
✗✓ | 70 |
CHECK_OO((tdef->type->e->parent = parent)); |
586 |
70 |
Type t = parent; |
|
587 |
✗✓ | 245 |
do if(tdef->type == t) |
588 |
ERR_O(td_pos(tdef->ext), _("recursive (%s <= %s) class declaration."), tdef->type->name, t->name) |
||
589 |
✓✓ | 245 |
while((t = t->e->parent)); |
590 |
70 |
return parent; |
|
591 |
} |
||
592 |
|||
593 |
70 |
ANN static m_bool scan1_parent(const Env env, const Class_Def cdef) { |
|
594 |
70 |
const loc_t pos = td_pos(cdef->base.ext); |
|
595 |
✓✓ | 70 |
if(cdef->base.ext->array) |
596 |
✗✓ | 9 |
CHECK_BB(scan1_exp(env, cdef->base.ext->array->exp)) |
597 |
✗✓ | 70 |
DECL_OB(const Type , parent, = scan1_get_parent(env, &cdef->base)) |
598 |
✓✓ | 70 |
if(isa(parent, env->gwion->type[et_object]) < 0) |
599 |
1 |
ERR_B(pos, _("cannot extend primitive type '%s'"), parent->name) |
|
600 |
✓✓✓✓ |
69 |
if(parent->e->def && !GET_FLAG(parent, scan1)) |
601 |
✗✓ | 6 |
CHECK_BB(ensure_scan1(env, parent)) |
602 |
✓✓ | 69 |
if(type_ref(parent)) |
603 |
1 |
ERR_B(pos, _("can't use ref type in class extend")) |
|
604 |
✓✓ | 68 |
if(GET_FLAG(parent, nonnull)) |
605 |
1 |
ERR_B(pos, _("can't use nonnull type in class extend")) |
|
606 |
67 |
return GW_OK; |
|
607 |
} |
||
608 |
|||
609 |
70 |
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { |
|
610 |
✓✓✓✗ |
70 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
611 |
✗✓ | 22 |
CHECK_BB(template_push_types(env, cdef->base.tmpl)) |
612 |
70 |
const m_bool ret = scan1_parent(env, cdef); |
|
613 |
✓✓✓✗ |
70 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
614 |
22 |
nspc_pop_type(env->gwion->mp, env->curr); |
|
615 |
70 |
return ret; |
|
616 |
} |
||
617 |
|||
618 |
291 |
ANN m_bool scan1_class_def(const Env env, const Class_Def cdef) { |
|
619 |
✓✓ | 291 |
if(tmpl_base(cdef->base.tmpl)) |
620 |
22 |
return GW_OK; |
|
621 |
269 |
const Type t = cdef->base.type; |
|
622 |
✓✓ | 269 |
if(GET_FLAG(t, scan1)) |
623 |
2 |
return GW_OK; |
|
624 |
267 |
SET_FLAG(t, scan1); |
|
625 |
✓✓✗✓ |
267 |
if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan1)) |
626 |
CHECK_BB(ensure_scan1(env, t->e->owner_class)) |
||
627 |
267 |
SET_FLAG(cdef->base.type, scan1); |
|
628 |
✓✓ | 267 |
if(cdef->base.ext) |
629 |
✓✓ | 70 |
CHECK_BB(cdef_parent(env, cdef)) |
630 |
✓✓ | 264 |
if(cdef->body) |
631 |
✓✓ | 217 |
CHECK_BB(env_body(env, cdef, scan1_section)) |
632 |
258 |
return GW_OK; |
|
633 |
} |
||
634 |
|||
635 |
1013 |
ANN m_bool scan1_ast(const Env env, Ast ast) { |
|
636 |
✓✓ | 1013 |
do CHECK_BB(scan1_section(env, ast->section)) |
637 |
✓✓ | 962 |
while((ast = ast->next)); |
638 |
558 |
return GW_OK; |
|
639 |
} |
Generated by: GCOVR (Version 4.2) |