From 3c0aba97a3f2ead50d1662626a1a00a6e9cccf08 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sat, 22 Feb 2020 23:09:08 +0100 Subject: [PATCH] :art: Refactor Gack --- include/gack.h | 8 +++++ include/opcode.h | 4 +-- opcode.txt | 2 +- src/emit/emit.c | 14 ++++----- src/lib/complex.c | 5 +-- src/lib/engine.c | 17 +++++----- src/lib/gack.c | 80 +++++++++++++++++++++++++++++++++++------------ src/lib/object.c | 3 +- src/lib/prim.c | 4 ++- src/lib/string.c | 3 +- src/lib/vec.c | 5 +-- src/vm/vm.c | 10 ++++-- 12 files changed, 106 insertions(+), 49 deletions(-) diff --git a/include/gack.h b/include/gack.h index d8a72e88..be039776 100644 --- a/include/gack.h +++ b/include/gack.h @@ -1,4 +1,12 @@ #ifndef __GACK #define __GACK ANN void gack(const VM_Shred, const Instr); + +#define INTERP_PRINTF(fmt, ...) { \ + m_str ret = *(m_str*)(VALUE - SZ_INT);\ + gw_asprintf(shred->info->vm->gwion->mp, &ret, fmt, ##__VA_ARGS__); \ + *(m_str*)(VALUE - SZ_INT) = ret;\ +} + +ANN2(2) int gw_asprintf(MemPool mp, char **str, const char *fmt, ...); #endif diff --git a/include/opcode.h b/include/opcode.h index 730c3f38..de85bdeb 100644 --- a/include/opcode.h +++ b/include/opcode.h @@ -170,7 +170,7 @@ enum { eGcAdd, eGcEnd, eGack, - eGack3, + eGackEnd, eNoOp, eDotTmplVal, eOP_MAX, @@ -346,7 +346,7 @@ enum { #define GcAdd (f_instr)eGcAdd #define GcEnd (f_instr)eGcEnd #define Gack (f_instr)eGack -#define Gack3 (f_instr)eGack3 +#define GackEnd (f_instr)eGackEnd #define NoOp (f_instr)eNoOp #define DotTmplVal (f_instr)eDotTmplVal #define OP_MAX (f_instr)eOP_MAX diff --git a/opcode.txt b/opcode.txt index ac8fb174..404f82cf 100644 --- a/opcode.txt +++ b/opcode.txt @@ -167,7 +167,7 @@ GcIni GcAdd GcEnd Gack -Gack3 +GackEnd NoOp DotTmplVal OP_MAX diff --git a/src/emit/emit.c b/src/emit/emit.c index 169484f8..708a5b11 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -163,6 +163,7 @@ ANN static inline Instr reg##name(const Emitter emit, const m_uint sz) { \ return instr; \ } regxxx(pop, Pop) +regxxx(push, Push) regxxx(pushi, PushImm) regxxx(seti, SetImm) @@ -598,6 +599,7 @@ ANN static m_bool emit_prim_str(const Emitter emit, const m_str *str) { } ANN static m_bool emit_prim_hack(const Emitter emit, const Exp *exp) { + regpushi(emit, 0); Exp e = *exp, next = NULL; do { next = e->next; @@ -611,7 +613,7 @@ ANN static m_bool emit_prim_hack(const Emitter emit, const Exp *exp) { instr->m_val2 = emit_code_offset(emit); } while((e = e->next = next)); if(!(emit->env->func && emit->env->func->def->base->xid == insert_symbol("@gack"))) - emit_add_instr(emit, Gack3); + emit_add_instr(emit, GackEnd); return GW_OK; } @@ -807,14 +809,9 @@ ANN static m_uint get_decl_size(Var_Decl_List a) { return size; } -ANN static m_uint pop_exp_size(const Emitter emit, Exp e) { +ANN static m_uint pop_exp_size(Exp e) { m_uint size = 0; do { - if(e->exp_type == ae_exp_primary && - e->d.prim.prim_type == ae_prim_hack) { - size += pop_exp_size(emit, e->d.prim.d.exp); - continue; - } size += (e->exp_type == ae_exp_decl ? get_decl_size(e->d.exp_decl.list) : e->type->size); } while((e = e->next)); @@ -822,7 +819,7 @@ ANN static m_uint pop_exp_size(const Emitter emit, Exp e) { } ANN static inline void pop_exp(const Emitter emit, Exp e) { - const m_uint size = pop_exp_size(emit, e); + const m_uint size = pop_exp_size(e); if(size) regpop(emit, size); } @@ -1873,6 +1870,7 @@ ANN static VM_Code emit_internal(const Emitter emit, const Func f) { ADD_REF(f->code) return f->code; } else if(f->def->base->xid == insert_symbol("@gack")) { + regpush(emit, SZ_INT); f->code = finalyze(emit, FuncReturn); return emit->env->class_def->e->gack = f->code; } diff --git a/src/lib/complex.c b/src/lib/complex.c index 64079ce2..5abd7981 100644 --- a/src/lib/complex.c +++ b/src/lib/complex.c @@ -10,6 +10,7 @@ #include "import.h" #include "gwi.h" +#include "gack.h" #define describe(name, op) \ static INSTR(Complex##name) {\ @@ -114,11 +115,11 @@ polar_def2_r(Mul, *, +) polar_def2_r(Div, /, -) static GACK(gack_complex) { - gw_out("#(%.4f, %.4f)", *(m_float*)VALUE, *(m_float*)(VALUE + SZ_FLOAT)); + INTERP_PRINTF("#(%.4f, %.4f)", *(m_float*)VALUE, *(m_float*)(VALUE + SZ_FLOAT)); } static GACK(gack_polar) { - gw_out("%%(%.4f, %.4f*pi)", *(m_float*)VALUE, *(m_float*)(VALUE + SZ_FLOAT) / M_PI); + INTERP_PRINTF("%%(%4f, %.4f*pi)", *(m_float*)VALUE, *(m_float*)(VALUE + SZ_FLOAT) / M_PI); } EQUALITY_OPER(complex, SZ_COMPLEX) diff --git a/src/lib/engine.c b/src/lib/engine.c index 23dc1969..bcd5ca0a 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -15,38 +15,39 @@ #include "parser.h" #include "lang_private.h" #include "specialid.h" +#include "gack.h" static GACK(gack_class) { const Type type = actual_type(shred->info->vm->gwion, t) ?: t; - gw_out("class(%s)", type->name); + INTERP_PRINTF("class(%s)", type->name) } static GACK(gack_function) { - gw_out("%s", t->name); + INTERP_PRINTF("%s", t->name) } static GACK(gack_fptr) { const VM_Code code = *(VM_Code*)VALUE; if(code) - gw_out("%s", code->name); + INTERP_PRINTF("%s", code->name) else - gw_out("%s", t->name); + INTERP_PRINTF("%s", t->name) } static GACK(gack_void) { - gw_out("(void)"); + INTERP_PRINTF("void"); } static GACK(gack_int) { - gw_out("%"INT_F, *(m_uint*)VALUE); + INTERP_PRINTF("%"INT_F, *(m_uint*)VALUE); } static GACK(gack_char) { - gw_out("%c", *(char*)VALUE); + INTERP_PRINTF("%c", *(char*)VALUE); } static GACK(gack_float) { - gw_out("%.4f", *(m_float*)VALUE); + INTERP_PRINTF("%.4f", *(m_float*)VALUE); } #define mk_class_instr(op, arg0, arg1, ...) \ diff --git a/src/lib/gack.c b/src/lib/gack.c index dedcf095..4b2af557 100644 --- a/src/lib/gack.c +++ b/src/lib/gack.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include "gwion_util.h" #include "gwion_ast.h" #include "gwion_env.h" @@ -12,24 +12,64 @@ #include "import.h" #include "gack.h" +ANN2(1) static int fmtlen(const char *fmt, va_list args) { + va_list tmpa; + va_copy(tmpa, args); + const int size = vsnprintf(NULL, 0, fmt, tmpa); + va_end(tmpa); + return size; +} + +ANN2(2) static int gw_vasprintf(MemPool mp, char **str, const char *fmt, va_list args) { + char *base = *str; + const size_t base_len = base ? strlen(base) : 0; + DECL_BB(const int, size, = fmtlen(fmt, args)) + char *ret = mp_malloc2(mp, base_len + size + 1); + if(base) + strcpy(ret, base); + DECL_BB(const int, final_len, = vsprintf(ret + base_len, fmt, args)) + if(base) + mp_free2(mp, strlen(base), base); + *str = ret; + return final_len; +} + +ANN2(2) int gw_asprintf(MemPool mp, char **str, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + const int ret = gw_vasprintf(mp, str, fmt, args); + va_end(args); + return ret; +} + +__attribute__((returns_nonnull)) +ANN static inline VM_Code get_gack(Type t) { + do if(t->e->gack) + return t->e->gack; + while((t = t->e->parent)); + return NULL; // unreachable +} + +ANN static void prepare_call(const VM_Shred shred, m_uint offset) { + shred->mem += offset; + *(m_uint*)(shred->mem+ SZ_INT) = offset + SZ_INT; + *(VM_Code*)(shred->mem+ SZ_INT*2) = shred->code; + *(m_uint*)(shred->mem+ SZ_INT*3) = shred->pc; + *(m_uint*)(shred->mem+ SZ_INT*4) = SZ_INT; + shred->mem += SZ_INT*5; + *(M_Object*)(shred->mem)= *(M_Object*)(shred->reg - SZ_INT); + shred->pc = 0; +} + ANN void gack(const VM_Shred shred, const Instr instr) { - Type base = (Type)instr->m_val, t = base; - do { - if(t->e->gack) { - if(GET_FLAG(t->e->gack, builtin)) - ((f_gack)t->e->gack->native_func)(base, (shred->reg - t->size), shred); - else { - shred->mem += instr->m_val2; - *(m_uint*)(shred->mem+ SZ_INT) = instr->m_val2 + SZ_INT; - *(VM_Code*)(shred->mem+ SZ_INT*2) = shred->code; - *(m_uint*)(shred->mem+ SZ_INT*3) = shred->pc; - *(m_uint*)(shred->mem+ SZ_INT*4) = SZ_INT; - shred->mem += SZ_INT*5; - *(M_Object*)(shred->mem)= *(M_Object*)(shred->reg - SZ_INT); - shred->code = t->e->gack; - shred->pc = 0; - } - return; - } - } while((t = t->e->parent)); + Type t = (Type)instr->m_val; + const VM_Code code = get_gack(t); + if(GET_FLAG(code, builtin)) { + ((f_gack)code->native_func)(t, (shred->reg - t->size), shred); + POP_REG(shred, t->size); + } else { + prepare_call(shred, instr->m_val2); + shred->code = code; + } + return; } diff --git a/src/lib/object.c b/src/lib/object.c index 5078fc39..21d271b9 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -15,6 +15,7 @@ #include "specialid.h" #include "gwi.h" +#include "gack.h" #undef insert_symbol ANN void exception(const VM_Shred shred, const m_str c) { @@ -221,7 +222,7 @@ static ID_CHECK(check_this) { } static GACK(gack_object) { - gw_out("%p", *(M_Object*)VALUE); + INTERP_PRINTF("%p", *(M_Object*)VALUE); } GWION_IMPORT(object) { diff --git a/src/lib/prim.c b/src/lib/prim.c index 326e124c..2846045d 100644 --- a/src/lib/prim.c +++ b/src/lib/prim.c @@ -14,6 +14,7 @@ #include "parse.h" #include "specialid.h" #include "array.h" +#include "gack.h" #define CHECK_OP(op, check, func) _CHECK_OP(op, check, int_##func) @@ -104,7 +105,8 @@ static GWION_IMPORT(int_unary) { return GW_OK; } static GACK(gack_bool) { - gw_out("%s", *(m_uint*)VALUE ? "true" : "false"); +// gw_out("%s", *(m_uint*)VALUE ? "true" : "false"); + INTERP_PRINTF("%s", *(m_uint*)VALUE ? "true" : "false"); } static GWION_IMPORT(int_values) { diff --git a/src/lib/string.c b/src/lib/string.c index 214f9c89..f9e0e270 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -14,6 +14,7 @@ #include "emit.h" #include "specialid.h" #include "gwi.h" +#include "gack.h" ANN static void push_string(const VM_Shred shred, const M_Object obj, const m_str c) { STRING(obj) = s_name(insert_symbol(shred->info->vm->gwion->st, c)); @@ -180,7 +181,7 @@ ID_CHECK(check_funcpp) { static GACK(gack_string) { const M_Object obj = *(M_Object*)VALUE; - gw_out("%s", obj ? STRING(obj) : "(null string)"); + INTERP_PRINTF("%s", obj ? STRING(obj) : "(null string)"); } static inline m_bool bounds(const m_str str, const m_int i) { diff --git a/src/lib/vec.c b/src/lib/vec.c index 56ac9419..5f5bb40a 100644 --- a/src/lib/vec.c +++ b/src/lib/vec.c @@ -9,6 +9,7 @@ #include "import.h" #include "driver.h" #include "gwi.h" +#include "gack.h" INSTR(VecCpy) { POP_REG(shred, instr->m_val2); @@ -157,7 +158,7 @@ static void vecx_base(const Gwi gwi) { } static GACK(gack_vec3) { - gw_out("%%(%.4f, %.4f, %.4f)", *(m_float*)VALUE, *(m_float*)(VALUE + SZ_FLOAT), *(m_float*)(VALUE + SZ_FLOAT*2)); + INTERP_PRINTF("%%(%.4f, %.4f, %.4f)", *(m_float*)VALUE, *(m_float*)(VALUE + SZ_FLOAT), *(m_float*)(VALUE + SZ_FLOAT*2)); } EQUALITY_OPER(vec3, SZ_VEC3); @@ -306,7 +307,7 @@ static INSTR(Vec4RAssign) { } static GACK(gack_vec4) { - gw_out("%%(%.4f, %.4f, %.4f, %.4f)", + INTERP_PRINTF("%%(%.4f, %.4f, %.4f, %.4f)", *(m_float*)VALUE, *(m_float*)(VALUE + SZ_FLOAT), *(m_float*)(VALUE + SZ_FLOAT*2), diff --git a/src/vm/vm.c b/src/vm/vm.c index eb165a3d..7c8becf8 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -340,7 +340,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] &&staticint, &&staticfloat, &&staticother, &&dotfunc, &&dotstaticfunc, &&pushstaticcode, &&gcini, &&gcadd, &&gcend, - &&gack, &&gack3, &&noop, &®pushimm, &&other, &&eoc + &&gack, &&gackend, &&noop, &®pushimm, &&other, &&eoc }; const Shreduler s = vm->shreduler; register VM_Shred shred; @@ -853,8 +853,12 @@ gack: VM_OUT gack(shred, (Instr)VAL); goto in; -gack3: - gw_out("\n"); +gackend: +{ + m_str str = *(m_str*)(reg - SZ_INT); + gw_out("%s\n", str); + mp_free2(vm->gwion->mp, strlen(str), str); +} noop: DISPATCH(); other: -- 2.43.0