GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/check.c Lines: 989 1027 96.3 %
Date: 2020-10-03 10:30:04 Branches: 759 922 82.3 %

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 "instr.h"
6
#include "object.h"
7
#include "traverse.h"
8
#include "template.h"
9
#include "gwion.h"
10
#include "operator.h"
11
#include "import.h"
12
#include "parse.h"
13
#include "match.h"
14
#include "emit.h"
15
#include "specialid.h"
16
17
ANN static m_bool check_stmt_list(const Env env, Stmt_List list);
18
ANN m_bool check_class_def(const Env env, const Class_Def class_def);
19
20
61
ANN static m_bool check_internal(const Env env, const Symbol sym,
21
      const Exp e, const Type t) {
22
61
  struct Implicit imp = { .e=e, .t=t, .pos=e->pos };
23
183
  struct Op_Import opi = { .op=sym, .lhs=e->info->type,
24
122
        .rhs=t, .data=(uintptr_t)&imp, .pos=e->pos, .op_type=op_implicit };
25
61
  CHECK_OB(op_check(env, &opi))
26
  assert(e->info->nspc);
27
44
  return GW_OK;
28
}
29
30
185
ANN m_bool check_implicit(const Env env, const Exp e, const Type t) {
31
185
  if(e->info->type == t)
32
124
    return GW_OK;
33
61
  const Symbol sym = insert_symbol("@implicit");
34
61
  return check_internal(env, sym, e, t);
35
}
36
37
79
ANN m_bool check_subscripts(Env env, const Array_Sub array, const m_bool is_decl) {
38
79
  CHECK_OB(check_exp(env, array->exp))
39
79
  m_uint depth = 0;
40
79
  Exp e = array->exp;
41
121
  do if(is_decl)
42
74
    CHECK_BB(check_implicit(env, e, env->gwion->type[et_int]))
43

121
  while(++depth && (e = e->next));
44
79
  if(depth != array->depth)
45
1
    ERR_B(array->exp->pos, _("invalid array acces expression."))
46
78
  return GW_OK;
47
}
48
49
11606
ANN static inline m_bool check_exp_decl_parent(const Env env, const Var_Decl var) {
50
11606
  const Value value = find_value(env->class_def->e->parent, var->xid);
51
11606
  if(value)
52
1
    ERR_B(var->pos,
53
          _("in class '%s': '%s' has already been defined in parent class '%s' ..."),
54
          env->class_def->name, s_name(var->xid),
55
          value->from->owner_class ? value->from->owner_class->name : "?")
56
11605
  return GW_OK;
57
}
58
59
#define describe_check_decl(a, b)                                 \
60
ANN static inline void decl_##a(const Env env, const Value v) {   \
61
  const Nspc nspc = env->curr;\
62
  SET_FLAG(v, a);                                                 \
63
  v->from->offset = nspc->info->b;                                \
64
  nspc->info->b += v->type->size;                                 \
65
}
66
11583
describe_check_decl(member, offset)
67
54
describe_check_decl(static, class_data_size)
68
69
57
ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) {
70
57
  const Value v    = var->value;
71
57
  Type t = v->type;
72
119
  while(GET_FLAG(t, typedef))
73
5
    t = t->e->parent;
74
57
  if(!t->e->d.func)
75
    return GW_ERROR;
76
57
  if(!env->class_def)
77
26
    return GW_OK;
78
31
  const Func  func = t->e->d.func;
79
31
  const Type type = func->value_ref->from->owner_class;
80

31
  if(type && isa(type, env->class_def) < 0 && !GET_FLAG(func, global))
81
2
    ERR_B(var->pos, _("can't use non global fptr of other class."))
82

29
  if(GET_FLAG(func, member) && GET_FLAG(v, static))
83
1
      ERR_B(var->pos, _("can't use static variables for member function."))
84
28
  return GW_OK;
85
}
86
87
10
ANN static inline m_bool check_td_exp(const Env env, Type_Decl *td) {
88
10
  RET_NSPC(traverse_exp(env, td->exp))
89
}
90
91
10
ANN Type check_td(const Env env, Type_Decl *td) {
92
10
  CHECK_BO(check_td_exp(env, td))
93
9
  const Type t = actual_type(env->gwion, td->exp->info->type);
94
  assert(t);
95

9
  if(GET_FLAG(t, template) && !GET_FLAG(t, ref))
96
    ERR_O(td_pos(td), _("type '%s' needs template types"), t->name)
97
9
  td->xid = insert_symbol("auto");
98
9
  return t;
99
}
100
101
8
ANN static Type no_xid(const Env env, const Exp_Decl *decl) {
102
8
  CHECK_OO((((Exp_Decl*)decl)->type = check_td(env, decl->td)))
103
7
  CHECK_BO(traverse_exp(env, exp_self(decl)))
104
7
  return decl->type;
105
}
106
107
21471
ANN static m_bool check_var(const Env env, const Var_Decl var) {
108

21471
  if(env->class_def && !env->scope->depth && env->class_def->e->parent)
109
11606
    CHECK_BB(check_exp_decl_parent(env, var))
110

21470
  if(var->array && var->array->exp)
111
37
    return check_subscripts(env, var->array, 1);
112
21433
  return GW_OK;
113
}
114
115
21470
ANN static m_bool check_var_td(const Env env, const Var_Decl var, Type_Decl *const td) {
116
21470
  const Value v = var->value;
117
21470
  if(env->class_def)  {
118
11613
    if(GET_FLAG(td, member)) {
119
11581
      decl_member(env, v);
120
11581
      if(env->class_def->e->tuple)
121
11581
        tuple_info(env, v);
122
32
    } else if(GET_FLAG(td, static))
123
24
      decl_static(env, v);
124
  }
125
21470
  return GW_OK;
126
}
127
128
21463
ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
129
21463
  Var_Decl_List list = decl->list;
130
  do {
131
21471
    const Var_Decl var = list->self;
132
21471
    CHECK_BB(check_var(env, var))
133
21470
    CHECK_BB(check_var_td(env, var, decl->td))
134
21470
    if(is_fptr(env->gwion, decl->type))
135
57
      CHECK_BB(check_fptr_decl(env, var))
136
21467
    SET_FLAG(var->value, valid | ae_flag_used);
137
21467
    nspc_add_value(env->curr, var->xid, var->value);
138
21467
  } while((list = list->next));
139
21459
  return GW_OK;
140
}
141
142
30
ANN static inline m_bool ensure_check(const Env env, const Type t) {
143
60
  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
144
30
    .scope=env->scope->depth, .flag=ae_flag_check };
145
30
  return envset_run(&es, t);
146
}
147
148
6
ANN m_bool ensure_traverse(const Env env, const Type t) {
149
12
  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)traverse_cdef,
150
6
    .scope=env->scope->depth, .flag=ae_flag_check };
151
6
  return envset_run(&es, t);
152
}
153
154
21499
ANN static inline m_bool inferable(const Env env, const Type t, const loc_t pos) {
155
21499
  if(!GET_FLAG(t, infer))
156
21497
    return GW_OK;
157
2
  ERR_B(pos, _("can't infer type."))
158
}
159
160
ANN static Type_Decl* type2td(const Env env, const Type t, const loc_t loc);
161
21472
ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
162
21472
  if(!decl->td->xid)
163
8
    return no_xid(env, decl);
164
21464
  if(decl->td->xid == insert_symbol("auto")) { // should be better
165
14
    SET_FLAG(decl->td, ref);
166
14
    CHECK_BO(scan1_exp(env, exp_self(decl)))
167
14
    CHECK_BO(scan2_exp(env, exp_self(decl)))
168
  }
169
21464
  if(!decl->type)
170
    ERR_O(td_pos(decl->td), _("can't find type"));
171
  {
172
21464
    const Type t = get_type(decl->type);
173
21464
    CHECK_BO(inferable(env, t, td_pos(decl->td)))
174

21463
    if(!GET_FLAG(t, check) && t->e->def)
175
24
      CHECK_BO(ensure_check(env, t))
176
  }
177
21463
  const m_bool global = GET_FLAG(decl->td, global);
178
21463
  const m_uint scope = !global ? env->scope->depth : env_push_global(env);
179
21463
  const m_bool ret = check_decl(env, decl);
180
21463
  if(global)
181
12
    env_pop(env, scope);
182
21463
  return ret > 0 ? decl->list->self->value->type : NULL;
183
}
184
185
186
4
ANN static inline void set_cast(const Env env, Type type, const Exp e) {
187
4
  e->info->cast_to = type;
188
4
  e->info->nspc = env->curr;
189
4
}
190
191
65
ANN static m_bool prim_array_inner(const Env env, Type type, const Exp e) {
192
65
  const Type common = find_common_anc(e->info->type, type);
193
65
  if(common)
194
59
    return GW_OK;
195
6
  if(check_implicit(env, e, type) < 0)
196
2
    ERR_B(e->pos, _("array init [...] contains incompatible types ..."))
197
4
  set_cast(env, type, e); // ???
198
4
  return GW_OK;
199
}
200
201
22
ANN static inline Type prim_array_match(const Env env, Exp e) {
202
22
  const Type type = e->info->type;
203
65
  do CHECK_BO(prim_array_inner(env, type, e))
204
63
  while((e = e->next));
205
20
  return array_type(env, array_base(type), type->array_depth + 1);
206
}
207
208
23
ANN static Type check_prim_array(const Env env, const Array_Sub *data) {
209
23
  const Array_Sub array = *data;
210
23
  const Exp e = array->exp;
211
23
  if(!e)
212
1
    ERR_O(prim_pos(data), _("must provide values/expressions for array [...]"))
213
22
  CHECK_OO(check_exp(env, e))
214
22
  return (array->type = prim_array_match(env, e));
215
}
216
217
12
ANN static m_bool check_range(const Env env, Range *range) {
218
12
  if(range->start)
219
11
    CHECK_OB(check_exp(env, range->start))
220
12
  if(range->end)
221
8
    CHECK_OB(check_exp(env, range->end))
222

12
  if(range->start && range->end) {
223
7
    if(isa(range->end->info->type, range->start->info->type) < 0)
224
1
      ERR_B(range->start->pos, _("range types do not match"))
225
  }
226
11
  return GW_OK;
227
}
228
229
3
ANN static Type check_prim_range(const Env env, Range **data) {
230
3
  Range *range = *data;
231
3
  CHECK_BO(check_range(env, range))
232
2
  const Exp e = range->start ?: range->end;
233
2
  const Symbol sym = insert_symbol("@range");
234
2
  struct Op_Import opi = { .op=sym, .rhs=e->info->type, .pos=e->pos, .data=(uintptr_t)prim_exp(data), .op_type=op_exp };
235
2
  return op_check(env, &opi);
236
}
237
238
903
ANN m_bool not_from_owner_class(const Env env, const Type t,
239
      const Value v, const loc_t pos) {
240

903
  if(!v->from->owner_class || isa(t, v->from->owner_class) < 0) {
241
1
    ERR_B(pos,
242
        _("'%s' from owner namespace '%s' used in '%s'."),
243
            v->name, v->from->owner ? v->from->owner->name : "?", t->name)
244
  }
245
902
  return GW_OK;
246
}
247
248
1952
ANN static Value check_non_res_value(const Env env, const Symbol *data) {
249
1952
  const Symbol var = *data;
250
1952
  const Value value = nspc_lookup_value1(env->curr, var);
251
1952
  if(env->class_def) {
252

285
    if(value && value->from->owner_class)
253
185
      CHECK_BO(not_from_owner_class(env, env->class_def, value, prim_pos(data)))
254
284
    const Value v = value ?: find_value(env->class_def, var);
255
284
    if(v) {
256

282
      if(env->func && GET_FLAG(env->func->def->base, static) && GET_FLAG(v, member))
257
2
        ERR_O(prim_pos(data),
258
              _("non-static member '%s' used from static function."), s_name(var))
259
    }
260
282
    return v;
261


1667
  } else if(SAFE_FLAG(env->class_def, global) || (env->func && GET_FLAG(env->func->def->base, global))) {
262

4
    if(!SAFE_FLAG(value, abstract))
263
1
      ERR_O(prim_pos(data),
264
            _("non-global variable '%s' used from global function/class."), s_name(var))
265
  }
266
1666
  return value;
267
}
268
269
ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data);
270
271
725
ANN static Type check_dot(const Env env, const Exp_Dot *member) {
272
1450
  struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, .data=(uintptr_t)member,
273
725
    .pos=exp_self(member)->pos, .op_type=op_dot };
274
725
  return op_check(env, &opi);
275
}
276
277
1
static inline Nspc value_owner(const Value v) {
278
1
  return v ? v->from->owner : NULL;
279
}
280
281
3
ANN static m_bool lambda_valid(const Env env, const Exp_Primary* exp) {
282
3
  const Value val = exp->value;
283
3
  const Symbol sym = insert_symbol(val->name);
284
3
  const Vector vec = (Vector)&env->curr->info->value->ptr;
285
3
  const m_uint scope = map_get(&env->curr->info->func->map, (m_uint)env->func->def->base);
286
3
  if(GET_FLAG(val, abstract))
287
3
    return GW_OK;
288
  if(val->from->owner_class && isa(val->from->owner_class, env->class_def) > 0)
289
    return GW_OK;
290
  const m_uint sz = vector_size(vec);
291
  for(m_uint i = scope; i < sz; ++i) {
292
    const Map map = (Map)vector_at(vec, i);
293
    if(map_get(map, (m_uint)sym))
294
      return GW_OK;
295
  }
296
  ERR_B(exp_self(exp)->pos, _("variable '%s' is not in lambda scope"), val->name)
297
}
298
299
1952
ANN static Type prim_id_non_res(const Env env, const Symbol *data) {
300
1952
  const Symbol sym = *data;
301
1952
  const Value v = check_non_res_value(env, data);
302


1952
  if(!v || !GET_FLAG(v, valid) || (v->from->ctx && v->from->ctx->error)) {
303
16
    env_err(env, prim_pos(data),
304
          _("variable %s not legit at this point."), s_name(sym));
305
16
    if(v)
306

1
      did_you_mean_nspc(value_owner(v) ?: env->curr, s_name(sym));
307
16
    return NULL;
308
  }
309
1936
  prim_self(data)->value = v;
310
1936
  if(env->func) {
311
299
    if(GET_FLAG(env->func->def->base, abstract))
312
3
      CHECK_BO(lambda_valid(env, prim_self(data)))
313

299
  if(env->func && !GET_FLAG(v, const) && v->from->owner)
314
19
    UNSET_FLAG(env->func, pure);
315
  }
316
1936
  SET_FLAG(v, used);
317
1936
  if(GET_FLAG(v, const))
318
585
    exp_setmeta(prim_exp(data), 1);
319
1936
  if(v->from->owner_class) {
320
182
    const Exp exp  = symbol_owned_exp(env->gwion, data);
321
182
    const Type ret = check_dot(env, &exp->d.exp_dot);
322
182
    prim_exp(data)->info->nspc = exp->info->nspc;
323
182
    free_exp(env->gwion->mp, exp);
324
182
    CHECK_OO(ret);
325
  }
326
1936
  return v->type;
327
}
328
329
263
ANN Type check_prim_str(const Env env, const m_str *data) {
330
263
  if(!prim_self(data)->value)
331
263
    prim_self(data)->value = global_string(env, *data);
332
263
  return env->gwion->type[et_string];// prim->value
333
}
334
335
2284
ANN static Type check_prim_id(const Env env, const Symbol *data) {
336
2284
  struct SpecialId_ * spid = specialid_get(env->gwion, *data);
337
2284
  if(spid)
338
332
    return specialid_type(env, spid, prim_self(data));
339
1952
  return prim_id_non_res(env, data);
340
}
341
342
35
ANN static Type check_prim_typeof(const Env env, const Exp *exp) {
343
35
  const Exp e = *exp;
344
35
  DECL_OO(const Type, t, = check_exp(env, e))
345
35
  CHECK_BO(inferable(env, t, (*exp)->pos))
346
34
  const Type force = force_type(env, t);
347
34
  return type_class(env->gwion, force);
348
}
349
350
928
ANN static Type check_prim_interp(const Env env, const Exp* exp) {
351
928
  CHECK_OO(check_exp(env, *exp))
352
895
  return env->gwion->type[et_string];
353
}
354
355
925
ANN static Type check_prim_hack(const Env env, const Exp *data) {
356
925
  if(env->func)
357
210
    UNSET_FLAG(env->func, pure);
358
925
  CHECK_OO(check_prim_interp(env, data))
359
892
  return env->gwion->type[et_gack];
360
}
361
362
#define describe_prim_xxx(name, type) \
363
ANN static Type check##_prim_##name(const Env env NUSED, const union prim_data* data NUSED) {\
364
  return type; \
365
}
366
859
describe_prim_xxx(num, env->gwion->type[et_int])
367
15
describe_prim_xxx(char, env->gwion->type[et_char])
368
119
describe_prim_xxx(float, env->gwion->type[et_float])
369
15
describe_prim_xxx(nil, env->gwion->type[et_void])
370
371
#define check_prim_complex check_prim_vec
372
#define check_prim_polar check_prim_vec
373
#define check_prim_char check_prim_char
374
DECL_PRIM_FUNC(check, Type, Env);
375
376
4544
ANN static Type check_prim(const Env env, Exp_Primary *prim) {
377
4544
  return exp_self(prim)->info->type = check_prim_func[prim->prim_type](env, &prim->d);
378
}
379
380
33
ANN Type check_array_access(const Env env, const Array_Sub array) {
381
33
  const Symbol sym = insert_symbol("@array");
382
99
  struct Op_Import opi = { .op=sym, .lhs=array->exp->info->type, .rhs=array->type,
383
66
    .pos=array->exp->pos, .data=(uintptr_t)array, .op_type=op_array };
384
33
  return op_check(env, &opi);
385
}
386
387
30
static ANN Type check_exp_array(const Env env, const Exp_Array* array) {
388
30
  CHECK_OO((array->array->type = check_exp(env, array->base)))
389
30
  CHECK_BO(check_subscripts(env, array->array, 0))
390
29
  return check_array_access(env, array->array);
391
}
392
393
9
static ANN Type check_exp_slice(const Env env, const Exp_Slice* range) {
394
9
  CHECK_OO(check_exp(env, range->base))
395
9
  CHECK_BO(check_range(env, range->range))
396
9
  const Symbol sym = insert_symbol("@slice");
397
9
  const Exp e = range->range->start ?: range->range->end;
398
27
  struct Op_Import opi = { .op=sym, .lhs=e->info->type, .rhs=range->base->info->type,
399
18
    .pos=e->pos, .data=(uintptr_t)exp_self(range), .op_type=op_exp };
400
9
  return op_check(env, &opi);
401
}
402
403
71
ANN2(1,2,4) static Type_Decl* prepend_type_decl(MemPool mp, const Symbol xid, Type_Decl* td, const loc_t pos) {
404
71
  Type_Decl *a = new_type_decl(mp, xid, loc_cpy(mp, pos));
405
71
  a->next = td;
406
71
  return a;
407
}
408
409
70
ANN static Type_List mk_type_list(const Env env, const Type type, const loc_t pos) {
410
  struct Vector_ v;
411
70
  vector_init(&v);
412
70
  vector_add(&v, (vtype)insert_symbol(type->name));
413
70
  Type owner = type->e->owner_class;
414
141
  while(owner) {
415
1
    vector_add(&v, (vtype)insert_symbol(owner->name));
416
1
    owner = owner->e->owner_class;
417
  }
418
70
  Type_Decl *td = NULL;
419
141
  for(m_uint i = 0 ; i < vector_size(&v); ++i)
420
71
    td = prepend_type_decl(env->gwion->mp, (Symbol)vector_at(&v, i), td, pos);
421
70
  vector_release(&v);
422
70
  return new_type_list(env->gwion->mp, td, NULL);
423
}
424
425
498
ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t,
426
  const m_bool implicit, const m_bool specific) {
427
498
  const m_bool match = (specific ? e->info->type == t : isa(e->info->type, t) > 0);
428
498
  if(!match) {
429

118
    if(e->info->type == env->gwion->type[et_lambda] && is_fptr(env->gwion, t)) {
430
1
      exp_setvar(e, 1);
431
1
      return check_lambda(env, t, &e->d.exp_lambda);
432
    }
433
117
    if(implicit)
434
52
      return check_implicit(env, e, t);
435
  }
436
445
  return match ? 1 : -1;
437
}
438
439
705
ANN2(1,2) static Func find_func_match_actual(const Env env, Func func, const Exp args,
440
  const m_bool implicit, const m_bool specific) {
441
  do {
442
705
    Exp e = args;
443
705
    Arg_List e1 = func->def->base->args;
444
1830
    while(e) {
445
683
      if(!e1) {
446
185
        if(GET_FLAG(func->def->base, variadic))
447
18
          return func;
448
167
        CHECK_OO(func->next);
449
61
        return find_func_match_actual(env, func->next, args, implicit, specific);
450
      }
451

996
      if(e1->type == env->gwion->type[et_undefined] ||
452
768
            (func->def->base->tmpl && is_fptr(env->gwion, func->value_ref->type) > 0)) {
453
4
        const Type owner = func->value_ref->from->owner_class;
454
4
        if(owner)
455
2
          CHECK_BO(template_push(env, owner))
456
4
        e1->type = known_type(env, e1->td);
457
4
        if(owner)
458
2
          nspc_pop_type(env->gwion->mp, env->curr);
459
4
        CHECK_OO(e1->type)
460
      }
461
498
      if(func_match_inner(env, e, e1->type, implicit, specific) < 0)
462
78
        break;
463
420
      e = e->next;
464
420
      e1 = e1->next;
465
    }
466
520
    if(!e1)
467
431
      return func;
468
89
  } while((func = func->next));
469
67
  return NULL;
470
}
471
472
483
ANN2(1, 2) static Func find_func_match(const Env env, const Func up, const Exp exp) {
473
  Func func;
474

483
  const Exp args = (exp && isa(exp->info->type, env->gwion->type[et_void]) < 0) ? exp : NULL;
475

483
  if((func = find_func_match_actual(env, up, args, 0, 1)) ||
476
35
     (func = find_func_match_actual(env, up, args, 1, 1)) ||
477
34
     (func = find_func_match_actual(env, up, args, 0, 0)) ||
478
     (func = find_func_match_actual(env, up, args, 1, 0)))
479
449
    return func;
480
34
  return NULL;
481
}
482
483
134
ANN static m_bool check_call(const Env env, const Exp_Call* exp) {
484
134
  ae_exp_t et = exp->func->exp_type;
485

134
  if(et != ae_exp_primary && et != ae_exp_dot && et != ae_exp_cast)
486
1
    ERR_B(exp->func->pos, _("invalid expression for function call."))
487
133
  CHECK_OB(check_exp(env, exp->func))
488
132
  if(exp->args)
489
124
    CHECK_OB(check_exp(env, exp->args))
490
131
  return GW_OK;
491
}
492
493
221
ANN static inline Value template_get_ready(const Env env, const Value v, const m_str tmpl, const m_uint i) {
494
221
  const Symbol sym = func_symbol(env, v->from->owner->name, v->name, tmpl, i);
495
282
  return v->from->owner_class ? find_value(v->from->owner_class, sym) :
496
61
      nspc_lookup_value1(v->from->owner, sym);
497
}
498
499
67
ANN m_bool check_traverse_fdef(const Env env, const Func_Def fdef) {
500
67
  struct Vector_ v = {};
501
67
  const m_uint scope = env->scope->depth;
502
67
  env->scope->depth = 1;
503
67
  vector_init(&v);
504
146
  while(vector_size((Vector)&env->curr->info->value->ptr) > 1)
505
12
    vector_add(&v, vector_pop((Vector)&env->curr->info->value->ptr));
506
67
  const m_bool ret = traverse_func_def(env, fdef);
507
146
  for(m_uint i = vector_size(&v) + 1; --i;)
508
12
    vector_add((Vector)&env->curr->info->value->ptr, vector_at(&v, i-1));
509
67
  vector_release(&v);
510
67
  env->scope->depth = scope;
511
67
  return ret;
512
}
513
514
103
ANN static Func ensure_tmpl(const Env env, const Func_Def fdef, const Exp_Call *exp) {
515

103
  const m_bool ret = GET_FLAG(fdef->base, valid) || check_traverse_fdef(env, fdef) > 0;
516
103
  if(ret) {
517
97
    const Func f = fdef->base->func;
518
97
    const Func next = f->next;
519
97
    f->next = NULL;
520
97
    const Func func = find_func_match(env, f, exp->args);
521
97
    f->next = next;
522
97
    if(func) {
523
72
      SET_FLAG(func, valid | ae_flag_template);
524
72
      return func;
525
    }
526
  }
527
31
  return NULL;
528
}
529
530
23781
ANN static m_bool check_func_args(const Env env, Arg_List arg_list) {
531
  do {
532
23781
    const Var_Decl decl = arg_list->var_decl;
533
23781
    const Value v = decl->value;
534

23781
    if(arg_list->td && !arg_list->td->xid)
535
1
      CHECK_OB((arg_list->type = v->type = check_td(env, arg_list->td)))
536
// TODO: use coumpound instead of object?
537

23781
    if(isa(v->type, env->gwion->type[et_object]) > 0 || isa(v->type, env->gwion->type[et_function]) > 0)
538
5053
      UNSET_FLAG(env->func, pure);
539
23781
    CHECK_BB(already_defined(env, decl->xid, decl->pos))
540
23780
    SET_FLAG(v, valid);
541
23780
    nspc_add_value(env->curr, decl->xid, v);
542
23780
  } while((arg_list = arg_list->next));
543
16571
  return GW_OK;
544
}
545
546
129
ANN static Func _find_template_match(const Env env, const Value v, const Exp_Call* exp) {
547
129
  CHECK_BO(check_call(env, exp))
548
126
  const Type_List types = exp->tmpl->call;
549
126
  Func m_func = NULL, former = env->func;
550
126
  DECL_OO(const m_str, tmpl_name, = tl2str(env, types))
551
125
  const m_uint scope = env->scope->depth;
552
125
  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
553
    .scope=scope, .flag=ae_flag_check };
554
125
  CHECK_BO(envset_push(&es, v->from->owner_class, v->from->owner))
555
125
  (void)env_push(env, v->from->owner_class, v->from->owner);
556
125
  if(is_fptr(env->gwion, v->type)) {
557
9
    const Symbol sym = func_symbol(env, v->from->owner->name, v->name, tmpl_name, 0);
558
9
    const Type exists = nspc_lookup_type0(v->from->owner, sym);
559
9
    if(exists)
560
      m_func = exists->e->d.func;
561
    else {
562
9
      Func_Def base = v->d.func_ref ? v->d.func_ref->def : exp->func->info->type->e->d.func->def;
563
9
      Func_Base *fbase = cpy_func_base(env->gwion->mp, base->base);
564
9
      fbase->xid = sym;
565
9
      fbase->tmpl->base = 0;
566
9
      fbase->tmpl->call = cpy_type_list(env->gwion->mp, types);
567
9
      if(template_push_types(env, fbase->tmpl) > 0) {
568
9
        const Fptr_Def fptr = new_fptr_def(env->gwion->mp, fbase);
569

18
        if(traverse_fptr_def(env, fptr) > 0 &&
570
18
            (base->base->ret_type = known_type(env, base->base->td)) &&
571
13
            (!exp->args || !!check_exp(env, exp->args))) {
572
9
          m_func = find_func_match(env, fbase->func, exp->args);
573
9
          nspc_pop_type(env->gwion->mp, env->curr);
574
9
          if(m_func)
575
9
            nspc_add_type_front(v->from->owner, sym, actual_type(env->gwion, m_func->value_ref->type));
576
        }
577
9
        free_fptr_def(env->gwion->mp, fptr);
578
9
        if(fptr->type)
579
9
          REM_REF(fptr->type, env->gwion)
580
      }
581
    }
582
  } else {
583
181
    for(m_uint i = 0; i < v->from->offset + 1; ++i) {
584
141
      const Value exists = template_get_ready(env, v, tmpl_name, i);
585
141
      if(exists) {
586
61
        if(env->func == exists->d.func_ref) {
587

10
          if(check_call(env, exp) < 0 ||
588
5
             !find_func_match(env, env->func, exp->args))
589
1
            continue;
590
4
          m_func = env->func;
591
4
          break;
592
        }
593
56
        if((m_func = ensure_tmpl(env, exists->d.func_ref->def, exp)))
594
33
          break;
595
      } else {
596
80
        const Value value = template_get_ready(env, v, "template", i);
597
80
        if(!value)
598
33
          continue;
599
47
        if(GET_FLAG(v, builtin)) {
600
1
          SET_FLAG(value, builtin);
601
1
          SET_FLAG(value->d.func_ref, builtin);
602
        }
603
47
        const Func_Def fdef = (Func_Def)cpy_func_def(env->gwion->mp, value->d.func_ref->def);
604
47
        SET_FLAG(fdef->base, template);
605
47
        fdef->base->tmpl->call = cpy_type_list(env->gwion->mp, types);
606
47
        fdef->base->tmpl->base = i;
607
47
        if((m_func = ensure_tmpl(env, fdef, exp)))
608
39
          break;
609
      }
610
    }
611
  }
612
125
  free_mstr(env->gwion->mp, tmpl_name);
613
125
  if(es.run)
614
2
    envset_pop(&es, v->from->owner_class);
615
125
  env_pop(env, scope);
616
125
  env->func = former;
617
125
  return m_func;
618
}
619
620
94
ANN Func find_template_match(const Env env, const Value value, const Exp_Call* exp) {
621
94
  const Func f = _find_template_match(env, value, exp);
622
94
  if(f)
623
72
    return f;
624
22
  Type t = value->from->owner_class;
625

66
  while(t && t->nspc) {
626
35
    Func_Def fdef = value->d.func_ref ? value->d.func_ref->def : value->type->e->d.func->def;
627
35
    const Value v = nspc_lookup_value0(t->nspc, fdef->base->xid);
628
35
    if(!v)
629
      goto next;
630
35
     const Func f = _find_template_match(env, v, exp);
631
35
     if(f)
632
13
       return f;
633
22
   next:
634
22
     t = t->e->parent;
635
  }
636
9
  ERR_O(exp_self(exp)->pos, _("arguments do not match for template call"))
637
}
638
639
#define next_arg(type) \
640
ANN static inline type next_arg_##type(const type e) { \
641
  const type next = e->next;                           \
642
  if(next)                                             \
643
    gw_err(",");                                       \
644
  return next;                                         \
645
}
646
9
next_arg(Exp)
647
8
next_arg(Arg_List)
648
649
7
ANN static void print_current_args(Exp e) {
650
7
  gw_err(_("and not\n  "));
651
9
  do gw_err(" \033[32m%s\033[0m", e->info->type->name);
652
9
  while((e = next_arg_Exp(e)));
653
7
  gw_err("\n");
654
7
}
655
656
8
ANN static void print_arg(Arg_List e) {
657

16
  do gw_err(" \033[32m%s\033[0m \033[1m%s\033[0m", e->type ? e->type->name : NULL,
658
16
       e->var_decl->xid ? s_name(e->var_decl->xid)  : "");
659
8
  while((e = next_arg_Arg_List(e)));
660
7
}
661
662
8
ANN2(1) static void function_alternative(const Env env, const Type f, const Exp args, const loc_t pos){
663
8
  env_err(env, pos, _("argument type(s) do not match for function. should be :"));
664
8
  Func up = f->e->d.func;
665
  do {
666
9
    gw_err("(%s)  ", up->name);
667
9
    const Arg_List e = up->def->base->args;
668
9
    if(e)
669
7
      print_arg(e);
670
    else
671
2
      gw_err("\033[32mvoid\033[0m");
672
9
    gw_err("\n");
673
9
  } while((up = up->next));
674
8
  if(args)
675
7
    print_current_args(args);
676
  else
677
1
    gw_err(_("and not:\n  \033[32mvoid\033[0m\n"));
678
8
}
679
680
68
ANN static m_uint get_type_number(ID_List list) {
681
68
  m_uint type_number = 0;
682
73
  do ++type_number;
683
73
  while((list = list->next));
684
68
  return type_number;
685
}
686
687
69
ANN static Func get_template_func(const Env env, const Exp_Call* func, const Value v) {
688
69
  const Func f = find_template_match(env, v, func);
689
69
  if(f) {
690
// copy that tmpl->call?
691
68
    Tmpl* tmpl = new_tmpl_call(env->gwion->mp, func->tmpl->call);
692
68
    tmpl->list = v->d.func_ref ? v->d.func_ref->def->base->tmpl->list : func->func->info->type->e->d.func->def->base->tmpl->list;
693
68
    ((Exp_Call*)func)->tmpl = tmpl;
694
68
    return ((Exp_Call*)func)->m_func = f;
695
  }
696
1
  ((Exp_Call*)func)->tmpl = NULL;
697
  assert(exp_self(func));
698
1
  ERR_O(exp_self(func)->pos,
699
        _("function is template. automatic type guess not fully implemented yet.\n"
700
        "  please provide template types. eg: ':[type1, type2, ...]'"))
701
}
702
703
3
ANN static Func predefined_func(const Env env, const Value v,
704
    Exp_Call *exp, const Tmpl *tm) {
705
3
  Tmpl tmpl = { .call=tm->call };
706
3
  exp->tmpl = &tmpl;
707
3
  DECL_OO(const Func, func, = get_template_func(env, exp, v))
708
3
  return v->d.func_ref = func;
709
}
710
711
19
ANN static Type check_predefined(const Env env, Exp_Call *exp, const Value v, const Tmpl *tm, const Func_Def fdef) {
712

19
  DECL_OO(const Func, func, = v->d.func_ref ?: predefined_func(env, v, exp, tm))
713
19
  if(!fdef->base->ret_type) { // template fptr
714
12
    struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
715
6
      .scope=env->scope->depth, .flag=ae_flag_check };
716
7
    CHECK_BO(envset_push(&es, v->from->owner_class, v->from->owner))
717
6
    SET_FLAG(func->def->base, typedef);
718
6
    const m_bool ret = check_traverse_fdef(env, func->def);
719
6
    if(es.run)
720
      envset_pop(&es, v->from->owner_class);
721
6
    CHECK_BO(ret)
722
  }
723
18
  exp->m_func = func;
724
18
  return func->def->base->ret_type;
725
}
726
727
68
ANN static Type_List check_template_args(const Env env, Exp_Call *exp, const Tmpl *tm, const Func_Def fdef) {
728
68
  m_uint args_number = 0;
729
68
  const m_uint type_number = get_type_number(tm->list);
730
68
  Type_List tl[type_number];
731
68
  tl[0] = NULL;
732
68
  ID_List list = tm->list;
733
209
  while(list) {
734
73
    Arg_List arg = fdef->base->args;
735
73
    Exp template_arg = exp->args;
736

164
    while(arg && template_arg) {
737
88
      if(list->xid == arg->td->xid) {
738
70
        tl[args_number] = mk_type_list(env, template_arg->info->type, fdef->pos);
739
70
        if(args_number)
740
3
          tl[args_number - 1]->next = tl[args_number];
741
70
        ++args_number;
742
70
        break;
743
      }
744
18
      arg = arg->next;
745
18
      template_arg = template_arg->next;
746
    }
747
73
    list = list->next;
748
  }
749
68
  if(args_number < type_number)
750
2
    ERR_O(exp->func->pos, _("not able to guess types for template call."))
751
66
  return tl[0];
752
}
753
754
87
ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) {
755
87
  const Type t = exp->func->info->type;
756
87
  DECL_OO(const Value, value, = type_value(env->gwion, t))
757
87
  const Func_Def fdef = value->d.func_ref ? value->d.func_ref->def : t->e->d.func->def;
758
87
  Tmpl *tm = fdef->base->tmpl;
759
87
  if(tm->call)
760
19
    return check_predefined(env, exp, value, tm, fdef);
761
68
  DECL_OO(const Type_List, tl, = check_template_args(env, exp, tm, fdef));
762
66
  Tmpl tmpl = { .call=tl };
763
66
  ((Exp_Call*)exp)->tmpl = &tmpl;
764
66
  DECL_OO(const Func,func, = get_template_func(env, exp, value))
765
65
  return func->def->base->ret_type;
766
}
767
768
9
ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
769
9
  if(exp->args)
770
5
    CHECK_OO(check_exp(env, exp->args))
771
9
  Exp_Lambda *l = &exp->func->d.exp_lambda;
772
9
  Arg_List arg = l->def->base->args;
773
9
  Exp e = exp->args;
774

24
  while(arg && e) {
775
6
    arg->type = e->info->type;
776
6
    arg = arg->next;
777
6
    e = e->next;
778
  }
779

9
  if(arg || e)
780
1
    ERR_O(exp_self(exp)->pos, _("argument number does not match for lambda"))
781
8
  CHECK_BO(check_traverse_fdef(env, l->def))
782
8
  if(env->class_def)
783
3
    SET_FLAG(l->def->base, member);
784
8
  ((Exp_Call*)exp)->m_func = l->def->base->func;
785
8
  return l->def->base->ret_type ?: (l->def->base->ret_type = env->gwion->type[et_void]);
786
}
787
788
473
ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
789
473
  CHECK_OO(check_exp(env, exp->func))
790
469
  if(isa(exp->func->info->type, env->gwion->type[et_function]) < 0) {
791
    // use func flag?
792
1
    if(isa(exp->func->info->type, env->gwion->type[et_class]) < 0)
793
1
      ERR_O(exp->func->pos, _("function call using a non-function value"))
794
    struct Op_Import opi = { .op=insert_symbol("@ctor"), .rhs=exp->func->info->type->e->d.base_type,
795
      .data=(uintptr_t)exp, .pos=exp_self(exp)->pos, .op_type=op_exp };
796
    const Type t = op_check(env, &opi);
797
    exp_self(exp)->info->nspc = t ? t->e->owner : NULL;
798
    return t;
799
  }
800
468
  if(exp->func->info->type == env->gwion->type[et_lambda])
801
9
    return check_lambda_call(env, exp);
802
459
  if(GET_FLAG(exp->func->info->type->e->d.func, ref)) {
803
5
    const Value value = exp->func->info->type->e->d.func->value_ref;
804

5
    if(value->from->owner_class && !GET_FLAG(value->from->owner_class, check))
805
      CHECK_BO(ensure_traverse(env, value->from->owner_class))
806
  }
807
459
  if(exp->args)
808
226
    CHECK_OO(check_exp(env, exp->args))
809
459
  if(GET_FLAG(exp->func->info->type, func))
810
87
    return check_exp_call_template(env, (Exp_Call*)exp);
811
372
  const Func func = find_func_match(env, exp->func->info->type->e->d.func, exp->args);
812
372
  if((exp_self(exp)->d.exp_call.m_func = func)) {
813
364
    exp->func->info->type = func->value_ref->type;
814
364
    return func->def->base->ret_type;
815
  }
816
8
  function_alternative(env, exp->func->info->type, exp->args, exp_self(exp)->pos);
817
8
  return NULL;
818
}
819
820
654
ANN static Type check_exp_binary(const Env env, const Exp_Binary* bin) {
821
654
  CHECK_OO(check_exp(env, bin->lhs))
822

653
  const m_bool is_auto = bin->rhs->exp_type == ae_exp_decl && bin->rhs->d.exp_decl.type == env->gwion->type[et_auto];
823
653
  if(is_auto)
824
6
    bin->rhs->d.exp_decl.type = bin->lhs->info->type;
825
653
  CHECK_OO(check_exp(env, bin->rhs))
826
651
  if(is_auto)
827
6
    bin->rhs->info->type = bin->lhs->info->type;
828
2604
  struct Op_Import opi = { .op=bin->op, .lhs=bin->lhs->info->type,
829
1953
    .rhs=bin->rhs->info->type, .data=(uintptr_t)bin, .pos=exp_self(bin)->pos, .op_type=op_binary };
830
651
  const Type ret = op_check(env, &opi);
831

651
  if(!ret && is_auto && exp_self(bin)->exp_type == ae_exp_binary)
832
1
    bin->rhs->d.exp_decl.list->self->value->type = env->gwion->type[et_auto];
833
651
  return ret;
834
}
835
836
41
ANN static Type check_exp_cast(const Env env, const Exp_Cast* cast) {
837
41
  DECL_OO(const Type, t, = check_exp(env, cast->exp))
838

41
  CHECK_OO((exp_self(cast)->info->type = cast->td->xid ? known_type(env, cast->td) : check_td(env, cast->td)))
839
120
  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=t, .rhs=exp_self(cast)->info->type,
840
80
    .data=(uintptr_t)cast, .pos=exp_self(cast)->pos, .op_type=op_cast };
841
40
  return op_check(env, &opi);
842
}
843
844
38
ANN static Type check_exp_post(const Env env, const Exp_Postfix* post) {
845
114
  struct Op_Import opi = { .op=post->op, .lhs=check_exp(env, post->exp),
846
76
    .data=(uintptr_t)post, .pos=exp_self(post)->pos, .op_type=op_postfix };
847
38
  CHECK_OO(opi.lhs)
848
38
  const Type t = op_check(env, &opi);
849

38
  if(t && isa(t, env->gwion->type[et_object]) < 0)
850
35
    exp_setmeta(exp_self(post), 1);
851
38
  return t;
852
}
853
854
2
ANN static m_bool predefined_call(const Env env, const Type t, const loc_t pos) {
855
2
  const m_str str = tl2str(env, t->e->d.func->def->base->tmpl->call);
856
2
  env_err(env, pos, _("Type '%s' has '%s' as pre-defined types."),
857
      t->name, str);
858
2
  free_mstr(env->gwion->mp, str);
859
2
  if(GET_FLAG(t, typedef)) {
860
1
    loc_header(t->e->d.func->def->pos, env->name);
861
1
    gw_err(_("from definition:\n"));
862
1
    loc_err(t->e->d.func->def->pos, env->name);
863
  }
864
2
  return GW_ERROR;
865
}
866
867
430
ANN static Type check_exp_call(const Env env, Exp_Call* exp) {
868
430
  if(exp->tmpl) {
869
30
    CHECK_OO(check_exp(env, exp->func))
870
29
    const Type t = actual_type(env->gwion, unflag_type(exp->func->info->type));
871
29
    if(isa(t, env->gwion->type[et_function]) < 0)
872
1
      ERR_O(exp_self(exp)->pos, _("template call of non-function value."))
873
28
    if(!t->e->d.func->def->base->tmpl)
874
1
      ERR_O(exp_self(exp)->pos, _("template call of non-template function."))
875
27
    if(t->e->d.func->def->base->tmpl->call) {
876
2
      if(env->func == t->e->d.func) {
877
        if(exp->args)
878
          CHECK_OO(check_exp(env, exp->args))
879
        exp->m_func = env->func;
880
        return env->func->def->base->ret_type;
881
      }  else
882
2
      CHECK_BO(predefined_call(env, t, exp_self(exp)->pos))
883
    }
884
25
    const Value v = type_value(env->gwion, t);
885
25
    CHECK_OO((exp->m_func = find_template_match(env, v, exp)))
886
17
    return exp->m_func->def->base->ret_type;
887
  }
888
400
  return check_exp_call1(env, exp);
889
}
890
891
135
ANN static Type check_exp_unary(const Env env, const Exp_Unary* unary) {
892
405
  struct Op_Import opi = { .op=unary->op, .rhs=unary->exp ? check_exp(env, unary->exp) : NULL,
893
270
    .data=(uintptr_t)unary, .pos=exp_self(unary)->pos, .op_type=op_unary };
894

135
  if(unary->exp && !opi.rhs)
895
    return NULL;
896
135
  DECL_OO(const Type, ret, = op_check(env, &opi))
897
128
  const Type t = get_type(actual_type(env->gwion, ret));
898

128
  if(t->e->def && !GET_FLAG(t, check))
899
1
    CHECK_BO(ensure_traverse(env, t))
900
128
  return ret;
901
}
902
903
89
ANN static Type _flow(const Env env, const Exp e, const m_bool b) {
904
89
  DECL_OO(const Type, type, = check_exp(env, e))
905
267
  struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"),
906
178
    .rhs=type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp };
907
89
  return op_check(env, &opi);
908
}
909
#define check_flow(emit,b) _flow(emit, b, 1)
910
911
10
ANN static Type check_exp_if(const Env env, const Exp_If* exp_if) {
912
10
  DECL_OO(const Type, cond, = check_flow(env, exp_if->cond))
913

10
  DECL_OO(const Type, if_exp, = (exp_if->if_exp ? check_exp(env, exp_if->if_exp) : cond))
914
10
  DECL_OO(const Type, else_exp, = check_exp(env, exp_if->else_exp))
915
10
  const Type ret = find_common_anc(if_exp, else_exp);
916
10
  if(!ret)
917
1
    ERR_O(exp_self(exp_if)->pos,
918
          _("incompatible types '%s' and '%s' in if expression..."),
919
          if_exp->name, else_exp->name)
920

9
  if(!exp_if->if_exp && isa(exp_if->cond->info->type, else_exp) < 0)
921
    ERR_O(exp_self(exp_if)->pos,
922
        _("condition type '%s' does not match '%s'"),
923
         cond->name, ret->name)
924

9
  if(exp_getmeta(exp_if->if_exp ?: exp_if->cond) || exp_getmeta(exp_if->else_exp))
925
9
    exp_setmeta(exp_self(exp_if), 1);
926
9
  return ret;
927
}
928
929
547
ANN static Type check_exp_dot(const Env env, Exp_Dot* member) {
930
547
  CHECK_OO((member->t_base = check_exp(env, member->base)))
931
543
  return check_dot(env, member);
932
}
933
934
733
ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
935
733
  return tdef->type->e->def ? check_class_def(env, tdef->type->e->def) : GW_OK;
936
}
937
18
ANN static Type check_exp_lambda(const Env env,
938
18
    const Exp_If* exp_if NUSED) { return env->gwion->type[et_lambda]; }
939
940
DECL_EXP_FUNC(check, Type, Env)
941
942
27365
ANN Type check_exp(const Env env, const Exp exp) {
943
27365
  Exp curr = exp;
944
  do {
945
27928
    CHECK_OO((curr->info->type = check_exp_func[curr->exp_type](env, &curr->d)))
946


27823
    if(env->func && isa(curr->info->type, env->gwion->type[et_lambda]) < 0 && isa(curr->info->type, env->gwion->type[et_function]) > 0 &&
947
65
        !GET_FLAG(curr->info->type->e->d.func, pure))
948
58
      UNSET_FLAG(env->func, pure);
949
27758
  } while((curr = curr->next));
950
27195
  return exp->info->type;
951
}
952
953
724
ANN m_bool check_enum_def(const Env env, const Enum_Def edef) {
954
724
  if(env->class_def) {
955
6
    ID_List list = edef->list;
956
28
    do decl_static(env, nspc_lookup_value0(env->curr, list->xid));
957
28
    while((list = list->next));
958
  }
959
724
  return GW_OK;
960
}
961
962
446
ANN static m_bool check_stmt_code(const Env env, const Stmt_Code stmt) {
963
446
  if(stmt->stmt_list) { RET_NSPC(check_stmt_list(env, stmt->stmt_list)) }
964
52
  return GW_OK;
965
}
966
967
10
ANN static m_bool check_stmt_varloop(const Env env, const Stmt_VarLoop stmt) {
968
10
  CHECK_OB(check_exp(env, stmt->exp))
969
10
  if(isa(stmt->exp->info->type, env->gwion->type[et_vararg]) < 0)
970
1
    ERR_B(stmt->exp->pos, "varloop expression type must be '%s', not '%s'",
971
      env->gwion->type[et_vararg]->name, stmt->exp->info->type->name)
972
9
  return check_stmt(env, stmt->body);
973
}
974
975
54
ANN static inline m_bool _check_breaks(const Env env, const Stmt b) {
976
54
  RET_NSPC(check_stmt(env, b))
977
}
978
979
54
ANN static m_bool check_breaks(const Env env, const Stmt a, const Stmt b) {
980
54
  vector_add(&env->scope->breaks, (vtype)a);
981
54
  const m_bool ret = _check_breaks(env, b);
982
54
  vector_pop(&env->scope->breaks);
983
54
  return ret;
984
}
985
986
54
ANN static m_bool check_conts(const Env env, const Stmt a, const Stmt b) {
987
54
  vector_add(&env->scope->conts, (vtype)a);
988
54
  CHECK_BB(check_breaks(env, a, b))
989
54
  vector_pop(&env->scope->conts);
990
54
  return GW_OK;
991
}
992
993
11
ANN static inline m_bool for_empty(const Env env, const Stmt_For stmt) {
994

11
  if(!stmt->c2 || !stmt->c2->d.stmt_exp.val)
995
1
    ERR_B(stmt_self(stmt)->pos, _("empty for loop condition..."
996
          "...(note: explicitly use 'true' if it's the intent)"
997
          "...(e.g., 'for(; true;){ /*...*/ }')"))
998
10
  return GW_OK;
999
}
1000
1001
// the two next function do not account for arrays. (they are only stmt_each() helpers
1002
ANN static Type_Decl* _type2td(const Env env, const Type t, Type_Decl *next) {
1003
  Type_Decl *td = new_type_decl(env->gwion->mp, insert_symbol(t->name),
1004
      loc_cpy(env->gwion->mp, td_pos(next)));
1005
  td->next = next;
1006
  return !t->e->owner_class ? td : _type2td(env, t->e->owner_class, td);
1007
1008
}
1009
1010
4
ANN static Type_Decl* type2td(const Env env, const Type t, const loc_t loc) {
1011
4
  Type_Decl *td = new_type_decl(env->gwion->mp, insert_symbol(t->name),
1012
4
      loc_cpy(env->gwion->mp, loc));
1013
4
  return !t->e->owner_class ? td : _type2td(env, t->e->owner_class, td);
1014
}
1015
1016
12
ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) {
1017
12
  DECL_OB(Type, t, = check_exp(env, stmt->exp))
1018
27
  while(GET_FLAG(t, typedef))
1019
3
    t = t->e->parent;
1020
12
  Type ptr = array_base(t);
1021
12
  const m_uint depth = t->array_depth - 1;
1022

12
  if(!ptr || isa(t, env->gwion->type[et_array]) < 0)
1023
1
    ERR_B(stmt_self(stmt)->pos, _("type '%s' is not array.\n"
1024
          " This is not allowed in auto loop"), stmt->exp->info->type->name)
1025
11
  if(stmt->is_ptr) {
1026
4
    struct Type_List_ tl = {};
1027
4
    if(depth)
1028
1
      ptr = array_type(env, ptr, depth);
1029
4
    Type_Decl *td0 = type2td(env, ptr, stmt->exp->pos),
1030
4
      td = { .xid=insert_symbol("Ptr"), .types=&tl, .pos=stmt->exp->pos };
1031
4
    tl.td = td0;
1032
4
    ptr = known_type(env, &td);
1033
4
    td0->array = NULL;
1034
4
    free_type_decl(env->gwion->mp, td0);
1035
4
    const Type base = get_type(ptr);
1036
4
    if(!GET_FLAG(base, check))
1037
3
      CHECK_BB(ensure_traverse(env, base))
1038
  }
1039

11
  t = (!stmt->is_ptr && depth) ? array_type(env, ptr, depth) : ptr;
1040
11
  stmt->v = new_value(env->gwion->mp, t, s_name(stmt->sym));
1041
11
  SET_FLAG(stmt->v, valid);
1042
11
  nspc_add_value(env->curr, stmt->sym, stmt->v);
1043
11
  return check_conts(env, stmt_self(stmt), stmt->body);
1044
}
1045
1046
8
ANN static inline m_bool cond_type(const Env env, const Exp e) {
1047
8
  const Type t_int = env->gwion->type[et_int];
1048
8
  if(check_implicit(env, e, t_int) < 0)
1049
1
    ERR_B(e->pos, _("invalid condition type"))
1050
7
  return GW_OK;
1051
}
1052
1053
#define stmt_func_xxx(name, type, prolog, exp) describe_stmt_func(check, name, type, prolog, exp)
1054


39
stmt_func_xxx(if, Stmt_If,, !(!check_flow(env, stmt->cond)   ||
1055
  check_stmt(env, stmt->if_body) < 0 ||
1056
  (stmt->else_body && check_stmt(env, stmt->else_body) < 0)) ? 1 : -1)
1057


26
stmt_func_xxx(flow, Stmt_Flow,,
1058
  !(!check_exp(env, stmt->cond) ||
1059
    !_flow(env, stmt->cond, !stmt->is_do ?
1060
       stmt_self(stmt)->stmt_type == ae_stmt_while :
1061
       stmt_self(stmt)->stmt_type != ae_stmt_while) ||
1062
    check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
1063



11
stmt_func_xxx(for, Stmt_For,, !(
1064
  for_empty(env, stmt) < 0 ||
1065
  check_stmt(env, stmt->c1) < 0 ||
1066
  !check_flow(env, stmt->c2->d.stmt_exp.val) ||
1067
  (stmt->c3 && !check_exp(env, stmt->c3)) ||
1068
  check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
1069

8
stmt_func_xxx(loop, Stmt_Loop,, !(!check_exp(env, stmt->cond) ||
1070
  cond_type(env, stmt->cond) < 0 ||
1071
  check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
1072
12
stmt_func_xxx(each, Stmt_Each,, do_stmt_each(env, stmt))
1073
1074
69
ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) {
1075
69
  if(!env->func)
1076
1
    ERR_B(stmt_self(stmt)->pos, _("'return' statement found outside function definition"))
1077

68
  DECL_OB(const Type, ret_type, = stmt->val ? check_exp(env, stmt->val) : env->gwion->type[et_void])
1078
68
  if(!env->func->def->base->ret_type) {
1079
    assert(isa(env->func->value_ref->type, env->gwion->type[et_lambda]) > 0);
1080
1
    env->func->def->base->ret_type = ret_type;
1081
1
    return GW_OK;
1082
  }
1083
67
  if(isa(ret_type, env->func->def->base->ret_type) > 0)
1084
63
    return GW_OK;
1085
4
  if(stmt->val) {
1086

3
    if(env->func->def->base->xid == insert_symbol("@implicit") && ret_type == env->func->def->base->args->type)
1087
1
      ERR_B(stmt_self(stmt)->pos, _("can't use implicit casting while defining it"))
1088
2
    if(check_implicit(env, stmt->val, env->func->def->base->ret_type) > 0)
1089
1
      return GW_OK;
1090
1
    ERR_B(stmt_self(stmt)->pos, _("invalid return type: got '%s', expected '%s'"),
1091
        ret_type->name, env->func->def->base->ret_type->name)
1092
  }
1093
1
  if(isa(env->func->def->base->ret_type, env->gwion->type[et_void]) > 0)
1094
    return GW_OK;
1095
1
  ERR_B(stmt_self(stmt)->pos, _("missing value for return statement"))
1096
}
1097
1098
#define describe_check_stmt_stack(stack, name)                                     \
1099
ANN static m_bool check_stmt_##name(const Env env, const Stmt stmt) {\
1100
  if(!vector_size(&env->scope->stack))                                                    \
1101
    ERR_B(stmt->pos, _("'"#name"' found outside of for/while/until..."))             \
1102
  return GW_OK;                                                                        \
1103
}
1104
10
describe_check_stmt_stack(conts,  continue)
1105
9
describe_check_stmt_stack(breaks, break)
1106
1107
13
ANN static m_bool check_stmt_jump(const Env env, const Stmt_Jump stmt) {
1108
13
  if(stmt->is_label)
1109
6
    return GW_OK;
1110
7
  const Map label = env_label(env);
1111
16
  const m_uint* key = env->class_def && !env->func ?
1112
9
                (m_uint*)env->class_def : (m_uint*)env->func;
1113
7
  const Map m = label->ptr ? (Map)map_get(label, (vtype)key) : NULL;
1114
7
  if(!m)
1115
1
    ERR_B(stmt_self(stmt)->pos, _("label '%s' used but not defined"), s_name(stmt->name))
1116
6
  const Stmt_Jump ref = (Stmt_Jump)map_get(m, (vtype)stmt->name);
1117
6
  if(!ref)
1118
1
    ERR_B(stmt_self(stmt)->pos, _("label '%s' used but not defined"), s_name(stmt->name))
1119
5
  vector_add(&ref->data.v, (vtype)stmt);
1120
5
  return GW_OK;
1121
}
1122
1123
21
ANN m_bool check_union_decl(const Env env, const Union_Def udef) {
1124
21
  Decl_List l = udef->l;
1125
  do {
1126
40
    CHECK_OB(check_exp(env, l->self))
1127
40
    Var_Decl_List list = l->self->d.exp_decl.list;
1128
40
    do SET_FLAG(list->self->value, pure);
1129
40
    while((list = list->next));
1130
40
    if(l->self->info->type->size > udef->s)
1131
19
      udef->s = l->self->info->type->size;
1132
40
  } while((l = l->next));
1133
21
  return GW_OK;
1134
}
1135
1136
21
ANN void check_udef(const Env env, const Union_Def udef) {
1137
21
  if(udef->xid) {
1138
8
    if(env->class_def)
1139
4
      (!GET_FLAG(udef, static) ? decl_member : decl_static)(env, udef->value);
1140
4
    else if(env->class_def) {
1141
      if(!GET_FLAG(udef, static))
1142
        udef->o = env->class_def->nspc->info->offset;
1143
      else {
1144
        udef->o = env->class_def->nspc->info->class_data_size;
1145
        env->class_def->nspc->info->class_data_size += SZ_INT;
1146
      }
1147
    }
1148
  }
1149
21
}
1150
1151
26
ANN m_bool check_union_def(const Env env, const Union_Def udef) {
1152
26
  if(tmpl_base(udef->tmpl)) // there's a func for this
1153
5
    return GW_OK;
1154
21
  check_udef(env, udef);
1155
21
  const m_uint scope = union_push(env, udef);
1156
21
  const m_bool ret = check_union_decl(env, udef);
1157


21
  if(!udef->xid && !udef->type_xid && env->class_def && !GET_FLAG(udef, static))
1158
1
    env->class_def->nspc->info->offset = udef->o + udef->s;
1159
21
  union_pop(env, udef, scope);
1160
21
  union_flag(udef, ae_flag_check);
1161
21
  union_flag(udef, ae_flag_valid);
1162
21
  return ret;
1163
}
1164
1165
2255
ANN static m_bool check_stmt_exp(const Env env, const Stmt_Exp stmt) {
1166

2255
  return stmt->val ? check_exp(env, stmt->val) ? 1 : -1 : 1;
1167
}
1168
1169
2
ANN static Value match_value(const Env env, const Exp_Primary* prim, const m_uint i) {
1170
2
  const Symbol sym = prim->d.var;
1171
4
  const Value v = new_value(env->gwion->mp,
1172
2
     ((Exp)VKEY(&env->scope->match->map, i))->info->type, s_name(sym));
1173
2
  SET_FLAG(v, valid);
1174
2
  nspc_add_value(env->curr, sym, v);
1175
2
  VVAL(&env->scope->match->map, i) = (vtype)v;
1176
2
  return v;
1177
}
1178
1179
12
ANN static Symbol case_op(const Env env, const Exp e, const m_uint i) {
1180
12
  if(e->exp_type == ae_exp_primary) {
1181
12
    if(e->d.prim.prim_type == ae_prim_id) {
1182
4
      if(e->d.prim.d.var == insert_symbol("_"))
1183
2
        return NULL;
1184
2
      if(!nspc_lookup_value1(env->curr, e->d.prim.d.var)) {
1185
2
        e->d.prim.value = match_value(env, &e->d.prim, i);
1186
2
        return NULL;
1187
      }
1188
    }
1189
  }
1190
8
  return insert_symbol("==");
1191
}
1192
1193
11
ANN static m_bool match_case_exp(const Env env, Exp e) {
1194
11
  Exp last = e;
1195
15
  for(m_uint i = 0; i < map_size(&env->scope->match->map); e = e->next, ++i) {
1196
12
    if(!e)
1197
      ERR_B(last->pos, _("no enough to match"))
1198
12
    last = e;
1199
12
    const Symbol op = case_op(env, e, i);
1200
12
    if(op) {
1201
8
      const Exp base = (Exp)VKEY(&env->scope->match->map, i);
1202
8
      CHECK_OB(check_exp(env, e))
1203
8
      Exp_Binary bin = { .lhs=base, .rhs=e, .op=op };
1204
8
      struct ExpInfo_ info = { .nspc=env->curr };
1205
8
      struct Exp_ ebin = { .d={.exp_binary=bin}, .info=&info };
1206
24
      struct Op_Import opi = { .op=op, .lhs=base->info->type, .rhs=e->info->type,
1207
16
        .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos, .op_type=op_binary };
1208
8
      CHECK_OB(op_check(env, &opi))
1209
8
      e->info->nspc= info.nspc;
1210
8
      return GW_OK;
1211
    }
1212
  }
1213
3
  if(e)
1214
1
    ERR_B(e->pos, _("too many expression to match"))
1215
2
  return GW_OK;
1216
}
1217
1218
11
ANN static m_bool _check_stmt_case(const Env env, const Stmt_Match stmt) {
1219
11
  CHECK_BB(match_case_exp(env, stmt->cond))
1220
10
  if(stmt->when)
1221
4
    CHECK_OB(check_flow(env, stmt->when))
1222
10
  return check_stmt_list(env, stmt->list);
1223
}
1224
1225
11
ANN static m_bool check_stmt_case(const Env env, const Stmt_Match stmt) {
1226
11
  RET_NSPC(_check_stmt_case(env, stmt))
1227
}
1228
1229
7
ANN static m_bool case_loop(const Env env, const Stmt_Match stmt) {
1230
7
  Stmt_List list = stmt->list;
1231
11
  do CHECK_BB(check_stmt_case(env, &list->stmt->d.stmt_match))
1232
10
  while((list = list->next));
1233
6
  return GW_OK;
1234
}
1235
1236
7
ANN static m_bool _check_stmt_match(const Env env, const Stmt_Match stmt) {
1237
7
  CHECK_OB(check_exp(env, stmt->cond))
1238
7
  MATCH_INI(env->scope)
1239
7
  const m_bool ret = case_loop(env, stmt);
1240
7
  MATCH_END(env->scope)
1241
7
  return ret;
1242
}
1243
1244
7
ANN static inline m_bool handle_where(const Env env, const Stmt_Match stmt) {
1245
7
  if(stmt->where)
1246
2
    CHECK_BB(check_stmt(env, stmt->where))
1247
7
  RET_NSPC(_check_stmt_match(env, stmt))
1248
}
1249
1250
7
ANN static m_bool check_stmt_match(const Env env, const Stmt_Match stmt) {
1251
7
  RET_NSPC(handle_where(env, stmt))
1252
}
1253
1254
#define check_stmt_while check_stmt_flow
1255
#define check_stmt_until check_stmt_flow
1256
1257
4
ANN static m_bool check_stmt_pp(const Env env, const Stmt_PP stmt) {
1258
4
  if(stmt->pp_type == ae_pp_include)
1259
3
    env->name = stmt->data;
1260
4
  return GW_OK;
1261
}
1262
1263
DECL_STMT_FUNC(check, m_bool , Env)
1264
1265
2626
ANN m_bool check_stmt(const Env env, const Stmt stmt) {
1266
2626
  return check_stmt_func[stmt->stmt_type](env, &stmt->d);
1267
}
1268
1269
2475
ANN static m_bool check_stmt_list(const Env env, Stmt_List l) {
1270
2475
  do CHECK_BB(check_stmt(env, l->stmt))
1271
2340
  while((l = l->next));
1272
956
  return GW_OK;
1273
}
1274
1275
735
ANN static m_bool check_signature_match(const Env env, const Func_Def fdef, const Func parent) {
1276
735
  if(GET_FLAG(parent->def->base, static) != GET_FLAG(fdef->base, static)) {
1277
2
    const m_str c_name  = fdef->base->func->value_ref->from->owner_class->name;
1278
2
    const m_str p_name = parent->value_ref->from->owner_class->name;
1279
2
    const m_str f_name = s_name(fdef->base->xid);
1280
2
    ERR_B(td_pos(fdef->base->td),
1281
          _("function '%s.%s' ressembles '%s.%s' but cannot override...\n"
1282
          "  ...(reason: '%s.%s' is declared as 'static')"),
1283
          c_name, f_name, p_name, c_name,
1284
          GET_FLAG(fdef->base, static) ? c_name : p_name, f_name)
1285
  }
1286
733
  return !fdef->base->tmpl ? isa(fdef->base->ret_type, parent->def->base->ret_type) : GW_OK;
1287
}
1288
1289
736
ANN static m_bool parent_match_actual(const Env env, const restrict Func_Def fdef,
1290
    const restrict Func func) {
1291
736
  Func parent_func = func;
1292
  do {
1293

763
    if(parent_func->def->base && compat_func(fdef, parent_func->def) > 0) {
1294
735
      CHECK_BB(check_signature_match(env, fdef, parent_func))
1295
733
      if(!fdef->base->tmpl) {
1296
716
        fdef->base->func->vt_index = parent_func->vt_index;
1297
716
        vector_set(&env->curr->info->vtable, fdef->base->func->vt_index, (vtype)fdef->base->func);
1298
      }
1299
733
      return GW_OK;
1300
    }
1301
28
  } while((parent_func = parent_func->next));
1302
1
  return 0;
1303
}
1304
1305
42250
ANN static m_bool check_parent_match(const Env env, const Func_Def fdef) {
1306
42250
  const Func func = fdef->base->func;
1307
42250
  const Type parent = env->class_def->e->parent;
1308
42250
  if(!env->curr->info->vtable.ptr)
1309
4362
    vector_init(&env->curr->info->vtable);
1310
42250
  if(parent) {
1311
42250
    const Value v = find_value(parent, fdef->base->xid);
1312

42250
    if(v && isa(v->type, env->gwion->type[et_function]) > 0) {
1313
736
      const m_bool match = parent_match_actual(env, fdef, v->d.func_ref);
1314
736
      if(match)
1315
735
        return match;
1316
    }
1317
  }
1318
41515
  func->vt_index = vector_size(&env->curr->info->vtable);
1319
41515
  vector_add(&env->curr->info->vtable, (vtype)func);
1320
41515
  return GW_OK;
1321
}
1322
1323
83
ANN static inline Func get_overload(const Env env, const Func_Def fdef, const m_uint i) {
1324
83
  const Symbol sym = func_symbol(env, env->curr->name, s_name(fdef->base->xid), NULL, i);
1325
83
  return nspc_lookup_func1(env->curr, sym);
1326
}
1327
1328
19
ANN static m_bool check_func_overload(const Env env, const Func_Def fdef) {
1329
19
  const Value v = fdef->base->func->value_ref;
1330
63
  for(m_uint i = 0; i <= v->from->offset; ++i) {
1331
45
    const Func f1 = get_overload(env, fdef, i);
1332

82
    for(m_uint j = i + 1; f1 && j <= v->from->offset; ++j) {
1333
38
      const Func f2 = get_overload(env, fdef, j);
1334

38
      if(f2 && compat_func(f1->def, f2->def) > 0)
1335
1
        ERR_B(td_pos(f2->def->base->td), _("global function '%s' already defined"
1336
          " for those arguments"), s_name(fdef->base->xid))
1337
    }
1338
  }
1339
18
  return GW_OK;
1340
}
1341
1342
42383
ANN static m_bool check_func_def_override(const Env env, const Func_Def fdef) {
1343
42383
  const Func func = fdef->base->func;
1344

42383
  if(env->class_def && env->class_def->e->parent) {
1345
42215
    const Value override = find_value(env->class_def->e->parent, fdef->base->xid);
1346

42215
    if(override && override->from->owner_class && isa(override->type, env->gwion->type[et_function]) < 0)
1347
3
      ERR_B(fdef->pos,
1348
            _("function name '%s' conflicts with previously defined value...\n"
1349
            "  from super class '%s'..."),
1350
            s_name(fdef->base->xid), override->from->owner_class->name)
1351
  }
1352

42380
  if(func->value_ref->from->offset && (!fdef->base->tmpl || !fdef->base->tmpl->base))
1353
19
    CHECK_BB(check_func_overload(env, fdef))
1354
42379
  return GW_OK;
1355
}
1356
1357
42379
ANN m_bool check_fdef(const Env env, const Func_Def fdef) {
1358
42379
  if(fdef->base->args)
1359
16572
    CHECK_BB(check_func_args(env, fdef->base->args))
1360
42378
  if(!GET_FLAG(fdef->base, builtin)) {
1361
298
    if(fdef->d.code)
1362
293
      CHECK_BB(check_stmt_code(env, &fdef->d.code->d.stmt_code))
1363
  } else
1364
42080
    fdef->base->func->code->stack_depth = fdef->stack_depth;
1365
42363
  return GW_OK;
1366
}
1367
1368
42446
ANN m_bool check_func_def(const Env env, const Func_Def f) {
1369
42446
  const Func func = f->base->func;
1370
42446
  const Func_Def fdef = func->def;
1371
  assert(func == fdef->base->func);
1372
42446
  if(env->class_def) // tmpl ?
1373
42250
    CHECK_BB(check_parent_match(env, fdef))
1374
42444
  if(tmpl_base(fdef->base->tmpl))
1375
60
    return GW_OK;
1376

42384
  if(fdef->base->td && !fdef->base->td->xid) { // tmpl ?
1377
1
    CHECK_OB((fdef->base->ret_type = check_td(env, fdef->base->td)))
1378
1
    return check_traverse_fdef(env, fdef);
1379
  }
1380
42383
  CHECK_BB(check_func_def_override(env, fdef))
1381

42379
  DECL_BB(const m_int, scope, = GET_FLAG(fdef->base, global) ? env_push_global(env) : env->scope->depth)
1382
42379
  const Func former = env->func;
1383
42379
  env->func = func;
1384
42379
  ++env->scope->depth;
1385
42379
  nspc_push_value(env->gwion->mp, env->curr);
1386
42379
  struct Op_Import opi = { };
1387
42379
  if(GET_FLAG(fdef->base, op)) {
1388
24
    func_operator(f, &opi);
1389
24
    operator_suspend(env->curr, &opi);
1390
  }
1391
42379
  const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)check_fdef);
1392
42379
  if(GET_FLAG(fdef->base, op))
1393
24
    operator_resume(&opi);
1394
42379
  nspc_pop_value(env->gwion->mp, env->curr);
1395
42379
  --env->scope->depth;
1396
42379
  env->func = former;
1397
42379
  if(ret > 0)
1398
42363
    SET_FLAG(fdef->base, valid);
1399
42379
  if(GET_FLAG(fdef->base, global))
1400
2
    env_pop(env,scope);
1401
42379
  return ret;
1402
}
1403
1404
#define check_fptr_def dummy_func
1405
1292
HANDLE_SECTION_FUNC(check, m_bool, Env)
1406
1407
64
ANN static m_bool check_parent(const Env env, const Class_Def cdef) {
1408
64
  const Type parent = cdef->base.type->e->parent;
1409
64
  const Type_Decl *td = cdef->base.ext;
1410
64
  if(td->array)
1411
9
    CHECK_BB(check_subscripts(env, td->array, 1))
1412

64
  if(parent->e->def && !GET_FLAG(parent, check))
1413
6
    CHECK_BB(ensure_check(env, parent))
1414
64
  if(GET_FLAG(parent, typedef))
1415
2
    SET_FLAG(cdef->base.type, typedef);
1416
64
  return GW_OK;
1417
}
1418
1419
64
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
1420

64
  if(cdef->base.tmpl && cdef->base.tmpl->list)
1421
21
    CHECK_BB(template_push_types(env, cdef->base.tmpl))
1422
64
  const m_bool ret = check_parent(env, cdef);
1423

64
  if(cdef->base.tmpl && cdef->base.tmpl->list)
1424
21
    nspc_pop_type(env->gwion->mp, env->curr);
1425
64
  return ret;
1426
}
1427
1428
264
ANN m_bool check_class_def(const Env env, const Class_Def cdef) {
1429
264
  if(tmpl_base(cdef->base.tmpl))
1430
18
    return GW_OK;
1431
246
  const Type t = cdef->base.type;
1432

246
  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, check))
1433
    CHECK_BB(ensure_check(env, t->e->owner_class))
1434
246
  if(GET_FLAG(t, check))return GW_OK;
1435
246
  SET_FLAG(t, check);
1436
246
  if(cdef->base.ext)
1437
64
    CHECK_BB(cdef_parent(env, cdef))
1438
246
  if(!GET_FLAG(cdef, struct))
1439
236
    inherit(t);
1440
246
  if(cdef->body) {
1441
204
    CHECK_BB(env_body(env, cdef, check_section))
1442
182
    SET_FLAG(t, ctor);
1443
  }
1444
224
  SET_FLAG(t, valid);
1445
224
  return GW_OK;
1446
}
1447
1448
933
ANN m_bool check_ast(const Env env, Ast ast) {
1449
933
  do CHECK_BB(check_section(env, ast->section))
1450
796
  while((ast = ast->next));
1451
418
  return GW_OK;
1452
}