]> Nishi Git Mirror - gwion.git/commitdiff
:art: Refactor Gack
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Sat, 22 Feb 2020 22:09:08 +0000 (23:09 +0100)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Sat, 22 Feb 2020 22:09:08 +0000 (23:09 +0100)
12 files changed:
include/gack.h
include/opcode.h
opcode.txt
src/emit/emit.c
src/lib/complex.c
src/lib/engine.c
src/lib/gack.c
src/lib/object.c
src/lib/prim.c
src/lib/string.c
src/lib/vec.c
src/vm/vm.c

index d8a72e88a4b95f994b9fa257e9531ef7f37f4434..be0397767bf927cc0bc61f2f9ed11b0b4e020d2a 100644 (file)
@@ -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
index 730c3f38a78618c913688ae4d19fc729fe54793d..de85bdebb92d40eef0cb170b137ed93dd4871479 100644 (file)
@@ -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
index ac8fb17434a8707e907e55528305821f1b3b438f..404f82cf4d2ae2b7055dfee2cc7bf843648968de 100644 (file)
@@ -167,7 +167,7 @@ GcIni
 GcAdd
 GcEnd
 Gack
-Gack3
+GackEnd
 NoOp
 DotTmplVal
 OP_MAX
index 169484f84ebe5406b23c2699567ff59cc2dbefee..708a5b119cb4dbf00f21e963f7a897bf5f593e77 100644 (file)
@@ -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;
   }
index 64079ce2f5c30c55b8a2858e07c91e1f99a25b51..5abd7981d1fedeee14d16d45e4da20f4e0a24b1d 100644 (file)
@@ -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)
index 23dc1969a571b6c9d864e72fc1595cb5e2288e0e..bcd5ca0a896fa659ebb5fcb1b001c8a1699ebf35 100644 (file)
 #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, ...)                          \
index dedcf095c41d13b1cb77ed4084badb87ad5f6ed4..4b2af557788219ae0b9fc61827a60a29c03a0712 100644 (file)
@@ -1,6 +1,6 @@
 #include <stdlib.h>
 #include <string.h>
-#include <complex.h>
+#include <stdarg.h>
 #include "gwion_util.h"
 #include "gwion_ast.h"
 #include "gwion_env.h"
 #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;
 }
index 5078fc397cba4065a6ba7c749637e036e72bc608..21d271b94cc459c5d5db3a786c7456c9a72e2c28 100644 (file)
@@ -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) {
index 326e124cf5b717ccf7c6089840c7593dbd35d0b1..2846045d49578ba92cca4f4eb6836c6155b3595b 100644 (file)
@@ -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) {
index 214f9c89ea5871ca8d8008093228b787791dd048..f9e0e270c79c312c99d8d3682c622deea7ba6773 100644 (file)
@@ -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) {
index 56ac9419600f4e43135c5a2854fa320c722e78fd..5f5bb40a76506cc411da3e94fa505f56959d9ab6 100644 (file)
@@ -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),
index eb165a3d8e2d8b763df5b2346e294aaceb944890..7c8becf81b1b41fff6058e943169ed8a81ccf945 100644 (file)
@@ -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, &&regpushimm, &&other, &&eoc
+    &&gack, &&gackend, &&noop, &&regpushimm, &&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: