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 |
|
2015 |
ANN static m_bool push_types(const Env env, const Tmpl *tmpl) { |
21 |
|
2015 |
ID_List list = tmpl->list; |
22 |
|
2015 |
Type_List call = tmpl->call; |
23 |
|
|
do { |
24 |
✓✓ |
2073 |
if(!call) |
25 |
|
1500 |
break; |
26 |
|
573 |
const Type t = known_type(env, call->td); |
27 |
✗✓ |
573 |
if(!t) |
28 |
|
|
return 1; |
29 |
|
573 |
nspc_add_type(env->curr, list->xid, t); |
30 |
|
573 |
call = call->next; |
31 |
✓✓ |
573 |
} while((list = list->next)); |
32 |
|
2015 |
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 |
|
2014 |
ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) { |
49 |
|
2014 |
nspc_push_type(env->gwion->mp, env->curr); |
50 |
✓✓ |
2014 |
if(push_types(env, tmpl)) |
51 |
|
2011 |
return GW_OK; |
52 |
|
3 |
POP_RET(GW_ERROR); |
53 |
|
|
} |
54 |
|
|
|
55 |
|
48 |
ANN Tmpl* mk_tmpl(const Env env, const Tmpl *tm, const Type_List types) { |
56 |
|
48 |
Tmpl *tmpl = new_tmpl(env->gwion->mp, tm->list, 0); |
57 |
|
48 |
tmpl->call = cpy_type_list(env->gwion->mp, types); |
58 |
|
48 |
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->base->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 |
|
438039 |
ANN Type _scan_type(const Env env, const Type t, Type_Decl* td) { |
96 |
✓✓✓✓
|
438039 |
if(GET_FLAG(t, template) && isa(t, env->gwion->type[et_function]) < 0) { |
97 |
✓✗✓✓ ✓✓ |
2906 |
if(GET_FLAG(t, ref) || (GET_FLAG(t, unary) && !td->types)) |
98 |
|
2848 |
return t; |
99 |
|
58 |
struct TemplateScan ts = { .t=t, .td=td }; |
100 |
|
58 |
struct Op_Import opi = { .op=insert_symbol("@scan"), .lhs=t, .data=(uintptr_t)&ts, .pos=td_pos(td), .op_type=op_scan }; |
101 |
|
58 |
return op_check(env, &opi); |
102 |
✓✓ |
435133 |
} else if(td->types) |
103 |
|
10 |
return maybe_func(env, t, td); |
104 |
|
435123 |
Type_Decl *next = td->next; |
105 |
|
435123 |
td->next = NULL; |
106 |
|
435123 |
const Type ret = find_type(env, td); |
107 |
|
435123 |
td->next = next; |
108 |
|
435123 |
return ret; |
109 |
|
|
} |
110 |
|
|
|
111 |
|
438060 |
ANN Type scan_type(const Env env, const Type t, Type_Decl* td) { |
112 |
✓✓ |
438060 |
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 |
|
438039 |
return _scan_type(env, t, td); |
131 |
|
|
} |