GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/template.c Lines: 84 88 95.5 %
Date: 2020-08-07 19:15:19 Branches: 33 42 78.6 %

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
1318
ANN static m_bool push_types(const Env env, const Tmpl *tmpl) {
21
1318
  ID_List list = tmpl->list;
22
1318
  Type_List call = tmpl->call;
23
  do {
24
1393
    if(!call)
25
809
      break;
26
584
    const Type t = known_type(env, call->td);
27
584
    if(!t)
28
      return 1;
29
584
    nspc_add_type(env->curr, list->xid, t);
30
584
    call = call->next;
31
584
  } while((list = list->next));
32
1318
  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
1317
ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) {
49
1317
  nspc_push_type(env->gwion->mp, env->curr);
50
1317
  if(push_types(env, tmpl))
51
1314
    return GW_OK;
52
3
  POP_RET(GW_ERROR);
53
}
54
55
53
ANN Tmpl* mk_tmpl(const Env env, const Tmpl *tm, const Type_List types) {
56
53
  Tmpl *tmpl = new_tmpl(env->gwion->mp, tm->list, 0);
57
53
  tmpl->call = cpy_type_list(env->gwion->mp, types);
58
53
  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
446929
ANN Type _scan_type(const Env env, const Type t, const Type_Decl* td) {
96
446929
  if(GET_FLAG(t, template)) {
97

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