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 |
11631 |
ANN static inline m_bool type_cyclic(const Env env, const Type t, const Type_Decl *td) { |
|
14 |
11631 |
Type owner = env->class_def; |
|
15 |
do { |
||
16 |
11642 |
Type parent = t; |
|
17 |
✓✓ | 43601 |
while(parent) { |
18 |
✓✓ | 20318 |
if(parent == owner) |
19 |
1 |
ERR_B(td_pos(td), _("%s declared inside %s"), t->name, owner->name); |
|
20 |
20317 |
parent = parent->e->parent; |
|
21 |
} |
||
22 |
✓✓ | 11641 |
} while((owner = owner->e->owner_class)); |
23 |
11630 |
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 |
45375 |
ANN static Type scan1_type(const Env env, Type_Decl* td) { |
|
33 |
✓✓ | 45375 |
DECL_OO(const Type, type, = known_type(env, td)) |
34 |
45352 |
const Type t = get_type(type); |
|
35 |
✓✓✓✓ ✓✓ |
45352 |
if(!env->func && env->class_def && !GET_FLAG(td, ref)) |
36 |
✓✓ | 11631 |
CHECK_BO(type_cyclic(env, t, td)) |
37 |
✓✓✓✓ |
45351 |
if(!GET_FLAG(t, scan1) && t->e->def) |
38 |
✗✓ | 29 |
CHECK_BO(ensure_scan1(env, t)) |
39 |
45351 |
return type; |
|
40 |
} |
||
41 |
|||
42 |
45311 |
ANN static Type void_type(const Env env, Type_Decl* td) { |
|
43 |
✓✓ | 45311 |
DECL_OO(const Type, type, = scan1_type(env, td)) |
44 |
✓✓ | 45289 |
if(type->size) |
45 |
45286 |
return type; |
|
46 |
3 |
ERR_O(td_pos(td), _("cannot declare variables of size '0' (i.e. 'void')...")) |
|
47 |
} |
||
48 |
|||
49 |
21517 |
ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) { |
|
50 |
✓✓ | 21517 |
if(decl->type) |
51 |
21 |
return decl->type; |
|
52 |
✓✓ | 21496 |
DECL_OO(const Type ,t, = void_type(env, decl->td)) |
53 |
✓✓✗✓ |
21477 |
if(decl->td->xid == insert_symbol("auto") && decl->type) |
54 |
return decl->type; |
||
55 |
✓✓✓✓ ✓✓ |
21477 |
if(!env->scope->depth && env->class_def && !GET_FLAG(decl->td, static)) |
56 |
11582 |
SET_FLAG(decl->td, member); |
|
57 |
✓✓✓✗ |
21477 |
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 |
✓✓✗✓ ✗✗ |
21476 |
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 |
21475 |
return decl->type = t; |
|
62 |
} |
||
63 |
|||
64 |
21503 |
static inline m_bool scan1_defined(const Env env, const Var_Decl var) { |
|
65 |
✓✓ | 21503 |
if(var->value) // from a `typeof` declaration |
66 |
21 |
return GW_OK; |
|
67 |
✓✓✓✓ ✓✓ |
21482 |
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 |
21479 |
return GW_OK; |
|
71 |
} |
||
72 |
|||
73 |
21494 |
ANN static m_bool scan1_decl(const Env env, const Exp_Decl* decl) { |
|
74 |
21494 |
Var_Decl_List list = decl->list; |
|
75 |
do { |
||
76 |
21503 |
const Var_Decl var = list->self; |
|
77 |
✗✓ | 21503 |
CHECK_BB(isres(env, var->xid, exp_self(decl)->pos)) |
78 |
21503 |
Type t = decl->type; |
|
79 |
✓✓ | 21503 |
CHECK_BB(scan1_defined(env, var)) |
80 |
✓✓ | 21500 |
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 |
✓✓✓✓ |
21454 |
} 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 |
✓✓ | 21498 |
const Value v = var->value = var->value ?: new_value(env->gwion->mp, t, s_name(var->xid)); |
95 |
✓✓✓✓ ✓✓ |
21498 |
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 |
21498 |
nspc_add_value(env->curr, var->xid, v); |
|
100 |
21498 |
v->flag = decl->td->flag; |
|
101 |
21498 |
v->type = t; |
|
102 |
✓✓✓✓ |
21498 |
if(var->array && !var->array->exp) |
103 |
8 |
SET_FLAG(v, ref); |
|
104 |
✓✓ | 21498 |
if(env->class_def) { |
105 |
✓✗ | 11619 |
if(env->class_def->e->tuple) |
106 |
11619 |
tuple_contains(env, v); |
|
107 |
✓✓ | 9879 |
} else if(!env->scope->depth) |
108 |
9690 |
SET_FLAG(v, global); |
|
109 |
21498 |
v->d.ptr = var->addr; |
|
110 |
✓✓ | 21498 |
if(GET_FLAG(decl->td, global)) |
111 |
6 |
SET_FLAG(v, abstract); |
|
112 |
✓✓ | 21498 |
if(!env->scope->depth) |
113 |
21301 |
valuefrom(env, v->from); |
|
114 |
✓✓ | 21498 |
} while((list = list->next)); |
115 |
21489 |
((Exp_Decl*)decl)->type = decl->list->self->value->type; |
|
116 |
21489 |
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 |
21521 |
ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) { |
|
127 |
✓✓ | 21521 |
CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos)) |
128 |
21517 |
((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl); |
|
129 |
✓✓ | 21517 |
CHECK_OB(decl->type) |
130 |
✗✓ | 21496 |
if(GET_FLAG(decl->type, const)) |
131 |
exp_setmeta(exp_self(decl), 1); |
||
132 |
21496 |
const m_bool global = GET_FLAG(decl->td, global); |
|
133 |
✓✓ | 21496 |
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 |
✓✓ | 21494 |
const m_uint scope = !global ? env->scope->depth : env_push_global(env); |
140 |
21494 |
const m_bool ret = scan1_decl(env, decl); |
|
141 |
✓✓ | 21494 |
if(global) |
142 |
6 |
env_pop(env, scope); |
|
143 |
21494 |
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 |
552 |
ANN static m_bool scan1_exp_call(const Env env, const Exp_Call* exp_call) { |
|
230 |
✓✓ | 552 |
if(exp_call->tmpl) |
231 |
32 |
return GW_OK; |
|
232 |
✗✓ | 520 |
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 |
554 |
ANN static inline m_bool scan1_exp_dot(const Env env, const Exp_Dot* member) { |
|
238 |
554 |
return scan1_exp(env, member->base); |
|
239 |
} |
||
240 |
|||
241 |
10 |
ANN static m_bool scan1_exp_if(const Env env, const Exp_If* exp_if) { |
|
242 |
✗✓ | 10 |
CHECK_BB(scan1_exp(env, exp_if->cond)) |
243 |
✓✓✗✓ |
10 |
CHECK_BB(scan1_exp(env, exp_if->if_exp ?: exp_if->cond)) |
244 |
10 |
return scan1_exp(env, exp_if->else_exp); |
|
245 |
} |
||
246 |
|||
247 |
142 |
ANN static inline m_bool scan1_exp_unary(const restrict Env env, const Exp_Unary *unary) { |
|
248 |
✓✓✓✓ ✓✓ |
142 |
if((unary->op == insert_symbol("spork") || unary->op == insert_symbol("fork")) && unary->code) |
249 |
25 |
{ RET_NSPC(scan1_stmt(env, unary->code)) } |
|
250 |
✓✓ | 117 |
else if(opiscall(unary->op)) { |
251 |
1 |
return exp2call(env, exp_self(unary), unary->op, unary->exp); |
|
252 |
} |
||
253 |
✓✓ | 116 |
return unary->exp ? scan1_exp(env, unary->exp) : GW_OK; |
254 |
} |
||
255 |
|||
256 |
#define scan1_exp_lambda dummy_func |
||
257 |
✓✓✓✓ |
27989 |
HANDLE_EXP_FUNC(scan1, m_bool, Env) |
258 |
|||
259 |
11 |
ANN static inline m_bool _scan1_stmt_match_case(const restrict Env env, const Stmt_Match stmt) { |
|
260 |
✗✓ | 11 |
CHECK_BB(scan1_exp(env, stmt->cond)) |
261 |
✓✓ | 11 |
if(stmt->when) |
262 |
✗✓ | 4 |
CHECK_BB(scan1_exp(env, stmt->when)) |
263 |
11 |
return scan1_stmt_list(env, stmt->list); |
|
264 |
} |
||
265 |
|||
266 |
11 |
ANN static inline m_bool scan1_stmt_match_case(const restrict Env env, const Stmt_Match stmt) { |
|
267 |
11 |
RET_NSPC(_scan1_stmt_match_case(env, stmt)) |
|
268 |
} |
||
269 |
|||
270 |
7 |
ANN static inline m_bool _scan1_stmt_match(const restrict Env env, const Stmt_Match stmt) { |
|
271 |
✓✓ | 7 |
if(stmt->where) |
272 |
✗✓ | 2 |
CHECK_BB(scan1_stmt(env, stmt->where)) |
273 |
7 |
Stmt_List list = stmt->list; |
|
274 |
✗✓ | 11 |
do CHECK_BB(scan1_stmt_match_case(env, &list->stmt->d.stmt_match)) |
275 |
✓✓ | 11 |
while((list = list->next)); |
276 |
7 |
return GW_OK; |
|
277 |
} |
||
278 |
|||
279 |
7 |
ANN static inline m_bool scan1_stmt_match(const restrict Env env, const Stmt_Match stmt) { |
|
280 |
✗✓ | 7 |
CHECK_BB(scan1_exp(env, stmt->cond)) |
281 |
7 |
RET_NSPC(_scan1_stmt_match(env, stmt)) |
|
282 |
} |
||
283 |
|||
284 |
#define describe_ret_nspc(name, type, prolog, exp) describe_stmt_func(scan1, name, type, prolog, exp) |
||
285 |
✓✗✓✗ |
26 |
describe_ret_nspc(flow, Stmt_Flow,, !(scan1_exp(env, stmt->cond) < 0 || |
286 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
287 |
✓✗✓✗ |
10 |
describe_ret_nspc(varloop, Stmt_VarLoop,, !(scan1_exp(env, stmt->exp) < 0 || |
288 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
289 |
✓✗✓✗ ✓✓✓✗ ✓✗ |
11 |
describe_ret_nspc(for, Stmt_For,, !(scan1_stmt(env, stmt->c1) < 0 || |
290 |
scan1_stmt(env, stmt->c2) < 0 || |
||
291 |
(stmt->c3 && scan1_exp(env, stmt->c3) < 0) || |
||
292 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
293 |
✓✗✓✗ |
12 |
describe_ret_nspc(each, Stmt_Each,, !(scan1_exp(env, stmt->exp) < 0 || |
294 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
295 |
✓✗✓✗ |
8 |
describe_ret_nspc(loop, Stmt_Loop,, !(scan1_exp(env, stmt->cond) < 0 || |
296 |
scan1_stmt(env, stmt->body) < 0) ? 1 : -1) |
||
297 |
✓✗✓✗ ✓✓✓✗ |
39 |
describe_ret_nspc(if, Stmt_If,, !(scan1_exp(env, stmt->cond) < 0 || |
298 |
scan1_stmt(env, stmt->if_body) < 0 || |
||
299 |
(stmt->else_body && scan1_stmt(env, stmt->else_body) < 0)) ? 1 : -1) |
||
300 |
|||
301 |
157 |
ANN static inline m_bool scan1_stmt_code(const Env env, const Stmt_Code stmt) { |
|
302 |
✓✓ | 157 |
if(stmt->stmt_list) |
303 |
153 |
{ RET_NSPC(scan1_stmt_list(env, stmt->stmt_list)) } |
|
304 |
4 |
return GW_OK; |
|
305 |
} |
||
306 |
|||
307 |
2534 |
ANN static inline m_bool scan1_stmt_exp(const Env env, const Stmt_Exp stmt) { |
|
308 |
✓✓ | 2534 |
return stmt->val ? scan1_exp(env, stmt->val) : 1; |
309 |
} |
||
310 |
|||
311 |
724 |
ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) { |
|
312 |
724 |
ID_List list = edef->list; |
|
313 |
do { |
||
314 |
✗✓ | 1482 |
CHECK_BB(already_defined(env, list->xid, edef->pos)) |
315 |
1482 |
const Value v = new_value(env->gwion->mp, edef->t, s_name(list->xid)); |
|
316 |
1482 |
valuefrom(env, v->from); |
|
317 |
✓✓ | 1482 |
if(env->class_def) { |
318 |
28 |
SET_FLAG(v, static); |
|
319 |
✓✓✗✓ |
28 |
SET_ACCESS(edef, v) |
320 |
✓✓✗✓ |
28 |
SET_ACCESS(edef, edef->t) |
321 |
} |
||
322 |
1482 |
SET_FLAG(v, const | ae_flag_enum | ae_flag_valid); |
|
323 |
1482 |
nspc_add_value(edef->t->e->owner, list->xid, v); |
|
324 |
1482 |
vector_add(&edef->values, (vtype)v); |
|
325 |
✓✓ | 1482 |
} while((list = list->next)); |
326 |
724 |
return GW_OK; |
|
327 |
} |
||
328 |
|||
329 |
23814 |
ANN static Value arg_value(const Env env, const Arg_List list) { |
|
330 |
23814 |
const Var_Decl var = list->var_decl; |
|
331 |
✓✓ | 23814 |
const Value v = new_value(env->gwion->mp, list->type, var->xid ? s_name(var->xid) : (m_str)__func__); |
332 |
✓✓ | 23814 |
if(var->array) |
333 |
8 |
v->type = list->type = array_type(env, list->type, var->array->depth); |
|
334 |
✓✓ | 23814 |
if(list->td) |
335 |
23809 |
v->flag = list->td->flag | ae_flag_abstract; |
|
336 |
23814 |
return v; |
|
337 |
} |
||
338 |
|||
339 |
23821 |
ANN static m_bool scan1_args(const Env env, Arg_List list) { |
|
340 |
do { |
||
341 |
23821 |
const Var_Decl var = list->var_decl; |
|
342 |
✓✓ | 23821 |
if(var->xid) |
343 |
✓✓ | 23815 |
CHECK_BB(isres(env, var->xid, var->pos)) |
344 |
✓✓ | 23820 |
if(list->td) |
345 |
✓✓ | 23815 |
CHECK_OB((list->type = void_type(env, list->td))) |
346 |
23814 |
var->value = arg_value(env, list); |
|
347 |
23814 |
nspc_add_value(env->curr, var->xid, var->value); |
|
348 |
✓✓ | 23814 |
} while((list = list->next)); |
349 |
16601 |
return GW_OK; |
|
350 |
} |
||
351 |
|||
352 |
139 |
ANN static m_bool _scan1_fdef_base_tmpl(const Env env, Func_Base *base) { |
|
353 |
139 |
ID_List id = base->tmpl->list; |
|
354 |
149 |
do nspc_add_type(env->curr, id->xid, env->gwion->type[et_undefined]); |
|
355 |
✓✓ | 149 |
while((id = id->next)); |
356 |
✓✓ | 139 |
CHECK_OB((base->ret_type = known_type(env, base->td))) |
357 |
✓✓ | 138 |
if(base->args) { |
358 |
92 |
Arg_List arg = base->args; |
|
359 |
✓✓ | 136 |
do CHECK_OB(known_type(env, arg->td)) |
360 |
✓✓ | 135 |
while((arg = arg->next)); |
361 |
} |
||
362 |
137 |
return GW_OK; |
|
363 |
} |
||
364 |
|||
365 |
139 |
ANN static m_bool scan1_fdef_base_tmpl(const Env env, Func_Base *base) { |
|
366 |
139 |
nspc_push_type(env->gwion->mp, env->curr); |
|
367 |
139 |
const m_bool ret = _scan1_fdef_base_tmpl(env, base); |
|
368 |
139 |
nspc_pop_type(env->gwion->mp, env->curr); |
|
369 |
139 |
return ret; |
|
370 |
} |
||
371 |
|||
372 |
80 |
ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) { |
|
373 |
✓✓ | 80 |
if(tmpl_base(fptr->base->tmpl)) |
374 |
16 |
return scan1_fdef_base_tmpl(env, fptr->base); |
|
375 |
✗✓ | 64 |
if(!fptr->base->func) { |
376 |
fptr->base->func = nspc_lookup_value0(env->curr, fptr->base->xid)->d.func_ref; |
||
377 |
fptr->type = nspc_lookup_type0(env->curr, fptr->base->xid); |
||
378 |
} |
||
379 |
64 |
const Func_Def fdef = fptr->base->func->def; |
|
380 |
✓✓ | 64 |
CHECK_OB((fdef->base->ret_type = scan1_type(env, fdef->base->td))) |
381 |
✓✓ | 62 |
if(!fdef->base->args) |
382 |
34 |
return GW_OK; |
|
383 |
28 |
RET_NSPC(scan1_args(env, fdef->base->args)) |
|
384 |
} |
||
385 |
|||
386 |
734 |
ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) { |
|
387 |
✗✓ | 734 |
if(!tdef->type) |
388 |
tdef->type = nspc_lookup_type0(env->curr, tdef->xid); |
||
389 |
✓✓ | 734 |
if(!tdef->type->e->def)return GW_OK; |
390 |
✓✗ | 8 |
return !is_fptr(env->gwion, tdef->type) ? scan1_cdef(env, tdef->type->e->def) : GW_OK; |
391 |
} |
||
392 |
|||
393 |
37 |
ANN static m_bool scan1_union_def_action(const Env env, const Union_Def udef, |
|
394 |
const Decl_List l) { |
||
395 |
37 |
const Exp_Decl decl = l->self->d.exp_decl; |
|
396 |
37 |
SET_FLAG(decl.td, valid | udef->flag); |
|
397 |
37 |
const m_bool global = GET_FLAG(udef, global); |
|
398 |
✓✓ | 37 |
if(global) |
399 |
6 |
UNSET_FLAG(decl.td, global); |
|
400 |
✓✓ | 37 |
if(GET_FLAG(udef, member)) |
401 |
3 |
SET_FLAG(decl.td, member); |
|
402 |
✓✓ | 34 |
else if(GET_FLAG(udef, static)) |
403 |
4 |
SET_FLAG(decl.td, static); |
|
404 |
✓✓ | 37 |
CHECK_BB(scan1_exp(env, l->self)) |
405 |
|||
406 |
35 |
Var_Decl_List list = decl.list; |
|
407 |
35 |
do ADD_REF(list->self->value) |
|
408 |
✗✓ | 35 |
while((list = list->next)); |
409 |
|||
410 |
✓✓ | 35 |
if(global) |
411 |
6 |
SET_FLAG(decl.td, global); |
|
412 |
35 |
return GW_OK; |
|
413 |
} |
||
414 |
|||
415 |
37 |
ANN static inline m_bool scan1_union_def_inner_loop(const Env env, const Union_Def udef, Decl_List l) { |
|
416 |
✓✓ | 37 |
do CHECK_BB(scan1_union_def_action(env, udef, l)) |
417 |
✓✓ | 35 |
while((l = l->next)); |
418 |
18 |
return GW_OK; |
|
419 |
} |
||
420 |
|||
421 |
20 |
ANN static m_bool scan1_union_def_inner(const Env env, const Union_Def udef) { |
|
422 |
✓✓✓✗ |
20 |
if(udef->tmpl && udef->tmpl->call) |
423 |
✗✓ | 3 |
CHECK_BB(template_push_types(env, udef->tmpl)) |
424 |
20 |
const m_bool ret = scan1_union_def_inner_loop(env, udef, udef->l); |
|
425 |
✓✓✓✗ |
20 |
if(udef->tmpl && udef->tmpl->call) |
426 |
3 |
nspc_pop_type(env->gwion->mp, env->curr); |
|
427 |
20 |
return ret; |
|
428 |
} |
||
429 |
|||
430 |
24 |
ANN m_bool scan1_union_def(const Env env, const Union_Def udef) { |
|
431 |
✓✓ | 24 |
if(tmpl_base(udef->tmpl)) |
432 |
4 |
return GW_OK; |
|
433 |
20 |
const m_uint scope = union_push(env, udef); |
|
434 |
✓✓✓✓ |
20 |
if(udef->xid || udef->type_xid) { |
435 |
12 |
UNSET_FLAG(udef, private); |
|
436 |
12 |
UNSET_FLAG(udef, protect); |
|
437 |
} |
||
438 |
20 |
const m_bool ret = scan1_union_def_inner(env, udef); |
|
439 |
20 |
union_pop(env, udef, scope); |
|
440 |
20 |
union_flag(udef, ae_flag_scan1); |
|
441 |
20 |
return ret; |
|
442 |
} |
||
443 |
|||
444 |
#define scan1_stmt_while scan1_stmt_flow |
||
445 |
#define scan1_stmt_until scan1_stmt_flow |
||
446 |
#define scan1_stmt_continue (void*)dummy_func |
||
447 |
#define scan1_stmt_break (void*)dummy_func |
||
448 |
#define scan1_stmt_jump (void*)dummy_func |
||
449 |
#define scan1_stmt_return scan1_stmt_exp |
||
450 |
|||
451 |
4 |
ANN static m_bool scan1_stmt_pp(const Env env, const Stmt_PP stmt) { |
|
452 |
✓✓ | 4 |
if(stmt->pp_type == ae_pp_include) |
453 |
3 |
env->name = stmt->data; |
|
454 |
4 |
return GW_OK; |
|
455 |
} |
||
456 |
|||
457 |
DECL_STMT_FUNC(scan1, m_bool, Env) |
||
458 |
|||
459 |
2842 |
ANN static inline m_bool scan1_stmt(const Env env, const Stmt stmt) { |
|
460 |
2842 |
return scan1_stmt_func[stmt->stmt_type](env, &stmt->d); |
|
461 |
} |
||
462 |
|||
463 |
2675 |
ANN static m_bool scan1_stmt_list(const Env env, Stmt_List l) { |
|
464 |
do { |
||
465 |
✓✓ | 2675 |
CHECK_BB(scan1_stmt(env, l->stmt)) |
466 |
✓✓ | 2643 |
if(l->next) { |
467 |
✓✓ | 1537 |
if(l->stmt->stmt_type != ae_stmt_return) { |
468 |
✓✓✓✓ |
2887 |
if(l->next->stmt->stmt_type == ae_stmt_exp && |
469 |
1351 |
!l->next->stmt->d.stmt_exp.val) { |
|
470 |
4 |
Stmt_List next = l->next; |
|
471 |
4 |
l->next = l->next->next; |
|
472 |
4 |
next->next = NULL; |
|
473 |
4 |
free_stmt_list(env->gwion->mp, next); |
|
474 |
} |
||
475 |
} else { |
||
476 |
1 |
Stmt_List tmp = l->next; |
|
477 |
1 |
l->next = NULL; |
|
478 |
1 |
free_stmt_list(env->gwion->mp, tmp); |
|
479 |
} |
||
480 |
} |
||
481 |
✓✓ | 2643 |
} while((l = l->next)); |
482 |
1111 |
return GW_OK; |
|
483 |
} |
||
484 |
|||
485 |
11 |
ANN static m_bool class_internal(const Env env, const Func_Base *base) { |
|
486 |
✓✓ | 11 |
if(!env->class_def) |
487 |
1 |
ERR_B(td_pos(base->td), _("'%s' must be in class def!!"), s_name(base->xid)) |
|
488 |
✓✓ | 10 |
if(base->args) |
489 |
1 |
ERR_B(td_pos(base->td), _("'%s' must not have args"), s_name(base->xid)) |
|
490 |
✓✓ | 9 |
if(base->ret_type != env->gwion->type[et_void]) |
491 |
1 |
ERR_B(td_pos(base->td), _("'%s' must return 'void'"), s_name(base->xid)) |
|
492 |
8 |
return GW_OK; |
|
493 |
} |
||
494 |
|||
495 |
6 |
ANN static inline m_bool scan_internal_arg(const Env env, const Func_Base *base) { |
|
496 |
✓✗✓✓ |
6 |
if(base->args && !base->args->next) |
497 |
5 |
return GW_OK; |
|
498 |
1 |
ERR_B(td_pos(base->td), _("'%s' must have one (and only one) argument"), s_name(base->xid)) |
|
499 |
} |
||
500 |
|||
501 |
3 |
ANN static inline m_bool scan_internal_int(const Env env, const Func_Base *base) { |
|
502 |
✗✓ | 3 |
CHECK_BB(scan_internal_arg(env, base)) |
503 |
✓✓ | 3 |
if(isa(base->ret_type, env->gwion->type[et_int]) > 0) |
504 |
2 |
return GW_OK; |
|
505 |
1 |
ERR_B(td_pos(base->td), _("'%s' must return 'int'"), s_name(base->xid)) |
|
506 |
} |
||
507 |
|||
508 |
22 |
ANN static m_bool scan_internal(const Env env, const Func_Base *base) { |
|
509 |
22 |
const Symbol op = base->xid; |
|
510 |
✓✓✓✓ |
22 |
if(op == insert_symbol("@dtor") || op == insert_symbol("@gack")) |
511 |
11 |
return class_internal(env, base); |
|
512 |
✓✓ | 11 |
if(op == insert_symbol("@implicit")) |
513 |
3 |
return scan_internal_arg(env, base); |
|
514 |
✓✓✓✓ |
14 |
if(op == insert_symbol("@conditionnal") || |
515 |
6 |
op == insert_symbol("@unconditionnal")) |
|
516 |
3 |
return scan_internal_int(env, base); |
|
517 |
5 |
return GW_OK; |
|
518 |
} |
||
519 |
|||
520 |
232 |
ANN static m_bool scan1_fdef_args(const Env env, Arg_List list) { |
|
521 |
do { |
||
522 |
232 |
Nspc nspc = env->curr; |
|
523 |
✗✓ | 1033 |
do if(nspc_lookup_value0(nspc, list->var_decl->xid)) |
524 |
ERR_B(list->var_decl->pos, _("argument '%s' shadows a previuosly defined variable"), |
||
525 |
s_name(list->var_decl->xid)) |
||
526 |
✓✓ | 1033 |
while((nspc = nspc->parent)); |
527 |
✓✓ | 232 |
} while((list = list->next)); |
528 |
173 |
return GW_OK; |
|
529 |
} |
||
530 |
|||
531 |
42398 |
ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) { |
|
532 |
✓✓ | 42398 |
if(fdef->base->args) { |
533 |
✓✓ | 16580 |
if(!GET_FLAG(fdef->base, builtin)) |
534 |
✗✓ | 173 |
CHECK_BB(scan1_fdef_args(env, fdef->base->args)) |
535 |
✓✓ | 16580 |
CHECK_BB(scan1_args(env, fdef->base->args)) |
536 |
} |
||
537 |
✓✓✓✓ ✓✓ |
42393 |
if(!GET_FLAG(fdef->base, builtin) && fdef->d.code && fdef->d.code->d.stmt_code.stmt_list) |
538 |
✓✓ | 248 |
CHECK_BB(scan1_stmt_list(env, fdef->d.code->d.stmt_code.stmt_list)) |
539 |
42392 |
return GW_OK; |
|
540 |
} |
||
541 |
|||
542 |
42404 |
ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) { |
|
543 |
✓✓ | 42404 |
if(fdef->base->td) |
544 |
✓✓ | 42396 |
CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td))) |
545 |
✓✓ | 42403 |
if(GET_FLAG(fdef->base, typedef)) |
546 |
✓✓ | 22 |
CHECK_BB(scan_internal(env, fdef->base)) |
547 |
✓✓✓✓ |
42381 |
else if(GET_FLAG(fdef->base, op) && env->class_def) |
548 |
2 |
SET_FLAG(fdef->base, static); |
|
549 |
42398 |
RET_NSPC(scan1_fbody(env, fdef)) |
|
550 |
return GW_OK; |
||
551 |
} |
||
552 |
|||
553 |
42531 |
ANN static inline m_bool scan1_fdef_defined(const Env env, const Func_Def fdef) { |
|
554 |
42531 |
const Value v = nspc_lookup_value1(env->curr, fdef->base->xid); |
|
555 |
✓✓ | 42531 |
if(!v) |
556 |
33883 |
return GW_OK; |
|
557 |
✓✓ | 8648 |
if(isa(actual_type(env->gwion, v->type), env->gwion->type[et_function]) > 0) |
558 |
8647 |
return GW_OK; |
|
559 |
1 |
ERR_B(fdef->pos, _("function '%s' has already been defined in the same scope..."), |
|
560 |
s_name(fdef->base->xid)) |
||
561 |
} |
||
562 |
|||
563 |
42534 |
ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) { |
|
564 |
✓✓ | 42534 |
if(fdef->base->td) |
565 |
✓✓ | 42526 |
CHECK_BB(env_storage(env, fdef->base->flag, td_pos(fdef->base->td))) |
566 |
✓✓ | 42531 |
CHECK_BB(scan1_fdef_defined(env, fdef)) |
567 |
✓✓ | 42530 |
if(tmpl_base(fdef->base->tmpl)) |
568 |
123 |
return scan1_fdef_base_tmpl(env, fdef->base); |
|
569 |
42407 |
struct Func_ fake = { .name=s_name(fdef->base->xid) }, *const former = env->func; |
|
570 |
42407 |
env->func = &fake; |
|
571 |
42407 |
++env->scope->depth; |
|
572 |
42407 |
const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)scan1_fdef); |
|
573 |
42407 |
--env->scope->depth; |
|
574 |
42407 |
env->func = former; |
|
575 |
42407 |
return ret; |
|
576 |
} |
||
577 |
|||
578 |
1384 |
HANDLE_SECTION_FUNC(scan1, m_bool, Env) |
|
579 |
|||
580 |
70 |
ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) { |
|
581 |
70 |
const Type parent = known_type(env, tdef->ext); |
|
582 |
✗✓ | 70 |
CHECK_OO((tdef->type->e->parent = parent)); |
583 |
70 |
Type t = parent; |
|
584 |
✗✓ | 245 |
do if(tdef->type == t) |
585 |
ERR_O(td_pos(tdef->ext), _("recursive (%s <= %s) class declaration."), tdef->type->name, t->name) |
||
586 |
✓✓ | 245 |
while((t = t->e->parent)); |
587 |
70 |
return parent; |
|
588 |
} |
||
589 |
|||
590 |
70 |
ANN static m_bool scan1_parent(const Env env, const Class_Def cdef) { |
|
591 |
70 |
const loc_t pos = td_pos(cdef->base.ext); |
|
592 |
✓✓ | 70 |
if(cdef->base.ext->array) |
593 |
✗✓ | 9 |
CHECK_BB(scan1_exp(env, cdef->base.ext->array->exp)) |
594 |
✗✓ | 70 |
DECL_OB(const Type , parent, = scan1_get_parent(env, &cdef->base)) |
595 |
✓✓ | 70 |
if(isa(parent, env->gwion->type[et_object]) < 0) |
596 |
1 |
ERR_B(pos, _("cannot extend primitive type '%s'"), parent->name) |
|
597 |
✓✓✓✓ |
69 |
if(parent->e->def && !GET_FLAG(parent, scan1)) |
598 |
✗✓ | 6 |
CHECK_BB(ensure_scan1(env, parent)) |
599 |
✓✓ | 69 |
if(type_ref(parent)) |
600 |
1 |
ERR_B(pos, _("can't use ref type in class extend")) |
|
601 |
✓✓ | 68 |
if(GET_FLAG(parent, nonnull)) |
602 |
1 |
ERR_B(pos, _("can't use nonnull type in class extend")) |
|
603 |
67 |
return GW_OK; |
|
604 |
} |
||
605 |
|||
606 |
70 |
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { |
|
607 |
✓✓✓✗ |
70 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
608 |
✗✓ | 22 |
CHECK_BB(template_push_types(env, cdef->base.tmpl)) |
609 |
70 |
const m_bool ret = scan1_parent(env, cdef); |
|
610 |
✓✓✓✗ |
70 |
if(cdef->base.tmpl && cdef->base.tmpl->list) |
611 |
22 |
nspc_pop_type(env->gwion->mp, env->curr); |
|
612 |
70 |
return ret; |
|
613 |
} |
||
614 |
|||
615 |
291 |
ANN m_bool scan1_class_def(const Env env, const Class_Def cdef) { |
|
616 |
✓✓ | 291 |
if(tmpl_base(cdef->base.tmpl)) |
617 |
22 |
return GW_OK; |
|
618 |
269 |
const Type t = cdef->base.type; |
|
619 |
✓✓ | 269 |
if(GET_FLAG(t, scan1)) |
620 |
2 |
return GW_OK; |
|
621 |
267 |
SET_FLAG(t, scan1); |
|
622 |
✓✓✗✓ |
267 |
if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan1)) |
623 |
CHECK_BB(ensure_scan1(env, t->e->owner_class)) |
||
624 |
267 |
SET_FLAG(cdef->base.type, scan1); |
|
625 |
✓✓ | 267 |
if(cdef->base.ext) |
626 |
✓✓ | 70 |
CHECK_BB(cdef_parent(env, cdef)) |
627 |
✓✓ | 264 |
if(cdef->body) |
628 |
✓✓ | 217 |
CHECK_BB(env_body(env, cdef, scan1_section)) |
629 |
258 |
return GW_OK; |
|
630 |
} |
||
631 |
|||
632 |
1012 |
ANN m_bool scan1_ast(const Env env, Ast ast) { |
|
633 |
✓✓ | 1012 |
do CHECK_BB(scan1_section(env, ast->section)) |
634 |
✓✓ | 962 |
while((ast = ast->next)); |
635 |
558 |
return GW_OK; |
|
636 |
} |
Generated by: GCOVR (Version 4.2) |