]> Nishi Git Mirror - gwion.git/commitdiff
:smile: Push tmp branch
authorJérémie Astor <fennecdjay@gmail.com>
Fri, 5 Nov 2021 10:07:24 +0000 (11:07 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Fri, 5 Nov 2021 10:07:24 +0000 (11:07 +0100)
16 files changed:
fmt
include/emit.h
include/looper.h [new file with mode: 0644]
include/object.h
src/emit/emit.c
src/env/value.c
src/lib/array.c
src/lib/dict.c
src/lib/instr.c
src/lib/object.c
src/lib/object_op.c
src/lib/opfunc.c
src/parse/check.c
src/vm/vm.c
tests/error/auto_not_array.gw [deleted file]
util

diff --git a/fmt b/fmt
index 35dae816a65843488b03d4dce27b1dfa8ddc09ea..f7c8eadcf1727a3132a8a5b970f1fc879e44138e 160000 (submodule)
--- a/fmt
+++ b/fmt
@@ -1 +1 @@
-Subproject commit 35dae816a65843488b03d4dce27b1dfa8ddc09ea
+Subproject commit f7c8eadcf1727a3132a8a5b970f1fc879e44138e
index 4e55dce8de3bf5d24f348a57fe2707e94a30f45a..de188b50fd7b2cc42cdacf77f9e75cbc54408ba9 100644 (file)
@@ -12,6 +12,7 @@ typedef struct Frame_ {
 
 typedef struct VMValue_ {
   Type     t;
+  void *local; /// :.....
   uint16_t offset;
   uint16_t start;
   uint16_t end;
diff --git a/include/looper.h b/include/looper.h
new file mode 100644 (file)
index 0000000..d5553c8
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __LOOPER
+#define __LOOPER
+
+typedef struct Looper Looper;
+
+typedef Instr (*f_looper)(const Emitter, const Looper *);
+
+struct Looper {
+  const Exp           exp;
+  const Stmt          stmt;
+  /*const */ m_uint   offset;
+  const m_uint        n;
+  const f_looper roll;
+  const f_looper unroll;
+//  union {
+    struct Vector_ unroll_v;
+    Instr instr;
+//  };
+  struct EachIdx_ *idx;
+  bool init;
+};
+#endif
index 45048912c751f2a327eadfca2d3394c800388f3f..dae95eb4bcf5d5159d7c6878840633f6af91a005 100644 (file)
@@ -3,9 +3,9 @@
 typedef struct M_Object_ *M_Object;
 struct M_Object_ {
   Type                  type_ref;
-  struct Vector_        vtable;
-  /*volatile */uint32_t ref;
-  uint32_t              offset;
+//  struct Vector_        vtable;
+  /*volatile */uint64_t ref;
+//  uint32_t              offset;
   m_bit                 data[];
 };
 
index f029649395051320e49987ea5861a88251b8b581..9e476de75cbaec67b2c8fad9ed841f77e7c1c718 100644 (file)
@@ -17,6 +17,7 @@
 #include "match.h"
 #include "specialid.h"
 #include "vararg.h"
+#include "looper.h"
 
 #undef insert_symbol
 #define insert_symbol(a) insert_symbol(emit->gwion->st, (a))
@@ -80,8 +81,8 @@ ANN static void free_frame(MemPool p, Frame *a) {
   mp_free(p, Frame, a);
 }
 
-ANN static Local *new_local(MemPool p, const Type type) {
-  Local *local = mp_calloc(p, Local);
+ANN static inline Local *new_local(MemPool p, const Type type) {
+  Local *const local = mp_calloc(p, Local);
   local->type  = type;
   return local;
 }
@@ -292,7 +293,7 @@ ANN m_uint emit_local(const Emitter emit, const Type t) {
   if (isa(t, emit->gwion->type[et_compound]) > 0) {
     l->is_compound = true;
     VMValue vmval  = {
-        .t = t, .offset = l->offset, .start = emit_code_size(emit)};
+        .t = t, .local = l, .offset = l->offset, .start = emit_code_size(emit)};
     m_vector_add(&emit->code->live_values, &vmval);
     ++emit->code->frame->value_count;
   }
@@ -303,7 +304,7 @@ ANN void* emit_localx(const Emitter emit, const Type t) {
   Local *const l = frame_local(emit->gwion->mp, emit->code->frame, t);
   l->is_compound = true;
   VMValue vmval  = {
-      .t = t, .offset = l->offset, .start = emit_code_size(emit)};
+      .t = t, .local = l, .offset = l->offset, .start = emit_code_size(emit)};
   m_vector_add(&emit->code->live_values, &vmval);
   ++emit->code->frame->value_count;
   l->instr = emit_add_instr(emit, Reg2Mem);
@@ -960,21 +961,26 @@ ANN static Instr emit_struct_decl(const Emitter emit, const Value v,
 }
 
 ANN void unset_local(const Emitter emit, Local *const l) {
+puts("unset");
   l->instr->opcode = eNoOp;
   for(m_uint i = m_vector_size(&emit->code->live_values) + 1; --i;) {
     VMValue vmval = *(VMValue*)(ARRAY_PTR((&emit->code->live_values)) + (i-1) * sizeof(VMValue));
-    if(vmval.offset != l->offset) continue;
+//    if(vmval.offset != l->offset) continue;
+    if(vmval.local != l) continue;
     m_vector_rem(&emit->code->live_values, i-1);
+    vector_rem2(&emit->code->frame->stack, (vtype)l);
+//vector_rem2(&emit->code->instr, l->instr);
+// free instr
+    --emit->code->frame->value_count;
     break;
   }
-  --emit->code->frame->value_count;
 }
 
 ANN static m_uint decl_non_static_offset(const Emitter emit, const Exp_Decl *decl, const Type t) {
-  if(!exp_self(decl)->data)
+//  if(!exp_self(decl)->data)
     return emit_local(emit, t);
-  Local *const l = exp_self(decl)->data;
-  return l->offset;
+//  Local *const l = exp_self(decl)->data;
+//  return l->offset;
 }
 
 ANN static m_bool emit_exp_decl_non_static(const Emitter   emit,
@@ -988,7 +994,8 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter   emit,
   const bool      is_array = array && array->exp;
   const bool      is_obj   = isa(type, emit->gwion->type[et_object]) > 0;
   const bool emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : true;
-  if (is_obj && (is_array || !is_ref))
+  if (is_obj && (is_array || !is_ref) && !exp_self(decl)->ref)
+//  if (is_obj && ((is_array && !exp_self(decl)->ref) || !is_ref))
     CHECK_BB(emit_instantiate_decl(emit, type, decl->td, array, is_ref));
   f_instr *exec = (f_instr *)allocmember;
   if (!emit->env->scope->depth) emit_debug(emit, v);
@@ -1007,7 +1014,7 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter   emit,
                       exec)
           : emit_struct_decl(emit, v, !struct_ctor(v) ? emit_addr : 1);
   instr->m_val = v->from->offset;
-  if (is_obj && (is_array || !is_ref)) {
+  if (is_obj && (is_array || !is_ref) && !exp_self(decl)->ref) {
     if (!emit_var)
       emit_add_instr(emit, Assign);
     else {
@@ -1326,10 +1333,11 @@ ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call *exp_call) {
     const Instr instr = emit_add_instr(emit, Reg2RegAddr);
     instr->m_val      = -SZ_INT;
   } else {
-//    if(isa(t, emit->gwion->type[et_object]) > 0)
-//    if(isa(t, emit->gwion->type[et_object]) > 0)
-//      emit_local_exp(emit, e);
-//      emit_localx(emit, t);
+    if(isa(t, emit->gwion->type[et_object]) > 0) {
+//emit_object_addref(emit, -SZ_INT, 0);
+      emit_local_exp(emit, e);
+//       emit_localx(emit, t);
+    }
     if (!is_func(emit->gwion, exp_call->func->type) &&
              tflag(e->type, tflag_struct))
     regpop(emit, SZ_INT);
@@ -2219,59 +2227,40 @@ ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
   return ret;
 }
 
-struct Looper;
-typedef Instr (*f_looper_init)(const Emitter, const struct Looper *);
-typedef void (*f_looper)(const Emitter, const struct Looper *);
-struct Looper {
-  const Exp           exp;
-  const Stmt          stmt;
-  /*const */ m_uint   offset;
-  const m_uint        n;
-  const f_looper_init roll;
-  const f_looper_init unroll;
-//  union {
-    struct Vector_ unroll_v;
-    Instr instr;
-//  };
-};
-
-ANN static inline m_bool roll(const Emitter emit, struct Looper *const loop) {
-  const Instr instr = loop->roll(emit, loop);
-  CHECK_BB(scoped_stmt(emit, loop->stmt, 1));
-  instr->m_val = emit_code_size(emit) + 1; // pass after goto
-  return GW_OK;
-}
-
-ANN static Instr stmt_each_roll(const Emitter emit, const struct Looper *loop) {
-//  const Instr instr = emit_add_instr(emit, AutoLoop);
-//  instr->m_val2     = loop->offset + SZ_INT;
-//  return instr;
+ANN static Instr each_op(const Emitter emit, const Looper *loop) {
   struct Op_Import opi = {
     .lhs = loop->exp->type,
-    .op = insert_symbol("@autoloop"),
+    .op = insert_symbol("@each"),
     .data = (m_uint)loop
   };
   CHECK_BO(op_emit(emit, &opi));
   return loop->instr;
 }
 
+ANN static inline m_bool roll(const Emitter emit, Looper*const loop) {
+const Instr instr = loop->roll(emit, loop);
+//  DECL_OB(const Instr, instr, = each_op(emit, loop)); // maybe check in check.c
+  CHECK_BB(scoped_stmt(emit, loop->stmt, 1));
+  instr->m_val = emit_code_size(emit) + 1; // pass after goto
+  return GW_OK;
+}
+
 ANN static inline void unroll_init(const Emitter emit, const m_uint n) {
-  emit->info->unroll = 0;
   const Instr instr  = emit_add_instr(emit, MemSetImm);
   instr->m_val       = emit_local(emit, emit->gwion->type[et_int]);
   instr->m_val2      = n;
 }
 
 ANN static inline m_bool unroll_run(const Emitter        emit,
-                                    struct Looper *const loop) {
-  const Instr instr = loop->unroll ? loop->unroll(emit, loop) : NULL;
+                                    struct Looper *loop) {
+  const Instr instr = each_op(emit, loop);
   CHECK_BB(scoped_stmt(emit, loop->stmt, 1));
   if(instr)
     vector_add(&loop->unroll_v, (m_uint)instr);
   return GW_OK;
 }
 
-ANN static m_bool _unroll(const Emitter emit, struct Looper *loop) {
+ANN static m_bool _unroll(const Emitter emit, Looper *loop) {
   scoped_ini(emit);
   const Instr unroll = emit_add_instr(emit, Unroll);
   unroll->m_val      = loop->offset;
@@ -2286,71 +2275,63 @@ ANN static m_bool _unroll(const Emitter emit, struct Looper *loop) {
   return GW_OK;
 }
 
-ANN static m_bool unroll(const Emitter emit, struct Looper *loop) {
+ANN static m_bool unroll(const Emitter emit, Looper *loop) {
   if(loop->unroll)
     vector_init(&loop->unroll_v);
   const m_bool ret = _unroll(emit, loop);
   if(loop->unroll) {
     for(m_uint i = 0; i < vector_size(&loop->unroll_v); i++) {
       const Instr instr = (Instr)vector_at(&loop->unroll_v, i);
-      instr->m_val = emit_code_size(emit) + 2;
+      instr->m_val = emit_code_size(emit) + 1; // + 2 for arrays
     }
     vector_release(&loop->unroll_v);
   }
   return ret;
 }
-ANN static Instr stmt_each_unroll(const Emitter        emit,
-                                 const struct Looper *loop) {
-  struct Op_Import opi = {
-    .lhs = loop->exp->type,
-    .op = insert_symbol("@autoloop"),
-    .data = (m_uint)loop
-  };
-  CHECK_BO(op_emit(emit, &opi));
-  return loop->instr;
-//  const Instr instr = emit_add_instr(emit, AutoLoop);
-//  instr->m_val2     = loop->offset + SZ_INT * 2;
-//  return instr;
-}
 
 ANN static inline m_bool looper_run(const Emitter        emit,
-                                    struct Looper *const loop) {
+                                    Looper *const loop) {
   return (!loop->n ? roll : unroll)(emit, loop);
 }
 
 ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt,
                                   m_uint *end_pc) {
   const uint n = emit->info->unroll;
-  if (n) {
-    unroll_init(emit, n);
-    emit_local(emit, emit->gwion->type[et_int]);
-  }
-
-  CHECK_BB(emit_exp(emit, stmt->exp)); // add ref?
-  regpop(emit, SZ_INT);
-  const m_uint offset = emit_local(emit, emit->gwion->type[et_int]); // array?
-  emit_local(emit, emit->gwion->type[et_int]);
-  emit_local(emit, emit->gwion->type[et_int]);
+  const m_uint arr_offset = emit_local(emit, emit->gwion->type[et_int]); // array?
+  const m_uint key_offset = /*!stmt->idx
+     ? */emit_local(emit, emit->gwion->type[et_int])
+     /*: emit_local(emit, stmt->idx->v->type)*/;
+  const m_uint val_offset = emit_local(emit, stmt->v->type);
   const Instr tomem     = emit_add_instr(emit, Reg2Mem);
-  tomem->m_val          = offset;
+  tomem->m_val          = arr_offset;
   const Instr loop_idx  = emit_add_instr(emit, MemSetImm);
-  loop_idx->m_val       = offset + SZ_INT;
+  loop_idx->m_val       = key_offset;
   loop_idx->m_val2      = -1;
-  stmt->v->from->offset = offset + SZ_INT * 2;
+  stmt->v->from->offset = val_offset;
   emit_debug(emit, stmt->v);
-  if (stmt->idx) stmt->idx->v->from->offset = offset + SZ_INT;
-  if (n) {
-    const Instr instr = emit_add_instr(emit, AutoUnrollInit);
-    instr->m_val      = offset - SZ_INT;
+  if (stmt->idx) {
+    stmt->idx->v->from->offset = key_offset;
+    emit_debug(emit, stmt->v);
   }
-  const m_uint  ini_pc = emit_code_size(emit);
   struct Looper loop   = {.exp  = stmt->exp,
                         .stmt   = stmt->body,
-                        .offset = offset,
+                        .offset = arr_offset,
                         .n      = n,
-                        .roll   = stmt_each_roll,
-                        .unroll = stmt_each_unroll};
-  if (n) loop.offset -= SZ_INT;
+                        .roll   = each_op,
+                        .unroll = each_op,
+                        .idx    = stmt->idx,
+.init = false
+                        };
+  if (n) {
+    loop.offset -= SZ_INT;
+    struct Op_Import opi = {
+      .lhs = loop.exp->type,
+      .op = insert_symbol("@each_init"),
+      .data = (m_uint)&loop
+    };
+    CHECK_BB(op_emit(emit, &opi));
+  }
+  const m_uint  ini_pc = emit_code_size(emit);
   CHECK_BB(looper_run(emit, &loop));
   *end_pc         = emit_code_size(emit);
   const Instr tgt = emit_add_instr(emit, Goto);
@@ -2359,21 +2340,32 @@ ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt,
 }
 
 ANN static m_bool emit_stmt_each(const Emitter emit, const Stmt_Each stmt) {
+  const uint n = emit->info->unroll;
+
+  CHECK_BB(emit_exp(emit, stmt->exp)); // add ref?
+  regpop(emit, SZ_INT);
+
+  if (n) {
+    unroll_init(emit, n);
+    emit_local(emit, emit->gwion->type[et_int]);
+  }
+
   emit_push_stack(emit);
   m_uint       end_pc = 0;
   const m_bool ret    = _emit_stmt_each(emit, stmt, &end_pc);
   emit_pop_stack(emit, end_pc);
+  emit->info->unroll = 0;
   return ret;
 }
 
-ANN static Instr stmt_loop_roll(const Emitter emit, const struct Looper *loop) {
+ANN static Instr stmt_loop_roll(const Emitter emit, const Looper *loop) {
   const Instr eq = emit_add_instr(emit, Repeat);
   eq->m_val2     = loop->offset;
   return eq;
 }
 
 ANN static Instr stmt_loop_roll_idx(const Emitter        emit,
-                                    const struct Looper *loop) {
+                                    const Looper *loop) {
   const Instr instr = emit_add_instr(emit, RepeatIdx);
   instr->m_val2     = loop->offset;
   return instr;
@@ -2382,7 +2374,10 @@ ANN static Instr stmt_loop_roll_idx(const Emitter        emit,
 ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt,
                                   m_uint *index) {
   const uint n = emit->info->unroll;
-  if (n) unroll_init(emit, n);
+  if (n) {
+    unroll_init(emit, n);
+    emit->info->unroll = 0;
+  }
   const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
   if (stmt->idx) {
     const Instr instr          = emit_add_instr(emit, MemSetImm);
@@ -2787,6 +2782,7 @@ ANN static VM_Code emit_func_def_code(const Emitter emit, const Func func) {
 }
 
 ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) {
+  if (fdef->base->xid == insert_symbol("@dtor")) emit_local(emit, emit->gwion->type[et_int]);
   if (fdef->base->args) emit_func_def_args(emit, fdef->base->args);
   if (fbflag(fdef->base, fbflag_variadic)) stack_alloc(emit);
   if (fdef->d.code) {
index 616c92e128077175e6e69004e5dcb0add0d04855..5d144c9ae8778960b79eb8d4c487b5850c1494ec 100644 (file)
@@ -29,7 +29,7 @@ ANN Value new_value(MemPool p, const Type type, const m_str name) {
 
 ANN void valuefrom(const Env env, struct ValueFrom_ *from, const loc_t loc) {
   from->owner       = env->curr;
-  from->owner_class = env->class_def;
+  from->owner_class = env->scope->depth ? NULL : env->class_def;
   from->ctx         = env->context;
   from->filename    = env->name;
   from->loc         = loc;
index fad912e18fa1aaa1619832b154e2b571f8df5725..3d73d2f54dbbdffa5b1f796b33d2ea9485c7fc76 100644 (file)
@@ -13,7 +13,7 @@
 #include "parse.h"
 #include "gwi.h"
 #include "emit.h"
-
+#include "looper.h"
 static DTOR(array_dtor) {
   if (*(void **)(o->data + SZ_INT)) xfree(*(void **)(o->data + SZ_INT));
   struct M_Vector_ *a = ARRAY(o);
@@ -124,6 +124,10 @@ static OP_CHECK(opck_array_at) {
       ERR_N(exp_self(bin)->pos,
             _("do not provide array for 'xxx => declaration'."));
   }
+  bin->rhs->ref = bin->lhs;
+//  bin->rhs->data = bin->lhs;
+  if(bin->rhs->exp_type == ae_exp_decl)
+    SET_FLAG(bin->rhs->d.exp_decl.list->self->value, late);
   exp_setvar(bin->rhs, 1);
   return bin->rhs->type;
 }
@@ -725,32 +729,43 @@ static OP_CHECK(opck_array_implicit) {
   return imp->t;
 }
 
-struct Looper;
-typedef Instr (*f_looper_init)(const Emitter, const struct Looper *);
-typedef void (*f_looper)(const Emitter, const struct Looper *);
-struct Looper {
-  const Exp           exp;
-  const Stmt          stmt;
-  /*const */ m_uint   offset;
-  const m_uint        n;
-  const f_looper_init roll;
-  const f_looper_init unroll;
-//  union {
-    struct Vector_ unroll_v;
-    Instr instr;
-//  };
-};
-
-static OP_EMIT(opem_array_autoloop) {
-  struct Looper *loop = (struct Looper *)data;
+static OP_EMIT(opem_array_each_init) {
+  Looper *loop = (Looper *)data;
+  const Instr instr = emit_add_instr(emit, AutoUnrollInit);
+  instr->m_val = loop->offset;
+  return GW_OK;
+}
+
+
+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;
+}
+
+// rewrite me
+static OP_CHECK(opck_array_each_val) {
+  const Exp exp = (const Exp) data;
+  DECL_ON(const Type, base, = foreach_type(env, exp));
+  CHECK_BN(ensure_traverse(env, base));
+  const m_str basename = type2str(env->gwion, base, exp->pos);
+  char c[15 + strlen(basename)];
+  sprintf(c, "Ref:[%s]", basename);
+  return str2type(env->gwion, c, exp->pos);
+}
+
+static OP_EMIT(opem_array_each) {
+  Looper *loop = (Looper *)data;
   const Instr instr = emit_add_instr(emit, AutoLoop);
   if(!loop->n) {
     instr->m_val2     = loop->offset + SZ_INT;
+    loop->instr = instr;
   } else {
     instr->m_val2     = loop->offset + SZ_INT*2;
     vector_add(&loop->unroll_v, (m_uint)instr);
   }
-  loop->instr = instr;
   return GW_OK;
 }
 
@@ -877,9 +892,17 @@ GWION_IMPORT(array) {
   GWI_BB(gwi_oper_add(gwi, opck_array))
   GWI_BB(gwi_oper_emi(gwi, opem_array_access))
   GWI_BB(gwi_oper_end(gwi, "@array", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, "void"))
+  GWI_BB(gwi_oper_emi(gwi, opem_array_each_init))
+  GWI_BB(gwi_oper_end(gwi, "@each_init", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, "int"))
+  GWI_BB(gwi_oper_emi(gwi, opem_array_each))
+  GWI_BB(gwi_oper_end(gwi, "@each", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_array_each_val))
+  GWI_BB(gwi_oper_end(gwi, "@each_val", NULL))
   GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, "int"))
-  GWI_BB(gwi_oper_emi(gwi, opem_array_autoloop))
-  GWI_BB(gwi_oper_end(gwi, "@autoloop", NULL))
+  GWI_BB(gwi_oper_end(gwi, "@each_idx", NULL))
   GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_scan))
   GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
@@ -980,7 +1003,7 @@ INSTR(ArrayAlloc) {
   if (!ref) {
     gw_err("{-}[{0}{+}Gwion{0}{-}](VM):{0} (note: in shred[id=%" UINT_F ":%s])\n",
            shred->tick->xid, shred->code->name);
-    if (info->is_obj) free(aai.data);
+    if (info->is_obj) xfree(aai.data);
     handle(shred, "ArrayAllocException");
     return; // TODO make exception vararg
   }
index 1a900fb8795513ebe43700d0cbc8287c6d3a067a..c796da8299ea9420a995d458b570c34abb3e39da 100644 (file)
@@ -15,6 +15,7 @@
 #include "gwi.h"
 #include "tmpl_info.h"
 #include "array.h"
+#include "looper.h"
 
 #define HMAP_MIN_CAP 32
 #define HMAP_MAX_LOAD 0.75
@@ -167,17 +168,17 @@ INSTR(dict_lit_ctor) {
 
 static CTOR(dict_ctor) {
   const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
-  HMap *a = &*(struct HMap*)o->data;
-  a->key_size = hinfo->key->size;
-  a->val_size = hinfo->val->size;
-  a->data  = (m_bit*)mp_calloc2(shred->info->mp, hinfo->sz * HMAP_MIN_CAP);
-  a->state = (m_bit*)mp_calloc2(shred->info->mp, sizeof(HState) * HMAP_MIN_CAP);
-  a->capacity = HMAP_MIN_CAP;
-  a->count    = 0;
+  HMap *const a = &*(struct HMap*)o->data;
+  a->key_size   = hinfo->key->size;
+  a->val_size   = hinfo->val->size;
+  a->data       = (m_bit*)mp_calloc2(shred->info->mp, hinfo->sz * HMAP_MIN_CAP);
+  a->state      = (m_bit*)mp_calloc2(shred->info->mp, sizeof(HState) * HMAP_MIN_CAP);
+  a->capacity   = HMAP_MIN_CAP;
+  a->count      = 0;
 }
 
 static DTOR(dict_dtor) {
-  HMap *a = &*(struct HMap*)o->data;
+  HMap *const a = &*(struct HMap*)o->data;
   const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
   mp_free2(shred->info->mp, hinfo->sz * a->capacity, a->data);
   mp_free2(shred->info->mp, sizeof(HState) * a->capacity, a->state);
@@ -295,7 +296,7 @@ static INSTR(hmap_grow_dec) {
   *(m_uint*)(shred->reg -SZ_INT) = 1;
 }
 
-static INSTR(hmap_wtf) {
+static INSTR(hmap_find) {
   const M_Object o = *(M_Object*)(shred->reg - SZ_INT*6);
   HMap *const hmap = (HMap*)o->data;
   const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
@@ -435,7 +436,7 @@ if(info->is_var) {
   const Instr endgrow = emit_add_instr(emit, BranchNeqInt);
   emit_exp(emit, call.d.exp_call.func);
   emit_exp_call1(emit, call.d.exp_call.func->type->info->func, true);
-  emit_add_instr(emit, hmap_wtf);
+  emit_add_instr(emit, hmap_find);
   const Instr regrow = emit_add_instr(emit, BranchEqInt);
   regrow->m_val = grow_pc;
   nogrow->m_val = emit_code_size(emit);
@@ -572,6 +573,71 @@ static OP_CHECK(opck_dict_access) {
   return check_array_access(env, &next) ?: env->gwion->type[et_error];
 }
 
+static INSTR(DictEach) {
+  const M_Object o = *(M_Object *)(shred->mem + instr->m_val2);
+  HMapInfo *const hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
+  const HMap *hmap = (HMap*)o->data;
+  m_uint bucket = ++*(m_uint *)(shred->mem + instr->m_val2 + SZ_INT);
+  while(bucket < hmap->capacity) {
+    const HState *state = (HState *)(hmap->state + bucket * sizeof(HState));
+    if (state->set && !state->deleted)
+      break;
+    bucket++;
+  }
+  *(m_uint *)(shred->mem + instr->m_val2 + SZ_INT) = bucket;
+  memcpy(shred->mem + instr->m_val2 + SZ_INT*2, hmap->data + (bucket * hinfo->sz) + hinfo->key->size, hinfo->val->size);
+  *(m_uint*)shred->reg = (bucket == hmap->capacity);
+  PUSH_REG(shred, SZ_INT);
+}
+
+static INSTR(DictEachIdx) {
+  const M_Object o = *(M_Object *)(shred->mem + instr->m_val2);
+  HMapInfo *const hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
+  const HMap *hmap = (HMap*)o->data;
+  DictEach(shred, instr);
+  const m_int bucket = *(m_uint *)(shred->mem + instr->m_val2 + SZ_INT);
+  memcpy(shred->mem + instr->m_val, hmap->data + (bucket * hinfo->sz), hinfo->key->size);
+}
+
+static OP_EMIT(opem_dict_each) {
+  Looper *loop = (Looper *)data;
+  HMapInfo *const hinfo = (HMapInfo*)loop->exp->type->nspc->class_data;
+  if(loop->idx && !loop->init) loop->idx->v->from->offset = emit_localn(emit, hinfo->key);
+  const Instr instr = emit_add_instr(emit, !loop->idx ? DictEach : DictEachIdx);
+  instr->m_val2 = loop->offset;
+  if(loop->idx) instr->m_val = loop->idx->v->from->offset;
+  if(loop->n)instr->m_val2 += SZ_INT;
+  const Instr go = emit_add_instr(emit, BranchNeqInt);
+  if(!loop->n) loop->instr = go;
+  else vector_add(&loop->unroll_v, (m_uint)go);
+  loop->init = true;
+  return GW_OK;
+}
+
+static INSTR(DictEachInit) {
+  const M_Object o = *(M_Object *)(shred->mem + instr->m_val + SZ_INT);
+  *(m_uint *)(shred->mem + instr->m_val) = ((HMap*)o->data)->capacity;
+}
+
+static OP_EMIT(opem_dict_each_init) {
+  const Looper *loop = (Looper *)data;
+  const Instr instr = emit_add_instr(emit, DictEachInit);
+  instr->m_val = loop->offset;
+  return GW_OK;
+}
+
+static OP_CHECK(opck_dict_each_key) {
+  const Exp exp = (const Exp)data;
+  HMapInfo *const hinfo = (HMapInfo*)exp->type->nspc->class_data;
+  return hinfo->key;
+}
+
+static OP_CHECK(opck_dict_each_val) {
+  const Exp exp = (const Exp)data;
+  HMapInfo *const hinfo = (HMapInfo*)exp->type->nspc->class_data;
+  return hinfo->val;
+}
+
 static OP_CHECK(opck_dict_scan) {
   struct TemplateScan *ts   = (struct TemplateScan *)data;
   struct tmpl_info     info = {
@@ -621,7 +687,6 @@ static OP_CHECK(opck_dict_scan) {
   }
 
   return ret > 0 ? t : NULL;
-//  return t;
 }
 
 GWION_IMPORT(dict) {
@@ -646,6 +711,22 @@ GWION_IMPORT(dict) {
   GWI_BB(gwi_oper_add(gwi, opck_dict_scan))
   GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
 
+  GWI_BB(gwi_oper_ini(gwi, "Dict", NULL, "int"))
+  GWI_BB(gwi_oper_emi(gwi, opem_dict_each))
+  GWI_BB(gwi_oper_end(gwi, "@each", NULL))
+
+  GWI_BB(gwi_oper_ini(gwi, "Dict", NULL, "void"))
+  GWI_BB(gwi_oper_emi(gwi, opem_dict_each_init))
+  GWI_BB(gwi_oper_end(gwi, "@each_init", NULL))
+
+  GWI_BB(gwi_oper_ini(gwi, "Dict", NULL, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_dict_each_val))
+  GWI_BB(gwi_oper_end(gwi, "@each_val", NULL))
+
+  GWI_BB(gwi_oper_ini(gwi, "Dict", NULL, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_dict_each_key))
+  GWI_BB(gwi_oper_end(gwi, "@each_idx", NULL))
+
   GWI_BB(gwi_func_ini(gwi, "int",    "hash"));
   GWI_BB(gwi_func_arg(gwi, "int",    "key"));
   GWI_BB(gwi_func_end(gwi, mfun_int_h, ae_flag_none));
index a6697344598ab35f38355c61e2b869570bcb0cd0..7d32b2ddc722b139d88f701c707e57a1a028b22f 100644 (file)
@@ -13,7 +13,7 @@
 #include "import.h"
 #include "emit.h"
 #include "template.h"
-
+/*
 INSTR(DTOR_EOC) {
   const M_Object o = *(M_Object *)MEM(0);
   o->type_ref      = o->type_ref->info->parent;
@@ -21,7 +21,7 @@ INSTR(DTOR_EOC) {
   shred->info->me->ref = 1;
   vm_shred_exit(shred);
 }
-
+*/
 ANN static Func_Def from_base(const Env env, struct dottmpl_ *const dt,
                               const Nspc nspc) {
   const Func_Def fdef = dt->def ?: dt->base;
index ab73235de42ec8c3a00b1bb53e98c58833946714..011840471b498c03f56a97793bf69cdf7bb185e7 100644 (file)
@@ -25,8 +25,6 @@ M_Object new_object(MemPool p, const Type t) {
   const M_Object a = _mp_calloc(p, offset);
   a->ref           = 1;
   a->type_ref      = t;
-  a->offset = t->nspc->offset;
-  a->vtable.ptr = t->nspc->vtable.ptr;
   return a;
 }
 
@@ -37,11 +35,11 @@ M_Object new_string(const struct Gwion_ *gwion, const m_str str) {
 }
 
 ANN static void user_dtor(const M_Object o, const VM_Shred shred, const Type t) {
-  o->type_ref = t;
-  const VM_Shred sh = new_vm_shred(shred->info->mp, o->type_ref->nspc->dtor);
-  vmcode_addref(o->type_ref->nspc->dtor);
+  const VM_Shred sh = new_vm_shred(shred->info->mp, t->nspc->dtor);
+  vmcode_addref(t->nspc->dtor);
   sh->base             = shred->base;
   *(M_Object *)sh->mem = o;
+  *(Type *)(sh->mem + SZ_INT) = t;
   vm_add_shred(shred->info->vm, sh);
   ++sh->info->me->ref;
 }
@@ -80,13 +78,21 @@ ANN static void do_release(const M_Object o,
   return do_release(o, shred, t->info->parent);
 }
 
+
+INSTR(DTOR_EOC) {
+  const M_Object o = *(M_Object *)MEM(0);
+  const Type t     = *(Type *)MEM(SZ_INT);
+  do_release(o, shred, t->info->parent);
+  shred->info->me->ref = 1;
+  vm_shred_exit(shred);
+}
+
 ANN void __release(const M_Object o, const VM_Shred shred) {
-//  vector_rem2(&shred->gc, (vtype)o);
   do_release(o, shred, o->type_ref);
 }
 
 ANN void free_object(MemPool p, const M_Object o) {
-    mp_free2(p, o->offset, o);
+  mp_free2(p, o->type_ref->nspc->offset, o);
 }
 
 static ID_CHECK(opck_this) {
index 1399724984e957bd872c451f3f25f49f3a078f49..3765540d8a1c3a2d5fb818db5840a4ac08e35b85 100644 (file)
@@ -35,6 +35,7 @@ static OP_CHECK(opck_object_at) {
   exp_setvar(bin->rhs, 1);
   CHECK_BO(isa(bin->lhs->type, bin->rhs->type));
   bin->lhs->ref = bin->rhs;
+//  bin->lhs->acquire = true;
 //  bin->rhs-> = bin->lhs;
   return bin->rhs->type;
 }
@@ -51,7 +52,6 @@ static bool exp_func(const Exp exp) {
 ANN void unset_local(const Emitter emit, void *const l);
 static OP_EMIT(opem_object_at) {
   const Exp_Binary *bin = (Exp_Binary *)data;
-
   if(!bin->rhs->data) {
     const Instr addref = emit_add_instr(emit, RegAddRef);
     addref->m_val      = -SZ_INT * 2;
index e05348a9cbe03698ecbb88b47c5f9c12441b8c89..1bcb49f52495f27c29580e12778e977b393608d0 100644 (file)
@@ -150,7 +150,7 @@ OP_EMIT(opem_new) {
   const Exp_Unary *unary = (Exp_Unary *)data;
   CHECK_BB(emit_instantiate_object(emit, exp_self(unary)->type,
                                    unary->ctor.td->array, 0));
-  if(!unary->ctor.exp)
-    emit_localx(emit, exp_self(unary)->type);
+//  if(!unary->ctor.exp)
+//    emit_local_exp(emit, exp_self(unary)->type);
   return GW_OK;
 }
index 0fb7affb3d470287c698681b427b5a4b546a9a57..8c09181d755463eb500b7457bfc4badd6408e59a 100644 (file)
@@ -112,6 +112,11 @@ 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;
   do {
@@ -119,9 +124,8 @@ ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
     CHECK_BB(check_var(env, var));
     CHECK_BB(check_var_td(env, var, decl->td));
     if (is_fptr(env->gwion, decl->type)) CHECK_BB(check_fptr_decl(env, var));
-    set_vflag(var->value, vflag_valid);
+    valid_value(env, var->xid, var->value);
     // set_vflag(var->value, vflag_used));
-    nspc_add_value(env->curr, var->xid, var->value);
   } while ((list = list->next));
   return GW_OK;
 }
@@ -583,8 +587,7 @@ ANN static m_bool check_func_args(const Env env, Arg_List arg_list) {
     const Var_Decl decl = arg_list->var_decl;
     const Value    v    = decl->value;
     CHECK_BB(already_defined(env, decl->xid, decl->pos));
-    set_vflag(v, vflag_valid);
-    nspc_add_value(env->curr, decl->xid, v);
+    valid_value(env, decl->xid, v);
   } while ((arg_list = arg_list->next));
   return GW_OK;
 }
@@ -1161,7 +1164,7 @@ ANN static inline m_bool for_empty(const Env env, const Stmt_For stmt) {
 }
 
 ANN static inline Type foreach_type(const Env env, const Exp exp) {
-  DECL_OO(Type, et, = check_exp(env, exp));
+  const Type et = exp->type;
   if (isa(et, env->gwion->type[et_array]) < 0)
     ERR_O(exp->pos,
           _("type '%s' is not array.\n"
@@ -1173,36 +1176,53 @@ ANN static inline Type foreach_type(const Env env, const Exp exp) {
   return depth ? array_type(env, t, depth) : t;
 }
 
-ANN static void check_idx(const Env env, struct EachIdx_ *const idx) {
-  idx->v =
-      new_value(env->gwion->mp, env->gwion->type[et_int], s_name(idx->sym));
+ANN static void check_idx(const Env env, const Type base, struct EachIdx_ *const idx) {
+  idx->v = new_value(env->gwion->mp, base, s_name(idx->sym));
   valuefrom(env, idx->v->from, idx->pos);
-  idx->v->from->owner_class = NULL;
-  set_vflag(idx->v, vflag_valid);
-  nspc_add_value(env->curr, idx->sym, idx->v);
+  valid_value(env, idx->sym, idx->v);
+}
+
+/** sets for the key expression value
+    with eg  type *int* for an array or the *Key* type of a Dict **/
+ANN static m_bool check_each_idx(const Env env, const Exp exp, struct EachIdx_ *const idx) {
+  struct Op_Import opi = {
+    .lhs = exp->type,
+    .op  = insert_symbol("@each_idx"),
+    .data = exp,
+    .pos = idx->pos
+  };
+  DECL_OB(const Type, t, = op_check(env, &opi));
+  check_idx(env, t, idx);
+  return GW_OK;
+}
+
+/** return the base type for the foreach expression
+    eg the base type of an array or the *Val* type of a Dict **/
+ANN static Type check_each_val(const Env env, const Exp exp) {
+  struct Op_Import opi = {
+    .lhs  = exp->type,
+    .op   = insert_symbol("@each_val"),
+    .data = (m_uint)exp
+  };
+  return op_check(env, &opi);
 }
 
 ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) {
-  DECL_OB(const Type, base, = foreach_type(env, stmt->exp));
-  CHECK_BB(ensure_traverse(env, base));
-  const m_str basename = type2str(env->gwion, base, stmt->exp->pos);
-  char        c[15 + strlen(basename)];
-  sprintf(c, "Ref:[%s]", basename);
-  const Type ret = str2type(env->gwion, c, stmt->exp->pos);
-  if (base->array_depth) set_tflag(ret, tflag_typedef);
+  CHECK_OB(check_exp(env, stmt->exp));
+  if (stmt->idx)
+    CHECK_BB(check_each_idx(env, stmt->exp, stmt->idx));
+  DECL_OB(const Type, ret, = check_each_val(env, stmt->exp));
   stmt->v = new_value(env->gwion->mp, ret, s_name(stmt->sym));
-  set_vflag(stmt->v, vflag_valid);
-  nspc_add_value(env->curr, stmt->sym, stmt->v);
-  if (stmt->idx) check_idx(env, stmt->idx);
+  valid_value(env, stmt->sym, stmt->v);
   return check_conts(env, stmt_self(stmt), stmt->body);
 }
 
 ANN static m_bool do_stmt_repeat(const Env env, const Stmt_Loop stmt) {
-  if (stmt->idx) check_idx(env, stmt->idx);
+  if (stmt->idx) check_idx(env, env->gwion->type[et_int], stmt->idx);
   return check_conts(env, stmt_self(stmt), stmt->body);
 }
 
-ANN static inline m_bool cond_type(const Env env, const Exp e) {
+ANN static inline m_bool repeat_type(const Env env, const Exp e) {
   const Type t_int = env->gwion->type[et_int];
   if (check_implicit(env, e, t_int) < 0) {
     char explain[40 + strlen(e->type->name)];
@@ -1234,7 +1254,7 @@ stmt_func_xxx(for, Stmt_For, env_inline_mult(env, 1.5), !(
   (stmt->c3 && !check_exp(env, stmt->c3)) ||
   check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1)
 stmt_func_xxx(loop, Stmt_Loop, env_inline_mult(env, 1.5); check_idx(env, stmt->idx), !(!check_exp(env, stmt->cond) ||
-  cond_type(env, stmt->cond) < 0 ||
+  repeat_type(env, stmt->cond) < 0 ||
   do_stmt_repeat(env, stmt) < 0) ? 1 : -1)
 stmt_func_xxx(each, Stmt_Each, env_inline_mult(env, 1.5), do_stmt_each(env, stmt))
 
@@ -1301,8 +1321,7 @@ ANN static Value match_value(const Env env, const Type base,
                              const Exp_Primary *prim) {
   const Symbol sym = prim->d.var;
   const Value  v   = new_value(env->gwion->mp, base, s_name(sym));
-  set_vflag(v, vflag_valid);
-  nspc_add_value(env->curr, sym, v);
+  valid_value(env, sym, v);
   return v;
 }
 
@@ -1914,13 +1933,13 @@ ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
 ANN m_bool check_class_def(const Env env, const Class_Def cdef) {
   if (tmpl_base(cdef->base.tmpl)) return GW_OK;
   const Type       t   = cdef->base.type;
+  if (tflag(t, tflag_check)) return GW_OK;
   const Class_Def  c   = t->info->cdef;
   struct Op_Import opi = {.op   = insert_symbol("@class_check"),
                           .lhs  = t,
                           .data = (uintptr_t)c,
                           .pos  = c->pos};
   CHECK_OB(op_check(env, &opi));
-  if (tflag(t, tflag_check)) return GW_OK;
   set_tflag(t, tflag_check);
   return _check_class_def(env, c);
 }
index f9338f4af374109d4e37b183f3ab434034f60e89..2ada2d4c74ef6918c9a0fed5e93b3ffbbfa05260 100644 (file)
@@ -1032,7 +1032,7 @@ vm_run(const VM *vm) { // lgtm [cpp/use-of-goto]
       DISPATCH()
     autounrollinit:
       *(m_uint *)(mem + VAL) =
-          m_vector_size(ARRAY(*(M_Object *)(mem + VAL + SZ_INT)));
+          m_vector_size(ARRAY(*(M_Object *)(mem + VAL + SZ_INT))) + 1;
       DISPATCH()
     autoloop: {
       const M_Vector array = ARRAY(*(M_Object *)(mem + VAL2 - SZ_INT));
@@ -1217,7 +1217,7 @@ vm_run(const VM *vm) { // lgtm [cpp/use-of-goto]
       DISPATCH()
     dotfunc:
       *(VM_Code *)(reg + (m_uint)VAL2) =
-          ((Func)(*(M_Object *)(reg - SZ_INT))->vtable.ptr[OFFSET + VAL])->code;
+          ((Func)(*(M_Object *)(reg - SZ_INT))->type_ref->nspc->vtable.ptr[OFFSET + VAL])->code;
       DISPATCH()
     gacktype : {
       const M_Object o = *(M_Object *)(reg - SZ_INT);
diff --git a/tests/error/auto_not_array.gw b/tests/error/auto_not_array.gw
deleted file mode 100644 (file)
index 9ee67a4..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#! [contains]  not allowed in foreach loop
-var Object i;
-foreach(a: i)
-  <<< a >>>;
diff --git a/util b/util
index 7643ceba751766ae5cd42da19667e1377a2b89d0..7b668adba0cd3d9e6af45e9c30456b5a6f171d74 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 7643ceba751766ae5cd42da19667e1377a2b89d0
+Subproject commit 7b668adba0cd3d9e6af45e9c30456b5a6f171d74