} Arg;
ANN void arg_release(Arg*);
-ANN void arg_parse(Arg*);
+ANN void arg_parse(const Gwion, Arg*);
#endif
ANEW ANN Emitter new_emitter(MemPool);
ANN void free_emitter(MemPool, Emitter);
-ANEW ANN VM_Code emit_code(const Emitter);
ANN m_bool emit_ast(const Env env, Ast ast);
ANN Instr emit_exp_call1(const Emitter, const Func);
ANN2(1) Instr emit_add_instr(const Emitter, const f_instr) __attribute__((returns_nonnull));
#ifndef __GWIONDATA
#define __GWIONDATA
-
+typedef struct Env_* Env;
+typedef m_bool (*compilation_pass)(Env, Ast);
typedef struct GwionData_ {
struct Map_ freearg;
MUTEX_TYPE mutex;
struct Vector_ child;
struct Vector_ reserved;
+ struct Map_ pass_map;
+ struct Vector_ pass;
} GwionData;
ANN GwionData* new_gwiondata(MemPool);
--- /dev/null
+#ifndef __GWIONPASS
+#define __GWIONPASS
+typedef m_bool (*compilation_pass)(Env, Ast);
+
+ANN void pass_register(const Gwion, const m_str, const compilation_pass);
+ANN void pass_default(const Gwion);
+ANN m_bool pass_set(const Gwion, const Vector);
+#endif
#include <string.h>
#include "gwion_util.h"
-#include "arg.h"
+#include "gwion_ast.h"
#include "soundinfo.h"
+#include "oo.h"
+#include "vm.h"
+#include "gwion.h"
+#include "arg.h"
+#include "pass.h"
+
#define GWIONRC ".gwionrc"
/* use before MemPool allocation */
vector_init(&arg->lib);
vector_init(&arg->mod);
vector_init(&arg->config);
-// vector_add(&arg->lib, (vtype)GWPLUG_DIR);
vector_add(&arg->lib, (vtype)plug_dir());
}
" -i <number> : set input channel number\n"
" -o <number> : set output channel number\n"
" -d <number> : set driver (and arguments)\n"
+" -l <number> : set loop mode\n"
" -z <number> : set memoization limit\n"
-" -m <mod:args> : load module (and arguments)\n";
+" -m <mod:args> : load module (and arguments)\n"
+" -g <mod:args> : set Gwion compiler passes order\n";
-ANN static void config_parse(Arg* arg, const m_str name);
+ANN static void config_parse(const Gwion, Arg*, const m_str);
#define CASE(a,b) case a: (b) ; break;
#define get_arg(a) (a[i][2] == '\0' ? arg->argv[++i] : a[i] + 2)
#define ARG2INT(a) strtol(get_arg(a), NULL, 10)
-ANN void _arg_parse(Arg* arg) {
+ANN2(1) static inline void arg_set_pass(const Gwion gwion, const m_str str) {
+ if(!str)
+ gw_err(_("needs arguments"));
+ const Vector v = split_args(gwion->mp, str);
+ pass_set(gwion, v);
+ for(m_uint i = 0; i < vector_size(v); ++i)
+ free_mstr(gwion->mp, (m_str)vector_at(v, i));
+ free_vector(gwion->mp, v);
+}
+
+ANN void _arg_parse(const Gwion gwion, Arg* arg) {
for(int i = 1; i < arg->argc; ++i) {
if(arg->argv[i][0] == '-') {
switch(arg->argv[i][1]) {
CASE('h', gw_err(usage))
CASE('k', gw_err("CFLAGS: %s\nLDFLAGS: %s\n", CFLAGS, LDFLAGS))
- CASE('c', config_parse(arg, get_arg(arg->argv)))
+ CASE('c', config_parse(gwion, arg, get_arg(arg->argv)))
CASE('p', vector_add(&arg->lib, (vtype)get_arg(arg->argv)))
CASE('m', vector_add(&arg->mod, (vtype)get_arg(arg->argv)))
CASE('l', arg->loop = (m_bool)ARG2INT(arg->argv) > 0 ? 1 : -1)
CASE('o', arg->si->out = (uint8_t)ARG2INT(arg->argv))
CASE('s', arg->si->sr = (uint32_t)ARG2INT(arg->argv))
CASE('d', arg->si->arg = get_arg(arg->argv))
+ CASE('g', arg_set_pass(gwion, get_arg(arg->argv)))
}
} else
vector_add(&arg->add, (vtype)arg->argv[i]);
return v;
}
-ANN static void config_parse(Arg* arg, const m_str name) {
+ANN static void config_parse(const Gwion gwion, Arg* arg, const m_str name) {
const Vector v = get_config(name);
if(v) {
int argc = arg->argc;
char** argv = arg->argv;
arg->argc = vector_size(v);
arg->argv = (m_str*)(v->ptr + OFFSET);
- _arg_parse(arg);
+ _arg_parse(gwion, arg);
arg->argc = argc;
arg->argv = argv;
vector_add(&arg->config, (vtype)v);
}
}
-ANN static void config_default(Arg* arg) {
+ANN static void config_default(const Gwion gwion , Arg* arg) {
char* home = getenv("HOME");
char c[strlen(home) + strlen(GWIONRC) + 2];
sprintf(c, "%s/%s", home, GWIONRC);
- config_parse(arg, c);
+ config_parse(gwion, arg, c);
}
-ANN void arg_parse(Arg* a) {
+ANN void arg_parse(const Gwion gwion, Arg* a) {
arg_init(a);
- config_default(a);
- _arg_parse(a);
+ config_default(gwion, a);
+ _arg_parse(gwion, a);
}
struct ScannerArg_ arg = { c->name, c->file, gwion->st };
CHECK_OB((c->ast = parse(&arg)))
gwion->env->name = c->name;
- return type_engine_check_prog(gwion->env, c->ast);
-}
-/*
-static m_bool check(struct Gwion_* gwion, struct Compiler* c) {
- MUTEX_LOCK(gwion->data->mutex);
- const m_bool ret = _check(gwion, c);
- MUTEX_UNLOCK(gwion->data->mutex);
- return ret;
+ for(m_uint i = 0; i < vector_size(&gwion->data->pass); ++i) {
+ const compilation_pass pass = (compilation_pass)vector_at(&gwion->data->pass, i);
+ CHECK_BB(pass(gwion->env, c->ast))
+ }
+ return GW_OK;
}
-*/
+
static m_uint _compile(struct Gwion_* gwion, struct Compiler* c) {
CHECK_BB(compiler_open(gwion->mp, c))
- if(_check(gwion, c) < 0 || emit_ast(gwion->env, c->ast) < 0) {
+ if(_check(gwion, c) < 0) {
gw_err(_("while compiling file '%s'\n"), c->base);
return 0;
}
return ret;
}
-/*
-m_bool check_filename(struct Gwion_* vm, const m_str filename) {
- struct Compiler c = { .base=filename, .type=COMPILE_NAME };
- CHECK_BB(compiler_open(gwion->mp, c))
- return check(&c, vm);
-}
-
-m_bool check_string(struct Gwion_* vm, const m_str filename, const m_str data) {
- struct Compiler c = { .base=filename, .type=COMPILE_MSTR, .data=data };
- CHECK_BB(compiler_open(gwion->mp, c))
- return check(&c, vm);
-}
-
-m_bool check_file(struct Gwion_* vm, const m_str filename, FILE* file) {
- struct Compiler c = { .base=filename, .type=COMPILE_FILE, .file = file};
- CHECK_BB(compiler_open(gwion->mp, c))
- return check(&c, vm);
-}
-*/
-//m_uint compile_filename(struct Gwion_* vm, const m_str filename) {
m_uint compile_filename(struct Gwion_* gwion, const m_str filename) {
struct Compiler c = { .base=filename, .type=COMPILE_NAME };
return compile(gwion, &c);
return GW_OK;
}
-ANEW ANN VM_Code emit_code(const Emitter emit) {
- Code* c = emit->code;
- const VM_Code code = new_vm_code(emit->gwion->mp, &c->instr, c->stack_depth,
- c->flag, c->name);
- free_code(emit->gwion->mp, c);
- return code;
-}
-
ANN static VM_Code finalyze(const Emitter emit, const f_instr exec) {
emit_add_instr(emit, exec);
- const VM_Code code = emit_code(emit);
+ const VM_Code code = emit->info->emit_code(emit);
+ free_code(emit->gwion->mp, emit->code);
emit->code = (Code*)vector_pop(&emit->stack);
return code;
}
#include "emit.h"
#include "escape.h"
+static ANEW ANN VM_Code emit_code(const Emitter emit) {
+ Code* const c = emit->code;
+ const VM_Code code = new_vm_code(emit->gwion->mp, &c->instr, c->stack_depth,
+ c->flag, c->name);
+ return code;
+}
+
ANEW Emitter new_emitter(MemPool p) {
Emitter emit = (Emitter)mp_calloc(p, Emitter);
vector_init(&emit->stack);
vector_init(&emit->info->pure);
vector_init(&emit->info->variadic);
emit->info->escape = escape_table(p);
+ emit->info->emit_code = emit_code;
emit->info->finalyzer = EOC;
return emit;
}
#include "emit.h"
#include "engine.h"
#include "driver.h"
-#include "arg.h"
#include "gwion.h"
+#include "arg.h"
#include "compile.h"
#include "object.h" // fork_clean
+#include "pass.h" // fork_clean
ANN m_bool gwion_audio(const Gwion gwion) {
Driver* di = gwion->vm->bbq;
gwion->vm->gwion = gwion;
gwion->env->gwion = gwion;
gwion->vm->bbq->si = new_soundinfo(gwion->mp);
+ gwion->data = new_gwiondata(gwion->mp);
+ pass_default(gwion);
arg->si = gwion->vm->bbq->si;
- arg_parse(arg);
+ arg_parse(gwion, arg);
gwion->emit->info->memoize = arg->memoize;
gwion->plug = new_plug(gwion->mp, &arg->lib);
- gwion->data = new_gwiondata(gwion->mp);
+// map_set(&gwion->data->pass_map, (vtype)"check", (vtype)type_engine_check_prog);
+// map_set(&gwion->data->pass_map, (vtype)"emit", (vtype)emit_ast);
+// vector_add(&gwion->data->pass, (vtype)type_engine_check_prog);
+// vector_add(&gwion->data->pass, (vtype)emit_ast);
shreduler_set_loop(gwion->vm->shreduler, arg->loop);
if(gwion_audio(gwion) > 0 && gwion_engine(gwion)) {
gwion_compile(gwion, &arg->add);
#include "gwion_util.h"
+#include "gwion_ast.h"
#include "gwiondata.h"
ANN GwionData* new_gwiondata(MemPool mp) {
struct GwionData_ *data = mp_calloc(mp, GwionData);
map_init(&data->freearg);
vector_init(&data->reserved);
+ map_init(&data->pass_map);
+ vector_init(&data->pass);
MUTEX_SETUP(data->mutex);
return data;
}
ANN void free_gwiondata(MemPool mp, GwionData *data) {
map_release(&data->freearg);
vector_release(&data->reserved);
+ map_release(&data->pass_map);
+ vector_release(&data->pass);
MUTEX_CLEANUP(data->mutex);
mp_free(mp, GwionData, data);
}
--- /dev/null
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "instr.h"
+#include "emit.h"
+#include "gwion.h"
+#include "pass.h"
+
+static const m_str default_passes_name[] = { "check", "emit" };
+static const compilation_pass default_passes[] = { type_engine_check_prog, emit_ast };
+#define NPASS sizeof(default_passes)/sizeof(default_passes[0])
+
+ANN void pass_register(const Gwion gwion, const m_str name, const compilation_pass pass) {
+ const Symbol sym = insert_symbol(gwion->st, name);
+ map_set(&gwion->data->pass_map, (vtype)sym, (vtype)pass);
+}
+
+ANN m_bool pass_set(const Gwion gwion, const Vector passes) {
+ const Vector v = &gwion->data->pass;
+ vector_clear(v);
+ for(m_uint i = 0; i < vector_size(passes); ++i) {
+ const m_str name = (m_str)vector_at(passes, i);
+ const Symbol sym = insert_symbol(gwion->st, name);
+ const compilation_pass pass = (compilation_pass)map_get(&gwion->data->pass_map, (vtype)sym);
+ if(!pass) {
+ gw_err("Failed to set compilation passes, back to default");
+ pass_default(gwion);
+ return GW_ERROR;
+ }
+ vector_add(v, (vtype)pass);
+ }
+ return GW_OK;
+}
+
+ANN void pass_default(const Gwion gwion) {
+ struct Vector_ v;
+ vector_init(&v);
+ for(m_uint i = 0; i < NPASS; ++i) {
+ vector_add(&v, (vtype)default_passes_name[i]);
+ pass_register(gwion, default_passes_name[i], default_passes[i]);
+ }
+ pass_set(gwion, &v);
+ vector_release(&v);
+}
}
ANN Vector split_args(MemPool p, const m_str str) {
- const m_str arg = strchr(str, '=');
- if(!arg)
- return NULL;
const Vector args = new_vector(p);
- m_str d = strdup(arg+1);
- while(d)
- vector_add(args, (vtype)mstrdup(p, strsep(&d, ",")));
+ m_str d = strdup(str), e = d;
+ while(e)
+ vector_add(args, (vtype)mstrdup(p, strsep(&e, ",")));
xfree(d);
return args;
}
const m_str str = (m_str)vector_at(v, i - 1);
if(!strncmp(name, str, len)) {
vector_rem(v, i-1);
- return split_args(p, str);
+ const m_str arg = strchr(str, '=');
+ return arg ? split_args(p, str) : NULL;
}
}
return NULL;
#!/bin/bash
-# [test] #15
+# [test] #16
n=0
[ "$1" ] && n="$1"
[ "$n" -eq 0 ] && n=1
n=$((n+1))
run "$n" "Kompile time Konfig" "-k" "file"
+# set compilation passes
+n=$((n+1))
+run "$n" "just check" "-g check" "file"
+
# test signal
./gwion -l1 &
PID=$!