GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/scan0.c Lines: 311 318 97.8 %
Date: 2020-10-03 11:54:50 Branches: 159 192 82.8 %

Line Branch Exec Source
1
#include <string.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 "parser.h"
9
#include "parse.h"
10
#include "object.h"
11
#include "instr.h"
12
#include "operator.h"
13
#include "import.h"
14
15
1861
static inline void add_type(const Env env, const Nspc nspc, const Type t) {
16
1861
  nspc_add_type_front(nspc, insert_symbol(t->name), t);
17
1861
}
18
19
11
static inline void context_global(const Env env) {
20
11
  if(env->context)
21
11
    env->context->global = 1;
22
11
}
23
24
1104
static inline Type scan0_type(const Env env, const m_uint xid,
25
    const m_str name, const Type t) {
26
1104
  const Type type = new_type(env->gwion->mp, xid, name, t);
27
1104
  type->e->ctx = env->context;
28
1104
  return type;
29
}
30
31
1878
ANN static inline m_bool scan0_defined(const Env env, const Symbol s, const loc_t pos) {
32
1878
  if(nspc_lookup_type1(env->curr, s))
33
3
    ERR_B(pos, _("type '%s' already defined"), s_name(s));
34
1875
  return already_defined(env, s, pos);
35
}
36
37
41
ANN static void fptr_assign(const Env env, const Fptr_Def fptr) {
38
41
  const Func_Def def = fptr->type->e->d.func->def;
39
41
  if(GET_FLAG(fptr->base, global)) {
40
2
    context_global(env);
41
2
    SET_FLAG(fptr->value, global);
42
2
    SET_FLAG(fptr->base->func, global);
43
2
    SET_FLAG(def->base, global);
44
39
  } else if(!GET_FLAG(fptr->base, static)) {
45
29
    SET_FLAG(fptr->value, member);
46
29
    SET_FLAG(fptr->base->func, member);
47
29
    SET_FLAG(def->base, member);
48
29
    def->stack_depth += SZ_INT;
49
  } else {
50
10
    SET_FLAG(fptr->value, static);
51
10
    SET_FLAG(fptr->base->func, static);
52
10
    SET_FLAG(def->base, static);
53
  }
54
41
  if(GET_FLAG(def->base, variadic))
55
1
    def->stack_depth += SZ_INT;
56
41
  fptr->value->from->owner_class = env->class_def;
57
41
}
58
59
82
static void fptr_def(const Env env, const Fptr_Def fptr) {
60
246
  const Func_Def def = new_func_def(env->gwion->mp,
61
82
      cpy_func_base(env->gwion->mp, fptr->base),
62
164
    NULL, loc_cpy(env->gwion->mp, td_pos(fptr->base->td)));
63
82
  fptr->base->func = new_func(env->gwion->mp, s_name(fptr->base->xid), def);
64
82
  fptr->value->d.func_ref = fptr->base->func;
65
82
  fptr->base->func->value_ref = fptr->value;
66
82
  fptr->type->e->d.func = fptr->base->func;
67
82
  def->base->func = fptr->base->func;
68
82
}
69
70
86
ANN m_bool scan0_fptr_def(const Env env, const Fptr_Def fptr) {
71
86
  CHECK_BB(env_access(env, fptr->base->flag, td_pos(fptr->base->td)))
72
83
  CHECK_BB(scan0_defined(env, fptr->base->xid, td_pos(fptr->base->td)));
73
82
  const m_str name = s_name(fptr->base->xid);
74
82
  const Type t = scan0_type(env, env->gwion->type[et_fptr]->xid, name, env->gwion->type[et_fptr]);
75
205
  t->e->owner = !(!env->class_def && GET_FLAG(fptr->base, global)) ?
76
164
    env->curr : env->global_nspc;
77
82
  t->e->owner_class = env->class_def;
78
82
  if(GET_FLAG(fptr->base, global))
79
2
    context_global(env);
80
82
  t->nspc = new_nspc(env->gwion->mp, name);
81
82
  t->flag = fptr->base->flag;
82
82
  fptr->type = t;
83
82
  fptr->value = mk_class(env, t);
84
82
  valuefrom(env, fptr->value->from);
85
82
  fptr_def(env, fptr);
86
82
  if(env->class_def)
87
41
    fptr_assign(env, fptr);
88
82
  SET_FLAG(fptr->value, func);
89
82
  add_type(env, t->e->owner, t);
90
82
  mk_class(env, t);
91
82
  ADD_REF(t);
92
82
  return GW_OK;
93
}
94
95
1
static OP_CHECK(opck_implicit_similar) {
96
1
  const struct Implicit *imp = (struct Implicit*)data;
97
1
  return imp->e->info->type;
98
}
99
100
2
static OP_CHECK(opck_cast_similar) {
101
2
  const Exp_Cast *cast = (Exp_Cast*)data;
102
2
  return exp_self(cast)->info->type;
103
}
104
105
1448
ANN static void scan0_implicit_similar(const Env env, const Type lhs, const Type rhs) {
106
1448
  struct Op_Func opfunc = { .ck=opck_cast_similar };
107
1448
  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .func=&opfunc };
108
1448
  add_op(env->gwion, &opi);
109
1448
  opi.lhs=rhs;
110
1448
  opi.rhs=lhs;
111
1448
  add_op(env->gwion, &opi);
112
1448
  opfunc.ck = opck_implicit_similar;
113
1448
  opi.op=insert_symbol("@implicit");
114
1448
  add_op(env->gwion, &opi);
115
1448
}
116
117
722
ANN static void typedef_simple(const Env env, const Type_Def tdef, const Type base) {
118
722
  const Type t = scan0_type(env, ++env->scope->type_xid, s_name(tdef->xid), base);
119
722
  t->size = base->size;
120
2164
  const Nspc nspc = (!env->class_def && GET_FLAG(tdef->ext, global)) ?
121
722
  env->global_nspc : env->curr;
122
722
  if(GET_FLAG(tdef->ext, global))
123
    context_global(env);
124
722
  add_type(env, nspc, t);
125
722
  t->e->owner = nspc;
126
722
  t->e->owner_class = env->class_def;
127
722
  tdef->type = t;
128
722
  if(base->nspc)
129
3
    ADD_REF((t->nspc = base->nspc));
130
722
  t->flag = tdef->ext->flag | ae_flag_valid;
131
722
  scan0_implicit_similar(env, t, base);
132

722
  if(tdef->ext->array && !tdef->ext->array->exp)
133
3
    SET_FLAG(t, empty);
134
722
}
135
136
9
ANN static m_bool typedef_complex(const Env env, const Type_Def tdef, const Type base) {
137
9
  const ae_flag flag = base->e->def ? base->e->def->flag : 0;
138
27
  const Class_Def cdef = new_class_def(env->gwion->mp, flag, tdef->xid,
139
9
       cpy_type_decl(env->gwion->mp, tdef->ext), NULL,
140
18
       loc_cpy(env->gwion->mp, td_pos(tdef->ext)));
141
9
  CHECK_BB(scan0_class_def(env, cdef))
142
8
  tdef->type = cdef->base.type;
143
8
  cdef->base.tmpl = tdef->tmpl;// check cpy
144
8
  return GW_OK;
145
}
146
147
5
ANN static void typedef_fptr(const Env env, const Type_Def tdef, const Type base) {
148
5
  tdef->type = type_copy(env->gwion->mp, base);
149
5
  ADD_REF(tdef->type->nspc)
150
5
  tdef->type->name = s_name(tdef->xid);
151
5
  tdef->type->e->parent = base;
152
5
  add_type(env, env->curr, tdef->type);
153
5
  mk_class(env, tdef->type);
154
5
  if(base->e->d.func->def->base->tmpl)
155
3
    SET_FLAG(tdef->type, func);
156
5
}
157
158
736
ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) {
159
736
  CHECK_BB(env_access(env, tdef->ext->flag, td_pos(tdef->ext)))
160

736
  DECL_OB(const Type, base, = tdef->tmpl ? find_type(env, tdef->ext) : known_type(env, tdef->ext))
161
736
  CHECK_BB(scan0_defined(env, tdef->xid, td_pos(tdef->ext)))
162
736
  if(isa(base, env->gwion->type[et_function]) < 0) {
163

731
    if(!tdef->ext->types && (!tdef->ext->array || !tdef->ext->array->exp))
164
722
      typedef_simple(env, tdef, base);
165
    else
166
9
      CHECK_BB(typedef_complex(env, tdef, base))
167
  } else
168
5
    typedef_fptr(env, tdef, base);
169
735
  SET_FLAG(tdef->type, typedef);
170
735
  return GW_OK;
171
}
172
173
742
ANN static Symbol scan0_sym(const Env env, const m_str name, const loc_t pos) {
174
742
  const size_t line_len = num_digit(pos->first.line);
175
742
  const size_t col_len = num_digit(pos->first.column);
176
742
  char c[strlen(env->curr->name) + strlen(env->name) + line_len + col_len + strlen(name) + 6];
177
742
  sprintf(c, "@%s:%s:%s:%u:%u", name, env->name, env->curr->name,
178
      pos->first.line, pos->first.column);
179
742
  return insert_symbol(c);
180
}
181
182
#define scan0_nspc(env, a) \
183
  GET_FLAG(a, global) ? !env->class_def ? env->global_nspc : NULL : env->curr
184
185
726
ANN static Type enum_type(const Env env, const Enum_Def edef) {
186
726
  const Type t = type_copy(env->gwion->mp, env->gwion->type[et_int]);
187
726
  t->xid = ++env->scope->type_xid;
188
726
  const Symbol sym = scan0_sym(env, "enum", edef->pos);
189
726
  t->name = edef->xid ? s_name(edef->xid) : s_name(sym);
190
726
  t->e->parent = env->gwion->type[et_int];
191
726
  const Nspc nspc = GET_FLAG(edef, global) ? env->global_nspc : env->curr;
192
726
  t->e->owner = nspc;
193
726
  t->e->owner_class = env->class_def;
194
726
  add_type(env, nspc, t);
195
726
  mk_class(env, t);
196
726
  scan0_implicit_similar(env, t, env->gwion->type[et_int]);
197
726
  return t;
198
}
199
200
1058
ANN static inline m_bool scan0_global(const Env env, const ae_flag flag, const loc_t pos) {
201

1058
  if(!env->class_def || !((flag & ae_flag_global) == ae_flag_global))
202
1058
    return GW_OK;
203
  ERR_B(pos, _("can't declare as global in class def"))
204
}
205
206
727
ANN m_bool scan0_enum_def(const Env env, const Enum_Def edef) {
207
727
  CHECK_BB(env_storage(env, edef->flag, edef->pos))
208
727
  CHECK_BB(scan0_defined(env, edef->xid, edef->pos))
209
726
  CHECK_BB(scan0_global(env, edef->flag, edef->pos))
210
726
  edef->t = enum_type(env, edef);
211
726
  if(GET_FLAG(edef, global))
212
    context_global(env);
213
726
  return GW_OK;
214
}
215
216
26
ANN static Type union_type(const Env env, const Symbol s, const m_bool add) {
217
26
  const m_str name = s_name(s);
218
26
  const Type t = type_copy(env->gwion->mp, env->gwion->type[et_union]);
219
26
  t->xid = ++env->scope->type_xid;
220
26
  t->name = name;
221
26
  t->nspc = new_nspc(env->gwion->mp, name);
222
26
  t->e->owner = t->nspc->parent = env->curr;
223
26
  t->e->owner_class = env->class_def;
224
26
  t->e->parent = env->gwion->type[et_union];
225
26
  t->e->tuple = new_tupleform(env->gwion->mp, NULL);
226
26
  add_type(env, env->curr, t);
227
26
  if(add)
228
18
    mk_class(env, t);
229
26
  SET_FLAG(t, union);
230
26
  return t;
231
}
232
233
5
ANN static void union_tmpl(const Env env, const Union_Def udef) {
234
5
  if(tmpl_base(udef->tmpl)) {
235
    assert(udef->type_xid);
236
15
    const Class_Def cdef = new_class_def(env->gwion->mp, udef->flag, udef->type_xid,
237
10
        NULL, (Ast)cpy_decl_list(env->gwion->mp, udef->l), loc_cpy(env->gwion->mp, udef->pos));
238
5
    udef->type->e->def = cdef;
239
5
    cdef->base.tmpl = cpy_tmpl(env->gwion->mp, udef->tmpl);
240
5
    cdef->base.type = udef->type;
241
5
    SET_FLAG(cdef, union);
242
5
    SET_FLAG(udef->type, pure);
243
5
    SET_FLAG(udef, template);
244
5
    SET_FLAG(udef->type, template);
245
  }
246
5
  if(GET_FLAG(udef, global))
247
    SET_FLAG(udef->type, global);
248
5
  SET_FLAG(udef->type, union);
249
5
}
250
251
16
ANN static Value union_value(const Env env, const Type t, const Symbol sym) {
252
16
  const Value v = new_value(env->gwion->mp, t, s_name(sym));
253
16
  valuefrom(env, v->from);
254
16
  nspc_add_value(env->curr, sym, v);
255
16
  SET_FLAG(v, valid | ae_flag_pure);
256
16
  return v;
257
}
258
259
32
ANN m_bool scan0_union_def(const Env env, const Union_Def udef) {
260
32
  CHECK_BB(env_storage(env, udef->flag, udef->pos))
261
26
  CHECK_BB(scan0_global(env, udef->flag, udef->pos))
262
26
  const m_uint scope = !GET_FLAG(udef, global) ? env->scope->depth :
263
      env_push_global(env);
264
26
  if(GET_FLAG(udef, global))
265
3
    context_global(env);
266
26
  if(udef->xid) {
267
8
    CHECK_BB(scan0_defined(env, udef->xid, udef->pos))
268
8
    const Symbol sym = udef->type_xid ?: scan0_sym(env, "union", udef->pos);
269
8
    const Type t = union_type(env, sym, !!udef->type_xid);
270
8
    udef->value = union_value(env, t, udef->xid);
271
8
    udef->value->flag |= udef->flag;
272

8
    SET_ACCESS(udef, t);
273

8
    if(env->class_def && !GET_FLAG(udef, static)) {
274
3
      SET_FLAG(udef->value, member);
275
3
      SET_FLAG(udef, member);
276
    }
277
18
  } else if(udef->type_xid) {
278
10
    CHECK_BB(scan0_defined(env, udef->type_xid, udef->pos))
279
10
    udef->type = union_type(env, udef->type_xid, 1);
280

10
    SET_ACCESS(udef, udef->type);
281
10
    SET_FLAG(udef->type, valid);
282
  } else {
283
8
    const Symbol sym = scan0_sym(env, "union", udef->pos);
284
8
    CHECK_BB(scan0_defined(env, sym, udef->pos))
285
8
    const Type t = union_type(env, sym, 1);
286

8
    SET_ACCESS(udef, t);
287
8
    udef->value = union_value(env, t, sym);
288
8
    udef->value->flag |= udef->flag;
289
  }
290
26
  if(udef->tmpl)
291
5
    union_tmpl(env, udef);
292
26
  if(GET_FLAG(udef, global))
293
3
    env_pop(env, scope);
294
26
  union_flag(udef, ae_flag_scan0);
295
26
  return GW_OK;
296
}
297
298
306
ANN static m_bool scan0_class_def_pre(const Env env, const Class_Def cdef) {
299
306
  CHECK_BB(env_storage(env, cdef->flag, cdef->pos))
300
306
  CHECK_BB(isres(env, cdef->base.xid, cdef->pos))
301
306
  CHECK_BB(scan0_global(env, cdef->flag, cdef->pos))
302
306
  return GW_OK;
303
}
304
305
300
ANN static void cdef_flag(const Class_Def cdef, const Type t) {
306
300
  if(cdef->base.tmpl) {
307
63
    SET_FLAG(t, template);
308
63
    SET_FLAG(cdef, template);
309
  }
310

300
  if(cdef->base.ext && cdef->base.ext->array)
311
9
    SET_FLAG(t, typedef);
312
300
}
313
314
8
ANN static Type get_parent_base(const Env env, Type_Decl *td) {
315
8
  DECL_OO(const Type, t, = find_type(env, td))
316
8
  Type owner = env->class_def;
317
16
  while(owner) {
318
    if(t == owner)
319
      ERR_O(td_pos(td), _("'%s' as parent inside itself\n."), owner->name);
320
    owner = owner->e->owner_class;
321
  }
322
8
  return t;
323
}
324
325
305
ANN static Type get_parent(const Env env, const Class_Def cdef) {
326
305
  if(GET_FLAG(cdef, struct))
327
11
    return env->gwion->type[et_compound];
328
294
  if(!cdef->base.ext)
329
210
    return env->gwion->type[et_object];
330
84
  if(tmpl_base(cdef->base.tmpl))
331
8
    return get_parent_base(env, cdef->base.ext);
332
76
  if(cdef->base.tmpl)
333
22
    template_push_types(env, cdef->base.tmpl);
334
76
  const Type t = known_type(env, cdef->base.ext);
335
76
  if(cdef->base.tmpl)
336
22
    nspc_pop_type(env->gwion->mp, env->curr);
337
76
  return t ?: (Type)GW_ERROR;
338
}
339
340
306
ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
341
306
  CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos))
342
305
  const Type parent = get_parent(env, cdef);
343
305
  if(parent == (Type)GW_ERROR)
344
5
    return NULL;
345
300
  const Type t = scan0_type(env, ++env->scope->type_xid, s_name(cdef->base.xid), parent);
346
300
  if(GET_FLAG(cdef, struct))
347
11
    SET_FLAG(t, struct);
348
300
  t->e->tuple = new_tupleform(env->gwion->mp, parent);
349
300
  t->e->owner = env->curr;
350
300
  t->e->owner_class = env->class_def;
351
300
  t->nspc = new_nspc(env->gwion->mp, t->name);
352
300
  t->nspc->parent = env->curr;
353
300
  t->e->def = cdef;
354
300
  t->flag = cdef->flag;
355
300
  add_type(env, t->e->owner, t);
356
300
  cdef_flag(cdef, t);
357

300
  if(cdef->base.ext && cdef->base.ext->array)
358
9
    SET_FLAG(t, typedef);
359
300
  return t;
360
}
361
362
2013
ANN static m_bool scan0_stmt_list(const Env env, Stmt_List list) {
363

2013
  do if(list->stmt->stmt_type == ae_stmt_pp && list->stmt->d.stmt_pp.pp_type == ae_pp_include)
364
3
    env->name = list->stmt->d.stmt_pp.data;
365
2013
  while((list = list->next));
366
747
  return GW_OK;
367
}
368
369
#define scan0_func_def dummy_func
370
1439
HANDLE_SECTION_FUNC(scan0, m_bool, Env)
371
372
306
ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
373
306
  CHECK_OB((cdef->base.type = scan0_class_def_init(env, cdef)))
374
300
  SET_FLAG(cdef->base.type, scan0);
375
300
  if(cdef->body)
376
235
    CHECK_BB(env_body(env, cdef, scan0_section))
377
299
  (void)mk_class(env, cdef->base.type);
378
299
  return GW_OK;
379
}
380
381
306
ANN m_bool scan0_class_def(const Env env, const Class_Def c) {
382
612
  const Class_Def cdef = !tmpl_base(c->base.tmpl) ?
383
306
    c : cpy_class_def(env->gwion->mp, c);
384
306
  if(GET_FLAG(cdef, global)) {
385
4
    vector_add(&env->scope->nspc_stack, (vtype)env->curr);
386
4
    env->curr = env->global_nspc;
387
4
    context_global(env);
388
  }
389
612
  const m_bool ret = scan0_class_def_pre(env, cdef) > 0 ?
390
306
    scan0_class_def_inner(env, cdef) : GW_ERROR;
391
306
  if(GET_FLAG(cdef, global))
392
4
    env->curr = (Nspc)vector_pop(&env->scope->nspc_stack);
393
306
  CHECK_BB(ret)
394

299
  if(GET_FLAG(cdef, global) || (cdef->base.tmpl && !cdef->base.tmpl->call))
395
30
    c->base.type = cdef->base.type;
396
299
  SET_FLAG(cdef->base.type, scan0);
397
299
  return GW_OK;
398
}
399
400
1035
ANN m_bool scan0_ast(const Env env, Ast ast) {
401
1035
  do CHECK_BB(scan0_section(env, ast->section))
402
1021
  while((ast = ast->next));
403
608
  return GW_OK;
404
}