From 941c608e7e8bfca93e37d0e78fe9281acfdab3b1 Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Mon, 23 Sep 2019 00:27:45 +0200 Subject: [PATCH] :art: Use compilation passes --- include/arg.h | 2 +- include/emit.h | 1 - include/gwiondata.h | 5 ++++- include/pass.h | 8 ++++++++ src/arg.c | 44 ++++++++++++++++++++++++++++++------------- src/compile.c | 37 +++++++----------------------------- src/emit/emit.c | 11 ++--------- src/emit/emitter.c | 8 ++++++++ src/gwion.c | 12 +++++++++--- src/gwiondata.c | 5 +++++ src/pass.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ src/plug.c | 12 +++++------- tests/sh/opt.sh | 6 +++++- 13 files changed, 131 insertions(+), 66 deletions(-) create mode 100644 include/pass.h create mode 100644 src/pass.c diff --git a/include/arg.h b/include/arg.h index 336cfdc6..f80ac7e4 100644 --- a/include/arg.h +++ b/include/arg.h @@ -14,5 +14,5 @@ typedef struct Arg_ { } Arg; ANN void arg_release(Arg*); -ANN void arg_parse(Arg*); +ANN void arg_parse(const Gwion, Arg*); #endif diff --git a/include/emit.h b/include/emit.h index e08bc23a..8c701214 100644 --- a/include/emit.h +++ b/include/emit.h @@ -35,7 +35,6 @@ struct Emitter_ { 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)); diff --git a/include/gwiondata.h b/include/gwiondata.h index 5136b21c..5624a6b7 100644 --- a/include/gwiondata.h +++ b/include/gwiondata.h @@ -1,11 +1,14 @@ #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); diff --git a/include/pass.h b/include/pass.h new file mode 100644 index 00000000..b8bc7e65 --- /dev/null +++ b/include/pass.h @@ -0,0 +1,8 @@ +#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 diff --git a/src/arg.c b/src/arg.c index 4a06f7d2..9f26475b 100644 --- a/src/arg.c +++ b/src/arg.c @@ -1,7 +1,13 @@ #include #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 */ @@ -30,7 +36,6 @@ ANN static void arg_init(Arg* arg) { 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()); } @@ -53,22 +58,34 @@ static const char usage[] = " -i : set input channel number\n" " -o : set output channel number\n" " -d : set driver (and arguments)\n" +" -l : set loop mode\n" " -z : set memoization limit\n" -" -m : load module (and arguments)\n"; +" -m : load module (and arguments)\n" +" -g : 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) @@ -77,6 +94,7 @@ ANN void _arg_parse(Arg* arg) { 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]); @@ -113,29 +131,29 @@ ANN static Vector get_config(const m_str name) { 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); } diff --git a/src/compile.c b/src/compile.c index fd8ad67f..baadc5a5 100644 --- a/src/compile.c +++ b/src/compile.c @@ -84,19 +84,16 @@ static inline m_bool _check(struct Gwion_* gwion, struct Compiler* c) { 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; } @@ -116,26 +113,6 @@ static m_uint compile(struct Gwion_* gwion, struct Compiler* c) { 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); diff --git a/src/emit/emit.c b/src/emit/emit.c index 6c126c6f..38681317 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -362,17 +362,10 @@ ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary* prim) { 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; } diff --git a/src/emit/emitter.c b/src/emit/emitter.c index 71c8df69..060b18ec 100644 --- a/src/emit/emitter.c +++ b/src/emit/emitter.c @@ -11,6 +11,13 @@ #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); @@ -18,6 +25,7 @@ ANEW Emitter new_emitter(MemPool p) { 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; } diff --git a/src/gwion.c b/src/gwion.c index c28493a6..edb8c222 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -12,10 +12,11 @@ #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; @@ -69,11 +70,16 @@ ANN m_bool gwion_ini(const Gwion gwion, Arg* arg) { 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); diff --git a/src/gwiondata.c b/src/gwiondata.c index 8d31b053..92645bf2 100644 --- a/src/gwiondata.c +++ b/src/gwiondata.c @@ -1,10 +1,13 @@ #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; } @@ -12,6 +15,8 @@ ANN GwionData* new_gwiondata(MemPool mp) { 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); } diff --git a/src/pass.c b/src/pass.c new file mode 100644 index 00000000..9a2434cb --- /dev/null +++ b/src/pass.c @@ -0,0 +1,46 @@ +#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); +} diff --git a/src/plug.c b/src/plug.c index 281906b9..e3611a15 100644 --- a/src/plug.c +++ b/src/plug.c @@ -117,13 +117,10 @@ void free_plug(const Gwion gwion) { } 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; } @@ -134,7 +131,8 @@ ANN static Vector get_arg(MemPool p, const m_str name, const Vector v) { 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; diff --git a/tests/sh/opt.sh b/tests/sh/opt.sh index 9b733534..65c18796 100644 --- a/tests/sh/opt.sh +++ b/tests/sh/opt.sh @@ -1,5 +1,5 @@ #!/bin/bash -# [test] #15 +# [test] #16 n=0 [ "$1" ] && n="$1" [ "$n" -eq 0 ] && n=1 @@ -68,6 +68,10 @@ run "$n" "module argument" "-mfake:test" "file" 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=$! -- 2.43.0