Gwion coverage report


Directory: src/
File: src/lib/modules.c
Date: 2023-01-30 18:32:28
Exec Total Coverage
Lines: 142 203 70.0%
Functions: 28 39 71.8%
Branches: 17 36 47.2%

Line Branch Exec Source
1 #include <stdlib.h>
2 #include <math.h>
3 #include "gwion_util.h"
4 #include "gwion_ast.h"
5 #include "gwion_env.h"
6 #include "vm.h"
7 #include "gwion.h"
8 #include "instr.h"
9 #include "object.h"
10 #include "operator.h"
11 #include "import.h"
12 #include "ugen.h"
13 #include "gwi.h"
14 #include "emit.h"
15
16 12 static DTOR(basic_dtor) { xfree(UGEN(o)->module.gen.data); }
17
18 480000 static TICK(gain_tick) { u->out = (u->in * *(m_float *)u->module.gen.data); }
19
20 1 static CTOR(gain_ctor) {
21 1 ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1);
22 1 ugen_gen(shred->info->vm->gwion, UGEN(o), gain_tick,
23 (m_float *)xmalloc(SZ_FLOAT), 0);
24 1 UGEN(o)->module.gen.tick = gain_tick;
25 1 *(m_float *)UGEN(o)->module.gen.data = 1;
26 1 }
27
28 67 static MFUN(gain_get_gain) {
29 67 *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data;
30 67 }
31
32 67 static MFUN(gain_set_gain) {
33 67 *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data =
34 67 *(m_float *)MEM(SZ_INT);
35 67 }
36
37 638 static GWION_IMPORT(gain) {
38 638 GWI_OB(gwi_class_ini(gwi, "Gain", "UGen"))
39 638 gwi_class_xtor(gwi, gain_ctor, basic_dtor);
40 638 gwi_func_ini(gwi, "float", "gain");
41 638 GWI_BB(gwi_func_end(gwi, gain_get_gain, ae_flag_none))
42 638 gwi_func_ini(gwi, "float", "gain");
43 638 gwi_func_arg(gwi, "float", "arg0");
44 638 GWI_BB(gwi_func_end(gwi, gain_set_gain, ae_flag_none))
45 638 return gwi_class_end(gwi);
46 }
47
48 18 static TICK(impulse_tick) {
49 18 u->out = *(m_float *)u->module.gen.data;
50 18 *(m_float *)u->module.gen.data = 0;
51 18 }
52
53 7 static CTOR(impulse_ctor) {
54 7 ugen_ini(shred->info->vm->gwion, UGEN(o), 0, 1);
55 7 ugen_gen(shred->info->vm->gwion, UGEN(o), impulse_tick,
56 (m_float *)xmalloc(SZ_FLOAT), 0);
57 7 *(m_float *)UGEN(o)->module.gen.data = 0;
58 7 }
59
60 1 static MFUN(impulse_get_next) {
61 1 *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data;
62 1 }
63
64 8 static MFUN(impulse_set_next) {
65 8 *(m_float *)RETURN =
66 8 (*(m_float *)UGEN(o)->module.gen.data = *(m_float *)MEM(SZ_INT));
67 8 }
68
69 638 static GWION_IMPORT(impulse) {
70 638 GWI_OB(gwi_class_ini(gwi, "Impulse", "UGen"))
71 638 gwi_class_xtor(gwi, impulse_ctor, basic_dtor);
72 638 gwi_func_ini(gwi, "float", "next");
73 638 GWI_BB(gwi_func_end(gwi, impulse_get_next, ae_flag_none))
74 638 gwi_func_ini(gwi, "float", "next");
75 638 gwi_func_arg(gwi, "float", "arg0");
76 638 GWI_BB(gwi_func_end(gwi, impulse_set_next, ae_flag_none))
77 638 return gwi_class_end(gwi);
78 }
79
80 2 static TICK(fullrect_tick) { u->out = fabs(u->in); }
81
82 1 static CTOR(fullrect_ctor) {
83 1 ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1);
84 1 ugen_gen(shred->info->vm->gwion, UGEN(o), fullrect_tick,
85 (m_float *)xmalloc(SZ_FLOAT), 0);
86 1 *(m_float *)UGEN(o)->module.gen.data = 1;
87 1 }
88
89 638 static GWION_IMPORT(fullrect) {
90 638 GWI_OB(gwi_class_ini(gwi, "FullRect", "UGen"))
91 638 gwi_class_xtor(gwi, fullrect_ctor, basic_dtor);
92 638 return gwi_class_end(gwi);
93 }
94
95 2 static TICK(halfrect_tick) {
96
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (u->in > 0)
97 1 u->out = u->in;
98 else
99 1 u->out = 0;
100 2 }
101
102 1 static CTOR(halfrect_ctor) {
103 1 ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1);
104 1 ugen_gen(shred->info->vm->gwion, UGEN(o), halfrect_tick,
105 (m_float *)xmalloc(SZ_FLOAT), 0);
106 1 *(m_float *)UGEN(o)->module.gen.data = 1;
107 1 }
108
109 638 static GWION_IMPORT(halfrect) {
110 638 GWI_OB(gwi_class_ini(gwi, "HalfRect", "UGen"))
111 638 gwi_class_xtor(gwi, halfrect_ctor, basic_dtor);
112 638 return gwi_class_end(gwi);
113 }
114
115 1 static TICK(step_tick) { u->out = *(m_float *)u->module.gen.data; }
116
117 1 static CTOR(step_ctor) {
118 1 ugen_ini(shred->info->vm->gwion, UGEN(o), 0, 1);
119 1 ugen_gen(shred->info->vm->gwion, UGEN(o), step_tick,
120 (m_float *)xmalloc(SZ_FLOAT), 0);
121 1 *(m_float *)UGEN(o)->module.gen.data = 0;
122 1 }
123
124 1 static MFUN(step_get_next) {
125 1 *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data;
126 1 }
127
128 1 static MFUN(step_set_next) {
129 1 *(m_float *)RETURN = *(m_float *)UGEN(o)->module.gen.data =
130 1 *(m_float *)(shred->mem + SZ_INT);
131 1 }
132
133 638 static GWION_IMPORT(step) {
134 638 GWI_OB(gwi_class_ini(gwi, "Step", "UGen"))
135 638 gwi_class_xtor(gwi, step_ctor, basic_dtor);
136 638 gwi_func_ini(gwi, "float", "next");
137 638 GWI_BB(gwi_func_end(gwi, step_get_next, ae_flag_none))
138 638 gwi_func_ini(gwi, "float", "next");
139 638 gwi_func_arg(gwi, "float", "arg0");
140 638 GWI_BB(gwi_func_end(gwi, step_set_next, ae_flag_none))
141 638 return gwi_class_end(gwi);
142 }
143
144 4 static TICK(zerox_tick) {
145
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
4 m_float in = (u->in < 0) ? -1 : (u->in > 0);
146 4 m_float f = *(m_float *)u->module.gen.data;
147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 u->out = f == in ? 1 : 0;
148 4 *(m_float *)u->module.gen.data = in;
149 4 }
150
151 1 static CTOR(zerox_ctor) {
152 1 ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1);
153 1 ugen_gen(shred->info->vm->gwion, UGEN(o), zerox_tick,
154 (m_float *)xmalloc(SZ_FLOAT), 0);
155 1 *(m_float *)UGEN(o)->module.gen.data = 1;
156 1 }
157
158 638 static GWION_IMPORT(zerox) {
159 638 GWI_OB(gwi_class_ini(gwi, "ZeroX", "UGen"))
160 638 gwi_class_xtor(gwi, zerox_ctor, basic_dtor);
161 638 return gwi_class_end(gwi);
162 }
163
164 struct UUGen_ {
165 M_Object self;
166 VM_Code code;
167 VM_Shred shred;
168 void (*prep)(struct UUGen_ *, const m_float);
169 };
170
171 ANN static void global_prep(struct UUGen_ *uu, const m_float in) {
172 *(m_float *)uu->shred->mem = in;
173 }
174
175 ANN static void member_prep(struct UUGen_ *uu, const m_float in) {
176 *(M_Object *)uu->shred->mem = uu->self;
177 *(m_float *)(uu->shred->mem + SZ_INT) = in;
178 }
179
180 static TICK(id_tick) { u->out = u->in; }
181
182 static TICK(usrugen_tick) {
183 struct UUGen_ *uu = u->module.gen.data;
184 uu->prep(uu, u->in);
185 uu->shred->pc = 0;
186 shredule(uu->shred->tick->shreduler, uu->shred, 0);
187 vm_run(uu->shred->info->vm);
188 uu->shred->reg -= SZ_FLOAT;
189 u->out = *(m_float *)(uu->shred->reg);
190 }
191
192 static CTOR(usrugen_ctor) {
193 struct UUGen_ *uu = mp_calloc(shred->info->mp, UUGen);
194 uu->self = o;
195 ugen_ini(shred->info->vm->gwion, UGEN(o), 1, 1);
196 ugen_gen(shred->info->vm->gwion, UGEN(o), id_tick, uu, 0);
197 }
198
199 static DTOR(usrugen_dtor) {
200 struct UUGen_ *uu = UGEN(o)->module.gen.data;
201 if (uu->shred) free_vm_shred(uu->shred);
202 mp_free(shred->info->mp, UUGen, UGEN(o)->module.gen.data);
203 }
204
205 9 static OP_CHECK(opck_usrugen) {
206 9 Exp_Binary * bin = (Exp_Binary *)data;
207 9 const Arg_List arg = bin->lhs->type->info->func->def->base->args;
208
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
9 if (!arg || arg->len > 1)
209 2 ERR_N(exp_self(bin)->pos,
210 _("Tick function take one and only one argument"));
211
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (isa(((Arg*)(arg->ptr))->type, env->gwion->type[et_float]) < 0)
212 1 ERR_N(exp_self(bin)->pos,
213 _("Tick functions argument must be of type float"));
214 6 if (isa(bin->lhs->type->info->func->def->base->ret_type,
215
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 env->gwion->type[et_float]) < 0)
216 1 ERR_N(exp_self(bin)->pos, _("Tick function must return float"));
217
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (bin->lhs->type->info->func->value_ref->from->owner_class)
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 CHECK_BN(isa(bin->lhs->type->info->func->value_ref->from->owner_class,
219 bin->rhs->type));
220 5 return bin->rhs->type;
221 }
222
223 static INSTR(UURet) { shreduler_remove(shred->tick->shreduler, shred, false); }
224
225 ANN static void code_prepare(const VM_Code code) {
226 m_bit *byte = code->bytecode;
227 for (m_uint i = 0; i < vector_size(&code->instr); ++i) {
228 if (*(m_bit *)(byte + i * BYTECODE_SZ) == eFuncReturn) {
229 *(m_bit *)(byte + i * BYTECODE_SZ) = eOP_MAX;
230 *(f_instr *)(byte + (i * BYTECODE_SZ) + SZ_INT * 2) = UURet;
231 }
232 }
233 }
234
235 static MFUN(default_tick) {
236 struct UUGen_ *uu = UGEN(o)->module.gen.data;
237 if (uu->shred) {
238 free_vm_shred(uu->shred);
239 uu->shred = NULL;
240 }
241 UGEN(o)->module.gen.tick = id_tick;
242 }
243
244 static INSTR(UsrUGenTick) {
245 const m_uint offset = !instr->m_val ? SZ_INT : 0;
246 shred->reg -= SZ_INT * 2 - offset;
247 const M_Object o = *(M_Object *)(shred->reg + SZ_INT - offset);
248 struct UUGen_ *uu = UGEN(o)->module.gen.data;
249 if (uu->shred) {
250 free_vm_shred(uu->shred);
251 return;
252 }
253 UGEN(o)->module.gen.tick = usrugen_tick;
254 const VM_Code code = *(VM_Code *)(shred->reg - offset);
255 if (!code) {
256 handle(shred, "NullTickException");
257 return;
258 }
259 uu->shred = new_vm_shred(shred->info->mp, *(VM_Code *)(shred->reg - offset));
260 vmcode_addref(*(VM_Code *)(shred->reg - offset));
261 uu->shred->info->vm = shred->info->vm;
262 code_prepare(vmcode_callback(shred->info->mp, uu->shred->code));
263 shreduler_ini(uu->shred->tick->shreduler, uu->shred);
264 uu->prep = instr->m_val ? member_prep : global_prep;
265 *(M_Object *)(shred->reg - SZ_INT) = o;
266 }
267
268 static OP_EMIT(opem_usrugen) {
269 Exp_Binary *bin = (Exp_Binary *)data;
270 const Instr instr = emit_add_instr(emit, UsrUGenTick);
271 instr->m_val = !!bin->lhs->type->info->func->value_ref->from->owner_class;
272 return GW_OK;
273 }
274
275 638 static GWION_IMPORT(usrugen) {
276 638 GWI_OB(gwi_class_ini(gwi, "UsrUGen", "UGen"))
277 638 gwi_class_xtor(gwi, usrugen_ctor, usrugen_dtor);
278 638 GWI_BB(gwi_func_ini(gwi, "int", "default_tick"))
279 638 GWI_BB(gwi_func_end(gwi, default_tick, 0))
280 638 GWI_BB(gwi_class_end(gwi))
281 638 GWI_BB(gwi_oper_ini(gwi, "function", "UsrUGen", "UsrUGen"))
282 638 GWI_BB(gwi_oper_add(gwi, opck_usrugen))
283 638 GWI_BB(gwi_oper_emi(gwi, opem_usrugen))
284 638 GWI_BB(gwi_oper_end(gwi, "~=>", NULL))
285 638 return GW_OK;
286 }
287
288 638 GWION_IMPORT(modules) {
289 638 GWI_BB(gwimport_gain(gwi))
290 638 GWI_BB(gwimport_impulse(gwi))
291 638 GWI_BB(gwimport_fullrect(gwi))
292 638 GWI_BB(gwimport_halfrect(gwi))
293 638 GWI_BB(gwimport_step(gwi))
294 638 GWI_BB(gwimport_zerox(gwi))
295 638 return gwimport_usrugen(gwi);
296 }
297