GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/check.c Lines: 993 1032 96.2 %
Date: 2020-07-24 14:14:26 Branches: 758 932 81.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
54
ANN static m_bool check_internal(const Env env, const Symbol sym,
21
      const Exp e, const Type t) {
22
54
  struct Implicit imp = { .e=e, .t=t, .pos=e->pos };
23
162
  struct Op_Import opi = { .op=sym, .lhs=e->info->type,
24
108
        .rhs=t, .data=(uintptr_t)&imp, .pos=e->pos, .op_type=op_implicit };
25
54
  CHECK_OB(op_check(env, &opi))
26
  assert(e->info->nspc);
27
39
  return GW_OK;
28
}
29
30
173
ANN m_bool check_implicit(const Env env, const Exp e, const Type t) {
31
173
  if(e->info->type == t)
32
119
    return GW_OK;
33
54
  const Symbol sym = insert_symbol("@implicit");
34
54
  return check_internal(env, sym, e, t);
35
}
36
37
76
ANN m_bool check_subscripts(Env env, const Array_Sub array, const m_bool is_decl) {
38
76
  CHECK_OB(check_exp(env, array->exp))
39
76
  m_uint depth = 0;
40
76
  Exp e = array->exp;
41
117
  do if(is_decl)
42
72
    CHECK_BB(check_implicit(env, e, env->gwion->type[et_int]))
43

117
  while(++depth && (e = e->next));
44
76
  if(depth != array->depth)
45
1
    ERR_B(array->exp->pos, _("invalid array acces expression."))
46
75
  return GW_OK;
47
}
48
49
12609
ANN static inline m_bool check_exp_decl_parent(const Env env, const Var_Decl var) {
50
12609
  const Value value = find_value(env->class_def->e->parent, var->xid);
51
12609
  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
12608
  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
12588
describe_check_decl(member, offset)
67
52
describe_check_decl(static, class_data_size)
68
69
53
ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) {
70
53
  const Value v    = var->value;
71
53
  Type t = v->type;
72
111
  while(GET_FLAG(t, typedef))
73
5
    t = t->e->parent;
74
53
  if(!t->e->d.func)
75
    return GW_ERROR;
76
53
  if(!env->class_def)
77
23
    return GW_OK;
78
30
  const Func  func = t->e->d.func;
79
30
  const Type type = func->value_ref->from->owner_class;
80

30
  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

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

9
  if(GET_FLAG(t, template) && !GET_FLAG(t, ref))
94
    ERR_O(td_pos(td), _("type '%s' needs template types"), t->name)
95
9
  td->xid = insert_symbol("@resolved");
96
9
  if(t->array_depth)
97
2
    SET_FLAG(td, force);
98
9
  return t;
99
}
100
101
13
ANN static inline void clear_decl(const Env env, const Exp_Decl *decl) {
102
13
  Var_Decl_List list = decl->list;
103
13
  do scope_add(env->curr->info->value, (vtype)list->self->xid, (vtype)NULL);
104
13
  while((list = list->next));
105
13
}
106
107
8
ANN static Type no_xid(const Env env, const Exp_Decl *decl) {
108
8
  CHECK_OO((((Exp_Decl*)decl)->type = check_td(env, decl->td)))
109
7
  clear_decl(env, decl);
110
7
  CHECK_BO(traverse_exp(env, exp_self(decl)))
111
7
  return decl->type;
112
}
113
114
22684
ANN static m_bool check_var(const Env env, const Var_Decl var) {
115

22684
  if(env->class_def && !env->scope->depth && env->class_def->e->parent)
116
12609
    CHECK_BB(check_exp_decl_parent(env, var))
117

22683
  if(var->array && var->array->exp)
118
35
    return check_subscripts(env, var->array, 1);
119
22648
  return GW_OK;
120
}
121
122
22683
ANN static m_bool check_var_td(const Env env, const Var_Decl var, Type_Decl *const td) {
123
22683
  const Value v = var->value;
124
22683
  if(env->class_def)  {
125
12615
    if(GET_FLAG(td, member)) {
126
12586
      decl_member(env, v);
127
12586
      if(env->class_def->e->tuple)
128
12586
        tuple_info(env, v);
129
29
    } else if(GET_FLAG(td, static))
130
22
      decl_static(env, v);
131
  }
132
22683
  return GW_OK;
133
}
134
135
22677
ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
136
22677
  Var_Decl_List list = decl->list;
137
  do {
138
22684
    const Var_Decl var = list->self;
139
22684
    CHECK_BB(check_var(env, var))
140
22683
    CHECK_BB(check_var_td(env, var, decl->td))
141
22683
    if(is_fptr(env->gwion, decl->type))
142
53
      CHECK_BB(check_fptr_decl(env, var))
143
22680
    SET_FLAG(var->value, valid | ae_flag_used);
144
22680
    nspc_add_value(env->curr, var->xid, var->value);
145
22680
  } while((list = list->next));
146
22673
  return GW_OK;
147
}
148
149
35
ANN static inline m_bool ensure_check(const Env env, const Type t) {
150
70
  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)check_cdef,
151
35
    .scope=env->scope->depth, .flag=ae_flag_check };
152
35
  return envset_run(&es, t);
153
}
154
155
5
ANN m_bool ensure_traverse(const Env env, const Type t) {
156
10
  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)traverse_cdef,
157
5
    .scope=env->scope->depth, .flag=ae_flag_check };
158
5
  return envset_run(&es, t);
159
}
160
161
22712
ANN static inline m_bool inferable(const Env env, const Type t, const loc_t pos) {
162
22712
  if(!GET_FLAG(t, infer))
163
22710
    return GW_OK;
164
2
  ERR_B(pos, _("can't infer type."))
165
}
166
167
ANN static Type_Decl* type2td(const Env env, const Type t, const loc_t loc);
168
22686
ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
169
22686
  if(!decl->td->xid)
170
8
    return no_xid(env, decl);
171
22678
  if(decl->td->xid == insert_symbol("auto")) { // should be better
172
6
    clear_decl(env, decl);
173
6
    SET_FLAG(decl->td, ref);
174
6
    CHECK_BO(scan1_exp(env, exp_self(decl)))
175
6
    CHECK_BO(scan2_exp(env, exp_self(decl)))
176
  }
177
22678
  if(!decl->type)
178
    ERR_O(td_pos(decl->td), _("can't find type"));
179
  {
180
22678
    const Type t = get_type(decl->type);
181
22678
    CHECK_BO(inferable(env, t, td_pos(decl->td)))
182

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

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

866
  if(!v->from->owner_class || isa(t, v->from->owner_class) < 0) {
249
1
    ERR_B(pos,
250
        _("'%s' from owner namespace '%s' used in '%s'."),
251
            v->name, v->from->owner ? v->from->owner->name : "?", t->name)
252
  }
253
865
  return GW_OK;
254
}
255
256
1856
ANN static Value check_non_res_value(const Env env, const Symbol *data) {
257
1856
  const Symbol var = *data;
258
1856
  const Value value = nspc_lookup_value1(env->curr, var);
259
1856
  if(env->class_def) {
260

270
    if(value && value->from->owner_class)
261
183
      CHECK_BO(not_from_owner_class(env, env->class_def, value, prim_pos(data)))
262
269
    const Value v = value ?: find_value(env->class_def, var);
263
269
    if(v) {
264

267
      if(env->func && GET_FLAG(env->func->def, static) && GET_FLAG(v, member))
265
2
        ERR_O(prim_pos(data),
266
              _("non-static member '%s' used from static function."), s_name(var))
267
    }
268
267
    return v;
269


1586
  } else if(SAFE_FLAG(env->class_def, global) || (env->func && GET_FLAG(env->func->def, global))) {
270

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


1856
  if(!v || !GET_FLAG(v, valid) || (v->from->ctx && v->from->ctx->error)) {
311
20
    env_err(env, prim_pos(data),
312
          _("variable %s not legit at this point."), s_name(sym));
313
20
    if(v)
314

1
      did_you_mean_nspc(value_owner(v) ?: env->curr, s_name(sym));
315
20
    return NULL;
316
  }
317
1836
  prim_self(data)->value = v;
318
1836
  if(env->func) {
319
280
    if(GET_FLAG(env->func->def, abstract))
320
3
      CHECK_BO(lambda_valid(env, prim_self(data)))
321

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

104
    if(e->info->type == env->gwion->type[et_lambda] && is_fptr(env->gwion, t)) {
438
1
      exp_setvar(e, 1);
439
1
      return check_lambda(env, t, &e->d.exp_lambda);
440
    }
441
103
    if(implicit)
442
45
      return check_implicit(env, e, t);
443
  }
444
389
  return match ? 1 : -1;
445
}
446
447
667
ANN2(1,2) static Func find_func_match_actual(const Env env, Func func, const Exp args,
448
  const m_bool implicit, const m_bool specific) {
449
  do {
450
667
    Exp e = args;
451
667
    Arg_List e1 = func->def->base->args;
452
1700
    while(e) {
453
617
      if(!e1) {
454
182
        if(GET_FLAG(func->def, variadic))
455
15
          return func;
456
167
        CHECK_OO(func->next);
457
61
        return find_func_match_actual(env, func->next, args, implicit, specific);
458
      }
459

870
      if(e1->type == env->gwion->type[et_undefined] ||
460
651
            (func->def->base->tmpl && is_fptr(env->gwion, func->value_ref->type) > 0)) {
461
2
        const Type owner = func->value_ref->from->owner_class;
462
2
        if(owner)
463
2
          CHECK_BO(template_push(env, owner))
464
2
        e1->type = known_type(env, e1->td);
465
2
        if(owner)
466
2
          nspc_pop_type(env->gwion->mp, env->curr);
467
2
        CHECK_OO(e1->type)
468
      }
469
435
      if(func_match_inner(env, e, e1->type, implicit, specific) < 0)
470
69
        break;
471
366
      e = e->next;
472
366
      e1 = e1->next;
473
    }
474
485
    if(!e1)
475
405
      return func;
476
80
  } while((func = func->next));
477
58
  return NULL;
478
}
479
480
452
ANN2(1, 2) static Func find_func_match(const Env env, const Func up, const Exp exp) {
481
  Func func;
482

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

452
  if((func = find_func_match_actual(env, up, args, 0, 1)) ||
484
35
     (func = find_func_match_actual(env, up, args, 1, 1)) ||
485
32
     (func = find_func_match_actual(env, up, args, 0, 0)) ||
486
     (func = find_func_match_actual(env, up, args, 1, 0)))
487
420
    return func;
488
32
  return NULL;
489
}
490
491
118
ANN static m_bool check_call(const Env env, const Exp_Call* exp) {
492
118
  ae_exp_t et = exp->func->exp_type;
493

118
  if(et != ae_exp_primary && et != ae_exp_dot && et != ae_exp_cast)
494
1
    ERR_B(exp->func->pos, _("invalid expression for function call."))
495
117
  CHECK_OB(check_exp(env, exp->func))
496
116
  if(exp->args)
497
110
    CHECK_OB(check_exp(env, exp->args))
498
116
  return GW_OK;
499
}
500
501
204
ANN static inline Value template_get_ready(const Env env, const Value v, const m_str tmpl, const m_uint i) {
502
204
  const Symbol sym = func_symbol(env, v->from->owner->name, v->name, tmpl, i);
503
268
  return v->from->owner_class ? find_value(v->from->owner_class, sym) :
504
64
      nspc_lookup_value1(v->from->owner, sym);
505
}
506
507
62
ANN m_bool check_traverse_fdef(const Env env, const Func_Def fdef) {
508
62
  struct Vector_ v = {};
509
62
  const m_uint scope = env->scope->depth;
510
62
  env->scope->depth = 1;
511
62
  vector_init(&v);
512
139
  while(vector_size((Vector)&env->curr->info->value->ptr) > 1)
513
15
    vector_add(&v, vector_pop((Vector)&env->curr->info->value->ptr));
514
62
  const m_bool ret = traverse_func_def(env, fdef);
515
139
  for(m_uint i = vector_size(&v) + 1; --i;)
516
15
    vector_add((Vector)&env->curr->info->value->ptr, vector_at(&v, i-1));
517
62
  vector_release(&v);
518
62
  env->scope->depth = scope;
519
62
  return ret;
520
}
521
522
90
ANN static Func ensure_tmpl(const Env env, const Func_Def fdef, const Exp_Call *exp) {
523

90
  const m_bool ret = GET_FLAG(fdef, valid) || check_traverse_fdef(env, fdef) > 0;
524
90
  if(ret) {
525
85
    const Func f = fdef->base->func;
526
85
    const Func next = f->next;
527
85
    f->next = NULL;
528
85
    const Func func = find_func_match(env, f, exp->args);
529
85
    f->next = next;
530
85
    if(func) {
531
60
      SET_FLAG(func, valid | ae_flag_template);
532
60
      return func;
533
    }
534
  }
535
30
  return NULL;
536
}
537
538
24309
ANN static m_bool check_func_args(const Env env, Arg_List arg_list) {
539
  do {
540
24309
    const Var_Decl decl = arg_list->var_decl;
541
24309
    const Value v = decl->value;
542

24309
    if(arg_list->td && !arg_list->td->xid)
543
1
      CHECK_OB((arg_list->type = v->type = check_td(env, arg_list->td)))
544
// TODO: use coumpound instead of object?
545

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

10
        if(traverse_fptr_def(env, fptr) > 0 &&
578
10
            (base->base->ret_type = known_type(env, base->base->td)) &&
579
7
            (!exp->args || !!check_exp(env, exp->args))) {
580
5
          m_func = find_func_match(env, fbase->func, exp->args);
581
5
          nspc_pop_type(env->gwion->mp, env->curr);
582
5
          if(m_func)
583
5
            nspc_add_type_front(v->from->owner, sym, actual_type(env->gwion, m_func->value_ref->type));
584
        }
585
5
        free_fptr_def(env->gwion->mp, fptr);
586
5
        if(fptr->type)
587
5
          REM_REF(fptr->type, env->gwion)
588
      }
589
    }
590
  } else {
591
168
    for(m_uint i = 0; i < v->from->offset + 1; ++i) {
592
129
      const Value exists = template_get_ready(env, v, tmpl_name, i);
593
129
      if(exists) {
594
54
        if(env->func == exists->d.func_ref) {
595

12
          if(check_call(env, exp) < 0 ||
596
6
             !find_func_match(env, env->func, exp->args))
597
1
            continue;
598
5
          m_func = env->func;
599
5
          break;
600
        }
601
48
        if((m_func = ensure_tmpl(env, exists->d.func_ref->def, exp)))
602
25
          break;
603
      } else {
604
75
        const Value value = template_get_ready(env, v, "template", i);
605
75
        if(!value)
606
33
          continue;
607
42
        if(GET_FLAG(v, builtin)) {
608
1
          SET_FLAG(value, builtin);
609
1
          SET_FLAG(value->d.func_ref, builtin);
610
        }
611
42
        const Func_Def fdef = (Func_Def)cpy_func_def(env->gwion->mp, value->d.func_ref->def);
612
42
        SET_FLAG(fdef, template);
613
42
        fdef->base->tmpl->call = cpy_type_list(env->gwion->mp, types);
614
42
        fdef->base->tmpl->base = i;
615
42
        if((m_func = ensure_tmpl(env, fdef, exp)))
616
35
          break;
617
      }
618
    }
619
  }
620
109
  free_mstr(env->gwion->mp, tmpl_name);
621
109
  if(es.run)
622
2
    envset_pop(&es, v->from->owner_class);
623
109
  env_pop(env, scope);
624
109
  env->func = former;
625
109
  return m_func;
626
}
627
628
77
ANN Func find_template_match(const Env env, const Value value, const Exp_Call* exp) {
629
77
  const Func f = _find_template_match(env, value, exp);
630
77
  if(f)
631
57
    return f;
632
20
  Type t = value->from->owner_class;
633

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

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

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

122
    while(arg && template_arg) {
745
60
      if(list->xid == arg->td->xid) {
746
56
        tl[args_number] = mk_type_list(env, template_arg->info->type, fdef->pos);
747
56
        if(args_number)
748
3
          tl[args_number - 1]->next = tl[args_number];
749
56
        ++args_number;
750
56
        break;
751
      }
752
4
      arg = arg->next;
753
4
      template_arg = template_arg->next;
754
    }
755
59
    list = list->next;
756
  }
757
54
  if(args_number < type_number)
758
2
    ERR_O(exp->func->pos, _("not able to guess types for template call."))
759
52
  return tl[0];
760
}
761
762
73
ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) {
763
73
  const Type t = exp->func->info->type;
764
73
  DECL_OO(const Value, value, = type_value(env->gwion, t))
765
73
  const Func_Def fdef = value->d.func_ref ? value->d.func_ref->def : t->e->d.func->def;
766
73
  Tmpl *tm = fdef->base->tmpl;
767
73
  if(tm->call)
768
19
    return check_predefined(env, exp, value, tm, fdef);
769
54
  DECL_OO(const Type_List, tl, = check_template_args(env, exp, tm, fdef));
770
52
  Tmpl tmpl = { .call=tl };
771
52
  ((Exp_Call*)exp)->tmpl = &tmpl;
772
52
  DECL_OO(const Func,func, = get_template_func(env, exp, value))
773
51
  return func->def->base->ret_type;
774
}
775
776
9
ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
777
9
  if(exp->args)
778
5
    CHECK_OO(check_exp(env, exp->args))
779
9
  Exp_Lambda *l = &exp->func->d.exp_lambda;
780
9
  Arg_List arg = l->def->base->args;
781
9
  Exp e = exp->args;
782

24
  while(arg && e) {
783
6
    arg->type = e->info->type;
784
6
    arg = arg->next;
785
6
    e = e->next;
786
  }
787

9
  if(arg || e)
788
1
    ERR_O(exp_self(exp)->pos, _("argument number does not match for lambda"))
789
8
  CHECK_BO(check_traverse_fdef(env, l->def))
790
8
  if(env->class_def)
791
3
    SET_FLAG(l->def, member);
792
8
  ((Exp_Call*)exp)->m_func = l->def->base->func;
793
8
  return l->def->base->ret_type ?: (l->def->base->ret_type = env->gwion->type[et_void]);
794
}
795
796
449
ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
797
449
  if(exp->func->exp_type == ae_exp_decl)
798
1
    ERR_O(exp_self(exp)->pos, _("It makes no sense to call a function pointer at declaration"))
799
448
  CHECK_OO(check_exp(env, exp->func))
800
439
  if(isa(exp->func->info->type, env->gwion->type[et_function]) < 0) {
801
    // use func flag?
802
1
    if(isa(exp->func->info->type, env->gwion->type[et_class]) < 0)
803
1
      ERR_O(exp->func->pos, _("function call using a non-function value"))
804
    struct Op_Import opi = { .op=insert_symbol("@ctor"), .rhs=exp->func->info->type->e->d.base_type,
805
      .data=(uintptr_t)exp, .pos=exp_self(exp)->pos, .op_type=op_exp };
806
    const Type t = op_check(env, &opi);
807
    exp_self(exp)->info->nspc = t ? t->e->owner : NULL;
808
    return t;
809
  }
810
438
  if(exp->func->info->type == env->gwion->type[et_lambda])
811
9
    return check_lambda_call(env, exp);
812
429
  if(GET_FLAG(exp->func->info->type->e->d.func, ref)) {
813
5
    const Value value = exp->func->info->type->e->d.func->value_ref;
814

5
    if(value->from->owner_class && !GET_FLAG(value->from->owner_class, check))
815
      CHECK_BO(ensure_traverse(env, value->from->owner_class))
816
  }
817
429
  if(exp->args)
818
205
    CHECK_OO(check_exp(env, exp->args))
819
429
  if(GET_FLAG(exp->func->info->type, func))
820
73
    return check_exp_call_template(env, (Exp_Call*)exp);
821
356
  const Func func = find_func_match(env, exp->func->info->type->e->d.func, exp->args);
822
356
  if((exp_self(exp)->d.exp_call.m_func = func)) {
823
350
    exp->func->info->type = func->value_ref->type;
824
350
    return func->def->base->ret_type;
825
  }
826
6
  function_alternative(env, exp->func->info->type, exp->args, exp_self(exp)->pos);
827
6
  return NULL;
828
}
829
830
671
ANN static Type check_exp_binary(const Env env, const Exp_Binary* bin) {
831
671
  CHECK_OO(check_exp(env, bin->lhs))
832

668
  const m_bool is_auto = bin->rhs->exp_type == ae_exp_decl && bin->rhs->d.exp_decl.type == env->gwion->type[et_auto];
833
668
  if(is_auto)
834
5
    bin->rhs->info->type = bin->rhs->d.exp_decl.type = bin->lhs->info->type;
835
668
  CHECK_OO(check_exp(env, bin->rhs))
836
2664
  struct Op_Import opi = { .op=bin->op, .lhs=bin->lhs->info->type,
837
1998
    .rhs=bin->rhs->info->type, .data=(uintptr_t)bin, .pos=exp_self(bin)->pos, .op_type=op_binary };
838
666
  const Type ret = op_check(env, &opi);
839

666
  if(!ret && is_auto && exp_self(bin)->exp_type == ae_exp_binary)
840
1
    bin->rhs->d.exp_decl.list->self->value->type = env->gwion->type[et_auto];
841
666
  return ret;
842
}
843
844
38
ANN static Type check_exp_cast(const Env env, const Exp_Cast* cast) {
845
38
  DECL_OO(const Type, t, = check_exp(env, cast->exp))
846

38
  CHECK_OO((exp_self(cast)->info->type = cast->td->xid ? known_type(env, cast->td) : check_td(env, cast->td)))
847
111
  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=t, .rhs=exp_self(cast)->info->type,
848
74
    .data=(uintptr_t)cast, .pos=exp_self(cast)->pos, .op_type=op_cast };
849
37
  return op_check(env, &opi);
850
}
851
852
37
ANN static Type check_exp_post(const Env env, const Exp_Postfix* post) {
853
111
  struct Op_Import opi = { .op=post->op, .lhs=check_exp(env, post->exp),
854
74
    .data=(uintptr_t)post, .pos=exp_self(post)->pos, .op_type=op_postfix };
855
37
  CHECK_OO(opi.lhs)
856
37
  const Type t = op_check(env, &opi);
857

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

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

27
    if(!v->d.func_ref || !v->d.func_ref->def->base->tmpl)
883
3
      ERR_O(exp_self(exp)->pos, _("template call of non-template function."))
884
24
    if(t->e->d.func->def->base->tmpl->call) {
885
2
      if(env->func == t->e->d.func) {
886
        if(exp->args)
887
          CHECK_OO(check_exp(env, exp->args))
888
        exp->m_func = env->func;
889
        return env->func->def->base->ret_type;
890
      }  else
891
2
      CHECK_BO(predefined_call(env, t, exp_self(exp)->pos))
892
    }
893
22
    CHECK_OO((exp->m_func = find_template_match(env, v, exp)))
894
16
    return exp->m_func->def->base->ret_type;
895
  }
896
376
  return check_exp_call1(env, exp);
897
}
898
899
139
ANN static Type check_exp_unary(const Env env, const Exp_Unary* unary) {
900
417
  struct Op_Import opi = { .op=unary->op, .rhs=unary->exp ? check_exp(env, unary->exp) : NULL,
901
278
    .data=(uintptr_t)unary, .pos=exp_self(unary)->pos, .op_type=op_unary };
902

139
  if(unary->exp && !opi.rhs)
903
    return NULL;
904
139
  DECL_OO(const Type, ret, = op_check(env, &opi))
905
132
  const Type t = get_type(actual_type(env->gwion, ret));
906

132
  if(t->e->def && !GET_FLAG(t, check))
907
    CHECK_BO(ensure_traverse(env, t))
908
132
  return ret;
909
}
910
911
84
ANN static Type _flow(const Env env, const Exp e, const m_bool b) {
912
84
  DECL_OO(const Type, type, = check_exp(env, e))
913
252
  struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"),
914
168
    .rhs=type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp };
915
84
  return op_check(env, &opi);
916
}
917
#define check_flow(emit,b) _flow(emit, b, 1)
918
919
10
ANN static Type check_exp_if(const Env env, const Exp_If* exp_if) {
920
10
  DECL_OO(const Type, cond, = check_flow(env, exp_if->cond))
921

10
  DECL_OO(const Type, if_exp, = (exp_if->if_exp ? check_exp(env, exp_if->if_exp) : cond))
922
10
  DECL_OO(const Type, else_exp, = check_exp(env, exp_if->else_exp))
923
10
  const Type ret = find_common_anc(if_exp, else_exp);
924
10
  if(!ret)
925
1
    ERR_O(exp_self(exp_if)->pos,
926
          _("incompatible types '%s' and '%s' in if expression..."),
927
          if_exp->name, else_exp->name)
928

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

9
  if(exp_getmeta(exp_if->if_exp ?: exp_if->cond) || exp_getmeta(exp_if->else_exp))
933
9
    exp_setmeta(exp_self(exp_if), 1);
934
9
  return ret;
935
}
936
937
515
ANN static Type check_exp_dot(const Env env, Exp_Dot* member) {
938
515
  CHECK_OO((member->t_base = check_exp(env, member->base)))
939
505
  return check_dot(env, member);
940
}
941
942
750
ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
943
750
  return tdef->type->e->def ? check_class_def(env, tdef->type->e->def) : GW_OK;
944
}
945
18
ANN static Type check_exp_lambda(const Env env,
946
18
    const Exp_If* exp_if NUSED) { return env->gwion->type[et_lambda]; }
947
948
DECL_EXP_FUNC(check, Type, Env)
949
950
28493
ANN Type check_exp(const Env env, const Exp exp) {
951
28493
  Exp curr = exp;
952
  do {
953
29000
    CHECK_OO((curr->info->type = check_exp_func[curr->exp_type](env, &curr->d)))
954


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

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

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

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


34
stmt_func_xxx(if, Stmt_If,, !(!check_flow(env, stmt->cond)   ||
1063
  check_stmt(env, stmt->if_body) < 0 ||
1064
  (stmt->else_body && check_stmt(env, stmt->else_body) < 0)) ? 1 : -1)
1065


26
stmt_func_xxx(flow, Stmt_Flow,,
1066
  !(!check_exp(env, stmt->cond) ||
1067
    !_flow(env, stmt->cond, !stmt->is_do ?
1068
       stmt_self(stmt)->stmt_type == ae_stmt_while :
1069
       stmt_self(stmt)->stmt_type != ae_stmt_while) ||
1070
    check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
1071



11
stmt_func_xxx(for, Stmt_For,, !(
1072
  for_empty(env, stmt) < 0 ||
1073
  check_stmt(env, stmt->c1) < 0 ||
1074
  !check_flow(env, stmt->c2->d.stmt_exp.val) ||
1075
  (stmt->c3 && !check_exp(env, stmt->c3)) ||
1076
  check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
1077

8
stmt_func_xxx(loop, Stmt_Loop,, !(!check_exp(env, stmt->cond) ||
1078
  cond_type(env, stmt->cond) < 0 ||
1079
  check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
1080
11
stmt_func_xxx(auto, Stmt_Auto,, do_stmt_auto(env, stmt))
1081
1082
48
ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) {
1083
48
  if(!env->func)
1084
1
    ERR_B(stmt_self(stmt)->pos, _("'return' statement found outside function definition"))
1085

47
  DECL_OB(const Type, ret_type, = stmt->val ? check_exp(env, stmt->val) : env->gwion->type[et_void])
1086
47
  if(!env->func->def->base->ret_type) {
1087
    assert(isa(env->func->value_ref->type, env->gwion->type[et_lambda]) > 0);
1088
1
    env->func->def->base->ret_type = ret_type;
1089
1
    return GW_OK;
1090
  }
1091
46
  if(isa(ret_type, env->func->def->base->ret_type) > 0)
1092
42
    return GW_OK;
1093
4
  if(stmt->val) {
1094

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


21
  if(!udef->xid && !udef->type_xid && env->class_def && !GET_FLAG(udef, static))
1166
1
    env->class_def->nspc->info->offset = udef->o + udef->s;
1167
21
  union_pop(env, udef, scope);
1168
21
  union_flag(udef, ae_flag_check);
1169
21
  union_flag(udef, ae_flag_valid);
1170
21
  return ret;
1171
}
1172
1173
2252
ANN static m_bool check_stmt_exp(const Env env, const Stmt_Exp stmt) {
1174

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

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

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

64
    for(m_uint j = i + 1; f1 && j <= v->from->offset; ++j) {
1335
27
      const Func f2 = get_overload(env, fdef, j);
1336

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

43365
  if(env->class_def && env->class_def->e->parent) {
1347
43213
    const Value override = find_value(env->class_def->e->parent, fdef->base->xid);
1348

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

43362
  if(func->value_ref->from->offset && (!fdef->base->tmpl || !fdef->base->tmpl->base))
1355
17
    CHECK_BB(check_func_overload(env, fdef))
1356
43361
  return GW_OK;
1357
}
1358
1359
43361
ANN m_bool check_fdef(const Env env, const Func_Def fdef) {
1360
43361
  if(fdef->base->args)
1361
16947
    CHECK_BB(check_func_args(env, fdef->base->args))
1362
43360
  if(!GET_FLAG(fdef, builtin)) {
1363
276
    if(fdef->d.code)
1364
271
      CHECK_BB(check_stmt_code(env, &fdef->d.code->d.stmt_code))
1365
  } else
1366
43084
    fdef->base->func->code->stack_depth = fdef->stack_depth;
1367
43342
  return GW_OK;
1368
}
1369
1370
43429
ANN m_bool check_func_def(const Env env, const Func_Def f) {
1371
43429
  const Func func = f->base->func;
1372
43429
  const Func_Def fdef = func->def;
1373
  assert(func == fdef->base->func);
1374
43429
  if(env->class_def) // tmpl ?
1375
43249
    CHECK_BB(check_parent_match(env, fdef))
1376
43427
  if(tmpl_base(fdef->base->tmpl))
1377
61
    return GW_OK;
1378

43366
  if(fdef->base->td && !fdef->base->td->xid) { // tmpl ?
1379
1
    CHECK_OB((fdef->base->ret_type = check_td(env, fdef->base->td)))
1380
1
    return check_traverse_fdef(env, fdef);
1381
  }
1382
43365
  CHECK_BB(check_func_def_override(env, fdef))
1383

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

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

64
  if(cdef->base.tmpl && cdef->base.tmpl->list)
1423
23
    CHECK_BB(template_push_types(env, cdef->base.tmpl))
1424
64
  const m_bool ret = check_parent(env, cdef);
1425

64
  if(cdef->base.tmpl && cdef->base.tmpl->list)
1426
23
    nspc_pop_type(env->gwion->mp, env->curr);
1427
64
  return ret;
1428
}
1429
1430
259
ANN m_bool check_class_def(const Env env, const Class_Def cdef) {
1431
259
  if(tmpl_base(cdef->base.tmpl))
1432
19
    return GW_OK;
1433
240
  const Type t = cdef->base.type;
1434

240
  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, check))
1435
    CHECK_BB(ensure_check(env, t->e->owner_class))
1436
240
  if(GET_FLAG(t, check))return GW_OK;
1437
240
  SET_FLAG(t, check);
1438
240
  if(cdef->base.ext)
1439
64
    CHECK_BB(cdef_parent(env, cdef))
1440
240
  if(!GET_FLAG(cdef, struct))
1441
228
    inherit(t);
1442
240
  if(cdef->body) {
1443
199
    CHECK_BB(env_body(env, cdef, check_section))
1444
176
    SET_FLAG(t, ctor);
1445
  }
1446
217
  SET_FLAG(t, valid);
1447
217
  return GW_OK;
1448
}
1449
1450
901
ANN m_bool check_ast(const Env env, Ast ast) {
1451
901
  do CHECK_BB(check_section(env, ast->section))
1452
753
  while((ast = ast->next));
1453
401
  return GW_OK;
1454
}