GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/scan0.c Lines: 317 324 97.8 %
Date: 2020-09-14 00:22:58 Branches: 158 196 80.6 %

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
1851
static inline void add_type(const Env env, const Nspc nspc, const Type t) {
16
1851
  nspc_add_type_front(nspc, insert_symbol(t->name), t);
17
1851
}
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
1096
static inline Type scan0_type(const Env env, const m_uint xid,
25
    const m_str name, const Type t) {
26
1096
  const Type type = new_type(env->gwion->mp, xid, name, t);
27
1096
  type->e->ctx = env->context;
28
1096
  return type;
29
}
30
31
1866
ANN static inline m_bool scan0_defined(const Env env, const Symbol s, const loc_t pos) {
32
1866
  if(nspc_lookup_type1(env->curr, s))
33
3
    ERR_B(pos, _("type '%s' already defined"), s_name(s));
34
1863
  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->td, 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, global);
44
39
  } else if(!GET_FLAG(fptr->base->td, static)) {
45
29
    SET_FLAG(fptr->value, member);
46
29
    SET_FLAG(fptr->base->func, member);
47
29
    SET_FLAG(def, 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, static);
53
  }
54
41
  if(GET_FLAG(def, variadic))
55
1
    def->stack_depth += SZ_INT;
56
41
  fptr->value->from->owner_class = env->class_def;
57
41
}
58
59
78
static void fptr_def(const Env env, const Fptr_Def fptr) {
60
312
  const Func_Def def = new_func_def(env->gwion->mp,
61
78
      cpy_func_base(env->gwion->mp, fptr->base),
62
234
    NULL, fptr->base->td->flag, loc_cpy(env->gwion->mp, td_pos(fptr->base->td)));
63
78
  fptr->base->func = new_func(env->gwion->mp, s_name(fptr->base->xid), def);
64
78
  fptr->value->d.func_ref = fptr->base->func;
65
78
  fptr->base->func->value_ref = fptr->value;
66
78
  fptr->type->e->d.func = fptr->base->func;
67
78
  def->base->func = fptr->base->func;
68
78
}
69
70
82
ANN m_bool scan0_fptr_def(const Env env, const Fptr_Def fptr) {
71
82
  CHECK_BB(env_access(env, fptr->base->td->flag, td_pos(fptr->base->td)))
72
79
  CHECK_BB(scan0_defined(env, fptr->base->xid, td_pos(fptr->base->td)));
73
78
  const m_str name = s_name(fptr->base->xid);
74
78
  const Type t = scan0_type(env, env->gwion->type[et_fptr]->xid, name, env->gwion->type[et_fptr]);
75
193
  t->e->owner = !(!env->class_def && GET_FLAG(fptr->base->td, global)) ?
76
156
    env->curr : env->global_nspc;
77
78
  t->e->owner_class = env->class_def;
78
78
  if(GET_FLAG(fptr->base->td, global))
79
2
    context_global(env);
80
78
  t->nspc = new_nspc(env->gwion->mp, name);
81
78
  t->flag = fptr->base->td->flag;
82
78
  fptr->type = t;
83
78
  fptr->value = mk_class(env, t);
84
78
  valuefrom(env, fptr->value->from);
85
78
  fptr_def(env, fptr);
86
78
  if(env->class_def)
87
41
    fptr_assign(env, fptr);
88
78
  SET_FLAG(fptr->value, func);
89
78
  add_type(env, t->e->owner, t);
90
78
  mk_class(env, t);
91
78
  ADD_REF(t);
92
78
  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
1444
ANN static void scan0_implicit_similar(const Env env, const Type lhs, const Type rhs) {
106
1444
  struct Op_Func opfunc = { .ck=opck_cast_similar };
107
1444
  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .func=&opfunc };
108
1444
  add_op(env->gwion, &opi);
109
1444
  opi.lhs=rhs;
110
1444
  opi.rhs=lhs;
111
1444
  add_op(env->gwion, &opi);
112
1444
  opfunc.ck = opck_implicit_similar;
113
1444
  opi.op=insert_symbol("@implicit");
114
1444
  add_op(env->gwion, &opi);
115
1444
}
116
117
720
ANN static void typedef_simple(const Env env, const Type_Def tdef, const Type base) {
118
720
  const Type t = scan0_type(env, ++env->scope->type_xid, s_name(tdef->xid), base);
119
720
  t->size = base->size;
120
2158
  const Nspc nspc = (!env->class_def && GET_FLAG(tdef->ext, global)) ?
121
720
  env->global_nspc : env->curr;
122
720
  if(GET_FLAG(tdef->ext, global))
123
    context_global(env);
124
720
  add_type(env, nspc, t);
125
720
  t->e->owner = nspc;
126
720
  t->e->owner_class = env->class_def;
127
720
  tdef->type = t;
128
720
  if(base->nspc)
129
3
    ADD_REF((t->nspc = base->nspc));
130
720
  t->flag = tdef->ext->flag | ae_flag_valid;
131
720
  scan0_implicit_similar(env, t, base);
132

720
  if(tdef->ext->array && !tdef->ext->array->exp)
133
3
    SET_FLAG(t, empty);
134
720
}
135
136
8
ANN static m_bool typedef_complex(const Env env, const Type_Def tdef, const Type base) {
137
8
  const ae_flag flag = base->e->def ? base->e->def->flag : 0;
138
24
  const Class_Def cdef = new_class_def(env->gwion->mp, flag, tdef->xid,
139
8
       cpy_type_decl(env->gwion->mp, tdef->ext), NULL,
140
16
       loc_cpy(env->gwion->mp, td_pos(tdef->ext)));
141
8
  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
733
ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) {
159
733
  CHECK_BB(env_access(env, tdef->ext->flag, td_pos(tdef->ext)))
160

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

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

1053
  if(!env->class_def || !((flag & ae_flag_global) == ae_flag_global))
202
1053
    return GW_OK;
203
  ERR_B(pos, _("can't declare as global in class def"))
204
}
205
206
725
ANN m_bool scan0_enum_def(const Env env, const Enum_Def edef) {
207
725
  CHECK_BB(env_storage(env, edef->flag, edef->pos))
208
725
  CHECK_BB(scan0_defined(env, edef->xid, edef->pos))
209
724
  CHECK_BB(scan0_global(env, edef->flag, edef->pos))
210
724
  edef->t = enum_type(env, edef);
211
724
  if(GET_FLAG(edef, global))
212
    context_global(env);
213
724
  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
303
ANN static m_bool scan0_class_def_pre(const Env env, const Class_Def cdef) {
299
303
  CHECK_BB(env_storage(env, cdef->flag, cdef->pos))
300
303
  CHECK_BB(isres(env, cdef->base.xid, cdef->pos))
301
303
  CHECK_BB(scan0_global(env, cdef->flag, cdef->pos))
302
303
  return GW_OK;
303
}
304
305
298
ANN static void cdef_flag(const Class_Def cdef, const Type t) {
306
298
  if(cdef->base.tmpl) {
307
62
    SET_FLAG(t, template);
308
62
    SET_FLAG(cdef, template);
309
  }
310

298
  if(cdef->base.ext && cdef->base.ext->array)
311
9
    SET_FLAG(t, typedef);
312
298
}
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
302
ANN static Type get_parent(const Env env, const Class_Def cdef) {
326
302
  if(GET_FLAG(cdef, struct))
327
11
    return env->gwion->type[et_compound];
328
291
  if(!cdef->base.ext)
329
208
    return env->gwion->type[et_object];
330
83
  if(tmpl_base(cdef->base.tmpl))
331
8
    return get_parent_base(env, cdef->base.ext);
332
75
  if(cdef->base.tmpl)
333
22
    template_push_types(env, cdef->base.tmpl);
334
75
  const Type t = known_type(env, cdef->base.ext);
335
75
  if(cdef->base.tmpl)
336
22
    nspc_pop_type(env->gwion->mp, env->curr);
337
75
  return t ?: (Type)GW_ERROR;
338
}
339
340
303
ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
341
303
  CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos))
342
302
  const Type parent = get_parent(env, cdef);
343
302
  if(parent == (Type)GW_ERROR)
344
4
    return NULL;
345
298
  const Type t = scan0_type(env, ++env->scope->type_xid, s_name(cdef->base.xid), parent);
346
298
  if(GET_FLAG(cdef, struct))
347
11
    SET_FLAG(t, struct);
348
298
  t->e->tuple = new_tupleform(env->gwion->mp, parent);
349
298
  t->e->owner = env->curr;
350
298
  t->e->owner_class = env->class_def;
351
298
  t->nspc = new_nspc(env->gwion->mp, t->name);
352
298
  t->nspc->parent = env->curr;
353
298
  t->e->def = cdef;
354
298
  t->flag = cdef->flag;
355
298
  add_type(env, t->e->owner, t);
356
298
  cdef_flag(cdef, t);
357

298
  if(cdef->base.ext && cdef->base.ext->array)
358
9
    SET_FLAG(t, typedef);
359
298
  return t;
360
}
361
362
1435
ANN static m_bool scan0_section(const Env env, const Section* section) {
363
1435
  if(section->section_type == ae_section_class)
364
260
    return scan0_class_def(env, section->d.class_def);
365
1175
  if(section->section_type == ae_section_enum)
366
8
    return scan0_enum_def(env, section->d.enum_def);
367
1167
  if(section->section_type == ae_section_union)
368
24
    return scan0_union_def(env, section->d.union_def);
369
1143
  if(section->section_type == ae_section_fptr)
370
72
    return scan0_fptr_def(env, section->d.fptr_def);
371
1071
  if(section->section_type == ae_section_type)
372
21
    return scan0_type_def(env, section->d.type_def);
373
1050
  return GW_OK;
374
}
375
376
303
ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
377
303
  CHECK_OB((cdef->base.type = scan0_class_def_init(env, cdef)))
378
298
  SET_FLAG(cdef->base.type, scan0);
379
298
  if(cdef->body)
380
234
    CHECK_BB(env_body(env, cdef, scan0_section))
381
297
  (void)mk_class(env, cdef->base.type);
382
297
  return GW_OK;
383
}
384
385
303
ANN m_bool scan0_class_def(const Env env, const Class_Def c) {
386
606
  const Class_Def cdef = !tmpl_base(c->base.tmpl) ?
387
303
    c : cpy_class_def(env->gwion->mp, c);
388
303
  if(GET_FLAG(cdef, global)) {
389
4
    vector_add(&env->scope->nspc_stack, (vtype)env->curr);
390
4
    env->curr = env->global_nspc;
391
4
    context_global(env);
392
  }
393
606
  const m_bool ret = scan0_class_def_pre(env, cdef) > 0 ?
394
303
    scan0_class_def_inner(env, cdef) : GW_ERROR;
395
303
  if(GET_FLAG(cdef, global))
396
4
    env->curr = (Nspc)vector_pop(&env->scope->nspc_stack);
397
303
  CHECK_BB(ret)
398

297
  if(GET_FLAG(cdef, global) || (cdef->base.tmpl && !cdef->base.tmpl->call))
399
30
    c->base.type = cdef->base.type;
400
297
  SET_FLAG(cdef->base.type, scan0);
401
297
  return GW_OK;
402
}
403
404
1032
ANN m_bool scan0_ast(const Env env, Ast ast) {
405
1032
  do CHECK_BB(scan0_section(env, ast->section))
406
1018
  while((ast = ast->next));
407
605
  return GW_OK;
408
}