Gwion coverage report


Directory: src/
File: src/parse/func_resolve_tmpl.c
Date: 2023-01-30 18:32:28
Exec Total Coverage
Lines: 111 140 79.3%
Functions: 10 12 83.3%
Branches: 78 102 76.5%

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 "instr.h"
6 #include "traverse.h"
7 #include "template.h"
8 #include "gwion.h"
9 #include "object.h"
10 #include "operator.h"
11 #include "import.h"
12 #include "parse.h"
13 #include "emit.h"
14 #include "specialid.h"
15 #include "tmp_resolve.h"
16 #include "spread.h"
17
18 struct ResolverArgs {
19 const Value v;
20 Exp_Call *const e;
21 const m_str tmpl_name;
22 const Type_List types;
23 };
24
25 160 ANN static inline Value template_get_ready(const Env env, const Value v,
26 const m_str tmpl, const m_uint i) {
27 160 const Symbol sym = func_symbol(env, v->from->owner->name, v->name, tmpl, i);
28 99 return v->from->owner_class ? find_value(v->from->owner_class, sym)
29
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 61 times.
259 : nspc_lookup_value1(v->from->owner, sym);
30 }
31
32 ANN static inline bool
33 75 tmpl_valid(const Env env, const Func_Def fdef, const m_str filename) {
34
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 43 times.
75 if (safe_fflag(fdef->base->func, fflag_valid)) return true;
35 43 const m_str old_file = env->name;
36 43 env->name = filename;
37 43 const bool ret = check_traverse_fdef(env, fdef) > 0;
38 43 env->name = old_file;
39
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 37 times.
43 if(!fdef->base->func) free_func_def(env->gwion->mp, fdef);
40 43 return ret;
41 }
42
43 75 ANN static Func ensure_tmpl(const Env env, const Func_Def fdef,
44 Exp_Call *const exp, const m_str filename) {
45
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 68 times.
75 if (!tmpl_valid(env, fdef, filename)) return NULL;
46
3/4
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 65 times.
68 if(env->context && env->context->error) return NULL;
47
3/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
65 if (exp->args && !exp->args->type) return NULL;
48 65 const Func f = fdef->base->func;
49 65 const Tmpl tmpl = {.list = fdef->base->tmpl->list, .call = exp->tmpl->call};
50
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
65 CHECK_BO(template_push_types(env, &tmpl));
51 65 const Func func = find_func_match(env, f, exp);
52 65 nspc_pop_type(env->gwion->mp, env->curr);
53
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 17 times.
65 if (func)
54 48 call_add_effect(env, func, exp->func->pos);
55 65 return func;
56 }
57
58 ANN static inline Func ensure_fptr(const Env env, struct ResolverArgs *ra,
59 const Fptr_Def fptr) {
60 CHECK_BO(traverse_fptr_def(env, fptr));
61 const Func_Def fdef = mp_vector_at(fptr->cdef->base.type->info->cdef->body, struct Section_ , 0)->d.func_def;
62 return find_func_match(env, fdef->base->func, ra->e);
63 }
64
65 ANN static Func fptr_match(const Env env, struct ResolverArgs *ra) {
66 const Value v = ra->v;
67 const Symbol sym =
68 func_symbol(env, v->from->owner->name, v->name, ra->tmpl_name, 0);
69 const Value exists = nspc_lookup_value0(v->from->owner, sym);
70 if(exists) {
71 const Type t = actual_type(env->gwion, exists->type);
72 const Func_Def fdef = mp_vector_at(t->info->cdef->body, struct Section_ , 0)->d.func_def;
73 return find_func_match(env, fdef->base->func, ra->e);
74 }
75 const Func_Def base =
76 v->d.func_ref ? v->d.func_ref->def : ra->e->func->type->info->func->def;
77 const Tmpl tmpl = {.list = base->base->tmpl->list, .call = ra->types};
78 CHECK_BO(template_push_types(env, &tmpl));
79 Func_Base *const fbase = cpy_func_base(env->gwion->mp, base->base);
80 fbase->xid = sym;
81 fbase->tmpl->call = cpy_type_list(env->gwion->mp, ra->types);
82 const Fptr_Def fptr = new_fptr_def(env->gwion->mp, fbase);
83 const Func m_func = ensure_fptr(env, ra, fptr);
84 if (m_func)
85 nspc_add_type_front(v->from->owner, sym,
86 actual_type(env->gwion, m_func->value_ref->type));
87 free_fptr_def(env->gwion->mp, fptr);
88 nspc_pop_type(env->gwion->mp, env->curr);
89 return m_func;
90 }
91
92 38 ANN static Func tmpl_exists(const Env env, struct ResolverArgs *ra,
93 const Value exists) {
94
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 32 times.
38 if (env->func == exists->d.func_ref)
95
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
6 return find_func_match(env, env->func, ra->e) ? env->func : NULL;
96 32 return ensure_tmpl(env, exists->d.func_ref->def, ra->e, ra->v->from->filename);
97 }
98
99 61 ANN static Func create_tmpl(const Env env, struct ResolverArgs *ra,
100 const m_uint i) {
101
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 43 times.
61 DECL_OO(const Value, value, = template_get_ready(env, ra->v, "template", i));
102
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 39 times.
43 if (value->d.func_ref->def->builtin) set_vflag(value, vflag_builtin);
103 43 const Func_Def fdef = cpy_func_def(env->gwion->mp, value->d.func_ref->def);
104 43 fdef->base->tmpl->call = cpy_type_list(env->gwion->mp, ra->types);
105
106 43 fdef->vt_index = i;
107
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 41 times.
43 if(is_spread_tmpl(value->d.func_ref->def->base->tmpl)) {
108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 Arg_List args = fdef->base->args ?: new_mp_vector(env->gwion->mp, Arg, 0);
109
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for(uint32_t idx = 0; idx < ra->types->len; idx++) {
110 char c[256];
111 2 sprintf(c, "arg%u", idx);
112 2 Type_Decl *td = *mp_vector_at(ra->types, Type_Decl*, idx);
113 2 Arg arg = { .td = cpy_type_decl(env->gwion->mp, td), .var_decl = {.xid = insert_symbol(c), /*.value = v*/ }};
114
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mp_vector_add(env->gwion->mp, &args, Arg, arg);
115 }
116 2 fdef->base->args = args;
117 }
118
119 43 const Func func = ensure_tmpl(env, fdef, ra->e, ra->v->from->filename);
120
4/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 31 times.
43 if (func && func->def->builtin) {
121 1 builtin_func(env->gwion, func, (void*)ra->v->d.func_ref->code->native_func);
122 1 set_vflag(func->value_ref, vflag_builtin);
123 1 struct Op_Import opi = { .lhs = ra->v->d.func_ref->value_ref->type, .rhs = func->value_ref->type };
124 1 op_cpy(env, &opi);
125 }
126 43 return func;
127 }
128
129 83 ANN static Func func_match(const Env env, struct ResolverArgs *ra) {
130
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 30 times.
129 for (m_uint i = 0; i < ra->v->from->offset + 1; ++i) {
131 99 const Value exists = template_get_ready(env, ra->v, ra->tmpl_name, i);
132 99 const Func func = exists
133 38 ? tmpl_exists(env, ra, exists)
134
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 61 times.
99 : create_tmpl(env, ra, i);
135
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 46 times.
99 if (func) return func;
136 }
137 30 return NULL;
138 }
139
140 83 ANN static Func find_tmpl(const Env env, const Value v, Exp_Call *const exp,
141 const m_str tmpl_name) {
142 83 const Type_List types = exp->tmpl->call;
143 83 const Func former = env->func;
144 83 const m_uint scope = env->scope->depth;
145 83 struct EnvSet es = {.env = env,
146 .data = env,
147 .func = (_exp_func)check_cdef,
148 .scope = scope,
149 .flag = tflag_check};
150 83 struct ResolverArgs ra = {
151 .v = v, .e = exp, .tmpl_name = tmpl_name, .types = types};
152
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
83 CHECK_BO(envset_pushv(&es, v));
153 83 (void)env_push(env, v->from->owner_class, v->from->owner);
154
3/4
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
132 const bool in_tmpl = v->from->owner_class && v->from->owner_class->info->cdef &&
155
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 42 times.
49 v->from->owner_class->info->cdef->base.tmpl;
156
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 76 times.
83 if(in_tmpl)
157 7 (void)template_push_types(env, v->from->owner_class->info->cdef->base.tmpl);
158 83 const bool is_clos = isa(exp->func->type, env->gwion->type[et_closure]) > 0;
159 83 const Func m_func = !is_clos ? func_match(env, &ra)
160
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 : fptr_match(env, &ra);
161
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 76 times.
83 if(in_tmpl)
162 7 nspc_pop_type(env->gwion->mp, env->curr);
163 83 env_pop(env, scope);
164 83 envset_pop(&es, v->from->owner_class);
165 83 env->func = former;
166 83 return m_func;
167 }
168
169 84 ANN static Func __find_template_match(const Env env, const Value v,
170 Exp_Call *const exp) {
171
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 83 times.
84 DECL_OO(const m_str, tmpl_name,
172 = tl2str(env->gwion, exp->tmpl->call, exp->func->pos));
173 83 const Func f = find_tmpl(env, v, exp, tmpl_name);
174 83 free_mstr(env->gwion->mp, tmpl_name);
175 83 return f;
176 }
177
178 84 ANN static Func _find_template_match(const Env env, const Value v,
179 Exp_Call *const exp) {
180
2/2
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 53 times.
84 DECL_OO(const Func, f, = __find_template_match(env, v, exp));
181 53 Type_List tl = exp->tmpl->call;
182 53 Specialized_List sl = f->def->base->tmpl->list;
183
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 53 times.
110 for(uint32_t i = 0; i < tl->len; i++) {
184 57 Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i);
185
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 DECL_OO(const Type, t, = known_type(env, td));
186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if(t->info->traits) {
187 Specialized * spec = mp_vector_at(sl, Specialized, i);
188 if (miss_traits(t, spec)) return NULL;
189 }
190 }
191 53 return f;
192 }
193
194 63 ANN static inline m_bool check_call(const Env env, const Exp_Call *exp) {
195 63 const ae_exp_t et = exp->func->exp_type;
196
5/6
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
63 if (et != ae_exp_primary && et != ae_exp_dot && et != ae_exp_cast)
197 1 ERR_B(exp->func->pos, _("invalid expression for function call."))
198 62 return GW_OK;
199 }
200
201 63 ANN Func find_template_match(const Env env, const Value value,
202 Exp_Call *const exp) {
203
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 62 times.
63 CHECK_BO(check_call(env, exp));
204 62 const Func f = _find_template_match(env, value, exp);
205
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 15 times.
62 if (f) return f;
206 15 Type t = value->from->owner_class;
207
4/4
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 5 times.
39 while (t && t->nspc) {
208 90 const Func_Def fdef = value->d.func_ref ? value->d.func_ref->def
209
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 : value->type->info->func->def;
210 30 const Value v = nspc_lookup_value0(t->nspc, fdef->base->xid);
211
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 8 times.
30 if (v) {
212 22 const Func f = _find_template_match(env, v, exp);
213
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 16 times.
22 if (f) return f;
214 }
215 24 t = t->info->parent;
216 }
217 9 ERR_O(exp_self(exp)->pos, _("arguments do not match for template call"))
218 }
219