GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/template.c Lines: 88 92 95.7 %
Date: 2020-09-12 17:36:58 Branches: 32 40 80.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 "traverse.h"
6
#include "template.h"
7
#include "vm.h"
8
#include "parse.h"
9
#include "gwion.h"
10
#include "operator.h"
11
12
struct tmpl_info {
13
  const  Class_Def cdef;
14
  Type_List        call;
15
  struct Vector_   type;
16
  struct Vector_   size;
17
  uint8_t index;
18
};
19
20
2045
ANN static m_bool push_types(const Env env, const Tmpl *tmpl) {
21
2045
  ID_List list = tmpl->list;
22
2045
  Type_List call = tmpl->call;
23
  do {
24
2120
    if(!call)
25
1503
      break;
26
617
    const Type t = known_type(env, call->td);
27
617
    if(!t)
28
      return 1;
29
617
    nspc_add_type(env->curr, list->xid, t);
30
617
    call = call->next;
31
617
  } while((list = list->next));
32
2045
  return !call;
33
}
34
35
2
ANN static m_bool _template_push(const Env env, const Type t) {
36
2
  if(t->e->owner_class)
37
    CHECK_BB(template_push(env, t->e->owner_class))
38
2
  if(GET_FLAG(t, template))
39
1
    return push_types(env, t->e->def->base.tmpl);
40
1
  return GW_OK;
41
}
42
43
2
ANN m_bool template_push(const Env env, const Type t) {
44
2
  nspc_push_type(env->gwion->mp, env->curr);
45
2
  return _template_push(env, t);
46
}
47
48
2044
ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) {
49
2044
  nspc_push_type(env->gwion->mp, env->curr);
50
2044
  if(push_types(env, tmpl))
51
2041
    return GW_OK;
52
3
  POP_RET(GW_ERROR);
53
}
54
55
54
ANN Tmpl* mk_tmpl(const Env env, const Tmpl *tm, const Type_List types) {
56
54
  Tmpl *tmpl = new_tmpl(env->gwion->mp, tm->list, 0);
57
54
  tmpl->call = cpy_type_list(env->gwion->mp, types);
58
54
  return tmpl;
59
}
60
61
9
static ANN Type scan_func(const Env env, const Type t, const Type_Decl* td) {
62
9
  DECL_OO(const m_str, tl_name, = tl2str(env, td->types))
63
9
  const Symbol sym = func_symbol(env, t->e->owner->name, t->e->d.func->name, tl_name, 0);
64
9
  free_mstr(env->gwion->mp, tl_name);
65
9
  const Type base_type = nspc_lookup_type1(t->e->owner, sym);
66
9
  if(base_type)
67
    return base_type;
68
9
  const Type ret = type_copy(env->gwion->mp, t);
69
9
  ADD_REF(ret->nspc)
70
9
  ret->e->parent = t;
71
9
  ret->name = s_name(sym);
72
9
  SET_FLAG(ret, func);
73
9
  nspc_add_type_front(t->e->owner, sym, ret);
74
9
  const Func_Def def = cpy_func_def(env->gwion->mp, t->e->d.func->def);
75
9
  const Func func = ret->e->d.func = new_func(env->gwion->mp, s_name(sym), def);
76
9
  const Value value = new_value(env->gwion->mp, ret, s_name(sym));
77
9
  func->flag = def->flag;
78
9
  value->d.func_ref = func;
79
9
  value->from->owner = t->e->owner;
80
9
  value->from->owner_class = t->e->owner_class;
81
9
  func->value_ref = value;
82
9
  func->def->base->tmpl = mk_tmpl(env, t->e->d.func->def->base->tmpl, td->types);
83
9
  def->base->func = func;
84
9
  nspc_add_value_front(t->e->owner, sym, value);
85
9
  return ret;
86
}
87
88
10
static ANN Type maybe_func(const Env env, const Type t, const Type_Decl* td) {
89

10
  if(isa(t, env->gwion->type[et_function]) > 0 && t->e->d.func->def->base->tmpl)
90
9
     return scan_func(env, t, td);
91
1
  ERR_O(td->pos,
92
     _("type '%s' is not template. You should not provide template types"), t->name)
93
}
94
95
436798
ANN Type _scan_type(const Env env, const Type t, Type_Decl* td) {
96
436798
  if(GET_FLAG(t, template)) {
97

2917
    if(GET_FLAG(t, ref) || (GET_FLAG(t, unary) && !td->types))
98
2845
      return t;
99
72
    struct TemplateScan ts = { .t=t, .td=td };
100
72
    struct Op_Import opi = { .op=insert_symbol("@scan"), .lhs=t, .data=(uintptr_t)&ts, .pos=td_pos(td), .op_type=op_scan };
101
72
    return op_check(env, &opi);
102
433881
  } else if(td->types)
103
10
    return maybe_func(env, t, td);
104
433871
  Type_Decl *next = td->next;
105
433871
  td->next = NULL;
106
433871
  const Type ret = find_type(env, td);
107
433871
  td->next = next;
108
433871
  return ret;
109
}
110
111
436819
ANN Type scan_type(const Env env, const Type t, Type_Decl* td) {
112
436819
  if(td->next) {
113
21
    Type_Decl *next = td->next;
114
21
    td->next = NULL;
115
21
    const Type owner = known_type(env, td);
116
21
    td->next = next;
117
21
    CHECK_OO(owner)
118
20
    if(!owner->nspc)
119
1
      ERR_O(td_pos(td), "type '%s' has no namespace", owner->name)
120
38
    struct EnvSet es = { .env=env, .data=env,
121
19
      .scope=env->scope->depth, .flag=ae_flag_none };
122
19
    envset_push(&es, owner, owner->nspc);
123
19
    (void)env_push(env, owner, owner->nspc);// TODO: is this needed?
124
19
    const Type ret = scan_type(env, t, td->next);
125
19
    env_pop(env, es.scope);
126
19
    if(es.run)
127
      envset_pop(&es, owner);
128
19
    return ret;
129
  }
130
436798
  return _scan_type(env, t, td);
131
}