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 |