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