GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/scan1.c Lines: 445 455 97.8 %
Date: 2020-09-21 18:02:52 Branches: 406 472 86.0 %

Line Branch Exec Source
1
#include <ctype.h>
2
#include "gwion_util.h"
3
#include "gwion_ast.h"
4
#include "gwion_env.h"
5
#include "vm.h"
6
#include "traverse.h"
7
#include "template.h"
8
#include "parse.h"
9
10
ANN static m_bool scan1_stmt_list(const Env env, Stmt_List list);
11
ANN static m_bool scan1_stmt(const Env env, Stmt stmt);
12
13
11615
ANN static inline m_bool type_cyclic(const Env env, const Type t, const Type_Decl *td) {
14
11615
  Type owner = env->class_def;
15
  do {
16
11626
    Type parent = t;
17
43541
    while(parent) {
18
20290
      if(parent == owner)
19
1
        ERR_B(td_pos(td), _("%s declared inside %s"), t->name, owner->name);
20
20289
      parent = parent->e->parent;
21
    }
22
11625
  } while((owner = owner->e->owner_class));
23
11614
  return GW_OK;
24
}
25
26
35
ANN static inline m_bool ensure_scan1(const Env env, const Type t) {
27
70
  struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan1_cdef,
28
35
    .scope=env->scope->depth, .flag=ae_flag_scan1 };
29
35
  return envset_run(&es, t);
30
}
31
32
45313
ANN static Type scan1_type(const Env env, Type_Decl* td) {
33
45313
  DECL_OO(const Type, type, = known_type(env, td))
34
45290
  const Type t = get_type(type);
35

45290
  if(!env->func && env->class_def && !GET_FLAG(td, ref))
36
11615
    CHECK_BO(type_cyclic(env, t, td))
37

45289
  if(!GET_FLAG(t, scan1) && t->e->def)
38
29
    CHECK_BO(ensure_scan1(env, t))
39
45289
  return type;
40
}
41
42
45249
ANN static Type void_type(const Env env, Type_Decl* td) {
43
45249
  DECL_OO(const Type, type, = scan1_type(env, td))
44
45227
  if(type->size)
45
45224
    return type;
46
3
  ERR_O(td_pos(td), _("cannot declare variables of size '0' (i.e. 'void')..."))
47
}
48
49
21488
ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) {
50
21488
  if(decl->type)
51
21
    return decl->type;
52
21467
  DECL_OO(const Type ,t, = void_type(env, decl->td))
53

21448
  if(decl->td->xid == insert_symbol("auto") && decl->type)
54
    return decl->type;
55

21448
  if(!env->scope->depth && env->class_def && !GET_FLAG(decl->td, static))
56
11566
    SET_FLAG(decl->td, member);
57

21448
  if(GET_FLAG(t, private) && t->e->owner != env->curr)
58
1
    ERR_O(exp_self(decl)->pos, _("can't use private type %s"), t->name)
59

21447
  if(GET_FLAG(t, protect) && (!env->class_def || isa(t, env->class_def) < 0))
60
1
    ERR_O(exp_self(decl)->pos, _("can't use protected type %s"), t->name)
61
21446
  return decl->type = t;
62
}
63
64
21474
static inline m_bool scan1_defined(const Env env, const Var_Decl var) {
65
21474
  if(var->value) // from a `typeof` declaration
66
21
    return GW_OK;
67

21453
  if(((!env->class_def || env->scope->depth) ? nspc_lookup_value1 : nspc_lookup_value2)(env->curr, var->xid))
68
3
    ERR_B(var->pos, _("variable %s has already been defined in the same scope..."),
69
              s_name(var->xid))
70
21450
  return GW_OK;
71
}
72
73
21465
ANN static m_bool scan1_decl(const Env env, const Exp_Decl* decl) {
74
21465
  Var_Decl_List list = decl->list;
75
  do {
76
21474
    const Var_Decl var = list->self;
77
21474
    CHECK_BB(isres(env, var->xid, exp_self(decl)->pos))
78
21474
    Type t = decl->type;
79
21474
    CHECK_BB(scan1_defined(env, var))
80
21471
    if(var->array) {
81
46
      if(var->array->exp) {
82
38
        if(GET_FLAG(decl->td, ref))
83
1
          ERR_B(var->array->exp->pos, _("ref array must not have array expression.\n"
84
            "e.g: int @my_array[];\nnot: int @my_array[2];"))
85
37
        CHECK_BB(scan1_exp(env, var->array->exp))
86
      }
87
45
      t = array_type(env, decl->type, var->array->depth);
88

21425
    } else if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref)) {
89
1
      if(decl->td->xid == insert_symbol("auto"))
90
        SET_FLAG(decl->td, ref);
91
      else
92
1
        ERR_B(exp_self(decl)->pos, _("Type '%s' is abstract, declare as ref. (use @)"), t->name)
93
    }
94
21469
    const Value v = var->value = var->value ?: new_value(env->gwion->mp, t, s_name(var->xid));
95

21469
    if(SAFE_FLAG(env->class_def, struct) && !GET_FLAG(decl->td, static)) {
96
22
      v->from->offset = env->class_def->size;
97
22
      env->class_def->size += t->size;
98
    }
99
21469
    nspc_add_value(env->curr, var->xid, v);
100
21469
    v->flag = decl->td->flag;
101
21469
    v->type = t;
102

21469
    if(var->array && !var->array->exp)
103
8
      SET_FLAG(v, ref);
104
21469
    if(env->class_def) {
105
11603
      if(env->class_def->e->tuple)
106
11603
        tuple_contains(env, v);
107
9866
    } else if(!env->scope->depth)
108
9677
      SET_FLAG(v, global);
109
21469
    v->d.ptr = var->addr;
110
21469
    if(GET_FLAG(decl->td, global))
111
6
      SET_FLAG(v, abstract);
112
21469
    if(!env->scope->depth)
113
21272
      valuefrom(env, v->from);
114
21469
  } while((list = list->next));
115
21460
  ((Exp_Decl*)decl)->type = decl->list->self->value->type;
116
21460
  return GW_OK;
117
}
118
119
19
ANN int is_global(const Nspc nspc, Nspc global) {
120
19
  do if(nspc == global)
121
6
    return 1;
122
13
  while((global = global->parent));
123
2
  return 0;
124
}
125
126
21492
ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) {
127
21492
  CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos))
128
21488
  ((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl);
129
21488
  CHECK_OB(decl->type)
130
21467
  if(GET_FLAG(decl->type, const))
131
    exp_setmeta(exp_self(decl), 1);
132
21467
  const m_bool global = GET_FLAG(decl->td, global);
133
21467
  if(global) {
134
8
    if(env->context)
135
7
      env->context->global = 1;
136
8
    if(!is_global(decl->type->e->owner, env->global_nspc))
137
2
      ERR_B(exp_self(decl)->pos, _("type '%s' is not global"), decl->type->name)
138
  }
139
21465
  const m_uint scope = !global ? env->scope->depth : env_push_global(env);
140
21465
  const m_bool ret = scan1_decl(env, decl);
141
21465
  if(global)
142
6
    env_pop(env, scope);
143
21465
  return ret;
144
}
145
146
799
ANN static inline int opiscall(const Symbol sym) {
147
799
  const m_str opname = s_name(sym);
148

911
  return (opname[0] == '@' || opname[0] == '$') &&
149
215
    (isalpha(opname[1]) || opname[1] == '_');
150
}
151
152
3
ANN static inline Exp sym2func(const Env env, const Symbol sym, const loc_t pos) {
153
3
  MemPool mp = env->gwion->mp;
154
3
  const m_str name = s_name(sym);
155
3
  return new_prim_id(mp, insert_symbol(name + 1), loc_cpy(mp, pos));
156
}
157
158
1
ANN static void binary_args(const Exp_Binary* bin) {
159
1
  Exp arg = bin->lhs;
160
2
  while(arg->next)
161
    arg = arg->next;
162
1
  arg->next = bin->rhs;
163
1
}
164
165
3
ANN static m_bool exp2call(const Env env, const Exp e, const Symbol sym, const Exp args) {
166
3
  e->exp_type = ae_exp_call;
167
3
  e->d.exp_call.func = sym2func(env, sym, e->pos);
168
3
  e->d.exp_call.args = args;
169
3
  return scan1_exp(env, e);
170
}
171
172
1
ANN static m_bool binary2call(const Env env, const Exp_Binary* bin) {
173
1
  binary_args(bin);
174
1
  return exp2call(env, exp_self(bin), bin->op, bin->lhs);
175
}
176
177
643
ANN static inline m_bool scan1_exp_binary(const Env env, const Exp_Binary* bin) {
178
643
  if(opiscall(bin->op))
179
1
    return binary2call(env, bin);
180
642
  CHECK_BB(scan1_exp(env, bin->lhs))
181
642
  return scan1_exp(env, bin->rhs);
182
}
183
184
12
ANN static m_bool scan1_range(const Env env, Range *range) {
185
12
  if(range->start)
186
11
    CHECK_BB(scan1_exp(env, range->start))
187
12
  if(range->end)
188
8
    CHECK_BB(scan1_exp(env, range->end))
189
12
  return GW_OK;
190
}
191
192
4432
ANN static inline m_bool scan1_prim(const Env env, const Exp_Primary* prim) {
193

7774
  if(prim->prim_type == ae_prim_hack || prim->prim_type == ae_prim_typeof ||
194
3342
        prim->prim_type == ae_prim_interp)
195
1093
    return scan1_exp(env, prim->d.exp);
196

3339
  if(prim->prim_type == ae_prim_array && prim->d.array->exp)
197
22
    return scan1_exp(env, prim->d.array->exp);
198
3317
  if(prim->prim_type == ae_prim_range)
199
3
    return scan1_range(env, prim->d.range);
200
3314
  return GW_OK;
201
}
202
203
30
ANN static inline m_bool scan1_exp_array(const Env env, const Exp_Array* array) {
204
30
  CHECK_BB(scan1_exp(env, array->base))
205
30
  return scan1_exp(env, array->array->exp);
206
}
207
208
9
ANN static inline m_bool scan1_exp_slice(const Env env, const Exp_Slice* range) {
209
9
  CHECK_BB(scan1_exp(env, range->base))
210
9
  return scan1_range(env, range->range);
211
}
212
213
40
ANN static inline m_bool scan1_exp_cast(const Env env, const Exp_Cast* cast) {
214
40
  return scan1_exp(env, cast->exp);
215
}
216
217
39
ANN static m_bool scan1_exp_post(const Env env, const Exp_Postfix* post) {
218
39
  if(opiscall(post->op)) {
219
1
    return exp2call(env, exp_self(post), post->op, post->exp);
220
  }
221
38
  CHECK_BB(scan1_exp(env, post->exp))
222
38
  const m_str access = exp_access(post->exp);
223
38
  if(!access)
224
37
    return GW_OK;
225
1
  ERR_B(post->exp->pos, _("post operator '%s' cannot be used"
226
      " on %s data-type..."), s_name(post->op), access);
227
}
228
229
553
ANN static m_bool scan1_exp_call(const Env env, const Exp_Call* exp_call) {
230
553
  if(exp_call->tmpl)
231
32
    return GW_OK;
232
521
  CHECK_BB(scan1_exp(env, exp_call->func))
233
520
  const Exp args = exp_call->args;
234
520
  return args ? scan1_exp(env, args) : GW_OK;
235
}
236
237
555
ANN static inline m_bool scan1_exp_dot(const Env env, const Exp_Dot* member) {
238
555
  if(member->base->next)
239
1
    ERR_B(member->base->pos, _("can't use multiple expression"
240
      " in dot member base expression"))
241
554
  return scan1_exp(env, member->base);
242
}
243
244
10
ANN static m_bool scan1_exp_if(const Env env, const Exp_If* exp_if) {
245
10
  CHECK_BB(scan1_exp(env, exp_if->cond))
246

10
  CHECK_BB(scan1_exp(env, exp_if->if_exp ?: exp_if->cond))
247
10
  return scan1_exp(env, exp_if->else_exp);
248
}
249
250
142
ANN static inline m_bool scan1_exp_unary(const restrict Env env, const Exp_Unary *unary) {
251

142
  if((unary->op == insert_symbol("spork") || unary->op == insert_symbol("fork")) && unary->code)
252
25
    { RET_NSPC(scan1_stmt(env, unary->code)) }
253
117
  else if(opiscall(unary->op)) {
254
1
    return exp2call(env, exp_self(unary), unary->op, unary->exp);
255
  }
256
116
  return unary->exp ? scan1_exp(env, unary->exp) : GW_OK;
257
}
258
259
#define scan1_exp_lambda dummy_func
260

27962
HANDLE_EXP_FUNC(scan1, m_bool, Env)
261
262
11
ANN static inline m_bool _scan1_stmt_match_case(const restrict Env env, const Stmt_Match stmt) {
263
11
  CHECK_BB(scan1_exp(env, stmt->cond))
264
11
  if(stmt->when)
265
4
    CHECK_BB(scan1_exp(env, stmt->when))
266
11
  return scan1_stmt_list(env, stmt->list);
267
}
268
269
11
ANN static inline m_bool scan1_stmt_match_case(const restrict Env env, const Stmt_Match stmt) {
270
11
  RET_NSPC(_scan1_stmt_match_case(env, stmt))
271
}
272
273
7
ANN static inline m_bool _scan1_stmt_match(const restrict Env env, const Stmt_Match stmt) {
274
7
  if(stmt->where)
275
2
    CHECK_BB(scan1_stmt(env, stmt->where))
276
7
  Stmt_List list = stmt->list;
277
11
  do CHECK_BB(scan1_stmt_match_case(env, &list->stmt->d.stmt_match))
278
11
  while((list = list->next));
279
7
  return GW_OK;
280
}
281
282
7
ANN static inline m_bool scan1_stmt_match(const restrict Env env, const Stmt_Match stmt) {
283
7
  CHECK_BB(scan1_exp(env, stmt->cond))
284
7
  RET_NSPC(_scan1_stmt_match(env, stmt))
285
}
286
287
#define describe_ret_nspc(name, type, prolog, exp) describe_stmt_func(scan1, name, type, prolog, exp)
288

26
describe_ret_nspc(flow, Stmt_Flow,, !(scan1_exp(env, stmt->cond) < 0 ||
289
    scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
290

10
describe_ret_nspc(varloop, Stmt_VarLoop,, !(scan1_exp(env, stmt->exp) < 0 ||
291
    scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
292


11
describe_ret_nspc(for, Stmt_For,, !(scan1_stmt(env, stmt->c1) < 0 ||
293
    scan1_stmt(env, stmt->c2) < 0 ||
294
    (stmt->c3 && scan1_exp(env, stmt->c3) < 0) ||
295
    scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
296

12
describe_ret_nspc(each, Stmt_Each,, !(scan1_exp(env, stmt->exp) < 0 ||
297
    scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
298

8
describe_ret_nspc(loop, Stmt_Loop,, !(scan1_exp(env, stmt->cond) < 0 ||
299
    scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
300


39
describe_ret_nspc(if, Stmt_If,, !(scan1_exp(env, stmt->cond) < 0 ||
301
    scan1_stmt(env, stmt->if_body) < 0 ||
302
    (stmt->else_body && scan1_stmt(env, stmt->else_body) < 0)) ? 1 : -1)
303
304
157
ANN static inline m_bool scan1_stmt_code(const Env env, const Stmt_Code stmt) {
305
157
  if(stmt->stmt_list)
306
153
    { RET_NSPC(scan1_stmt_list(env, stmt->stmt_list)) }
307
4
  return GW_OK;
308
}
309
310
2535
ANN static inline m_bool scan1_stmt_exp(const Env env, const Stmt_Exp stmt) {
311
2535
  return stmt->val ? scan1_exp(env, stmt->val) : 1;
312
}
313
314
723
ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) {
315
723
  ID_List list = edef->list;
316
  do {
317
1480
    CHECK_BB(already_defined(env, list->xid, edef->pos))
318
1480
    const Value v = new_value(env->gwion->mp, edef->t, s_name(list->xid));
319
1480
    valuefrom(env, v->from);
320
1480
    if(env->class_def) {
321
28
      SET_FLAG(v, static);
322

28
      SET_ACCESS(edef, v)
323

28
      SET_ACCESS(edef, edef->t)
324
    }
325
1480
    SET_FLAG(v, const | ae_flag_enum | ae_flag_valid);
326
1480
    nspc_add_value(edef->t->e->owner, list->xid, v);
327
1480
    vector_add(&edef->values, (vtype)v);
328
1480
  } while((list = list->next));
329
723
  return GW_OK;
330
}
331
332
23781
ANN static Value arg_value(const Env env, const Arg_List list) {
333
23781
  const Var_Decl var = list->var_decl;
334
23781
  const Value v = new_value(env->gwion->mp, list->type, var->xid ? s_name(var->xid) : (m_str)__func__);
335
23781
  if(var->array)
336
8
    v->type = list->type = array_type(env, list->type, var->array->depth);
337
23781
  if(list->td)
338
23776
    v->flag = list->td->flag | ae_flag_abstract;
339
23781
  return v;
340
}
341
342
23788
ANN static m_bool scan1_args(const Env env, Arg_List list) {
343
  do {
344
23788
    const Var_Decl var = list->var_decl;
345
23788
    if(var->xid)
346
23782
      CHECK_BB(isres(env, var->xid, var->pos))
347
23787
    if(list->td)
348
23782
      CHECK_OB((list->type = void_type(env, list->td)))
349
23781
    var->value = arg_value(env, list);
350
23781
    nspc_add_value(env->curr, var->xid, var->value);
351
23781
  } while((list = list->next));
352
16578
  return GW_OK;
353
}
354
355
139
ANN static m_bool _scan1_fdef_base_tmpl(const Env env, Func_Base *base) {
356
139
  ID_List id = base->tmpl->list;
357
149
  do nspc_add_type(env->curr, id->xid, env->gwion->type[et_undefined]);
358
149
  while((id = id->next));
359
139
  CHECK_OB((base->ret_type = known_type(env, base->td)))
360
138
  if(base->args) {
361
92
    Arg_List arg = base->args;
362
136
    do CHECK_OB(known_type(env, arg->td))
363
135
    while((arg = arg->next));
364
  }
365
137
  return GW_OK;
366
}
367
368
139
ANN static m_bool scan1_fdef_base_tmpl(const Env env, Func_Base *base) {
369
139
  nspc_push_type(env->gwion->mp, env->curr);
370
139
  const m_bool ret = _scan1_fdef_base_tmpl(env, base);
371
139
  nspc_pop_type(env->gwion->mp, env->curr);
372
139
  return ret;
373
}
374
375
80
ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) {
376
80
  if(tmpl_base(fptr->base->tmpl))
377
16
    return scan1_fdef_base_tmpl(env, fptr->base);
378
64
  if(!fptr->base->func) {
379
    fptr->base->func = nspc_lookup_value0(env->curr, fptr->base->xid)->d.func_ref;
380
    fptr->type = nspc_lookup_type0(env->curr, fptr->base->xid);
381
  }
382
64
  const Func_Def fdef = fptr->base->func->def;
383
64
  CHECK_OB((fdef->base->ret_type = scan1_type(env, fdef->base->td)))
384
62
  if(!fdef->base->args)
385
34
    return GW_OK;
386
28
  RET_NSPC(scan1_args(env, fdef->base->args))
387
}
388
389
733
ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) {
390
733
  if(!tdef->type)
391
    tdef->type = nspc_lookup_type0(env->curr, tdef->xid);
392
733
  if(!tdef->type->e->def)return GW_OK;
393
8
  return !is_fptr(env->gwion, tdef->type) ? scan1_cdef(env, tdef->type->e->def) : GW_OK;
394
}
395
396
37
ANN static m_bool scan1_union_def_action(const Env env, const Union_Def udef,
397
    const Decl_List l) {
398
37
  const Exp_Decl decl = l->self->d.exp_decl;
399
37
  SET_FLAG(decl.td, valid | udef->flag);
400
37
  const m_bool global = GET_FLAG(udef, global);
401
37
  if(global)
402
6
    UNSET_FLAG(decl.td, global);
403
37
  if(GET_FLAG(udef, member))
404
3
    SET_FLAG(decl.td, member);
405
34
  else if(GET_FLAG(udef, static))
406
4
    SET_FLAG(decl.td, static);
407
37
  CHECK_BB(scan1_exp(env, l->self))
408
409
35
  Var_Decl_List list = decl.list;
410
35
  do ADD_REF(list->self->value)
411
35
  while((list = list->next));
412
413
35
  if(global)
414
6
    SET_FLAG(decl.td, global);
415
35
  return GW_OK;
416
}
417
418
37
ANN static inline m_bool scan1_union_def_inner_loop(const Env env, const Union_Def udef, Decl_List l) {
419
37
  do CHECK_BB(scan1_union_def_action(env, udef, l))
420
35
  while((l = l->next));
421
18
  return GW_OK;
422
}
423
424
20
ANN static m_bool scan1_union_def_inner(const Env env, const Union_Def udef) {
425

20
  if(udef->tmpl && udef->tmpl->call)
426
3
    CHECK_BB(template_push_types(env, udef->tmpl))
427
20
  const m_bool ret = scan1_union_def_inner_loop(env, udef, udef->l);
428

20
  if(udef->tmpl && udef->tmpl->call)
429
3
    nspc_pop_type(env->gwion->mp, env->curr);
430
20
  return ret;
431
}
432
433
24
ANN m_bool scan1_union_def(const Env env, const Union_Def udef) {
434
24
  if(tmpl_base(udef->tmpl))
435
4
    return GW_OK;
436
20
  const m_uint scope = union_push(env, udef);
437

20
  if(udef->xid || udef->type_xid) {
438
12
    UNSET_FLAG(udef, private);
439
12
    UNSET_FLAG(udef, protect);
440
  }
441
20
  const m_bool ret = scan1_union_def_inner(env, udef);
442
20
  union_pop(env, udef, scope);
443
20
  union_flag(udef, ae_flag_scan1);
444
20
  return ret;
445
}
446
447
#define scan1_stmt_while    scan1_stmt_flow
448
#define scan1_stmt_until    scan1_stmt_flow
449
#define scan1_stmt_continue (void*)dummy_func
450
#define scan1_stmt_break    (void*)dummy_func
451
#define scan1_stmt_jump     (void*)dummy_func
452
#define scan1_stmt_return   scan1_stmt_exp
453
454
4
ANN static m_bool scan1_stmt_pp(const Env env, const Stmt_PP stmt) {
455
4
  if(stmt->pp_type == ae_pp_include)
456
3
    env->name = stmt->data;
457
4
  return GW_OK;
458
}
459
460
DECL_STMT_FUNC(scan1, m_bool, Env)
461
462
2843
ANN static inline m_bool scan1_stmt(const Env env, const Stmt stmt) {
463
2843
  return scan1_stmt_func[stmt->stmt_type](env, &stmt->d);
464
}
465
466
2676
ANN static m_bool scan1_stmt_list(const Env env, Stmt_List l) {
467
  do {
468
2676
    CHECK_BB(scan1_stmt(env, l->stmt))
469
2643
    if(l->next) {
470
1537
      if(l->stmt->stmt_type != ae_stmt_return) {
471

2887
        if(l->next->stmt->stmt_type == ae_stmt_exp &&
472
1351
          !l->next->stmt->d.stmt_exp.val) {
473
4
           Stmt_List next = l->next;
474
4
           l->next = l->next->next;
475
4
           next->next = NULL;
476
4
           free_stmt_list(env->gwion->mp, next);
477
        }
478
      } else {
479
1
        Stmt_List tmp = l->next;
480
1
        l->next = NULL;
481
1
        free_stmt_list(env->gwion->mp, tmp);
482
      }
483
    }
484
2643
  } while((l = l->next));
485
1111
  return GW_OK;
486
}
487
488
11
ANN static m_bool class_internal(const Env env, const Func_Base *base) {
489
11
  if(!env->class_def)
490
1
    ERR_B(td_pos(base->td), _("'%s' must be in class def!!"), s_name(base->xid))
491
10
  if(base->args)
492
1
    ERR_B(td_pos(base->td), _("'%s' must not have args"), s_name(base->xid))
493
9
  if(base->ret_type != env->gwion->type[et_void])
494
1
    ERR_B(td_pos(base->td), _("'%s' must return 'void'"), s_name(base->xid))
495
8
  return GW_OK;
496
}
497
498
6
ANN static inline m_bool scan_internal_arg(const Env env, const Func_Base *base) {
499

6
  if(base->args && !base->args->next)
500
5
    return GW_OK;
501
1
  ERR_B(td_pos(base->td), _("'%s' must have one (and only one) argument"), s_name(base->xid))
502
}
503
504
3
ANN static inline m_bool scan_internal_int(const Env env, const Func_Base *base) {
505
3
    CHECK_BB(scan_internal_arg(env, base))
506
3
    if(isa(base->ret_type, env->gwion->type[et_int]) > 0)
507
2
      return GW_OK;
508
1
    ERR_B(td_pos(base->td), _("'%s' must return 'int'"), s_name(base->xid))
509
}
510
511
22
ANN static m_bool scan_internal(const Env env, const Func_Base *base) {
512
22
  const Symbol op = base->xid;
513

22
  if(op == insert_symbol("@dtor") || op == insert_symbol("@gack"))
514
11
    return class_internal(env, base);
515
11
  if(op == insert_symbol("@implicit"))
516
3
    return scan_internal_arg(env, base);
517

14
  if(op == insert_symbol("@conditionnal") ||
518
6
     op == insert_symbol("@unconditionnal"))
519
3
    return scan_internal_int(env, base);
520
5
  return GW_OK;
521
}
522
523
232
ANN static m_bool scan1_fdef_args(const Env env, Arg_List list) {
524
  do {
525
232
    Nspc nspc = env->curr;
526
1033
    do if(nspc_lookup_value0(nspc, list->var_decl->xid))
527
       ERR_B(list->var_decl->pos, _("argument '%s' shadows a previuosly defined variable"),
528
            s_name(list->var_decl->xid))
529
1033
    while((nspc = nspc->parent));
530
232
  } while((list = list->next));
531
173
  return GW_OK;
532
}
533
534
42339
ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) {
535
42339
  if(fdef->base->args) {
536
16557
    if(!GET_FLAG(fdef->base, builtin))
537
173
      CHECK_BB(scan1_fdef_args(env, fdef->base->args))
538
16557
    CHECK_BB(scan1_args(env, fdef->base->args))
539
  }
540

42334
  if(!GET_FLAG(fdef->base, builtin) && fdef->d.code && fdef->d.code->d.stmt_code.stmt_list)
541
248
    CHECK_BB(scan1_stmt_list(env, fdef->d.code->d.stmt_code.stmt_list))
542
42333
  return GW_OK;
543
}
544
545
42345
ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) {
546
42345
  if(fdef->base->td)
547
42337
    CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td)))
548
42344
  if(GET_FLAG(fdef->base, typedef))
549
22
    CHECK_BB(scan_internal(env, fdef->base))
550

42322
  else if(GET_FLAG(fdef->base, op) && env->class_def)
551
2
    SET_FLAG(fdef->base, static);
552
42339
  RET_NSPC(scan1_fbody(env, fdef))
553
  return GW_OK;
554
}
555
556
42472
ANN static inline m_bool scan1_fdef_defined(const Env env, const Func_Def fdef) {
557
42472
  const Value v = nspc_lookup_value1(env->curr, fdef->base->xid);
558
42472
  if(!v)
559
33836
    return GW_OK;
560
8636
  if(isa(actual_type(env->gwion, v->type), env->gwion->type[et_function]) > 0)
561
8635
    return GW_OK;
562
1
  ERR_B(fdef->pos, _("function '%s' has already been defined in the same scope..."),
563
       s_name(fdef->base->xid))
564
}
565
566
42475
ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
567
42475
  if(fdef->base->td)
568
42467
    CHECK_BB(env_storage(env, fdef->base->flag, td_pos(fdef->base->td)))
569
42472
  CHECK_BB(scan1_fdef_defined(env, fdef))
570
42471
  if(tmpl_base(fdef->base->tmpl))
571
123
    return scan1_fdef_base_tmpl(env, fdef->base);
572
42348
  struct Func_ fake = { .name=s_name(fdef->base->xid) }, *const former = env->func;
573
42348
  env->func = &fake;
574
42348
  ++env->scope->depth;
575
42348
  const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)scan1_fdef);
576
42348
  --env->scope->depth;
577
42348
  env->func = former;
578
42348
  return ret;
579
}
580
581
1385
HANDLE_SECTION_FUNC(scan1, m_bool, Env)
582
583
70
ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) {
584
70
  const Type parent = known_type(env, tdef->ext);
585
70
  CHECK_OO((tdef->type->e->parent = parent));
586
70
  Type t = parent;
587
245
  do if(tdef->type == t)
588
      ERR_O(td_pos(tdef->ext), _("recursive (%s <= %s) class declaration."), tdef->type->name, t->name)
589
245
  while((t = t->e->parent));
590
70
  return parent;
591
}
592
593
70
ANN static m_bool scan1_parent(const Env env, const Class_Def cdef) {
594
70
  const loc_t pos = td_pos(cdef->base.ext);
595
70
  if(cdef->base.ext->array)
596
9
    CHECK_BB(scan1_exp(env, cdef->base.ext->array->exp))
597
70
  DECL_OB(const Type , parent, = scan1_get_parent(env, &cdef->base))
598
70
  if(isa(parent, env->gwion->type[et_object]) < 0)
599
1
    ERR_B(pos, _("cannot extend primitive type '%s'"), parent->name)
600

69
  if(parent->e->def && !GET_FLAG(parent, scan1))
601
6
    CHECK_BB(ensure_scan1(env, parent))
602
69
  if(type_ref(parent))
603
1
    ERR_B(pos, _("can't use ref type in class extend"))
604
68
  if(GET_FLAG(parent, nonnull))
605
1
    ERR_B(pos, _("can't use nonnull type in class extend"))
606
67
  return GW_OK;
607
}
608
609
70
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
610

70
  if(cdef->base.tmpl && cdef->base.tmpl->list)
611
22
    CHECK_BB(template_push_types(env, cdef->base.tmpl))
612
70
  const m_bool ret = scan1_parent(env, cdef);
613

70
  if(cdef->base.tmpl && cdef->base.tmpl->list)
614
22
    nspc_pop_type(env->gwion->mp, env->curr);
615
70
  return ret;
616
}
617
618
291
ANN m_bool scan1_class_def(const Env env, const Class_Def cdef) {
619
291
  if(tmpl_base(cdef->base.tmpl))
620
22
    return GW_OK;
621
269
  const Type t = cdef->base.type;
622
269
  if(GET_FLAG(t, scan1))
623
2
    return GW_OK;
624
267
  SET_FLAG(t, scan1);
625

267
  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, scan1))
626
    CHECK_BB(ensure_scan1(env, t->e->owner_class))
627
267
  SET_FLAG(cdef->base.type, scan1);
628
267
  if(cdef->base.ext)
629
70
    CHECK_BB(cdef_parent(env, cdef))
630
264
  if(cdef->body)
631
217
    CHECK_BB(env_body(env, cdef, scan1_section))
632
258
  return GW_OK;
633
}
634
635
1013
ANN m_bool scan1_ast(const Env env, Ast ast) {
636
1013
  do CHECK_BB(scan1_section(env, ast->section))
637
962
  while((ast = ast->next));
638
558
  return GW_OK;
639
}