]> Nishi Git Mirror - gwion.git/commitdiff
:bug: Fix array bug wrt Refs
authorJérémie Astor <fennecdjay@gmail.com>
Tue, 26 Apr 2022 11:04:32 +0000 (13:04 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Tue, 26 Apr 2022 11:04:32 +0000 (13:04 +0200)
include/env/value.h
include/opcode.h
opcode.txt
src/emit/emit.c
src/lib/array.c
src/lib/lib_func.c
src/parse/check.c
src/parse/scan1.c
src/vm/vm.c

index 8b93a5cad226b6593369e9b6f4794d40a98f6b9a..35d5d51309112e8ef7902fdabdcd2f79e7ce3e4c 100644 (file)
@@ -51,4 +51,9 @@ ANN static inline void defined_here(const Value v) {
   if (v->from->filename) // TODO: check why is that from check
     gwerr_secondary(_("defined here"), v->from->filename, v->from->loc);
 }
+
+ANN static inline void valid_value(const Env env, const Symbol xid, const Value v) {
+  set_vflag(v, vflag_valid);
+  nspc_add_value(env->curr, xid, v);
+}
 #endif
index 76b978cb1a0872669390468d3f6eecd08827ee13..a9e0912ed28a04c6d207c3175fa898dad1c6da3e 100644 (file)
@@ -159,6 +159,8 @@ enum {
   eSporkFunc,
   eSporkMemberFptr,
   eSporkExp,
+  eSporkCode,
+  eForkEnd,
   eSporkEnd,
   eBranchEqInt,
   eBranchNeqInt,
@@ -376,6 +378,8 @@ enum {
 #define  SporkFunc            (f_instr)eSporkFunc
 #define  SporkMemberFptr      (f_instr)eSporkMemberFptr
 #define  SporkExp             (f_instr)eSporkExp
+#define  SporkCode            (f_instr)eSporkCode
+#define  ForkEnd              (f_instr)eForkEnd
 #define  SporkEnd             (f_instr)eSporkEnd
 #define  BranchEqInt          (f_instr)eBranchEqInt
 #define  BranchNeqInt         (f_instr)eBranchNeqInt
@@ -1153,6 +1157,15 @@ ANN static inline void dump_opcodes(const VM_Code code) {
         gw_out(" {-R}%-14"UINT_F"{0}", instr->m_val);
         gw_out("\n");
         break;
+      case eSporkCode:
+        gw_out("{Y}┃{0}{-}% 4lu{0}: SporkCode   ", j);
+        gw_out(" {-R}%-14"UINT_F"{0}", instr->m_val);
+        gw_out("\n");
+        break;
+      case eForkEnd:
+        gw_out("{Y}┃{0}{-}% 4lu{0}: ForkEnd     ", j);
+        gw_out("\n");
+        break;
       case eSporkEnd:
         gw_out("{Y}┃{0}{-}% 4lu{0}: SporkEnd    ", j);
         gw_out("\n");
index 1ef10f3bae6682a508008fe0e390bd97789ba350..2de1c0f6b3c3d04ad8ab5d49093bb13184056c3e 100644 (file)
@@ -156,6 +156,8 @@ ForkIni~p~i
 SporkFunc
 SporkMemberFptr~u
 SporkExp~u
+SporkCode~u
+ForkEnd
 SporkEnd
 BranchEqInt~pc
 BranchNeqInt~pc
index dc7d90c0e2b3d42d418bdaa803112d683b024421..4b3fcd975827b5cce39bfc637f1018bee10acb40 100644 (file)
@@ -1860,6 +1860,7 @@ struct Sporker {
   const Exp  exp;
   VM_Code    vm_code;
   const Type type;
+  const Capture_List captures;
   const bool emit_var;
   const bool is_spork;
 };
@@ -1900,7 +1901,7 @@ ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
 ANN void spork_code(const Emitter emit, const struct Sporker *sp) {
   const Instr args  = emit_add_instr(emit, SporkExp);
   args->m_val       = emit->code->stack_depth;
-  const Instr instr = emit_add_instr(emit, SporkEnd);
+  const Instr instr = emit_add_instr(emit, sp->is_spork ? SporkEnd : ForkEnd);
   instr->m_val      = sp->emit_var;
 }
 
@@ -1943,12 +1944,41 @@ ANN m_bool emit_exp_spork(const Emitter emit, const Exp_Unary *unary) {
       .exp      = unary->unary_type == unary_exp ? unary->exp : NULL,
       .code     = unary->unary_type == unary_code ? unary->code : NULL,
       .type     = exp_self(unary)->type,
+      .captures = unary->captures,
       .is_spork = (unary->op == insert_symbol("spork")),
       .emit_var = exp_getvar(exp_self(unary))};
   CHECK_OB((sporker.vm_code = spork_prepare(emit, &sporker)));
   if(!sporker.is_spork)
     emit_local_exp(emit, exp_self(unary));
   spork_ini(emit, &sporker);
+
+if(sporker.captures) {
+    Capture_List caps = sporker.captures;
+// what about types?
+    uint32_t offset = 0;
+    for (uint32_t i = 0; i < caps->len; i++) {
+      Capture *cap = mp_vector_at(caps, Capture, i);
+      const Value v = nspc_lookup_value1(emit->env->curr, cap->xid);
+      struct Exp_ exp = {
+        .d = { .prim = {
+          .d = { .var = cap->xid },
+          .value = v,
+          .prim_type = ae_prim_id
+        }},
+        .type = v->type,
+        .exp_type = ae_exp_primary
+      };
+// handle emit var?
+//exp_setvar(&exp, false);
+      emit_exp(emit, &exp);
+    }
+//      pop_exp(emit, &exp);
+regpop(emit, SZ_INT);
+    const Instr args  = emit_add_instr(emit, SporkCode);
+    args->m_val       = 8; //emit->code->stack_depth;
+  }
+
+//    emit_local_exp(emit, exp_self(unary));
   (unary->unary_type == unary_code ? spork_code : spork_func)(emit, &sporker);
   return GW_OK;
 }
@@ -2470,10 +2500,14 @@ ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt,
   loop_idx->m_val       = key_offset;
   loop_idx->m_val2      = -1;
   stmt->v->from->offset = val_offset;
+//value_addref(stmt->v);
+nspc_add_value(emit->env->curr, stmt->sym, stmt->v);
   emit_debug(emit, stmt->v);
   if (stmt->idx) {
     stmt->idx->v->from->offset = key_offset;
-    emit_debug(emit, stmt->v);
+nspc_add_value(emit->env->curr, stmt->idx->sym, stmt->idx->v);
+//value_addref(stmt->idx->v);
+    emit_debug(emit, stmt->idx->v);
   }
   struct Looper loop   = {.exp  = stmt->exp,
                         .stmt   = stmt->body,
index 3614edbe2873a6445474263b2c99cf635ec5c015..7400d1999a8185e1dd91b14eaf7df5f923fcbbfc 100644 (file)
@@ -763,8 +763,14 @@ ANN static inline Type foreach_type(const Env env, const Exp exp) {
   const Type et = exp->type;
   DECL_OO(Type, base, = typedef_base(et));
   DECL_OO(const Type, t, = array_base_simple(base));
-  const m_uint depth = base->array_depth - 1;
-  return depth ? array_type(env, t, depth) : t;
+  if(!tflag(base, tflag_ref)) {
+    const m_uint depth = base->array_depth - 1;
+    return depth ? array_type(env, t, depth) : t;
+  }
+  const Type  inner = (Type)vector_front(&base->info->tuple->contains);
+  const Type  refbase = array_base_simple(inner);
+  const m_uint depth = inner->array_depth - 1;
+  return depth ? array_type(env, refbase, depth) : refbase;
 }
 
 // rewrite me
index 834b5634616b70243c4592bdd1fa1cd27bdd97bb..3edb530d0848fd50e256c0ced79bd2a4ec73530f 100644 (file)
@@ -615,9 +615,7 @@ static OP_EMIT(opem_op_impl) {
   instr->m_val2          = -SZ_INT;
   return ret;
 }
-
-ANN Type check_exp_unary_spork(const Env env, const Stmt code);
-
+/*
 ANN static void fork_exp(const Env env, const Exp_Unary *unary) {
   Stmt_List slist = new_mp_vector(env->gwion->mp, sizeof(struct Stmt_), 1);
   mp_vector_set(slist, struct Stmt_, 0,
@@ -630,10 +628,10 @@ ANN static void fork_exp(const Env env, const Exp_Unary *unary) {
   ((Exp_Unary *)unary)->code       = code;
   ((Exp_Unary *)unary)->unary_type = unary_code;
 }
-
+*/
 ANN static Type fork_type(const Env env, const Exp_Unary *unary) {
   const Type t = unary->exp->type;
-  fork_exp(env, unary);
+//  fork_exp(env, unary);
   if (t == env->gwion->type[et_void]) return env->gwion->type[et_fork];
   char c[21 + strlen(t->name)];
   sprintf(c, "TypedFork:[%s]", t->name);
@@ -650,6 +648,16 @@ ANN static Type fork_type(const Env env, const Exp_Unary *unary) {
   return ret;
 }
 
+ANN Type upvalue_type(const Env env, Capture *cap) {
+  const Value v = nspc_lookup_value1(env->curr, cap->xid);
+  if(!v)exit(3);
+  if(cap->is_ref && not_upvalue(env, v))
+    ERR_O(cap->pos, _("can't take ref of a scoped value"));
+  cap->v = v;
+  const Type base_type = !tflag(v->type, tflag_ref) ? v->type : (Type)vector_front(&v->type->info->tuple->contains);
+  return !cap->is_ref ? base_type :  ref_type(env->gwion, base_type, cap->pos);
+}
+
 static OP_CHECK(opck_spork) {
   const Exp_Unary *unary = (Exp_Unary *)data;
   if (unary->unary_type == unary_exp && unary->exp->exp_type == ae_exp_call) {
@@ -657,10 +665,36 @@ static OP_CHECK(opck_spork) {
     return is_spork ? env->gwion->type[et_shred] : fork_type(env, unary);
   }
   if (unary->unary_type == unary_code) {
+    if(unary->captures) {
+      uint32_t offset = 0;
+      for(uint32_t i = 0; i < unary->captures->len; i++) {
+        Capture *const cap = mp_vector_at(unary->captures, Capture, i);
+        DECL_OO(const Type, t, = upvalue_type(env, cap));
+        cap->v = new_value(env->gwion->mp, t, s_name(cap->xid));
+        cap->v->from->offset = offset;
+        offset += cap->v->type->size;
+      }
+    }
     ++env->scope->depth;
-    nspc_push_value(env->gwion->mp, env->curr);
+    const Scope scope = env->curr->info->value;
+    env->curr->info->value = new_scope(env->gwion->mp);
+    if(unary->captures) {
+      for(uint32_t i = 0; i < unary->captures->len; i++) {
+        Capture *const cap = mp_vector_at(unary->captures, Capture, i);
+        valid_value(env, cap->xid, cap->v);
+      }
+    }
+    const Func f = env->func;
+    struct Value_ value = {};
+    set_vflag(&value, vflag_member);
+    struct Func_Base_ fbase = { .xid=insert_symbol("in spork"), .values = scope};
+    struct Func_Def_ fdef = { .base = &fbase};
+    struct Func_ func = { .name = "in spork", .def = &fdef, .value_ref = &value};
+    env->func = &func;
     const m_bool ret = check_stmt(env, unary->code);
-    nspc_pop_value(env->gwion->mp, env->curr);
+    env->func = f;
+    free_scope(env->gwion->mp, env->curr->info->value);
+    env->curr->info->value = scope;
     --env->scope->depth;
     CHECK_BN(ret);
     return env->gwion
index 81587e2ebd80d8010df3f3dc042f5e7ae7375c2f..a374bf54b9bfcd370e47610bc196ec730720635b 100644 (file)
@@ -113,11 +113,6 @@ ANN static m_bool check_var_td(const Env env, const Var_Decl var,
   return GW_OK;
 }
 
-ANN static inline void valid_value(const Env env, const Symbol xid, const Value v) {
-  set_vflag(v, vflag_valid);
-  nspc_add_value(env->curr, xid, v);
-}
-
 ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
   Var_Decl_List list = decl->list;
   for(uint32_t i = 0; i < list->len; i++) {
@@ -369,7 +364,9 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) {
       prim_self(data)->value = env->gwion->type[et_op]->info->value;
       return env->gwion->type[et_op];
     }
-    gwerr_basic(_("Invalid variable"), _("not legit at this point."), NULL,
+    const m_str hint = (!env->func || strcmp(env->func->name, "in spork")) ?
+        NULL : "vapturelist?";
+    gwerr_basic(_("Invalid variable"), _("not legit at this point."), hint,
                 env->name, prim_pos(data), 0);
     did_you_mean_nspc(v ? value_owner(env, v) : env->curr, s_name(sym));
     env_set_error(env);
@@ -724,6 +721,7 @@ ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) {
     func->def->base->ret_type : exp->func->d.exp_dot.base->type;
 }
 
+ANN Type upvalue_type(const Env env, Capture *cap);
 ANN static Type check_lambda_call(const Env env, Exp_Call *const exp) {
   const Func_Def fdef = exp->func->d.exp_lambda.def;
   if (exp->args) {
@@ -739,13 +737,7 @@ ANN static Type check_lambda_call(const Env env, Exp_Call *const exp) {
       fdef->base->args = new_mp_vector(env->gwion->mp, sizeof(Arg), 0);
     for(uint32_t i = 0; i < fdef->captures->len; i++) {
       Capture *const cap = mp_vector_at(fdef->captures, Capture, i);
-      const Value v = nspc_lookup_value1(env->curr, cap->xid);
-      if(!v)exit(3);
-      if(cap->is_ref && not_upvalue(env, v))
-        ERR_O(cap->pos, _("can't take ref of a scoped value"));
-      cap->v = v;
-      const Type base_type = !tflag(v->type, tflag_ref) ? v->type : (Type)vector_front(&v->type->info->tuple->contains);
-      const Type t = !cap->is_ref ? base_type :  ref_type(env->gwion, base_type, cap->pos);
+      DECL_OO(const Type, t, = upvalue_type(env, cap)); // could leak
       Arg arg = {
         .td = type2td(env->gwion, t, exp->func->pos),
         .var_decl = { .xid = cap->xid }
index 128519f135e311a3aac7b9aaa182439a0f190cf2..8dba5259a2a96782b85bd574855c1b4ee61fe82e 100644 (file)
@@ -236,6 +236,7 @@ ANN static m_bool scan1_exp_if(const Env env, const Exp_If *exp_if) {
 ANN static inline m_bool scan1_exp_unary(const restrict Env env,
                                          Exp_Unary *const  unary) {
   if (unary->unary_type == unary_code) {
+if(strcmp("fork", s_name(unary->op))) {
     const loc_t pos = exp_self(unary)->pos;
     const Symbol sym = lambda_name(env->gwion->st, pos.first);
     Exp lambda = new_exp_lambda(env->gwion->mp, sym, NULL, unary->code, pos);
@@ -244,6 +245,10 @@ ANN static inline m_bool scan1_exp_unary(const restrict Env env,
     mp_free(env->gwion->mp, Stmt, unary->code);
     unary->exp = new_exp_call(env->gwion->mp, lambda, NULL, pos);
     unary->unary_type = unary_exp;
+} else {
+return scan1_stmt(env, unary->code);
+}
+
   }
   return unary->unary_type == unary_exp ? scan1_exp(env, unary->exp) : GW_OK;
 }
index deb2b8eb0aa8920172c0769cd882dad3773430a3..71e90553f2d76ff6b595df15d79aecb353853e4f 100644 (file)
@@ -267,7 +267,6 @@ ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code,
   VM *           vm = shred->info->vm;
   if (!vm->gwion->data->child.ptr) vector_init(&vm->gwion->data->child);
   vector_add(&vm->gwion->data->child, (vtype)o);
-  fork_launch(o);
   return ME(o);
 }
 
@@ -471,8 +470,8 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto]
       &&regtomem, &&regtomemother,
       &&overflow,
       &&funcusrend, &&funcusrend2, &&funcmemberend,
-      &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp,
-      &&sporkend, &&brancheqint, &&branchneint, &&brancheqfloat,
+      &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkcode,
+      &&forkend, &&sporkend, &&brancheqint, &&branchneint, &&brancheqfloat,
       &&branchnefloat, &&unroll, &&arrayappend, &&autounrollinit, &&autoloop,
       &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&newobj, &&addref,
       &&addrefaddr, &&structaddref, &&structaddrefaddr, &&objassign, &&assign,
@@ -540,7 +539,7 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto]
     regpushmemaddr:
       *(m_bit **)reg = &*(m_bit *)(mem + IVAL);
       reg += SZ_INT;
-      DISPATCH()
+      DISPATCH();
     regpushmemderef:
       memcpy(reg, *(m_bit **)(mem + IVAL), VAL2);
       reg += VAL2;
@@ -981,6 +980,13 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto]
       for (m_uint i = 0; i < VAL; i += SZ_INT)
         *(m_uint *)(child->mem + i) = *(m_uint *)(mem + i);
       DISPATCH()
+    sporkcode:
+      //  LOOP_OPTIM
+      for (m_uint i = 0; i < VAL; i += SZ_INT)
+        *(m_uint *)(child->mem + i) = *(m_uint *)(reg + i);
+      DISPATCH()
+    forkend:
+      fork_launch(child->info->me);
     sporkend:
       assert(!VAL); // spork are not mutable
       *(M_Object *)(reg - SZ_INT) = child->info->me;
@@ -1308,7 +1314,7 @@ static void *_dispatch[] = {
       &&_regtomem, &&_regtomemother,
       &&_overflow,
       &&_funcusrend, &&_funcusrend2, &&_funcmemberend,
-      &&_sporkini, &&_forkini, &&_sporkfunc, &&_sporkmemberfptr, &&_sporkexp,
+      &&_sporkini, &&_forkini, &&_sporkfunc, &&_sporkmemberfptr, &&_sporkexp, &&_sporkcode, &&_forkend,
       &&_sporkend, &&_brancheqint, &&_branchneint, &&_brancheqfloat,
       &&_branchnefloat, &&_unroll, &&_arrayappend, &&_autounrollinit, &&_autoloop,
       &&_arraytop, &&_arrayaccess, &&_arrayget, &&_arrayaddr, &&_newobj, &&_addref,
@@ -1512,6 +1518,8 @@ return;
     PREPARE(sporkfunc);
     PREPARE(sporkmemberfptr);
     PREPARE(sporkexp);
+    PREPARE(sporkcode);
+    PREPARE(forkend);
     PREPARE(sporkend);
     PREPARE(brancheqint);
     PREPARE(branchneint);