GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/scan1.c Lines: 441 451 97.8 %
Date: 2020-09-14 09:03:05 Branches: 404 470 86.0 %

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
11599
ANN static inline m_bool type_cyclic(const Env env, const Type t, const Type_Decl *td) {
14
11599
  Type owner = env->class_def;
15
  do {
16
11610
    Type parent = t;
17
43481
    while(parent) {
18
20262
      if(parent == owner)
19
1
        ERR_B(td_pos(td), _("%s declared inside %s"), t->name, owner->name);
20
20261
      parent = parent->e->parent;
21
    }
22
11609
  } while((owner = owner->e->owner_class));
23
11598
  return GW_OK;
24
}
25
26
34
ANN static inline m_bool ensure_scan1(const Env env, const Type t) {
27
68
  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan1_cdef,
28
34
    .scope=env->scope->depth, .flag=ae_flag_scan1 };
29
34
  return envset_run(&es, t);
30
}
31
32
45241
ANN static Type scan1_type(const Env env, Type_Decl* td) {
33
45241
  DECL_OO(const Type, type, = known_type(env, td))
34
45217
  const Type t = get_type(type);
35

45217
  if(!env->func && env->class_def && !GET_FLAG(td, ref))
36
11599
    CHECK_BO(type_cyclic(env, t, td))
37

45216
  if(!GET_FLAG(t, scan1) && t->e->def)
38
28
    CHECK_BO(ensure_scan1(env, t))
39
45216
  return type;
40
}
41
42
45181
ANN static Type void_type(const Env env, Type_Decl* td) {
43
45181
  DECL_OO(const Type, type, = scan1_type(env, td))
44
45158
  if(type->size)
45
45155
    return type;
46
3
  ERR_O(td_pos(td), _("cannot declare variables of size '0' (i.e. 'void')..."))
47
}
48
49
21457
ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) {
50
21457
  if(decl->type)
51
21
    return decl->type;
52
21436
  DECL_OO(const Type ,t, = void_type(env, decl->td))
53

21416
  if(decl->td->xid == insert_symbol("auto") && decl->type)
54
    return decl->type;
55

21416
  if(!env->scope->depth && env->class_def && !GET_FLAG(decl->td, static))
56
11550
    SET_FLAG(decl->td, member);
57

21416
  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

21415
  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
21414
  return decl->type = t;
62
}
63
64
21441
static inline m_bool scan1_defined(const Env env, const Var_Decl var) {
65
21441
  if(var->value) // from a `typeof` declaration
66
21
    return GW_OK;
67

21420
  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
21417
  return GW_OK;
71
}
72
73
21433
ANN static m_bool scan1_decl(const Env env, const Exp_Decl* decl) {
74
21433
  Var_Decl_List list = decl->list;
75
  do {
76
21441
    const Var_Decl var = list->self;
77
21441
    CHECK_BB(isres(env, var->xid, exp_self(decl)->pos))
78
21441
    Type t = decl->type;
79
21441
    CHECK_BB(scan1_defined(env, var))
80
21438
    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

21394
    } 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
21436
    const Value v = var->value = var->value ?: new_value(env->gwion->mp, t, s_name(var->xid));
95

21436
    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
21436
    nspc_add_value(env->curr, var->xid, v);
100
21436
    v->flag = decl->td->flag;
101
21436
    v->type = t;
102

21436
    if(var->array && !var->array->exp)
103
8
      SET_FLAG(v, ref);
104
21436
    if(env->class_def) {
105
11587
      if(env->class_def->e->tuple)
106
11587
        tuple_contains(env, v);
107
9849
    } else if(!env->scope->depth)
108
9660
      SET_FLAG(v, global);
109
21436
    v->d.ptr = var->addr;
110
21436
    if(GET_FLAG(decl->td, global))
111
6
      SET_FLAG(v, abstract);
112
21436
    if(!env->scope->depth)
113
21239
      valuefrom(env, v->from);
114
21436
  } while((list = list->next));
115
21428
  ((Exp_Decl*)decl)->type = decl->list->self->value->type;
116
21428
  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
21461
ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) {
127
21461
  CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos))
128
21457
  ((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl);
129
21457
  CHECK_OB(decl->type)
130
21435
  if(GET_FLAG(decl->type, const))
131
    exp_setmeta(exp_self(decl), 1);
132
21435
  const m_bool global = GET_FLAG(decl->td, global);
133
21435
  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
21433
  const m_uint scope = !global ? env->scope->depth : env_push_global(env);
140
21433
  const m_bool ret = scan1_decl(env, decl);
141
21433
  if(global)
142
6
    env_pop(env, scope);
143
21433
  return ret;
144
}
145
146
795
ANN static inline int opiscall(const Symbol sym) {
147
795
  const m_str opname = s_name(sym);
148

907
  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
639
ANN static inline m_bool scan1_exp_binary(const Env env, const Exp_Binary* bin) {
178
639
  if(opiscall(bin->op))
179
1
    return binary2call(env, bin);
180
638
  CHECK_BB(scan1_exp(env, bin->lhs))
181
638
  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
4412
ANN static inline m_bool scan1_prim(const Env env, const Exp_Primary* prim) {
193

7740
  if(prim->prim_type == ae_prim_hack || prim->prim_type == ae_prim_typeof ||
194
3328
        prim->prim_type == ae_prim_interp)
195
1089
    return scan1_exp(env, prim->d.exp);
196

3323
  if(prim->prim_type == ae_prim_array && prim->d.array->exp)
197
22
    return scan1_exp(env, prim->d.array->exp);
198
3301
  if(prim->prim_type == ae_prim_range)
199
3
    return scan1_range(env, prim->d.range);
200
3298
  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

27907
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

11
describe_ret_nspc(auto, Stmt_Auto,, !(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
2524
ANN static inline m_bool scan1_stmt_exp(const Env env, const Stmt_Exp stmt) {
311
2524
  return stmt->val ? scan1_exp(env, stmt->val) : 1;
312
}
313
314
722
ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) {
315
722
  ID_List list = edef->list;
316
  do {
317
1478
    CHECK_BB(already_defined(env, list->xid, edef->pos))
318
1478
    const Value v = new_value(env->gwion->mp, edef->t, s_name(list->xid));
319
1478
    valuefrom(env, v->from);
320
1478
    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
1478
    SET_FLAG(v, const | ae_flag_enum | ae_flag_valid);
326
1478
    nspc_add_value(edef->t->e->owner, list->xid, v);
327
1478
    vector_add(&edef->values, (vtype)v);
328
1478
  } while((list = list->next));
329
722
  return GW_OK;
330
}
331
332
23744
ANN static Value arg_value(const Env env, const Arg_List list) {
333
23744
  const Var_Decl var = list->var_decl;
334
23744
  const Value v = new_value(env->gwion->mp, list->type, var->xid ? s_name(var->xid) : (m_str)__func__);
335
23744
  if(var->array)
336
8
    v->type = list->type = array_type(env, list->type, var->array->depth);
337
23744
  if(list->td)
338
23739
    v->flag = list->td->flag | ae_flag_abstract;
339
23744
  return v;
340
}
341
342
23751
ANN static m_bool scan1_args(const Env env, Arg_List list) {
343
  do {
344
23751
    const Var_Decl var = list->var_decl;
345
23751
    if(var->xid)
346
23747
      CHECK_BB(isres(env, var->xid, var->pos))
347
23750
    if(list->td)
348
23745
      CHECK_OB((list->type = void_type(env, list->td)))
349
23744
    var->value = arg_value(env, list);
350
23744
    nspc_add_value(env->curr, var->xid, var->value);
351
23744
  } while((list = list->next));
352
16551
  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
76
ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) {
376
76
  if(tmpl_base(fptr->base->tmpl))
377
16
    return scan1_fdef_base_tmpl(env, fptr->base);
378
60
  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
60
  const Func_Def fdef = fptr->base->func->def;
383
60
  CHECK_OB((fdef->base->ret_type = scan1_type(env, fdef->base->td)))
384
58
  if(!fdef->base->args)
385
32
    return GW_OK;
386
26
  RET_NSPC(scan1_args(env, fdef->base->args))
387
}
388
389
732
ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) {
390
732
  if(!tdef->type)
391
    tdef->type = nspc_lookup_type0(env->curr, tdef->xid);
392
732
  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
#define scan1_stmt_pp       (void*)dummy_func
454
DECL_STMT_FUNC(scan1, m_bool, Env)
455
456
2828
ANN static inline m_bool scan1_stmt(const Env env, const Stmt stmt) {
457
2828
  return scan1_stmt_func[stmt->stmt_type](env, &stmt->d);
458
}
459
460
2662
ANN static m_bool scan1_stmt_list(const Env env, Stmt_List l) {
461
  do {
462
2662
    CHECK_BB(scan1_stmt(env, l->stmt))
463
2628
    if(l->next) {
464
1530
      if(l->stmt->stmt_type != ae_stmt_return) {
465

2875
        if(l->next->stmt->stmt_type == ae_stmt_exp &&
466
1346
          !l->next->stmt->d.stmt_exp.val) {
467
4
           Stmt_List next = l->next;
468
4
           l->next = l->next->next;
469
4
           next->next = NULL;
470
4
           free_stmt_list(env->gwion->mp, next);
471
        }
472
      } else {
473
1
        Stmt_List tmp = l->next;
474
1
        l->next = NULL;
475
1
        free_stmt_list(env->gwion->mp, tmp);
476
      }
477
    }
478
2628
  } while((l = l->next));
479
1103
  return GW_OK;
480
}
481
482
11
ANN static m_bool class_internal(const Env env, const Func_Base *base) {
483
11
  if(!env->class_def)
484
1
    ERR_B(td_pos(base->td), _("'%s' must be in class def!!"), s_name(base->xid))
485
10
  if(base->args)
486
1
    ERR_B(td_pos(base->td), _("'%s' must not have args"), s_name(base->xid))
487
9
  if(base->ret_type != env->gwion->type[et_void])
488
1
    ERR_B(td_pos(base->td), _("'%s' must return 'void'"), s_name(base->xid))
489
8
  return GW_OK;
490
}
491
492
6
ANN static inline m_bool scan_internal_arg(const Env env, const Func_Base *base) {
493

6
  if(base->args && !base->args->next)
494
5
    return GW_OK;
495
1
  ERR_B(td_pos(base->td), _("'%s' must have one (and only one) argument"), s_name(base->xid))
496
}
497
498
3
ANN static inline m_bool scan_internal_int(const Env env, const Func_Base *base) {
499
3
    CHECK_BB(scan_internal_arg(env, base))
500
3
    if(isa(base->ret_type, env->gwion->type[et_int]) > 0)
501
2
      return GW_OK;
502
1
    ERR_B(td_pos(base->td), _("'%s' must return 'int'"), s_name(base->xid))
503
}
504
505
22
ANN static m_bool scan_internal(const Env env, const Func_Base *base) {
506
22
  const Symbol op = base->xid;
507

22
  if(op == insert_symbol("@dtor") || op == insert_symbol("@gack"))
508
11
    return class_internal(env, base);
509
11
  if(op == insert_symbol("@implicit"))
510
3
    return scan_internal_arg(env, base);
511

14
  if(op == insert_symbol("@conditionnal") ||
512
6
     op == insert_symbol("@unconditionnal"))
513
3
    return scan_internal_int(env, base);
514
5
  return GW_OK;
515
}
516
517
230
ANN static m_bool scan1_fdef_args(const Env env, Arg_List list) {
518
  do {
519
230
    Nspc nspc = env->curr;
520
1025
    do if(nspc_lookup_value0(nspc, list->var_decl->xid))
521
       ERR_B(list->var_decl->pos, _("argument '%s' shadows a previuosly defined variable"),
522
            s_name(list->var_decl->xid))
523
1025
    while((nspc = nspc->parent));
524
230
  } while((list = list->next));
525
171
  return GW_OK;
526
}
527
528
42277
ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) {
529
42277
  if(fdef->base->args) {
530
16532
    if(!GET_FLAG(fdef, builtin))
531
171
      CHECK_BB(scan1_fdef_args(env, fdef->base->args))
532
16532
    CHECK_BB(scan1_args(env, fdef->base->args))
533
  }
534

42272
  if(!GET_FLAG(fdef, builtin) && fdef->d.code && fdef->d.code->d.stmt_code.stmt_list)
535
245
    CHECK_BB(scan1_stmt_list(env, fdef->d.code->d.stmt_code.stmt_list))
536
42271
  return GW_OK;
537
}
538
539
42283
ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) {
540
42283
  if(fdef->base->td)
541
42275
    CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td)))
542
42282
  if(GET_FLAG(fdef, typedef))
543
22
    CHECK_BB(scan_internal(env, fdef->base))
544

42260
  else if(GET_FLAG(fdef, op) && env->class_def)
545
2
    SET_FLAG(fdef, static);
546
42277
  RET_NSPC(scan1_fbody(env, fdef))
547
  return GW_OK;
548
}
549
550
42410
ANN static inline m_bool scan1_fdef_defined(const Env env, const Func_Def fdef) {
551
42410
  const Value v = nspc_lookup_value1(env->curr, fdef->base->xid);
552
42410
  if(!v)
553
33789
    return GW_OK;
554
8621
  if(isa(actual_type(env->gwion, v->type), env->gwion->type[et_function]) > 0)
555
8620
    return GW_OK;
556
1
  ERR_B(fdef->pos, _("function '%s' has already been defined in the same scope..."),
557
       s_name(fdef->base->xid))
558
}
559
560
42413
ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
561
42413
  if(fdef->base->td)
562
42405
    CHECK_BB(env_storage(env, fdef->flag, td_pos(fdef->base->td)))
563
42410
  CHECK_BB(scan1_fdef_defined(env, fdef))
564
42409
  if(tmpl_base(fdef->base->tmpl))
565
123
    return scan1_fdef_base_tmpl(env, fdef->base);
566
42286
  struct Func_ fake = { .name=s_name(fdef->base->xid) }, *const former = env->func;
567
42286
  env->func = &fake;
568
42286
  ++env->scope->depth;
569
42286
  const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)scan1_fdef);
570
42286
  --env->scope->depth;
571
42286
  env->func = former;
572
42286
  return ret;
573
}
574
575
1380
HANDLE_SECTION_FUNC(scan1, m_bool, Env)
576
577
70
ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) {
578
70
  const Type parent = known_type(env, tdef->ext);
579
70
  CHECK_OO((tdef->type->e->parent = parent));
580
70
  Type t = parent;
581
245
  do if(tdef->type == t)
582
      ERR_O(td_pos(tdef->ext), _("recursive (%s <= %s) class declaration."), tdef->type->name, t->name)
583
245
  while((t = t->e->parent));
584
70
  return parent;
585
}
586
587
70
ANN static m_bool scan1_parent(const Env env, const Class_Def cdef) {
588
70
  const loc_t pos = td_pos(cdef->base.ext);
589
70
  if(cdef->base.ext->array)
590
9
    CHECK_BB(scan1_exp(env, cdef->base.ext->array->exp))
591
70
  DECL_OB(const Type , parent, = scan1_get_parent(env, &cdef->base))
592
70
  if(isa(parent, env->gwion->type[et_object]) < 0)
593
1
    ERR_B(pos, _("cannot extend primitive type '%s'"), parent->name)
594

69
  if(parent->e->def && !GET_FLAG(parent, scan1))
595
6
    CHECK_BB(ensure_scan1(env, parent))
596
69
  if(type_ref(parent))
597
1
    ERR_B(pos, _("can't use ref type in class extend"))
598
68
  if(GET_FLAG(parent, nonnull))
599
1
    ERR_B(pos, _("can't use nonnull type in class extend"))
600
67
  return GW_OK;
601
}
602
603
70
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
604

70
  if(cdef->base.tmpl && cdef->base.tmpl->list)
605
22
    CHECK_BB(template_push_types(env, cdef->base.tmpl))
606
70
  const m_bool ret = scan1_parent(env, cdef);
607

70
  if(cdef->base.tmpl && cdef->base.tmpl->list)
608
22
    nspc_pop_type(env->gwion->mp, env->curr);
609
70
  return ret;
610
}
611
612
289
ANN m_bool scan1_class_def(const Env env, const Class_Def cdef) {
613
289
  if(tmpl_base(cdef->base.tmpl))
614
22
    return GW_OK;
615
267
  const Type t = cdef->base.type;
616
267
  if(GET_FLAG(t, scan1))
617
2
    return GW_OK;
618
265
  SET_FLAG(t, scan1);
619

265
  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan1))
620
    CHECK_BB(ensure_scan1(env, t->e->owner_class))
621
265
  SET_FLAG(cdef->base.type, scan1);
622
265
  if(cdef->base.ext)
623
70
    CHECK_BB(cdef_parent(env, cdef))
624
262
  if(cdef->body)
625
216
    CHECK_BB(env_body(env, cdef, scan1_section))
626
256
  return GW_OK;
627
}
628
629
1009
ANN m_bool scan1_ast(const Env env, Ast ast) {
630
1009
  do CHECK_BB(scan1_section(env, ast->section))
631
957
  while((ast = ast->next));
632
553
  return GW_OK;
633
}