GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/check.c Lines: 987 1025 96.3 %
Date: 2020-09-12 17:36:58 Branches: 759 926 82.0 %

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
62
ANN static m_bool check_internal(const Env env, const Symbol sym,
21
      const Exp e, const Type t) {
22
62
  struct Implicit imp = { .e=e, .t=t, .pos=e->pos };
23
186
  struct Op_Import opi = { .op=sym, .lhs=e->info->type,
24
124
        .rhs=t, .data=(uintptr_t)&imp, .pos=e->pos, .op_type=op_implicit };
25
62
  CHECK_OB(op_check(env, &opi))
26
  assert(e->info->nspc);
27
45
  return GW_OK;
28
}
29
30
184
ANN m_bool check_implicit(const Env env, const Exp e, const Type t) {
31
184
  if(e->info->type == t)
32
122
    return GW_OK;
33
62
  const Symbol sym = insert_symbol("@implicit");
34
62
  return check_internal(env, sym, e, t);
35
}
36
37
77
ANN m_bool check_subscripts(Env env, const Array_Sub array, const m_bool is_decl) {
38
77
  CHECK_OB(check_exp(env, array->exp))
39
77
  m_uint depth = 0;
40
77
  Exp e = array->exp;
41
119
  do if(is_decl)
42
72
    CHECK_BB(check_implicit(env, e, env->gwion->type[et_int]))
43

119
  while(++depth && (e = e->next));
44
77
  if(depth != array->depth)
45
1
    ERR_B(array->exp->pos, _("invalid array acces expression."))
46
76
  return GW_OK;
47
}
48
49
11583
ANN static inline m_bool check_exp_decl_parent(const Env env, const Var_Decl var) {
50
11583
  const Value value = find_value(env->class_def->e->parent, var->xid);
51
11583
  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
11582
  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
11560
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
ANN static inline void clear_decl(const Env env, const Exp_Decl *decl) {
102
  Var_Decl_List list = decl->list;
103
  do scope_add(env->curr->info->value, (vtype)list->self->xid, (vtype)NULL);
104
  while((list = list->next));
105
}
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
//  clear_decl(env, decl);
110
7
  CHECK_BO(traverse_exp(env, exp_self(decl)))
111
7
  return decl->type;
112
}
113
114
21423
ANN static m_bool check_var(const Env env, const Var_Decl var) {
115

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

21422
  if(var->array && var->array->exp)
118
35
    return check_subscripts(env, var->array, 1);
119
21387
  return GW_OK;
120
}
121
122
21422
ANN static m_bool check_var_td(const Env env, const Var_Decl var, Type_Decl *const td) {
123
21422
  const Value v = var->value;
124
21422
  if(env->class_def)  {
125
11590
    if(GET_FLAG(td, member)) {
126
11558
      decl_member(env, v);
127
11558
      if(env->class_def->e->tuple)
128
11558
        tuple_info(env, v);
129
32
    } else if(GET_FLAG(td, static))
130
24
      decl_static(env, v);
131
  }
132
21422
  return GW_OK;
133
}
134
135
21416
ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
136
21416
  Var_Decl_List list = decl->list;
137
  do {
138
21423
    const Var_Decl var = list->self;
139
21423
    CHECK_BB(check_var(env, var))
140
21422
    CHECK_BB(check_var_td(env, var, decl->td))
141
21422
    if(is_fptr(env->gwion, decl->type))
142
56
      CHECK_BB(check_fptr_decl(env, var))
143
21419
    SET_FLAG(var->value, valid | ae_flag_used);
144
21419
    nspc_add_value(env->curr, var->xid, var->value);
145
21419
  } while((list = list->next));
146
21412
  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
6
ANN m_bool ensure_traverse(const Env env, const Type t) {
156
12
  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)traverse_cdef,
157
6
    .scope=env->scope->depth, .flag=ae_flag_check };
158
6
  return envset_run(&es, t);
159
}
160
161
21452
ANN static inline m_bool inferable(const Env env, const Type t, const loc_t pos) {
162
21452
  if(!GET_FLAG(t, infer))
163
21450
    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
21425
ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
169
21425
  if(!decl->td->xid)
170
8
    return no_xid(env, decl);
171
21417
  if(decl->td->xid == insert_symbol("auto")) { // should be better
172
14
    SET_FLAG(decl->td, ref);
173
14
    CHECK_BO(scan1_exp(env, exp_self(decl)))
174
14
    CHECK_BO(scan2_exp(env, exp_self(decl)))
175
  }
176
21417
  if(!decl->type)
177
    ERR_O(td_pos(decl->td), _("can't find type"));
178
  {
179
21417
    const Type t = get_type(decl->type);
180
21417
    CHECK_BO(inferable(env, t, td_pos(decl->td)))
181

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

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

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

285
    if(value && value->from->owner_class)
260
185
      CHECK_BO(not_from_owner_class(env, env->class_def, value, prim_pos(data)))
261
284
    const Value v = value ?: find_value(env->class_def, var);
262
284
    if(v) {
263

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


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

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


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

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

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

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

1002
      if(e1->type == env->gwion->type[et_undefined] ||
459
777
            (func->def->base->tmpl && is_fptr(env->gwion, func->value_ref->type) > 0)) {
460
2
        const Type owner = func->value_ref->from->owner_class;
461
2
        if(owner)
462
2
          CHECK_BO(template_push(env, owner))
463
2
        e1->type = known_type(env, e1->td);
464
2
        if(owner)
465
2
          nspc_pop_type(env->gwion->mp, env->curr);
466
2
        CHECK_OO(e1->type)
467
      }
468
501
      if(func_match_inner(env, e, e1->type, implicit, specific) < 0)
469
79
        break;
470
422
      e = e->next;
471
422
      e1 = e1->next;
472
    }
473
518
    if(!e1)
474
428
      return func;
475
90
  } while((func = func->next));
476
68
  return NULL;
477
}
478
479
480
ANN2(1, 2) static Func find_func_match(const Env env, const Func up, const Exp exp) {
480
  Func func;
481

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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


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


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



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

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

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

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


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

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

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

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

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

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

42263
  if(env->class_def && env->class_def->e->parent) {
1348
42098
    const Value override = find_value(env->class_def->e->parent, fdef->base->xid);
1349

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

42260
  if(func->value_ref->from->offset && (!fdef->base->tmpl || !fdef->base->tmpl->base))
1356
19
    CHECK_BB(check_func_overload(env, fdef))
1357
42259
  return GW_OK;
1358
}
1359
1360
42259
ANN m_bool check_fdef(const Env env, const Func_Def fdef) {
1361
42259
  if(fdef->base->args)
1362
16524
    CHECK_BB(check_func_args(env, fdef->base->args))
1363
42258
  if(!GET_FLAG(fdef, builtin)) {
1364
295
    if(fdef->d.code)
1365
290
      CHECK_BB(check_stmt_code(env, &fdef->d.code->d.stmt_code))
1366
  } else
1367
41963
    fdef->base->func->code->stack_depth = fdef->stack_depth;
1368
42245
  return GW_OK;
1369
}
1370
1371
42329
ANN m_bool check_func_def(const Env env, const Func_Def f) {
1372
42329
  const Func func = f->base->func;
1373
42329
  const Func_Def fdef = func->def;
1374
  assert(func == fdef->base->func);
1375
42329
  if(env->class_def) // tmpl ?
1376
42136
    CHECK_BB(check_parent_match(env, fdef))
1377
42327
  if(tmpl_base(fdef->base->tmpl))
1378
63
    return GW_OK;
1379

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

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

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

67
  if(cdef->base.tmpl && cdef->base.tmpl->list)
1424
24
    CHECK_BB(template_push_types(env, cdef->base.tmpl))
1425
67
  const m_bool ret = check_parent(env, cdef);
1426

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

251
  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, check))
1436
    CHECK_BB(ensure_check(env, t->e->owner_class))
1437
251
  if(GET_FLAG(t, check))return GW_OK;
1438
251
  SET_FLAG(t, check);
1439
251
  if(cdef->base.ext)
1440
67
    CHECK_BB(cdef_parent(env, cdef))
1441
251
  if(!GET_FLAG(cdef, struct))
1442
239
    inherit(t);
1443
251
  if(cdef->body) {
1444
209
    CHECK_BB(env_body(env, cdef, check_section))
1445
187
    SET_FLAG(t, ctor);
1446
  }
1447
229
  SET_FLAG(t, valid);
1448
229
  return GW_OK;
1449
}
1450
1451
930
ANN m_bool check_ast(const Env env, Ast ast) {
1452
930
  do CHECK_BB(check_section(env, ast->section))
1453
790
  while((ast = ast->next));
1454
412
  return GW_OK;
1455
}