]> Nishi Git Mirror - gwion.git/commitdiff
:wrench: Introduce perform
authorJérémie Astor <fennecdjay@gmail.com>
Wed, 21 Apr 2021 23:18:44 +0000 (01:18 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Wed, 21 Apr 2021 23:18:44 +0000 (01:18 +0200)
15 files changed:
ast
include/opcode.h
include/vm.h
plug
src/emit/emit.c
src/lib/array.c
src/lib/engine.c
src/lib/instr.c
src/lib/modules.c
src/lib/ptr.c
src/lib/string.c
src/lib/ugen.c
src/lib/vararg.c
src/parse/check.c
src/vm/vm.c

diff --git a/ast b/ast
index 742af1c3723d56bef451ca480904689927ac7f7f..039b37610ecc8f3ed162e6a9f7a20b1612109dea 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 742af1c3723d56bef451ca480904689927ac7f7f
+Subproject commit 039b37610ecc8f3ed162e6a9f7a20b1612109dea
index 77410da206c69c6137219906de6d92ade7603e06..fab83001aa37c4acfc957a7cede4a9bfeef9815d 100644 (file)
@@ -186,6 +186,7 @@ enum {
   eTryIni,
   eTryEnd,
   eHandleEffect,
+  ePerformEffect,
   eNoOp,
   eEOC,
   eUnroll2,
@@ -378,6 +379,7 @@ enum {
 #define  TryIni               (f_instr)eTryIni
 #define  TryEnd               (f_instr)eTryEnd
 #define  HandleEffect         (f_instr)eHandleEffect
+#define  PerformEffect        (f_instr)ePerformEffect
 #define  NoOp                 (f_instr)eNoOp
 #define  EOC                  (f_instr)eEOC
 #define  Unroll2              (f_instr)eUnroll2
index 1911d73ed790e1a911b00683bf511923bf7f555e..3e3b8cf2f0e40ad4f753e72309dad048271de656 100644 (file)
@@ -107,4 +107,5 @@ ANN m_str code_name_set(MemPool p, const m_str, const m_str);
 ANN m_str code_name(const m_str, const bool);
 ANN uint32_t gw_rand(uint32_t s[2]);
 ANN void gw_seed(uint32_t s[2], const uint64_t);
+ANN void handle(VM_Shred shred, const m_str effect);
 #endif
diff --git a/plug b/plug
index 035fcc8a3deddce84a262b4bfee2360dc8bfbfbc..cef9b411504a524d73b2e282de45bbd30fd22751 160000 (submodule)
--- a/plug
+++ b/plug
@@ -1 +1 @@
-Subproject commit 035fcc8a3deddce84a262b4bfee2360dc8bfbfbc
+Subproject commit cef9b411504a524d73b2e282de45bbd30fd22751
index baad0e3f751733e9249f4950126a4c8391fe03e7..21874c26ee134a9a62d8bec8c8f3f5d4b3d173a5 100644 (file)
@@ -630,6 +630,12 @@ ANN static m_bool emit_prim_id(const Emitter emit, const Symbol *data) {
   return emit_symbol(emit, prim_self(data));
 }
 
+ANN static m_bool emit_prim_perform(const Emitter emit, const Symbol *xid) {
+  const Instr instr = emit_add_instr(emit, PerformEffect);
+  instr->m_val = (m_uint)s_name(*xid);
+  return GW_OK;
+}
+
 ANN static m_bool emit_prim_num(const Emitter emit, const m_uint *num) {
   regpushi(emit, *num);
   return GW_OK;
index 271343074586e97e448427ae248032365569a781..92f7b4a83ce58be64845070b185000368f83d146 100644 (file)
@@ -329,7 +329,7 @@ static INSTR(ArraySlice) {
   const m_int op    = start < end ? 1 : -1;
   const m_uint sz    = op > 0 ? end - start : start - end;
   if(bounds(in, start) < 0 || bounds(in, end) < 0)
-    Except(shred, "OutOfBoundsArraySliceException");
+    handle(shred, "OutOfBoundsArraySliceException");
   const M_Object out = new_array(shred->info->vm->gwion->mp, array->type_ref, sz);
   for(m_int i = start, j = 0; i != end; i += op, ++j) {
     m_bit buf[ARRAY_SIZE(in)];
index e1c8260e584c297d1dc9992edea4e427da36ea12..5525687c0dea4fd8207fcce6b3c9220063cfac3a 100644 (file)
@@ -75,7 +75,7 @@ static OP_CHECK(opck_basic_ctor) {
 
 static INSTR(PredicateCheck) {
   if(!*(m_uint*)REG(-SZ_INT))
-    Except(shred, "predicate failed");
+    handle(shred, "predicate failed");
 }
 
 ANN static m_bool import_core_libs(const Gwi gwi) {
index a8b9132119416affd57dcdc26e1772a178dc907c..cd362e7f20836e0b76c76664de25d06b1bdb1939 100644 (file)
@@ -56,7 +56,7 @@ INSTR(GTmpl) {
   struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val;
   const Func f = *(Func*)REG(-SZ_INT);
   if(!f)
-    Except(shred, _("EmptyFuncPointerException"));
+    handle(shred, "EmptyFuncPointerException");
 if(f->code) {
   *(VM_Code*)(shred->reg -SZ_INT) = f->code;
  return;
@@ -81,7 +81,7 @@ if(f->code) {
   dt->def = f->def;
   const Func_Def def = traverse_tmpl(emit, dt, f->value_ref->from->owner);
   if(!def)
-    Except(shred, "MissigTmplPtrException[internal]");
+    handle(shred, "MissigTmplPtrException");
   *(VM_Code*)(shred->reg -SZ_INT) = def->base->func->code;
 }
 
@@ -115,7 +115,7 @@ INSTR(DotTmpl) {
       return;
     }
   } while((t = t->info->parent));
-  Except(shred, "MissigTmplException[internal]");
+  handle(shred, "MissigTmplException");
 }
 
 #define VAL (*(m_uint*)(byte + SZ_INT))
index cd94424a9a7b05b1383c4770f1bf38db6ed85ba4..92cd7ee47a3810fb76f2a9cfb2b93df65af30b6f 100644 (file)
@@ -248,14 +248,14 @@ static INSTR(UsrUGenTick) {
   shred->reg -= SZ_INT*2 - offset;
   const M_Object o = *(M_Object*)(shred->reg + SZ_INT - offset);
   if(!o)
-    Except(shred, "[NullPtrException]");
+    handle(shred, "NullPtrException");
   struct UUGen_ *uu = UGEN(o)->module.gen.data;
   if(uu->shred)
     free_vm_shred(uu->shred);
   UGEN(o)->module.gen.tick = usrugen_tick;
   const VM_Code code = *(VM_Code*)(shred->reg-offset);
   if(!code)
-    Except(shred, "[NullTickException]");
+    handle(shred, "NullTickException");
   uu->shred = new_vm_shred(shred->info->vm->gwion->mp, *(VM_Code*)(shred->reg-offset));
   vmcode_addref(*(VM_Code*)(shred->reg - offset));
   uu->shred->info->vm = shred->info->vm;
index b981136f50d22f69a16ffc44de715640936842d7..815853058fe1b6383fbc29722bf3175d8609b8fe 100644 (file)
@@ -90,7 +90,7 @@ static OP_CHECK(opck_ptr_implicit) {
 static INSTR(instr_ptr_deref) {
   const m_bit *o = *(m_bit**)REG(-SZ_INT);
   if(!o)
-    Except(shred, _("EmptyPointerException"));
+    handle(shred, _("EmptyPointerException"));
   if(instr->m_val2)
     memcpy(REG(-SZ_INT), &o, SZ_INT);
   else {
index 25b80dfc4af79e7eaa4e628afbf4cae98567fc39..63e961125edbedf557f9e727db3ef3beca4764eb 100644 (file)
@@ -84,7 +84,7 @@ static INSTR(StringSlice) {
   if(end < 0)
     end = strsz + end;
   if(bounds(str, start) < 0 || bounds(str, end) < 0)
-    Except(shred, "OutOfBoundsStringSlice");
+    handle(shred, "OutOfBoundsStringSlice");
   const m_int op    = start < end ? 1 : -1;
   const m_uint sz    = op > 0 ? end - start : start - end;
   char c[sz + 1];
index 428a53a6d38788dafc0b465d010bb0385c221bb2..cc94d44552ccfba324aabe6f78c862cd92f5cd51 100644 (file)
@@ -185,7 +185,7 @@ ANN void ugen_disconnect(const restrict UGen lhs, const restrict UGen rhs) {
 #define TRIG_EX                         \
 if(!UGEN(rhs)->module.gen.trig) {       \
   release_connect(shred);               \
-  Except(shred, "NonTriggerException"); \
+  handle(shred, "NonTriggerException"); \
 }
 #define describe_connect_instr(name, func, tgt, opt) \
 static INSTR(name##func) {                           \
index 644c71bde42c5ca22fdd9edec65965d8fd4b866c..c6e384554bca50456767fc000fc4f9ddb22e6099 100644 (file)
@@ -108,7 +108,7 @@ static OP_CHECK(opck_vararg_cast) {
 static INSTR(VarargCast) {
   const M_Object o = *(M_Object*)REG(-SZ_INT);
   if(!*(m_uint*)(o->data + SZ_INT))
-         Except(shred, "Using Vararg outside varloop");
+         handle(shred, "Using Vararg outside varloop");
   struct Vararg_* arg = *(struct Vararg_**)o->data;
   const Type t = (Type)instr->m_val,
              u = (Type)vector_at(&arg->t, *(m_uint*)(o->data + SZ_INT*4));
@@ -118,7 +118,7 @@ static INSTR(VarargCast) {
     for(m_uint i = 0; i < t->size; i += SZ_INT)
       *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + *(m_uint*)(o->data + SZ_INT*3) + i);
   } else
-         Except(shred, "InvalidVariadicAccess");
+         handle(shred, "InvalidVariadicAccess");
 }
 
 static OP_EMIT(opem_vararg_cast) {
index 0b76cd677258d784ca496f0063e7bddc5c2f826e..6cdb5918cb67673e487f4ecdd0c4d796985fe1c8 100644 (file)
@@ -345,6 +345,10 @@ ANN static Type check_prim_id(const Env env, const Symbol *data) {
   return prim_id_non_res(env, data);
 }
 
+ANN static Type check_prim_perform(const Env env, const Symbol *data NUSED) {
+  return env->gwion->type[et_void];
+}
+
 ANN static Type check_prim_interp(const Env env, const Exp* exp) {
   CHECK_OO(check_exp(env, *exp))
   return env->gwion->type[et_string];
index 18a641f84df4b128726d25f54b0bb6ffe866d2a6..b83b1f365ae5c738f0eee893bbc1d619e892b257 100644 (file)
@@ -40,13 +40,66 @@ uint32_t gw_rand(uint32_t s[2]) {
   return ret;
 }
 
+ANN static bool unwind(VM_Shred shred, const Symbol effect) {
+  if(!shred->info->frame.ptr || !map_size(&shred->info->frame))
+    return true;
+  if(shred->code->handlers.ptr) {
+    const m_uint start = VKEY(&shred->info->frame, VLEN(&shred->info->frame) - 1);
+    if(start > shred->pc)
+      return true;
+    const Map m = &shred->code->handlers;
+    m_uint pc = 0;
+    for(m_uint i = 0; i < map_size(m); i++) {
+      if(start > shred->pc)
+        break;
+      if(start < shred->pc && VKEY(m, i) > shred->pc) {
+         const m_uint next = VKEY(m, i);
+         const Instr instr = (Instr)vector_at(shred->code->instr, next + 1);
+         if(!instr->m_val2 || (Symbol)instr->m_val2 == effect) {
+           pc = next + 1;
+           break;
+         }
+      }
+    }
+    if(!pc) // outside of a try statement
+      return true;
+    shred->reg = (m_bit*)VVAL(&shred->info->frame, VLEN(&shred->info->frame) - 1);
+    shredule(shred->tick->shreduler, shred, 0);
+    shred->pc = pc;//VKEY(m, i);
+    return false;
+  }
+  // there might be no more stack to unwind
+  map_remove(&shred->info->frame, VLEN(&shred->info->frame)-1);
+  if(shred->mem == (m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG)
+    return true;
+  // literally unwind
+  shred->pc   = *(m_uint*) (shred->mem - SZ_INT * 2);
+  shred->code = *(VM_Code*)(shred->mem - SZ_INT * 3);
+  shred->mem -= (*(m_uint*)(shred->mem - SZ_INT * 4) + SZ_INT * 4);
+  return unwind(shred, effect);
+}
+
+ANN void handle(VM_Shred shred, const m_str effect) {
+  // remove from the shreduler
+  // TODO: get shred->mem and shred->reg offsets
+  shreduler_remove(shred->tick->shreduler, shred, false);
+  // do the unwiding
+  if(unwind(shred, insert_symbol(shred->info->vm->gwion->st, effect))) {
+    vm_shred_exit(shred);
+    gw_err("{-C}shred{W}[{Y}% 5" UINT_F "{W}]{-}: {-R}Unhandled {+R}%s{0}\n", shred->tick->xid, effect);
+  }
+  // I guess the VM could have *trace mode*
+  // which would happen here from the top
+}
+
+
 void vm_remove(const VM* vm, const m_uint index) {
   const Vector v = (Vector)&vm->shreduler->shreds;
   LOOP_OPTIM
   for(m_uint i = vector_size(v) + 1; --i;) {
     const VM_Shred sh = (VM_Shred)vector_at(v, i - 1);
     if(sh && sh->tick->xid == index)
-       Except(sh, "MsgRemove");
+       handle(sh, "MsgRemove");
   }
 }
 
@@ -144,60 +197,7 @@ ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code, co
   return ME(o);
 }
 
-ANN static bool unwind(VM_Shred shred, const Symbol effect) {
-  // there is an handler
-  if(!map_size(&shred->info->frame))
-    return true;
-  if(shred->code->handlers.ptr) {
-    const m_uint start = VKEY(&shred->info->frame, VLEN(&shred->info->frame) - 1);
-    if(start > shred->pc)
-      return true;
-    const Map m = &shred->code->handlers;
-    m_uint pc = 0;
-    for(m_uint i = 0; i < map_size(m); i++) {
-      if(start > shred->pc)
-        break;
-      if(start < shred->pc && VKEY(m, i) > shred->pc) {
-         const m_uint next = VKEY(m, i);
-         const Instr instr = (Instr)vector_at(shred->code->instr, next + 1);
-         if(!instr->m_val2 || (Symbol)instr->m_val2 == effect) {
-           pc = next + 1;
-           break;
-         }
-      }
-    }
-    if(!pc) // outside of a try statement
-      return true;
-    shred->reg = (m_bit*)VVAL(&shred->info->frame, VLEN(&shred->info->frame) - 1);
-    shredule(shred->tick->shreduler, shred, 0);
-    shred->pc = pc;//VKEY(m, i);
-    return false;
-  }
-  // there might be no more stack to unwind
-  map_remove(&shred->info->frame, VLEN(&shred->info->frame)-1);
-  if(shred->mem == (m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG)
-    return true;
-  // literally unwind
-  shred->pc   = *(m_uint*) (shred->mem - SZ_INT * 2);
-  shred->code = *(VM_Code*)(shred->mem - SZ_INT * 3);
-  shred->mem -= (*(m_uint*)(shred->mem - SZ_INT * 4) + SZ_INT * 4);
-  return unwind(shred, effect);
-}
-
-ANN void handle(VM_Shred shred, const Symbol xid) {
-  // remove from the shreduler
-  // TODO: get shred->mem and shred->reg offsets
-  shreduler_remove(shred->tick->shreduler, shred, false);
-  // do the unwiding
-  if(unwind(shred, xid)) {
-    vm_shred_exit(shred);
-    puts(s_name(xid));
-  }
-  // I guess the VM could have *trace mode*
-  // which would happen here from the top
-}
-
-#define TEST0(t, pos) if(!*(t*)(reg-pos)){ shred->pc = PC; handle(shred, insert_symbol(vm->gwion->st, "ZeroDivideException")); break; }
+#define TEST0(t, pos) if(!*(t*)(reg-pos)){ shred->pc = PC; handle(shred, "ZeroDivideException"); break; }
 
 #define ADVANCE() byte += BYTECODE_SZ;
 
@@ -384,7 +384,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
     &&upvalueint, &&upvaluefloat, &&upvalueother, &&upvalueaddr,
     &&dotfunc,
     &&gcini, &&gcadd, &&gcend,
-    &&gacktype, &&gackend, &&gack, &&try_ini, &&try_end, &&handleeffect, &&noop, &&eoc, &&unroll2, &&other, &&regpushimm
+    &&gacktype, &&gackend, &&gack, &&try_ini, &&try_end, &&handleeffect, &&performeffect, &&noop, &&eoc, &&unroll2, &&other, &&regpushimm
   };
   const Shreduler s = vm->shreduler;
   register VM_Shred shred;
@@ -697,7 +697,7 @@ regtomemother:
 overflow:
   if(overflow_(mem + VAL2, shred)) {
     shred->pc = PC;
-    exception(shred, "StackOverflow");
+    handle(shred, "StackOverflow");
     continue;
   }
 PRAGMA_PUSH()
@@ -798,10 +798,10 @@ arrayaccess:
   register const m_int idx = *(m_int*)(reg + VAL);
   a.obj = *(M_Object*)(reg-VAL2);
   if(idx < 0 || (m_uint)idx >= m_vector_size(ARRAY(a.obj))) {
-    gw_err(_("  ... at index [%" INT_F "]\n"), idx);
-    gw_err(_("  ... at dimension [%" INT_F "]\n"), VAL);
+    gw_err(_("{-}  ... at index {W}[{Y}%" INT_F "{W}]{0}\n"), idx);
+//    gw_err(_("  ... at dimension [%" INT_F "]\n"), VAL);
     VM_OUT
-    exception(shred, "ArrayOutofBounds");
+    handle(shred, "ArrayOutofBounds");
     continue; // or break ?
   }
   DISPATCH()
@@ -865,7 +865,7 @@ except:
  * grep for GWOP_EXCEPT and Except, exception... */
   if(!*(m_bit**)(reg+(m_int)(VAL))) {
     shred->pc = PC;
-    exception(shred, "NullPtrException");
+    handle(shred, "NullPtrException");
     continue;
   }
   DISPATCH();
@@ -895,7 +895,7 @@ dotaddr:
 #define UNION_CHECK\
   register const m_bit *data  = (*(M_Object*)(reg-SZ_INT))->data;\
   if(*(m_uint*)data != VAL) {\
-    exception(shred, "invalid union acces");\
+    handle(shred, "invalid union acces");\
     continue;\
   }
 
@@ -1013,6 +1013,11 @@ try_ini:
 try_end:
   map_remove(&shred->info->frame, VLEN(&shred->info->frame)-1);
 handleeffect:
+// this should check the *xid* of the exception
+  DISPATCH();
+performeffect:
+  handle(shred, (m_str)VAL);
+  break;
 // this should check the *xid* of the exception
 noop:
   DISPATCH();