GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/scan1.c Lines: 443 453 97.8 %
Date: 2020-10-03 09:50:08 Branches: 403 470 85.7 %

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
}