Line | Branch | Exec | Source |
---|---|---|---|
1 | #include <stdlib.h> | ||
2 | #include <string.h> | ||
3 | #include "gwion_util.h" | ||
4 | #include "gwion_ast.h" | ||
5 | #include "gwion_env.h" | ||
6 | #include "vm.h" | ||
7 | #include "instr.h" | ||
8 | #include "gwion.h" | ||
9 | #include "object.h" | ||
10 | #include "operator.h" | ||
11 | #include "import.h" | ||
12 | #include "emit.h" | ||
13 | #include "traverse.h" | ||
14 | #include "parse.h" | ||
15 | |||
16 | 6 | ANN static Func_Def traverse_tmpl(const Emitter emit, Func_Def fdef, Func_Def fbase, | |
17 | const Nspc nspc) { | ||
18 | 6 | const Env env = emit->env; | |
19 | 6 | const Symbol sym = func_symbol(env, nspc->name, s_name(fdef->base->xid), | |
20 | 6 | "template", fbase->vt_index); | |
21 |
3/4✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
|
6 | DECL_OO(const Value, v, = nspc_lookup_value0(nspc, sym) |
22 | ?: nspc_lookup_value0(nspc, fdef->base->xid)); | ||
23 | 6 | const f_xfun xfun = v->d.func_ref->def->d.dl_func_ptr; | |
24 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | if (vflag(v, vflag_builtin)) |
25 | ✗ | v->d.func_ref->def->d.dl_func_ptr = NULL; // why | |
26 | 6 | const Func_Def def = cpy_func_def(env->gwion->mp, v->d.func_ref->def); | |
27 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | if (vflag(v, vflag_builtin)) v->d.func_ref->def->d.dl_func_ptr = xfun; |
28 | 6 | def->base->tmpl->call = cpy_type_list(env->gwion->mp, fbase->base->tmpl->call); | |
29 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | CHECK_BO(traverse_dot_tmpl(emit, def, v)); |
30 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | if (vflag(v, vflag_builtin)) builtin_func(emit->gwion, def->base->func, xfun); |
31 | 6 | return def; | |
32 | } | ||
33 | |||
34 | 6 | ANN static void foo(const VM_Shred shred, Type t, const Func_Def fbase, const m_str tmpl_name) { | |
35 | 6 | const Emitter emit = shred->info->vm->gwion->emit; | |
36 | 6 | emit->env->name = "runtime"; | |
37 | do { | ||
38 | 6 | const Func base = fbase->base->func; | |
39 | 6 | const Symbol sym = func_symbol(emit->env, t->name, base->name, tmpl_name, base->def->vt_index); | |
40 | 6 | const Func f = nspc_lookup_func0(t->nspc, sym); | |
41 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (f) { |
42 | ✗ | if(!f->code) continue; | |
43 | ✗ | if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT; | |
44 | ✗ | *(VM_Code *)(shred->reg - SZ_INT) = f->code; | |
45 | ✗ | return; | |
46 | } else { | ||
47 | 6 | const Func_Def def = traverse_tmpl(emit, fbase, fbase, t->nspc); | |
48 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!def) continue; |
49 | 6 | const Func f = def->base->func; | |
50 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT; |
51 | 6 | *(VM_Code *)(shred->reg - SZ_INT) = f->code; | |
52 | 6 | return; | |
53 | } | ||
54 | ✗ | } while ((t = t->info->parent)); | |
55 | ✗ | handle(shred, "MissigTmplPtrException"); | |
56 | } | ||
57 | |||
58 | 2 | INSTR(GTmpl) { | |
59 | 2 | const Func_Def fbase = (Func_Def)instr->m_val; | |
60 | 2 | const m_str tmpl = (m_str)instr->m_val2; | |
61 | 2 | const Func f = *(Func *)REG(-SZ_INT); | |
62 | 2 | const Func _f = *(Func *)REG(-SZ_INT); | |
63 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (!f) { |
64 | 2 | handle(shred, "EmptyFuncPointerException"); | |
65 | 2 | return; | |
66 | } | ||
67 | ✗ | if (f->code) { | |
68 | ✗ | *(VM_Code *)(shred->reg - SZ_INT) = f->code; | |
69 | ✗ | return; | |
70 | } | ||
71 | ✗ | const Emitter emit = shred->info->vm->gwion->emit; | |
72 | ✗ | emit->env->name = "runtime"; | |
73 | ✗ | Type t = f->value_ref->from->owner_class; | |
74 | ✗ | if(!t) { | |
75 | ✗ | const Nspc nspc = f->value_ref->from->owner; | |
76 | ✗ | for (m_uint i = 0; i <= f->value_ref->from->offset; ++i) { | |
77 | ✗ | const Symbol sym = func_symbol(emit->env, nspc->name, f->name, tmpl, i); | |
78 | ✗ | const Func base = nspc_lookup_func0(nspc, sym); | |
79 | ✗ | if (base) { | |
80 | assert(base->code); | ||
81 | ✗ | *(VM_Code *)(shred->reg - SZ_INT) = base->code; | |
82 | ✗ | return; | |
83 | } | ||
84 | } | ||
85 | ✗ | const Func_Def def = traverse_tmpl(emit, f->def, fbase, nspc); | |
86 | ✗ | if (def) { | |
87 | ✗ | *(VM_Code *)(shred->reg - SZ_INT) = def->base->func->code; | |
88 | ✗ | return; | |
89 | } | ||
90 | } else { | ||
91 | do { | ||
92 | ✗ | const Symbol sym = func_symbol(emit->env, t->name, f->name, tmpl, f->def->vt_index); | |
93 | ✗ | const Func f = nspc_lookup_func0(t->nspc, sym); | |
94 | ✗ | if (f) { | |
95 | ✗ | if (!f->code) continue; | |
96 | ✗ | *(VM_Code *)(shred->reg - SZ_INT) = f->code; | |
97 | ✗ | return; | |
98 | } else { | ||
99 | ✗ | const Func_Def def = traverse_tmpl(emit, _f->def, fbase, t->nspc); | |
100 | ✗ | if (!def) continue; | |
101 | ✗ | const Func f = def->base->func; | |
102 | ✗ | *(VM_Code *)(shred->reg - SZ_INT) = f->code; | |
103 | ✗ | return; | |
104 | } | ||
105 | ✗ | } while ((t = t->info->parent)); | |
106 | } | ||
107 | } | ||
108 | |||
109 | 11 | INSTR(DotTmpl) { | |
110 | 11 | const Func_Def fbase = (Func_Def)instr->m_val; | |
111 | 11 | const M_Object o = *(M_Object *)REG(-SZ_INT); | |
112 | 11 | const Func f = fbase->base->func; | |
113 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
|
11 | if(o->type_ref == f->value_ref->from->owner_class) { |
114 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT; |
115 | 5 | *(VM_Code *)(shred->reg - SZ_INT) = f->code; | |
116 | 5 | return; | |
117 | } | ||
118 | 6 | const struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val2; | |
119 | 6 | foo(shred, o->type_ref, fbase, dt->tmpl_name); | |
120 | } | ||
121 | |||
122 | #define VAL (*(m_uint *)(byte + SZ_INT)) | ||
123 | #define FVAL (*(m_float *)(byte + SZ_INT)) | ||
124 | #define VAL2 (*(m_uint *)(byte + SZ_INT * 2)) | ||
125 | #define BYTE(a) \ | ||
126 | m_bit *byte = shred->code->bytecode + (shred->pc - 1) * BYTECODE_SZ; \ | ||
127 | *(m_uint *)byte = instr->opcode; \ | ||
128 | instr->opcode = a; | ||
129 | |||
130 | 13 | INSTR(SetFunc) { | |
131 | 13 | BYTE(eRegPushImm); | |
132 | 13 | const Func f = (Func)instr->m_val; | |
133 | 13 | VAL = *(m_uint *)(shred->reg) = (m_uint)f->code; | |
134 | 13 | shred->reg += SZ_INT; | |
135 | 13 | } | |
136 | |||
137 | 5 | INSTR(FuncWait) { | |
138 | 5 | const Func f = (Func)instr->m_val; | |
139 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if(f->_wait->len - instr->m_val2) { |
140 | ✗ | if(!handle(shred, "UninitValue")) { | |
141 | ✗ | gw_err("{-}some values are not instantiated yet{0}\n"); | |
142 | ✗ | for(uint32_t i = instr->m_val2; i < f->_wait->len; i++) { | |
143 | ✗ | Value v = *mp_vector_at(f->_wait, Value, i); | |
144 | ✗ | defined_here(v); | |
145 | } | ||
146 | } | ||
147 | } else { | ||
148 | 5 | BYTE(eNoOp); | |
149 | } | ||
150 | 5 | } | |
151 | |||
152 | 17 | INSTR(fast_except) { | |
153 | 17 | struct FastExceptInfo *info = (struct FastExceptInfo *)instr->m_val2; | |
154 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
|
17 | if(*(m_uint*)REG(-SZ_INT)) { |
155 | 14 | BYTE(eNoOp); | |
156 | 14 | VAL = -SZ_INT; | |
157 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | if(info) mp_free2(shred->info->mp, sizeof(struct FastExceptInfo), info); |
158 | 14 | instr->m_val2 = 0; | |
159 | 14 | return; | |
160 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | } else if(info) { |
161 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if(info->file) |
162 | 3 | gwerr_basic("Object not instantiated", NULL, NULL, info->file, info->loc, 0); | |
163 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if(info->file2) |
164 | 3 | gwerr_warn("declared here", NULL, NULL, info->file2, info->loc2); | |
165 | } | ||
166 | 3 | handle(shred, "NullPtrException"); | |
167 | } | ||
168 |