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