GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/scan1.c Lines: 431 449 96.0 %
Date: 2020-09-12 17:36:58 Branches: 400 468 85.5 %

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
}