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 "emit.h" |
7 |
|
|
#include "driver.h" |
8 |
|
|
#include "gwion.h" |
9 |
|
|
#include "engine.h" |
10 |
|
|
#include "arg.h" |
11 |
|
|
#include "compile.h" |
12 |
|
|
#include "object.h" // fork_clean |
13 |
|
|
#include "pass.h" // fork_clean |
14 |
|
|
#include "shreduler_private.h" |
15 |
|
|
|
16 |
|
709 |
ANN static void driver_arg(const Gwion gwion, Driver *di) { |
17 |
✓✓ |
714 |
for(m_uint i = 0; i < map_size(&gwion->data->plug->drv); ++i) { |
18 |
|
6 |
const m_str name = (m_str)VKEY(&gwion->data->plug->drv, i); |
19 |
|
6 |
const size_t len = strlen(name); |
20 |
✓✓ |
6 |
if(!strncmp(name, di->si->arg, len)) { |
21 |
|
1 |
di->func = (f_bbqset)VVAL(&gwion->data->plug->drv, i); |
22 |
|
1 |
break; |
23 |
|
|
} |
24 |
|
|
} |
25 |
|
709 |
} |
26 |
|
|
|
27 |
|
711 |
ANN m_bool gwion_audio(const Gwion gwion) { |
28 |
|
711 |
Driver *const di = gwion->vm->bbq; |
29 |
✓✓ |
711 |
if(di->si->arg) |
30 |
|
709 |
driver_arg(gwion, di); |
31 |
|
711 |
di->func(di->driver); |
32 |
✗✓ |
711 |
CHECK_BB(di->driver->ini(gwion->vm, di)); |
33 |
|
711 |
driver_alloc(di); |
34 |
|
711 |
return GW_OK; |
35 |
|
|
} |
36 |
|
|
|
37 |
|
711 |
ANN static inline m_bool gwion_engine(const Gwion gwion) { |
38 |
|
711 |
return type_engine_init(gwion, &gwion->data->plug->vec[GWPLUG_IMPORT]) > 0; |
39 |
|
|
} |
40 |
|
|
|
41 |
|
711 |
ANN static inline void gwion_compile(const Gwion gwion, const Vector v) { |
42 |
✓✓ |
2042 |
for(m_uint i = 0; i < vector_size(v); i++) |
43 |
|
1331 |
compile_filename(gwion, (m_str)vector_at(v, i)); |
44 |
|
711 |
} |
45 |
|
|
|
46 |
|
711 |
ANN static void gwion_cleaner(const Gwion gwion) { |
47 |
|
711 |
const VM_Code code = new_vm_code(gwion->mp, NULL, 0, ae_flag_builtin, "in code dtor"); |
48 |
|
711 |
gwion->vm->cleaner_shred = new_vm_shred(gwion->mp, code); |
49 |
|
711 |
vm_ini_shred(gwion->vm, gwion->vm->cleaner_shred); |
50 |
|
711 |
} |
51 |
|
|
|
52 |
|
7 |
ANN VM* gwion_cpy(const VM* src) { |
53 |
|
7 |
const Gwion gwion = mp_calloc(src->gwion->mp, Gwion); |
54 |
|
7 |
gwion->vm = new_vm(src->gwion->mp, 0); |
55 |
|
7 |
gwion->vm->gwion = gwion; |
56 |
|
7 |
gwion->vm->bbq->si = soundinfo_cpy(src->gwion->mp, src->bbq->si); |
57 |
|
7 |
gwion->emit = src->gwion->emit; |
58 |
|
7 |
gwion->env = src->gwion->env; |
59 |
|
7 |
gwion->data = cpy_gwiondata(src->gwion->mp, src->gwion->data); |
60 |
|
7 |
gwion->st = src->gwion->st; |
61 |
|
7 |
gwion->mp = src->gwion->mp; |
62 |
|
7 |
gwion->type = src->gwion->type; |
63 |
|
7 |
return gwion->vm; |
64 |
|
|
} |
65 |
|
|
|
66 |
|
714 |
ANN static void gwion_core(const Gwion gwion) { |
67 |
|
714 |
gwion->vm = new_vm(gwion->mp, 1); |
68 |
|
714 |
gwion->emit = new_emitter(gwion->mp); |
69 |
|
714 |
gwion->env = new_env(gwion->mp); |
70 |
|
714 |
gwion->emit->env = gwion->env; |
71 |
|
714 |
gwion->vm->gwion = gwion->emit->gwion = gwion->env->gwion = gwion; |
72 |
|
714 |
} |
73 |
|
|
|
74 |
|
711 |
ANN static m_bool gwion_ok(const Gwion gwion, Arg* arg) { |
75 |
|
711 |
gwion->data->plug = new_pluginfo(gwion->mp, &arg->lib); |
76 |
|
711 |
shreduler_set_loop(gwion->vm->shreduler, arg->loop); |
77 |
✓✗ |
711 |
if(gwion_audio(gwion) > 0) { |
78 |
|
711 |
plug_run(gwion, &arg->mod); |
79 |
✓✗ |
711 |
if(gwion_engine(gwion)) { |
80 |
|
711 |
gwion_cleaner(gwion); |
81 |
|
711 |
gwion_compile(gwion, &arg->add); |
82 |
|
711 |
return GW_OK; |
83 |
|
|
} |
84 |
|
|
} |
85 |
|
|
return GW_ERROR; |
86 |
|
|
} |
87 |
|
|
|
88 |
|
714 |
ANN m_bool gwion_ini(const Gwion gwion, Arg* arg) { |
89 |
|
714 |
gwion->mp = mempool_ini((sizeof(struct VM_Shred_) + SIZEOF_REG + SIZEOF_MEM)); |
90 |
|
714 |
gwion->st = new_symbol_table(gwion->mp, 65347); |
91 |
|
714 |
gwion->ppa = mp_calloc(gwion->mp, PPArg); |
92 |
|
714 |
pparg_ini(gwion->mp, gwion->ppa); |
93 |
|
714 |
gwion_core(gwion); |
94 |
|
714 |
gwion->data = new_gwiondata(gwion->mp); |
95 |
|
714 |
gwion->type = (Type*)xcalloc(MAX_TYPE, sizeof(struct Type_*)); |
96 |
|
714 |
pass_default(gwion); |
97 |
|
714 |
arg->si = gwion->vm->bbq->si = new_soundinfo(gwion->mp); |
98 |
✓✓ |
714 |
CHECK_BB(arg_parse(gwion, arg)) |
99 |
|
711 |
return gwion_ok(gwion, arg); |
100 |
|
|
} |
101 |
|
|
|
102 |
|
711 |
ANN void gwion_run(const Gwion gwion) { |
103 |
|
711 |
VM* vm = gwion->vm; |
104 |
|
711 |
vm->bbq->driver->run(vm, vm->bbq); |
105 |
|
710 |
} |
106 |
|
|
|
107 |
|
4 |
ANN static inline void free_gwion_cpy(const Gwion gwion, const VM_Shred shred) { |
108 |
|
4 |
gwion_end_child(shred, gwion); |
109 |
|
4 |
free_vm(gwion->vm); |
110 |
|
4 |
free_gwiondata_cpy(gwion->mp, gwion->data); |
111 |
|
4 |
mp_free(gwion->mp, Gwion, gwion); |
112 |
|
4 |
} |
113 |
|
|
|
114 |
|
4 |
ANN static void fork_clean2(const VM_Shred shred, const Vector v) { |
115 |
✓✓ |
8 |
for(m_uint i = 0; i < vector_size(v); ++i) { |
116 |
|
4 |
const Gwion gwion = (Gwion)vector_at(v, i); |
117 |
|
4 |
free_gwion_cpy(gwion, shred); |
118 |
|
|
} |
119 |
|
4 |
vector_release(v); |
120 |
|
4 |
v->ptr = NULL; |
121 |
|
4 |
} |
122 |
|
|
|
123 |
|
724 |
ANN void gwion_end_child(const VM_Shred shred, const Gwion gwion) { |
124 |
✓✓ |
724 |
if(gwion->data->child.ptr) |
125 |
|
7 |
fork_clean(shred, &gwion->data->child); |
126 |
✓✓ |
724 |
if(gwion->data->child2.ptr) |
127 |
|
4 |
fork_clean2(shred, &gwion->data->child2); |
128 |
|
724 |
} |
129 |
|
|
|
130 |
|
713 |
ANN void gwion_end(const Gwion gwion) { |
131 |
|
713 |
gwion_end_child(gwion->vm->cleaner_shred, gwion); |
132 |
|
713 |
free_env(gwion->env); |
133 |
✓✓ |
713 |
if(gwion->vm->cleaner_shred) |
134 |
|
710 |
free_vm_shred(gwion->vm->cleaner_shred); |
135 |
|
713 |
free_emitter(gwion->mp, gwion->emit); |
136 |
|
713 |
free_vm(gwion->vm); |
137 |
|
713 |
pparg_end(gwion->ppa); |
138 |
|
713 |
mp_free(gwion->mp, PPArg, gwion->ppa); |
139 |
|
713 |
free_gwiondata(gwion); |
140 |
|
713 |
free_symbols(gwion->st); |
141 |
|
713 |
xfree(gwion->type); |
142 |
|
713 |
mempool_end(gwion->mp); |
143 |
|
713 |
} |
144 |
|
|
|
145 |
|
257 |
ANN static void env_header(const Env env) { |
146 |
✓✓ |
257 |
if(env->class_def) |
147 |
|
40 |
gw_err(_("in class: '%s'\n"), env->class_def->name); |
148 |
✓✓ |
257 |
if(env->func) |
149 |
|
26 |
gw_err(_("in function: '%s'\n"), env->func->name); |
150 |
|
257 |
} |
151 |
|
|
|
152 |
|
363 |
ANN void env_err(const Env env, const loc_t pos, const m_str fmt, ...) { |
153 |
✓✓✓✓
|
363 |
if(env->context && env->context->error) |
154 |
|
106 |
return; |
155 |
|
|
#ifndef __FUZZING__ |
156 |
|
257 |
env_header(env); |
157 |
|
257 |
loc_header(pos, env->name); |
158 |
|
|
va_list arg; |
159 |
|
257 |
va_start(arg, fmt); |
160 |
|
257 |
vfprintf(stderr, fmt, arg); |
161 |
|
257 |
va_end(arg); |
162 |
|
257 |
fprintf(stderr, "\n"); |
163 |
|
257 |
loc_err(pos, env->name); |
164 |
|
|
#endif |
165 |
✓✓ |
257 |
if(env->context) |
166 |
|
212 |
env->context->error = 1; |
167 |
|
|
} |
168 |
|
|
|
169 |
|
4080 |
ANN struct SpecialId_* specialid_get(const Gwion gwion, const Symbol sym) { |
170 |
|
4080 |
const Map map = &gwion->data->id; |
171 |
✓✓ |
25826 |
for(m_uint i = 0; i < map_size(map); ++i) { |
172 |
✓✓ |
22457 |
if(sym == (Symbol)VKEY(map, i)) |
173 |
|
711 |
return (struct SpecialId_*)VVAL(map, i); |
174 |
|
|
} |
175 |
|
3369 |
return NULL; |
176 |
|
|
} |
177 |
|
|
|
178 |
|
1422 |
ANN void push_global(struct Gwion_ *gwion, const m_str name) { |
179 |
|
1422 |
const Nspc nspc = new_nspc(gwion->mp, name); |
180 |
|
1422 |
nspc->parent = gwion->env->global_nspc; |
181 |
|
1422 |
gwion->env->curr = gwion->env->global_nspc = nspc; |
182 |
|
1422 |
} |
183 |
|
|
|
184 |
|
2133 |
ANN Nspc pop_global(struct Gwion_ *gwion) { |
185 |
|
2133 |
const Nspc nspc = gwion->env->global_nspc->parent; |
186 |
|
2133 |
REM_REF(gwion->env->global_nspc, gwion) |
187 |
|
2133 |
return gwion->env->curr = gwion->env->global_nspc = nspc; |
188 |
|
|
} |