Gwion coverage report


Directory: src/
File: src/parse/template.c
Date: 2023-01-30 18:32:28
Exec Total Coverage
Lines: 108 162 66.7%
Functions: 10 13 76.9%
Branches: 66 100 66.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 #include "instr.h"
12 #include "object.h"
13 #include "import.h"
14 #include "spread.h"
15
16 23275 ANN static m_bool _push_types(const Env env, const Nspc nspc,
17 const Tmpl *tmpl) {
18 23275 Specialized_List sl = tmpl->list;
19 23275 Type_List tl = tmpl->call;
20 23275 Specialized *spec = mp_vector_at(sl, Specialized, sl->len - 1);
21
22
2/2
✓ Branch 0 taken 23258 times.
✓ Branch 1 taken 17 times.
23275 const uint32_t len = strcmp(s_name(spec->xid), "...") ? sl->len : sl->len-1;
23
2/2
✓ Branch 0 taken 12072 times.
✓ Branch 1 taken 11203 times.
23275 if(!tl) return GW_OK;
24
2/2
✓ Branch 0 taken 11268 times.
✓ Branch 1 taken 11203 times.
22471 for(uint32_t i = 0; i < len; i++) {
25
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11268 times.
11268 if (i >= tl->len) return GW_OK;
26 11268 Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i);
27 11268 const Type t = known_type(env, td);
28 11268 Specialized *spec = mp_vector_at(sl, Specialized, i);
29 11268 nspc_add_type(nspc, spec->xid, t);
30 };
31
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 11187 times.
11203 if(len != sl->len) return GW_OK;
32
2/2
✓ Branch 0 taken 11184 times.
✓ Branch 1 taken 3 times.
11187 return tl->len == sl->len ? GW_OK : GW_ERROR;
33 }
34
35 23275 ANN static m_bool push_types(const Env env, const Nspc nspc, const Tmpl *tmpl) {
36 23275 const Type t = env->class_def;
37
2/2
✓ Branch 0 taken 15787 times.
✓ Branch 1 taken 7488 times.
23275 if (t) {
38 15787 env->class_def = t->info->value->from->owner_class;
39 15787 env->curr = t->info->value->from->owner;
40 }
41 23275 const m_bool ret = _push_types(env, nspc, tmpl);
42
2/2
✓ Branch 0 taken 15787 times.
✓ Branch 1 taken 7488 times.
23275 if (t) {
43 15787 env->class_def = t;
44 15787 env->curr = t->nspc;
45 }
46 23275 return ret;
47 }
48
49 ANN static m_bool _template_push(const Env env, const Type t) {
50 if (t->info->value->from->owner_class)
51 CHECK_BB(template_push(env, t->info->value->from->owner_class));
52 if (tflag(t, tflag_tmpl))
53 return push_types(env, t->nspc, t->info->cdef->base.tmpl); // incorrect
54 return GW_OK;
55 }
56
57 ANN m_bool template_push(const Env env, const Type t) {
58 nspc_push_type(env->gwion->mp, env->curr);
59 return _template_push(env, t);
60 }
61
62 11203 ANN void check_call(const Env env, const Tmpl *tmpl) {
63
2/2
✓ Branch 0 taken 11295 times.
✓ Branch 1 taken 11203 times.
22498 for(uint32_t i = 0; i < tmpl->call->len; i++) {
64 11295 Specialized *spec = mp_vector_at(tmpl->list, Specialized, i);
65 11295 Type_Decl *call = *mp_vector_at(tmpl->call, Type_Decl*, i);
66
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11292 times.
11295 if(spec->xid == call->xid) {
67
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!nspc_lookup_type1(env->curr, spec->xid))
68 call->xid = insert_symbol("auto");
69 else {
70 3 const Type t = nspc_lookup_type1(env->curr, spec->xid);
71 3 Type_Decl *td = type2td(env->gwion, t, call->pos);
72 3 free_type_decl(env->gwion->mp, call);
73 3 mp_vector_set(tmpl->call, Type_Decl*, i, td);
74 }
75 }
76 }
77 11203 }
78 23275 ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) {
79 23275 nspc_push_type(env->gwion->mp, env->curr);
80
2/2
✓ Branch 0 taken 11203 times.
✓ Branch 1 taken 12072 times.
23275 if (tmpl->call) check_call(env, tmpl);
81
2/2
✓ Branch 1 taken 23272 times.
✓ Branch 2 taken 3 times.
23275 if (push_types(env, env->curr, tmpl) > 0) return GW_OK;
82 3 POP_RET(GW_ERROR);
83 }
84
85 659 ANN Tmpl *mk_tmpl(const Env env, const Tmpl *tm, const Type_List types) {
86 659 Tmpl *tmpl = new_tmpl(env->gwion->mp, tm->list);
87 659 tmpl->call = cpy_type_list(env->gwion->mp, types);
88 659 return tmpl;
89 }
90
91 static ANN Type scan_func(const Env env, const Type t, const Type_Decl *td) {
92 DECL_OO(const m_str, tl_name, = tl2str(env->gwion, td->types, td->pos));
93 const Symbol sym = func_symbol(env, t->info->value->from->owner->name,
94 t->info->func->name, tl_name, 0);
95 free_mstr(env->gwion->mp, tl_name);
96 const Type base_type = nspc_lookup_type1(t->info->value->from->owner, sym);
97 if (base_type) return base_type;
98 const Type ret = type_copy(env->gwion->mp, t);
99 ret->info->parent = t;
100 ret->info->value = t->info->func->value_ref;
101 ret->name = s_name(sym);
102 set_tflag(ret, tflag_ftmpl);
103 nspc_add_type_front(t->info->value->from->owner, sym, ret);
104 void *func_ptr = t->info->func->def->d.dl_func_ptr;
105 if (vflag(t->info->func->value_ref, vflag_builtin))
106 t->info->func->def->d.dl_func_ptr = NULL;
107 const Func_Def def = cpy_func_def(env->gwion->mp, t->info->func->def);
108 const Func func = ret->info->func =
109 new_func(env->gwion->mp, s_name(sym), def);
110 const Value value = new_value(env, ret, s_name(sym), def->base->pos);
111 func->flag = def->base->flag;
112 if (vflag(t->info->func->value_ref, vflag_member))
113 set_vflag(value, vflag_member);
114 value->d.func_ref = func;
115 value->from->owner = t->info->value->from->owner;
116 value->from->owner_class = t->info->value->from->owner_class;
117 func->value_ref = value;
118 func->def->base->tmpl =
119 mk_tmpl(env, t->info->func->def->base->tmpl, td->types);
120 def->base->func = func;
121 nspc_add_value_front(t->info->value->from->owner, sym, value);
122 if (vflag(t->info->func->value_ref, vflag_builtin)) {
123 builtin_func(env->gwion, func, func_ptr);
124 t->info->func->def->d.dl_func_ptr = func_ptr;
125 }
126 return ret;
127 }
128
129 1 static ANN Type maybe_func(const Env env, const Type t, const Type_Decl *td) {
130
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 if (is_func(env->gwion, t) && t->info->func->def->base->tmpl) // is_callable needs type
131 return scan_func(env, t, td);
132 1 ERR_O(td->pos,
133 _("type '%s' is not template. You should not provide template types"),
134 t->name)
135 }
136
137 3421 static ANN bool is_single_variadic(const MP_Vector *v) {
138
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 3410 times.
3421 if(v->len != 1) return false;
139 3410 const Specialized *spec = mp_vector_at(v, Specialized, 0);
140 3410 return !strcmp(s_name(spec->xid), "...");
141 }
142
143 3414 ANN2(1,2) static m_bool check_tmpl(const Env env, const Type_List tl, const Specialized_List sl, const loc_t pos, const bool is_spread) {
144
5/8
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3414 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3413 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
3414 if (!sl || sl->len > tl->len || (tl->len != sl->len && !is_spread))
145 1 ERR_B(pos, "invalid template type number");
146
2/2
✓ Branch 0 taken 3424 times.
✓ Branch 1 taken 3410 times.
6834 for (uint32_t i = 0; i < sl->len; i++) {
147 3424 Type_Decl *tmp = *mp_vector_at(tl, Type_Decl*, i);
148
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3421 times.
3424 DECL_OB(const Type, t, = known_type(env, tmp));
149 3421 Specialized *spec = mp_vector_at(sl, Specialized, i);
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3421 times.
3421 if(spec->traits) {
151 Symbol missing = miss_traits(t, spec);
152 if (missing) {
153 ERR_B(pos, "does not implement requested trait '{/}%s{0}'",
154 s_name(missing));
155 }
156 }
157 }
158 3410 return GW_OK;
159 }
160
161 557818 ANN static Type _scan_type(const Env env, const Type t, Type_Decl *td) {
162
3/4
✓ Branch 1 taken 19533 times.
✓ Branch 2 taken 538285 times.
✓ Branch 4 taken 19533 times.
✗ Branch 5 not taken.
557818 if (tflag(t, tflag_tmpl) && !is_func(env->gwion, t)) { // is_callable
163
4/4
✓ Branch 1 taken 16772 times.
✓ Branch 2 taken 2761 times.
✓ Branch 3 taken 16112 times.
✓ Branch 4 taken 660 times.
19533 if (tflag(t, tflag_ntmpl) && !td->types) return t;
164 3421 const bool single_variadic = is_single_variadic(t->info->cdef->base.tmpl->list);
165
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3416 times.
3421 if(!td->types) {
166 5 const Type new_type = nspc_lookup_type1(env->curr, td->xid);
167 5 Type_Decl *new_td = type2td(env->gwion, new_type, td->pos);
168 5 Type_Decl *d = new_td;
169
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 while(d->next) d = d->next;
170
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(!d->types) {
171
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(!single_variadic)
172 5 ERR_O(td->pos, _("you must provide template types for type '%s'"), t->name);
173 d->types = new_mp_vector(env->gwion->mp, Type_Decl*, 0);
174 }
175 const Type ret = _scan_type(env, t, d);
176 free_type_decl(env->gwion->mp, new_td);
177 return ret;
178 }
179 3416 struct TemplateScan ts = {.t = t, .td = td};
180 3416 Type_List tl = td->types;
181 6832 Specialized_List sl = t->info->cdef->base.tmpl
182
1/2
✓ Branch 0 taken 3416 times.
✗ Branch 1 not taken.
3416 ? t->info->cdef->base.tmpl->list : NULL;
183 3416 const bool is_spread = is_spread_tmpl(t->info->cdef->base.tmpl);
184
4/4
✓ Branch 0 taken 3414 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 3410 times.
3416 if(!single_variadic) CHECK_BO(check_tmpl(env, tl, sl, td->pos, is_spread));
185 3412 struct Op_Import opi = {.op = insert_symbol("class"),
186 .lhs = t,
187 3412 .data = (uintptr_t)&ts,
188 .pos = td->pos};
189 3412 return op_check(env, &opi);
190
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 538284 times.
538285 } else if (td->types)
191 1 return maybe_func(env, t, td);
192 538284 return find_type(env, td);
193 }
194
195 557913 ANN Type scan_type(const Env env, const Type t, Type_Decl *td) {
196
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 557893 times.
557913 if (td->next) {
197 20 Type_Decl *next = td->next;
198 20 td->next = NULL;
199
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 DECL_OO(const Type, maybe_array, = known_type(env, td));
200 20 const Type owner = array_base_simple(maybe_array);
201 20 td->next = next;
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 CHECK_OO(owner);
203
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19 times.
20 if (!owner->nspc) ERR_O(td->pos, "type '%s' has no namespace", owner->name)
204 19 struct EnvSet es = {.env = env,
205 .data = env,
206 19 .scope = env->scope->depth,
207 .flag = tflag_none};
208 19 const Context ctx = env->context;
209 19 const m_str name = env->name;
210 19 envset_push(&es, owner, owner->nspc);
211 19 (void)env_push(env, owner, owner->nspc); // TODO: is this needed?
212 19 env->context = owner->info->value->from->ctx;
213 19 env->name = owner->info->value->from->filename;
214 19 const Type ret = known_type(env, td->next);
215 19 env_pop(env, es.scope);
216 19 envset_pop(&es, owner);
217 19 env->context = ctx;
218 19 env->name = name;
219
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (!td->array) return ret;
220 return array_type(env, ret, td->array->depth);
221 }
222
2/2
✓ Branch 0 taken 557818 times.
✓ Branch 1 taken 75 times.
557893 return !t->array_depth ? _scan_type(env, t, td) : t;
223 }
224