GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/check.c Lines: 987 1025 96.3 %
Date: 2020-09-14 20:46:08 Branches: 761 926 82.2 %

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
11590
ANN static inline m_bool check_exp_decl_parent(const Env env, const Var_Decl var) {
50
11590
  const Value value = find_value(env->class_def->e->parent, var->xid);
51
11590
  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
11589
  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
11567
describe_check_decl(member, offset)
67
54
describe_check_decl(static, class_data_size)
68
69
56
ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) {
70
56
  const Value v    = var->value;
71
56
  Type t = v->type;
72
117
  while(GET_FLAG(t, typedef))
73
5
    t = t->e->parent;
74
56
  if(!t->e->d.func)
75
    return GW_ERROR;
76
56
  if(!env->class_def)
77
25
    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
21439
ANN static m_bool check_var(const Env env, const Var_Decl var) {
108

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

21438
  if(var->array && var->array->exp)
111
37
    return check_subscripts(env, var->array, 1);
112
21401
  return GW_OK;
113
}
114
115
21438
ANN static m_bool check_var_td(const Env env, const Var_Decl var, Type_Decl *const td) {
116
21438
  const Value v = var->value;
117
21438
  if(env->class_def)  {
118
11597
    if(GET_FLAG(td, member)) {
119
11565
      decl_member(env, v);
120
11565
      if(env->class_def->e->tuple)
121
11565
        tuple_info(env, v);
122
32
    } else if(GET_FLAG(td, static))
123
24
      decl_static(env, v);
124
  }
125
21438
  return GW_OK;
126
}
127
128
21431
ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
129
21431
  Var_Decl_List list = decl->list;
130
  do {
131
21439
    const Var_Decl var = list->self;
132
21439
    CHECK_BB(check_var(env, var))
133
21438
    CHECK_BB(check_var_td(env, var, decl->td))
134
21438
    if(is_fptr(env->gwion, decl->type))
135
56
      CHECK_BB(check_fptr_decl(env, var))
136
21435
    SET_FLAG(var->value, valid | ae_flag_used);
137
21435
    nspc_add_value(env->curr, var->xid, var->value);
138
21435
  } while((list = list->next));
139
21427
  return GW_OK;
140
}
141
142
29
ANN static inline m_bool ensure_check(const Env env, const Type t) {
143
58
  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
144
29
    .scope=env->scope->depth, .flag=ae_flag_check };
145
29
  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
21467
ANN static inline m_bool inferable(const Env env, const Type t, const loc_t pos) {
155
21467
  if(!GET_FLAG(t, infer))
156
21465
    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
21440
ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
162
21440
  if(!decl->td->xid)
163
8
    return no_xid(env, decl);
164
21432
  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
21432
  if(!decl->type)
170
    ERR_O(td_pos(decl->td), _("can't find type"));
171
  {
172
21432
    const Type t = get_type(decl->type);
173
21432
    CHECK_BO(inferable(env, t, td_pos(decl->td)))
174

21431
    if(!GET_FLAG(t, check) && t->e->def)
175
23
      CHECK_BO(ensure_check(env, t))
176
  }
177
21431
  const m_bool global = GET_FLAG(decl->td, global);
178
21431
  const m_uint scope = !global ? env->scope->depth : env_push_global(env);
179
21431
  const m_bool ret = check_decl(env, decl);
180
21431
  if(global)
181
12
    env_pop(env, scope);
182
21431
  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
912
ANN m_bool not_from_owner_class(const Env env, const Type t,
239
      const Value v, const loc_t pos) {
240

912
  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
911
  return GW_OK;
246
}
247
248
1944
ANN static Value check_non_res_value(const Env env, const Symbol *data) {
249
1944
  const Symbol var = *data;
250
1944
  const Value value = nspc_lookup_value1(env->curr, var);
251
1944
  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, 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


1659
  } else if(SAFE_FLAG(env->class_def, global) || (env->func && GET_FLAG(env->func->def, 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
1658
  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
1944
ANN static Type prim_id_non_res(const Env env, const Symbol *data) {
300
1944
  const Symbol sym = *data;
301
1944
  const Value v = check_non_res_value(env, data);
302


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

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

297
  if(env->func && !GET_FLAG(v, const) && v->from->owner)
314
19
    UNSET_FLAG(env->func, pure);
315
  }
316
1929
  SET_FLAG(v, used);
317
1929
  if(GET_FLAG(v, const))
318
585
    exp_setmeta(prim_exp(data), 1);
319
1929
  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
1929
  return v->type;
327
}
328
329
262
ANN Type check_prim_str(const Env env, const m_str *data) {
330
262
  if(!prim_self(data)->value)
331
262
    prim_self(data)->value = global_string(env, *data);
332
262
  return env->gwion->type[et_string];// prim->value
333
}
334
335
2276
ANN static Type check_prim_id(const Env env, const Symbol *data) {
336
2276
  struct SpecialId_ * spid = specialid_get(env->gwion, *data);
337
2276
  if(spid)
338
332
    return specialid_type(env, spid, prim_self(data));
339
1944
  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
923
ANN static Type check_prim_interp(const Env env, const Exp* exp) {
351
923
  CHECK_OO(check_exp(env, *exp))
352
891
  return env->gwion->type[et_string];
353
}
354
355
920
ANN static Type check_prim_hack(const Env env, const Exp *data) {
356
920
  if(env->func)
357
207
    UNSET_FLAG(env->func, pure);
358
920
  CHECK_OO(check_prim_interp(env, data))
359
888
  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
856
describe_prim_xxx(num, env->gwion->type[et_int])
367
15
describe_prim_xxx(char, env->gwion->type[et_char])
368
117
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
4525
ANN static Type check_prim(const Env env, Exp_Primary *prim) {
377
4525
  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
495
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
495
  const m_bool match = (specific ? e->info->type == t : isa(e->info->type, t) > 0);
428
495
  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
442
  return match ? 1 : -1;
437
}
438
439
700
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
700
    Exp e = args;
443
700
    Arg_List e1 = func->def->base->args;
444
1817
    while(e) {
445
680
      if(!e1) {
446
185
        if(GET_FLAG(func->def, 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

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

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

478
  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
444
    return func;
480
34
  return NULL;
481
}
482
483
130
ANN static m_bool check_call(const Env env, const Exp_Call* exp) {
484
130
  ae_exp_t et = exp->func->exp_type;
485

130
  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
129
  CHECK_OB(check_exp(env, exp->func))
488
128
  if(exp->args)
489
122
    CHECK_OB(check_exp(env, exp->args))
490
127
  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, 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
23746
ANN static m_bool check_func_args(const Env env, Arg_List arg_list) {
531
  do {
532
23746
    const Var_Decl decl = arg_list->var_decl;
533
23746
    const Value v = decl->value;
534

23746
    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

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

10
        if(traverse_fptr_def(env, fptr) > 0 &&
570
10
            (base->base->ret_type = known_type(env, base->base->td)) &&
571
7
            (!exp->args || !!check_exp(env, exp->args))) {
572
5
          m_func = find_func_match(env, fbase->func, exp->args);
573
5
          nspc_pop_type(env->gwion->mp, env->curr);
574
5
          if(m_func)
575
5
            nspc_add_type_front(v->from->owner, sym, actual_type(env->gwion, m_func->value_ref->type));
576
        }
577
5
        free_fptr_def(env->gwion->mp, fptr);
578
5
        if(fptr->type)
579
5
          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, 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
121
  free_mstr(env->gwion->mp, tmpl_name);
613
121
  if(es.run)
614
2
    envset_pop(&es, v->from->owner_class);
615
121
  env_pop(env, scope);
616
121
  env->func = former;
617
121
  return m_func;
618
}
619
620
90
ANN Func find_template_match(const Env env, const Value value, const Exp_Call* exp) {
621
90
  const Func f = _find_template_match(env, value, exp);
622
90
  if(f)
623
68
    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, 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, 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
  if(exp->func->exp_type == ae_exp_decl)
790
1
    ERR_O(exp_self(exp)->pos, _("It makes no sense to call a function pointer at declaration"))
791
472
  CHECK_OO(check_exp(env, exp->func))
792
468
  if(isa(exp->func->info->type, env->gwion->type[et_function]) < 0) {
793
    // use func flag?
794
1
    if(isa(exp->func->info->type, env->gwion->type[et_class]) < 0)
795
1
      ERR_O(exp->func->pos, _("function call using a non-function value"))
796
    struct Op_Import opi = { .op=insert_symbol("@ctor"), .rhs=exp->func->info->type->e->d.base_type,
797
      .data=(uintptr_t)exp, .pos=exp_self(exp)->pos, .op_type=op_exp };
798
    const Type t = op_check(env, &opi);
799
    exp_self(exp)->info->nspc = t ? t->e->owner : NULL;
800
    return t;
801
  }
802
467
  if(exp->func->info->type == env->gwion->type[et_lambda])
803
9
    return check_lambda_call(env, exp);
804
458
  if(GET_FLAG(exp->func->info->type->e->d.func, ref)) {
805
5
    const Value value = exp->func->info->type->e->d.func->value_ref;
806

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

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

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

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

38
  if(t && isa(t, env->gwion->type[et_object]) < 0)
852
35
    exp_setmeta(exp_self(post), 1);
853
38
  return t;
854
}
855
856
2
ANN static m_bool predefined_call(const Env env, const Type t, const loc_t pos) {
857
2
  const m_str str = tl2str(env, t->e->d.func->def->base->tmpl->call);
858
2
  env_err(env, pos, _("Type '%s' has '%s' as pre-defined types."),
859
      t->name, str);
860
2
  free_mstr(env->gwion->mp, str);
861
2
  if(GET_FLAG(t, typedef)) {
862
1
    loc_header(t->e->d.func->def->pos, env->name);
863
1
    gw_err(_("from definition:\n"));
864
1
    loc_err(t->e->d.func->def->pos, env->name);
865
  }
866
2
  return GW_ERROR;
867
}
868
869
429
ANN static Type check_exp_call(const Env env, Exp_Call* exp) {
870
429
  if(exp->tmpl) {
871
29
    CHECK_OO(check_exp(env, exp->func))
872
28
    const Type t = actual_type(env->gwion, unflag_type(exp->func->info->type));
873
28
    const Value v = type_value(env->gwion, t) ?: t->e->d.func->value_ref;
874

28
    if(!GET_FLAG(v, func) && !GET_FLAG(exp->func->info->type, func) )
875
2
      ERR_O(exp_self(exp)->pos, _("template call of non-function value."))
876

26
    if(!v->d.func_ref || !v->d.func_ref->def->base->tmpl)
877
3
      ERR_O(exp_self(exp)->pos, _("template call of non-template function."))
878
23
    if(t->e->d.func->def->base->tmpl->call) {
879
2
      if(env->func == t->e->d.func) {
880
        if(exp->args)
881
          CHECK_OO(check_exp(env, exp->args))
882
        exp->m_func = env->func;
883
        return env->func->def->base->ret_type;
884
      }  else
885
2
      CHECK_BO(predefined_call(env, t, exp_self(exp)->pos))
886
    }
887
21
    CHECK_OO((exp->m_func = find_template_match(env, v, exp)))
888
13
    return exp->m_func->def->base->ret_type;
889
  }
890
400
  return check_exp_call1(env, exp);
891
}
892
893
135
ANN static Type check_exp_unary(const Env env, const Exp_Unary* unary) {
894
405
  struct Op_Import opi = { .op=unary->op, .rhs=unary->exp ? check_exp(env, unary->exp) : NULL,
895
270
    .data=(uintptr_t)unary, .pos=exp_self(unary)->pos, .op_type=op_unary };
896

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

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

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

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

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


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

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

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

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


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


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



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

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

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

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


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

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

762
    if(parent_func->def->base && compat_func(fdef, parent_func->def) > 0) {
1290
734
      CHECK_BB(check_signature_match(env, fdef, parent_func))
1291
732
      if(!fdef->base->tmpl) {
1292
715
        fdef->base->func->vt_index = parent_func->vt_index;
1293
715
        vector_set(&env->curr->info->vtable, fdef->base->func->vt_index, (vtype)fdef->base->func);
1294
      }
1295
732
      return GW_OK;
1296
    }
1297
28
  } while((parent_func = parent_func->next));
1298
1
  return 0;
1299
}
1300
1301
42191
ANN static m_bool check_parent_match(const Env env, const Func_Def fdef) {
1302
42191
  const Func func = fdef->base->func;
1303
42191
  const Type parent = env->class_def->e->parent;
1304
42191
  if(!env->curr->info->vtable.ptr)
1305
4356
    vector_init(&env->curr->info->vtable);
1306
42191
  if(parent) {
1307
42191
    const Value v = find_value(parent, fdef->base->xid);
1308

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

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

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

42321
  if(env->class_def && env->class_def->e->parent) {
1341
42156
    const Value override = find_value(env->class_def->e->parent, fdef->base->xid);
1342

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

42318
  if(func->value_ref->from->offset && (!fdef->base->tmpl || !fdef->base->tmpl->base))
1349
19
    CHECK_BB(check_func_overload(env, fdef))
1350
42317
  return GW_OK;
1351
}
1352
1353
42317
ANN m_bool check_fdef(const Env env, const Func_Def fdef) {
1354
42317
  if(fdef->base->args)
1355
16547
    CHECK_BB(check_func_args(env, fdef->base->args))
1356
42316
  if(!GET_FLAG(fdef, builtin)) {
1357
295
    if(fdef->d.code)
1358
290
      CHECK_BB(check_stmt_code(env, &fdef->d.code->d.stmt_code))
1359
  } else
1360
42021
    fdef->base->func->code->stack_depth = fdef->stack_depth;
1361
42302
  return GW_OK;
1362
}
1363
1364
42384
ANN m_bool check_func_def(const Env env, const Func_Def f) {
1365
42384
  const Func func = f->base->func;
1366
42384
  const Func_Def fdef = func->def;
1367
  assert(func == fdef->base->func);
1368
42384
  if(env->class_def) // tmpl ?
1369
42191
    CHECK_BB(check_parent_match(env, fdef))
1370
42382
  if(tmpl_base(fdef->base->tmpl))
1371
60
    return GW_OK;
1372

42322
  if(fdef->base->td && !fdef->base->td->xid) { // tmpl ?
1373
1
    CHECK_OB((fdef->base->ret_type = check_td(env, fdef->base->td)))
1374
1
    return check_traverse_fdef(env, fdef);
1375
  }
1376
42321
  CHECK_BB(check_func_def_override(env, fdef))
1377

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

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

64
  if(cdef->base.tmpl && cdef->base.tmpl->list)
1417
21
    CHECK_BB(template_push_types(env, cdef->base.tmpl))
1418
64
  const m_bool ret = check_parent(env, cdef);
1419

64
  if(cdef->base.tmpl && cdef->base.tmpl->list)
1420
21
    nspc_pop_type(env->gwion->mp, env->curr);
1421
64
  return ret;
1422
}
1423
1424
261
ANN m_bool check_class_def(const Env env, const Class_Def cdef) {
1425
261
  if(tmpl_base(cdef->base.tmpl))
1426
17
    return GW_OK;
1427
244
  const Type t = cdef->base.type;
1428

244
  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, check))
1429
    CHECK_BB(ensure_check(env, t->e->owner_class))
1430
244
  if(GET_FLAG(t, check))return GW_OK;
1431
244
  SET_FLAG(t, check);
1432
244
  if(cdef->base.ext)
1433
64
    CHECK_BB(cdef_parent(env, cdef))
1434
244
  if(!GET_FLAG(cdef, struct))
1435
234
    inherit(t);
1436
244
  if(cdef->body) {
1437
203
    CHECK_BB(env_body(env, cdef, check_section))
1438
181
    SET_FLAG(t, ctor);
1439
  }
1440
222
  SET_FLAG(t, valid);
1441
222
  return GW_OK;
1442
}
1443
1444
928
ANN m_bool check_ast(const Env env, Ast ast) {
1445
928
  do CHECK_BB(check_section(env, ast->section))
1446
787
  while((ast = ast->next));
1447
410
  return GW_OK;
1448
}