]> Nishi Git Mirror - gwion.git/commitdiff
:art: union as struct
authorfennecdjay <fennecdjay@gmail.com>
Sun, 5 Feb 2023 22:11:15 +0000 (23:11 +0100)
committerfennecdjay <fennecdjay@gmail.com>
Sun, 5 Feb 2023 22:11:15 +0000 (23:11 +0100)
25 files changed:
ast
include/dict.h
include/emit.h
include/object.h
include/opcode.h
opcode.txt
plug
src/emit/emit.c
src/env/nspc.c
src/lib/array.c
src/lib/dict.c
src/lib/union.c
src/parse/check.c
src/parse/operator.c
src/parse/scan0.c
src/parse/scan1.c
src/plug.c
src/vm/vm.c
tests/struct/member_func.gw
tests/struct/struct_gack.gw [deleted file]
tests/struct/struct_global0.gw [deleted file]
tests/struct/struct_global1.gw [deleted file]
tests/union/option.gw
tests/union/option_check.gw
tests/union/option_invalid_runtime.gw

diff --git a/ast b/ast
index 368e64e5442209148ef1e8b271e645e05b125fdb..d8d61d8a6395dd2b79e96bd1fcaaec54e324685b 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 368e64e5442209148ef1e8b271e645e05b125fdb
+Subproject commit d8d61d8a6395dd2b79e96bd1fcaaec54e324685b
index 74bb30ea9aeb7fac7749a99bef912c084bb185f9..84e830a960ab13a4c3eb76ea6549004f9463e8ef 100644 (file)
@@ -13,18 +13,10 @@ typedef struct HMap {
 } HMap;
 
 
-enum HMapKind {
-  HKIND_NONE,
-  HKIND_OBJ,
-  HKIND_STRUCT
-};
-
 typedef struct HMapInfo {
   Type key;
   Type val;
   m_uint sz;
-  enum HMapKind keyk;
-  enum HMapKind valk;
 } HMapInfo;
 
 #endif
index e3d030b6b9792363f06472d09ab8ab2078c1f3af..5656c156f375d441cca41e59b9b0b4063120bf6a 100644 (file)
@@ -66,7 +66,7 @@ ANEW ANN Emitter new_emitter(MemPool);
 ANN void         free_emitter(MemPool, Emitter);
 ANN m_bool       emit_ast(const Env env, Ast *ast);
 ANN m_bool       emit_func_def(const Emitter emit, const Func_Def fdef);
-ANN m_bool emit_exp_call1(const Emitter, const Func, const bool is_static);
+ANN m_bool emit_exp_call1(const Emitter, const Func, const m_uint size, const bool is_static);
 ANN2(1)
 Instr emit_add_instr(const Emitter, const f_instr)
     __attribute__((returns_nonnull));
index f2157ee5c315418eab728c1c48dabaa107697f75..8838a549c48299969bc7c62321bb6c4184371240 100644 (file)
@@ -53,30 +53,55 @@ typedef void(f_release)(const VM_Shred shred, const Type t NUSED,
                         const m_bit *ptr);
 #define RELEASE_FUNC(a)                                                        \
   void(a)(const VM_Shred shred, const Type t NUSED, const m_bit *ptr)
-static inline RELEASE_FUNC(object_release) { release(*(M_Object *)ptr, shred); }
 RELEASE_FUNC(struct_release);
+RELEASE_FUNC(union_release);
+static inline RELEASE_FUNC(object_release) { release(*(M_Object *)ptr, shred); }
+static inline RELEASE_FUNC(compound_release) {
+  if (!tflag(t, tflag_struct))
+    object_release(shred, t, ptr);
+  else if (!tflag(t, tflag_union))
+    struct_release(shred, t, ptr);
+  else union_release(shred, t, ptr);
+}
+static inline RELEASE_FUNC(anytype_release) {
+  if (tflag(t, tflag_release))
+    compound_release(shred, t, ptr);
+}
+static inline void object_addref(const m_bit *ptr) {
+  M_Object o = (M_Object)ptr;
+  if(o) o->ref++;
+}
 
-static inline void struct_addref(const Gwion gwion, const Type type,
-                                 const m_bit *ptr) {
-  for (m_uint i = 0; i < vector_size(&type->info->tuple->types); ++i) {
-    const Type t = (Type)vector_at(&type->info->tuple->types, i);
-    if (tflag(t, tflag_compound)) {
-      if (!tflag(t, tflag_struct)) {
-        const M_Object o =
-          *(M_Object *)(ptr + vector_at(&type->info->tuple->offset, i));
-        if(o) o->ref++;
-      } else struct_addref(gwion, t,
-          *(m_bit **)(ptr + vector_at(&type->info->tuple->offset, i)));
-    }
+ANN static inline void union_addref(const Type type, const m_bit*);
+ANN static inline void struct_addref(const Type type, const m_bit*);
+ANN static inline void compound_addref(const Type t, const m_bit *ptr) {
+  if (!tflag(t, tflag_struct))
+    object_addref(ptr);
+  else if (!tflag(t, tflag_union))
+    struct_addref(t, ptr);
+  else union_addref(t, ptr);
+}
+
+ANN static inline void struct_addref(const Type type, const m_bit *ptr) {
+  const Vector v = &type->info->tuple->types;
+  for (m_uint i = 0; i < vector_size(v); ++i) {
+    const Type t = (Type)vector_at(v, i);
+    const m_bit *data = *(m_bit**)(ptr + vector_at(v, i));
+    if (tflag(t, tflag_release)) compound_addref(t, data);
   }
 }
 
-ANN static inline void compound_release(const VM_Shred shred, const Type t,
-                                    const m_bit *ptr) {
-  if (!tflag(t, tflag_struct))
-    object_release(shred, t, ptr);
-  else
-    struct_release(shred, t, ptr);
+ANN static inline void union_addref(const Type t, const m_bit *ptr) {
+  const m_uint idx = *(m_uint *)ptr;
+  if (idx) {
+    const Map   map = &t->nspc->info->value->map;
+    const Value v   = (Value)map_at(map, idx - 1);
+    if (tflag(v->type, tflag_release))
+      compound_addref(v->type, ptr + SZ_INT);
+  }
 }
 
+ANN static inline void anytype_addref(const Type t, const m_bit *ptr) {
+  if(tflag(t, tflag_release)) compound_addref(t, ptr);
+}
 #endif
index d6069550f9d5754bcb584c68fc7f8708ca8c4211..9e8f041d7b5531f6a19d00154e78e1a439c9997d 100644 (file)
@@ -177,12 +177,16 @@ enum {
   eRegAddRefAddr,
   eStructRegAddRef,
   eStructRegAddRefAddr,
+  eUnionRegAddRef,
+  eUnionRegAddRefAddr,
   eObjectAssign,
   eAssign,
   eObjectRelease,
   eObjectRelease2,
   eStructReleaseRegAddr,
   eStructReleaseMem,
+  eUnionReleaseRegAddr,
+  eUnionReleaseMem,
   eGWOP_EXCEPT,
   eDotMemberMem,
   eDotMemberMem2,
@@ -393,12 +397,16 @@ enum {
 #define  RegAddRefAddr         (f_instr)eRegAddRefAddr
 #define  StructRegAddRef       (f_instr)eStructRegAddRef
 #define  StructRegAddRefAddr   (f_instr)eStructRegAddRefAddr
+#define  UnionRegAddRef        (f_instr)eUnionRegAddRef
+#define  UnionRegAddRefAddr    (f_instr)eUnionRegAddRefAddr
 #define  ObjectAssign          (f_instr)eObjectAssign
 #define  Assign                (f_instr)eAssign
 #define  ObjectRelease         (f_instr)eObjectRelease
 #define  ObjectRelease2        (f_instr)eObjectRelease2
 #define  StructReleaseRegAddr  (f_instr)eStructReleaseRegAddr
 #define  StructReleaseMem      (f_instr)eStructReleaseMem
+#define  UnionReleaseRegAddr   (f_instr)eUnionReleaseRegAddr
+#define  UnionReleaseMem       (f_instr)eUnionReleaseMem
 #define  GWOP_EXCEPT           (f_instr)eGWOP_EXCEPT
 #define  DotMemberMem          (f_instr)eDotMemberMem
 #define  DotMemberMem2         (f_instr)eDotMemberMem2
@@ -1247,6 +1255,17 @@ ANN static inline void dump_opcodes(const VM_Code code) {
         gw_out(" {-R}%-14"INT_F"{0}", instr->m_val);
         gw_out("\n");
         break;
+      case eUnionRegAddRef:
+        gw_out("{Y}┃{0}{-}% 4lu{0}: UnionRegAddRef", j);
+        gw_out(" {-R}%-14"INT_F"{0}", instr->m_val);
+        gw_out(" {-M}%-14"UINT_F"{0}", instr->m_val2);
+        gw_out("\n");
+        break;
+      case eUnionRegAddRefAddr:
+        gw_out("{Y}┃{0}{-}% 4lu{0}: UnionRegAddRefAddr", j);
+        gw_out(" {-R}%-14"INT_F"{0}", instr->m_val);
+        gw_out("\n");
+        break;
       case eObjectAssign:
         gw_out("{Y}┃{0}{-}% 4lu{0}: ObjectAssign", j);
         gw_out("\n");
@@ -1277,6 +1296,18 @@ ANN static inline void dump_opcodes(const VM_Code code) {
         gw_out(" {-B}%-14s"UINT_F"{0}", ((Type)instr->m_val2)->name);
         gw_out("\n");
         break;
+      case eUnionReleaseRegAddr:
+        gw_out("{Y}┃{0}{-}% 4lu{0}: UnionReleaseRegAddr", j);
+        gw_out(" {-R}%-14"UINT_F"{0}", instr->m_val);
+        gw_out(" {-B}%-14s"UINT_F"{0}", ((Type)instr->m_val2)->name);
+        gw_out("\n");
+        break;
+      case eUnionReleaseMem:
+        gw_out("{Y}┃{0}{-}% 4lu{0}: UnionReleaseMem", j);
+        gw_out(" {-R}%-14"UINT_F"{0}", instr->m_val);
+        gw_out(" {-B}%-14s"UINT_F"{0}", ((Type)instr->m_val2)->name);
+        gw_out("\n");
+        break;
       case eGWOP_EXCEPT:
         gw_out("{Y}┃{0}{-}% 4lu{0}: GWOP_EXCEPT ", j);
         gw_out(" {-R}%-14"UINT_F"{0}", instr->m_val);
index 773403aabfcd0ccde753511a02df9b19ca6abf4b..f7db6f75e37142e224b5d9b355adbbc340a31b70 100644 (file)
@@ -174,12 +174,16 @@ RegAddRef~i
 RegAddRefAddr~i
 StructRegAddRef~i~u
 StructRegAddRefAddr~i
+UnionRegAddRef~i~u
+UnionRegAddRefAddr~i
 ObjectAssign
 Assign
 ObjectRelease~u
 ObjectRelease2~p
 StructReleaseRegAddr~u~t
 StructReleaseMem~u~t
+UnionReleaseRegAddr~u~t
+UnionReleaseMem~u~t
 GWOP_EXCEPT~u
 DotMemberMem~u
 DotMemberMem2~u
diff --git a/plug b/plug
index d868f2419d0981580c2e85a717ea6c42995582b2..ce09a14cc01ba003fcbc2120f5a4434e6cccc671 160000 (submodule)
--- a/plug
+++ b/plug
@@ -1 +1 @@
-Subproject commit d868f2419d0981580c2e85a717ea6c42995582b2
+Subproject commit ce09a14cc01ba003fcbc2120f5a4434e6cccc671
index 5d0cd104eb6920a26d9b621bafaf39ad8d965ad9..8cd85a0404fa61b25ddb910b04a0b727b1e96311 100644 (file)
@@ -145,7 +145,10 @@ ANN void emit_compound_release(const Emitter emit, const Type t, const m_uint of
 ANN void emit_struct_release(const Emitter emit, const Type type,
                              const m_uint offset) {
   if(!tflag(type, tflag_release)) return;
-  const Instr instr = emit_add_instr(emit, StructReleaseMem);
+  f_instr exec = tflag(type, tflag_union)
+    ? UnionReleaseMem
+    : StructReleaseMem;
+  const Instr instr = emit_add_instr(emit, exec);
   instr->m_val = offset;
   instr->m_val2 = (m_uint)type;
 }
@@ -307,6 +310,12 @@ ANN m_uint emit_local_exp(const Emitter emit, const Exp e) {
   return l->offset;
 }
 
+ANN m_uint emit_local_exp2(const Emitter emit, const Exp e) {
+  Local *const l = emit_localx(emit, e->type);
+  e->data = l;
+  return l->offset;
+}
+
 ANN m_uint emit_localn(const Emitter emit, const Type t) {
   Local *const l = frame_local(emit->gwion->mp, emit->code->frame, t);
   l->skip        = true;
@@ -406,14 +415,15 @@ static ArrayInfo *emit_array_extend_inner(const Emitter emit, const Type t,
   return info;
 }
 
-ANN static void call_finish(const Emitter emit, const Func f,const bool);
+ANN static void call_finish(const Emitter emit, const Func f, const m_uint size, const bool);
 ANN void emit_ext_ctor(const Emitter emit, const Type t) {
   const Instr cpy = emit_add_instr(emit, Reg2Reg);
   cpy->m_val2     = -SZ_INT;
-  const Func f = (Func)vector_front(&t->nspc->vtable);
   emit_regmove(emit, SZ_INT);
+  const Func f = (Func)vector_front(&t->nspc->vtable);
   emit_pushfunc(emit, f);
-  call_finish(emit, f, false);
+  const m_uint size = !tflag(t, tflag_union) ? 0 : t->size;
+  call_finish(emit, f, size, false);
 }
 
 ANN static inline void emit_notpure(const Emitter emit) {
@@ -430,8 +440,7 @@ m_bool emit_instantiate_object(const Emitter emit, const Type type,
                                       is_ref));
     return GW_OK;
   } else if (!is_ref) {
-    if(!tflag(type, tflag_typedef) || isa(type, emit->gwion->type[et_closure]) > 0 ||
-       tflag(type, tflag_union)) {
+    if(!tflag(type, tflag_typedef) || isa(type, emit->gwion->type[et_closure]) > 0) {
       const Instr instr = emit_add_instr(emit, ObjectInstantiate);
       instr->m_val2     = (m_uint)type;
     } // maybe we should instantiate the first actual type
@@ -661,7 +670,8 @@ ANN static m_bool emit_prim_dict(const Emitter emit, Exp *data) {
     }
     e->next = next;
     CHECK_BB(emit_exp(emit, &func));
-    CHECK_BB(emit_exp_call1(emit, func.type->info->func, true));
+    CHECK_BB(emit_exp_call1(emit, func.type->info->func,
+          func.type->info->func->def->base->ret_type->size, true));
     count++;
   } while((e = e->next->next));
   init->m_val = int2pow2(count);
@@ -856,7 +866,7 @@ ANN static m_bool emit_prim_locale(const Emitter emit, const Symbol *id) {
   const M_Object string = new_string(emit->gwion, s_name(*id));
   emit_pushimm(emit, (m_uint)string);
   emit_pushimm(emit, (m_uint)emit->locale->code);
-  CHECK_BB(emit_exp_call1(emit, emit->locale, true));
+  CHECK_BB(emit_exp_call1(emit, emit->locale, SZ_FLOAT, true));
   emit_regmove(emit, -emit->locale->def->base->ret_type->size);
   const VM_Code code = finalyze(emit, EOC);
   const VM_Shred shred = new_vm_shred(emit->gwion->mp, code);
@@ -908,7 +918,7 @@ ANN static m_bool decl_static(const Emitter emit, const Exp_Decl *decl,
 }
 
 ANN static inline int struct_ctor(const Value v) {
-  return tflag(v->type, tflag_struct) && tflag(v->type, tflag_ctor);
+  return tflag(v->type, tflag_struct) /*&& tflag(v->type, tflag_ctor)*/;
 }
 
 ANN static void decl_expand(const Emitter emit, const Type t) {
@@ -927,18 +937,25 @@ ANN static m_uint decl_non_static_offset(const Emitter emit, const Exp_Decl *dec
 ANN static m_bool struct_finish(const Emitter emit, const Exp_Decl *decl) {
   const Type t = decl->type;
   const bool emit_addr = exp_getvar(exp_self(decl));
+  if(GET_FLAG(decl->vd.value, late) || GET_FLAG(decl->td, late)) {
+    if(!emit_addr)
+    decl_expand(emit, t);
+    return GW_OK;
+  }
+  if(!decl->args && !tflag(t, tflag_ctor) && emit_addr)
+    return GW_OK;
   if (decl->args) {
-    CHECK_BB(emit_exp(emit, decl->args));
     if (emit_addr) {
-      emit_regmove(emit, -t->size);
-      emit_regpushmem4(emit, decl->vd.value->from->offset, 0);
+      const Instr back = (Instr)vector_back(&emit->code->instr);
+      const Instr instr = emit_add_instr(emit, NoOp);
+      memcpy(instr, back, sizeof(struct Instr_));
     }
+    CHECK_BB(emit_exp(emit, decl->args));
+    if (emit_addr) emit_regmove(emit, -t->size);
     return GW_OK;
   }
-  if(tflag(t, tflag_ctor)) {
-    emit_ext_ctor(emit, t);
-    if (!emit_addr) decl_expand(emit, t);
-  }
+  if(tflag(t, tflag_ctor)) emit_ext_ctor(emit, t);
+  if (!emit_addr) decl_expand(emit, t);
   return GW_OK;
 }
 
@@ -1125,7 +1142,7 @@ ANN static m_bool emit_decl(const Emitter emit, Exp_Decl *const decl) {
     }
     return GW_ERROR;
   }
-  if(GET_FLAG(v, late) && exp_getuse(exp_self(decl)))
+  if(isa(v->type, emit->gwion->type[et_object]) > 0 && GET_FLAG(v, late) && exp_getuse(exp_self(decl)))
     emit_add_instr(emit, GWOP_EXCEPT);
   return GW_OK;
 }
@@ -1303,17 +1320,11 @@ ANN static m_bool emit_new_struct(const Emitter emit,const Exp_Call *call)  {
   const m_int offset = self->ref ? emit->code->frame->curr_offset - t->size: emit_local(emit, t);
   const Instr back = self->ref ? (Instr)vector_pop(&emit->code->instr) : NULL;
   CHECK_BB(emit_func_args(emit, call));
-  if(back)
-    vector_add(&emit->code->instr, (m_uint)back);
-  else if(tflag(t, tflag_ctor))
-    emit_regpushmem4(emit, offset, 0);
+  if(back) vector_add(&emit->code->instr, (m_uint)back);
+  else emit_regpushmem(emit, offset, t->size, true);
   if(tflag(t, tflag_ctor)) emit_ext_ctor(emit, t);
-  else if(!back) {
-    emit_regmove(emit, -SZ_INT + t->size);
-    emit_regpushmem4(emit, offset, 0);
-  }
   emit_add_instr(emit, NoOp);
-  CHECK_BB(emit_exp_call1(emit, call->func->type->info->func, is_static_call(emit->gwion, call->func))); // is a ctor, is_static is true
+  CHECK_BB(emit_exp_call1(emit, call->func->type->info->func, t->size, is_static_call(emit->gwion, call->func))); // is a ctor, is_static is true
   return GW_OK;
 }
 
@@ -1332,7 +1343,6 @@ ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *call) {
   #endif
 
   const Type t = call->func->type;
-
   if(unlikely(!is_func(emit->gwion, t))) {
     const Type t = actual_type(emit->gwion, call->func->type);
     struct Op_Import opi = {.op   = insert_symbol("call_type"),
@@ -1348,7 +1358,7 @@ ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *call) {
     if (f != emit->env->func || (f && f->value_ref->from->owner_class))
       CHECK_BB(prepare_call(emit, call));
     else CHECK_BB(emit_func_args(emit, call));
-    CHECK_BB(emit_exp_call1(emit, f, is_static_call(emit->gwion, call->func)));
+    CHECK_BB(emit_exp_call1(emit, f, exp_self(call)->type->size, is_static_call(emit->gwion, call->func)));
   }
   return GW_OK;
 }
@@ -1357,7 +1367,7 @@ ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call *exp_call) {
   CHECK_BB(_emit_exp_call(emit, exp_call));
   const Exp e = exp_self(exp_call);
   if (exp_getvar(e)) {
-    const m_uint size = exp_self(exp_call)->type->size;
+    const m_uint size = e->type->size;
     emit_regmove(emit, -size);
     const Local *l = e->ref ? e->ref->data : NULL;
     const m_uint offset  = l ? l->offset : emit_local_exp(emit, e);
@@ -1615,17 +1625,17 @@ ANN static void emit_fptr_call(const Emitter emit, const Func f) {
 }
 
 ANN static void call_finish(const Emitter emit, const Func f,
-                          const bool is_static) {
+                          const m_uint size, const bool is_static) {
   const m_uint offset = emit_code_offset(emit);
   if (f != emit->env->func || !is_static || !is_new(f->def))
     emit_regsetimm(emit, offset, 0);
   const Instr instr   = emit_call(emit, f, is_static);
-  instr->m_val        = f->def->base->ret_type->size;
+  instr->m_val        = size;
   instr->m_val2       = offset;
 }
 
 ANN m_bool emit_exp_call1(const Emitter emit, const Func f,
-                          const bool is_static) {
+                          const m_uint size, const bool is_static) {
   const EmitterStatus status = emit->status;
   emit->status =  (EmitterStatus){};
   if(unlikely(fflag(f, fflag_fptr))) emit_fptr_call(emit, f);
@@ -1641,7 +1651,7 @@ CHECK_BB(emit_ensure_func(emit, f));
 }
   } else if(is_static)
     push_func_code(emit, f);
-  call_finish(emit, f, is_static);
+  call_finish(emit, f, size, is_static);
   emit->status = status;
   return GW_OK;
 }
@@ -1703,7 +1713,7 @@ ANN static m_bool spork_prepare_func(const Emitter         emit,
     CHECK_BB(emit_ensure_func(emit, f));
   push_spork_code(emit, sp->is_spork ? SPORK_FUNC_PREFIX : FORK_CODE_PREFIX,
                   sp->exp->pos);
-  return emit_exp_call1(emit, f, false);
+  return emit_exp_call1(emit, f, f->def->base->ret_type->size, false);
 }
 
 ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
@@ -2488,7 +2498,7 @@ ANN static Symbol case_op(const Emitter emit, const Exp base, const Exp e,
         return CASE_PASS;
       }
     }
-  } else if (isa(base->type, emit->gwion->type[et_union]) > 0 &&
+  } else if (tflag(base->type, tflag_union) &&
              e->exp_type == ae_exp_call) {
     const Exp func = e->d.exp_call.func;
     if (func->d.prim.prim_type == ae_prim_id) {
index f5421e2e803f8c9e3f7ce8ca39a5d38ee49230d0..5fe2b2867c51612bb5646135eefe21cf3603f335 100644 (file)
@@ -13,43 +13,14 @@ ANN void nspc_commit(const Nspc nspc) {
   scope_commit(nspc->info->trait);
 }
 
-ANN static inline void nspc_release_object(const Nspc a, Value value,
-                                           Gwion gwion) {
-  if ((GET_FLAG(value, static) && a->class_data) ||
-      (value->d.ptr && vflag(value, vflag_builtin))) {
-    const M_Object obj =
-        value->d.ptr ? (M_Object)value->d.ptr
-                     : *(M_Object *)(a->class_data + value->from->offset);
-    release(obj, gwion->vm->cleaner_shred);
-  }
-}
-
-ANN2(1, 3)
-static inline void nspc_release_struct(const Nspc a, Value value, Gwion gwion) {
-  if (value && ((GET_FLAG(value, static) && a->class_data) ||
-                (vflag(value, vflag_builtin) && value->d.ptr))) {
-    const m_bit *ptr =
-        (value && value->d.ptr)
-            ? (m_bit *)value->d.ptr
-            : (m_bit *)(a->class_data + value->from->offset);
-    for (m_uint i = 0; i < vector_size(&value->type->info->tuple->types); ++i) {
-      const Type t = (Type)vector_at(&value->type->info->tuple->types, i);
-      if (isa(t, gwion->type[et_object]) > 0)
-        release(*(M_Object *)(ptr +
-                              vector_at(&value->type->info->tuple->offset, i)),
-                gwion->vm->cleaner_shred);
-      else if (tflag(t, tflag_struct))
-        nspc_release_struct(t->nspc, NULL, gwion);
-    }
-  }
-}
-
 static inline void _free_nspc_value(const Nspc a, const Value v, Gwion gwion) {
   if(v->from->ctx && v->from->ctx->error) return; // this is quite a hack
-  if (tflag(v->type, tflag_compound) ) {
-    if (!tflag(v->type, tflag_struct))
-      nspc_release_object(a, v, gwion);
-    else nspc_release_struct(a, v, gwion);
+  if (GET_FLAG(v, static) && a->class_data) {
+    const m_bit *ptr = *(m_bit **)(a->class_data + v->from->offset);
+    anytype_release(gwion->vm->cleaner_shred, v->type, ptr);
+  } else if (vflag(v, vflag_builtin) && v->d.ptr) {
+    const m_bit *ptr = (m_bit*)v->d.ptr;
+    anytype_release(gwion->vm->cleaner_shred, v->type, ptr);
   }
   value_remref(v, gwion);
 }
@@ -67,15 +38,17 @@ describe_nspc_free(Func, func, func_remref(a, gwion));
 describe_nspc_free(Type, type, type_remref(a, gwion));
 describe_nspc_free(Trait, trait, free_trait(gwion->mp, a));
 
+ANN static void free_operators(NspcOp *a, const Gwion gwion) {
+    if (a->map.ptr) free_op_map(&a->map, gwion);
+    if (a->tmpl.ptr) free_op_tmpl(&a->tmpl, gwion);
+    mp_free(gwion->mp, NspcOp, a);
+
+}
 ANN void free_nspc(const Nspc a, const Gwion gwion) {
   nspc_free_value(a, gwion);
   nspc_free_func(a, gwion);
   nspc_free_trait(a, gwion);
-  if(a->operators) {
-    if (a->operators->map.ptr) free_op_map(&a->operators->map, gwion);
-    if (a->operators->tmpl.ptr) free_op_tmpl(&a->operators->tmpl, gwion);
-    mp_free(gwion->mp, NspcOp, a->operators);
-  }
+  if(a->operators) free_operators(a->operators, gwion);
   nspc_free_type(a, gwion);
   if (a->class_data && a->class_data_size)
     mp_free2(gwion->mp, a->class_data_size, a->class_data);
index fba2b6f8cb20fedb39f8208eee26c51823bb2958..1faf90a2850539790b9e216fe38e75327f84771e 100644 (file)
@@ -34,6 +34,13 @@ static DTOR(array_dtor_struct) {
                    &*(m_bit *)(ARRAY_PTR(a) + i * SZ_INT));
 }
 
+static DTOR(array_dtor_union) {
+  struct M_Vector_ *a = ARRAY(o);
+  for (m_uint i = 0; i < ARRAY_LEN(a); ++i)
+    union_release(shred, array_base(o->type_ref),
+                   &*(m_bit *)(ARRAY_PTR(a) + i * SZ_INT));
+}
+
 ANN M_Object new_array(MemPool p, const Type t, const m_uint length) {
   const M_Object a = new_object(p, t);
   const m_uint   depth =
@@ -69,6 +76,15 @@ static MFUN(vm_vector_rem_struct) {
   m_vector_rem(v, (vtype)index);
 }
 
+static MFUN(vm_vector_rem_union) {
+  const m_int    index = *(m_int *)(shred->mem + SZ_INT);
+  const M_Vector v     = ARRAY(o);
+  if (index < 0 || (m_uint)index >= ARRAY_LEN(v)) return;
+  const Type t = o->type_ref;
+  union_release(shred, array_base(t), ARRAY_PTR(v) + index * ARRAY_SIZE(v));
+  m_vector_rem(v, (vtype)index);
+}
+
 static MFUN(vm_vector_insert) {
   const m_int    index = *(m_int *)(shred->mem + SZ_INT);
   const M_Vector v     = ARRAY(o);
@@ -89,8 +105,15 @@ static MFUN(vm_vector_insert_struct) {
   const M_Vector v     = ARRAY(o);
   if (index < 0 || (m_uint)index > ARRAY_LEN(v)) return;
   m_vector_insert(v, index, shred->mem + SZ_INT * 2);
-  struct_addref(shred->info->vm->gwion, array_base(o->type_ref),
-                shred->mem + SZ_INT * 2);
+  struct_addref(array_base(o->type_ref), shred->mem + SZ_INT * 2);
+}
+
+static MFUN(vm_vector_insert_union) {
+  const m_int    index = *(m_int *)(shred->mem + SZ_INT);
+  const M_Vector v     = ARRAY(o);
+  if (index < 0 || (m_uint)index > ARRAY_LEN(v)) return;
+  m_vector_insert(v, index, shred->mem + SZ_INT * 2);
+  union_addref(array_base(o->type_ref), shred->mem + SZ_INT * 2);
 }
 
 static MFUN(vm_vector_size) { *(m_uint *)RETURN = ARRAY_LEN(ARRAY(o)); }
@@ -703,6 +726,26 @@ static void array_func(const Env env, const Type t, const m_str name, f_xfun fun
   builtin_func(env->gwion, v->d.func_ref, fun);
 }
 
+ANN static f_xfun get_rem(const Type t) {
+  if(!tflag(t, tflag_release)) return vm_vector_rem;
+  if(!tflag(t, tflag_struct)) return vm_vector_rem_obj;
+  if(!tflag(t, tflag_union)) return vm_vector_rem_struct;
+  return vm_vector_rem_union;
+}
+
+ANN static f_xfun get_insert(const Type t) {
+  if(!tflag(t, tflag_release)) return vm_vector_insert;
+  if(!tflag(t, tflag_struct)) return vm_vector_insert_obj;
+  if(!tflag(t, tflag_union)) return vm_vector_insert_struct;
+  return vm_vector_insert_union;
+}
+
+ANN static f_xfun get_dtor(const Type t) {
+  if(!tflag(t, tflag_struct)) return array_dtor_obj;
+  if(!tflag(t, tflag_union)) return array_dtor_struct;
+  return array_dtor_union;
+}
+
 static OP_CHECK(opck_array_scan) {
   struct TemplateScan *ts      = (struct TemplateScan *)data;
   const Type           t_array = env->gwion->type[et_array];
@@ -721,14 +764,6 @@ static OP_CHECK(opck_array_scan) {
     env_set_error(env, true);
     return env->gwion->type[et_error];
   }
-/*
-  if (!strncmp(base->name, "Option:[", 5)) {
-    gwerr_basic("Can't use option types as array base", NULL, NULL, "/dev/null",
-                (loc_t) {}, 0);
-    env_set_error(env, true);
-    return env->gwion->type[et_error];
-  }
-*/
   const Symbol sym  = array_sym(env, array_base_simple(base), base->array_depth + 1);
   const Type   type = nspc_lookup_type1(base->info->value->from->owner, sym);
   if (type) return type;
@@ -756,16 +791,9 @@ static OP_CHECK(opck_array_scan) {
   t->array_depth     = base->array_depth + 1;
   t->info->base_type = array_base(base);
   set_tflag(t, tflag_cdef | tflag_tmpl);
-  void *rem = tflag(base, tflag_compound)
-                  ? !tflag(base, tflag_struct) ? vm_vector_rem_obj
-                                               : vm_vector_rem_struct
-                  : vm_vector_rem;
-  builtin_func(env->gwion, (Func)vector_at(&t->nspc->vtable, 0), rem);
-  void *insert = tflag(base, tflag_compound)
-                     ? !tflag(base, tflag_struct) ? vm_vector_insert_obj
-                                                  : vm_vector_insert_struct
-                     : vm_vector_insert;
-  array_func(env, t, "insert", insert);
+  
+  builtin_func(env->gwion, (Func)vector_at(&t->nspc->vtable, 0), get_rem(t)); 
+  array_func(env, t, "insert", get_insert(t));
   array_func(env, t, "size", vm_vector_size);
   array_func(env, t, "depth", vm_vector_depth);
   array_func(env, t, "cap", vm_vector_cap);
@@ -777,14 +805,12 @@ static OP_CHECK(opck_array_scan) {
   array_func(env, t, "count", vm_vector_count);
   array_func(env, t, "foldl", vm_vector_foldl);
   array_func(env, t, "foldr", vm_vector_foldr);
-//  array_func(env, t, "new", vm_vector_new);
 
   if (tflag(base, tflag_compound)) {
     t->nspc->dtor = new_vmcode(env->gwion->mp, NULL, NULL,
                                "array component dtor", SZ_INT, true, false);
     set_tflag(t, tflag_dtor);
-    t->nspc->dtor->native_func = (m_uint)(
-        !tflag(base, tflag_struct) ? array_dtor_obj : array_dtor_struct);
+    t->nspc->dtor->native_func = (m_uint)get_dtor(base);
   }
   return t;
 }
index b92a8fb24d68bea89f5214671a9ab43ef46613d9..a111dbcda287f0899c42ac57ae0e14418259e3e7 100644 (file)
@@ -21,8 +21,6 @@
 #define HMAP_MIN_CAP 32
 #define HMAP_MAX_LOAD 0.75
 
-typedef void (clear_fn)(const HMap*, const VM_Shred, const struct HMapInfo*, const m_uint);
-
 // TODO: arch sensible hash
 static SFUN(mfun_int_h) {
   m_int x = *(m_uint*)MEM(0);
@@ -42,64 +40,24 @@ static SFUN(mfun_string_h) {
   *(m_int*)RETURN = hash(STRING(*(M_Object*)MEM(0)));
 }
 
-ANN static void clear_oo(const HMap *a, const VM_Shred shred, const HMapInfo *info NUSED, const m_uint idx) {
-  release(*(M_Object*)(a->data + idx * SZ_INT*2), shred);
-  release(*(M_Object*)((a->data + idx * SZ_INT*2) + SZ_INT), shred);
-}
-
-ANN static void clear_ss(const HMap *a, const VM_Shred shred, const HMapInfo *info, const m_uint idx) {
-  struct_release(shred, info->key, a->data + idx * info->sz);
-  struct_release(shred, info->val, a->data + idx * info->sz + info->key->size);
-}
-
-ANN static void clear_os(const HMap *a, const VM_Shred shred, const HMapInfo *info, const m_uint idx) {
-  release(*(M_Object*)(a->data + idx * info->sz), shred);
-  struct_release(shred, info->val, a->data + idx * info->sz + SZ_INT);
-}
-
-ANN static void clear_so(const HMap *a, const VM_Shred shred, const HMapInfo *info, const m_uint idx) {
-  struct_release(shred, info->key, a->data + idx * info->sz);
-  release(*(M_Object*)(a->data + idx * info->sz + info->key->size), shred);
-}
-
-ANN static void clear_on(const HMap *a, const VM_Shred shred, const HMapInfo *info, const m_uint idx) {
-  release(*(M_Object*)(a->data + idx * info->sz), shred);
-}
-
-ANN static void clear_sn(const HMap *a, const VM_Shred shred, const HMapInfo *info, const m_uint idx) {
-  struct_release(shred, info->key, a->data + idx * info->sz);
-}
-
-ANN static void clear_no(const HMap *a, const VM_Shred shred, const HMapInfo *info, const m_uint idx) {
-  release(*(M_Object*)(a->data + idx * info->sz + info->key->size), shred);
-}
-
-
-ANN static void clear_ns(const HMap *a, const VM_Shred shred, const HMapInfo *info, const m_uint idx) {
-  struct_release(shred, info->val, a->data + idx * info->sz + info->key->size);
+ANN static void clear_all(const HMap *a, const VM_Shred shred, const HMapInfo *info, const m_uint idx) {
+  compound_release(shred, info->key, a->data + idx * info->sz);
+  compound_release(shred, info->val, a->data + idx * info->sz + info->key->size);
 }
 
-static clear_fn *const n_clear[3]  = { NULL,     clear_no, clear_ns };
-static clear_fn* o_clear[3]  = { clear_on, clear_oo, clear_os };
-static clear_fn* s_clear[3]  = { clear_sn, clear_so, clear_ss };
-static clear_fn*const* clear[3] = { n_clear, o_clear, s_clear };
-
 ANN static void hmapinfo_init(HMapInfo *const info, const Type key, const Type val) {
   info->key = key;
   info->val = val;
   info->sz = key->size + val->size;
-  info->keyk = tflag(key, tflag_compound) + tflag(key, tflag_struct);
-  info->valk = tflag(val, tflag_compound) + tflag(val, tflag_struct);
 }
 
 static DTOR(dict_clear_dtor) {
   const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
-  clear_fn *fn = clear[hinfo->keyk][hinfo->valk];
   HMap *a = &*(struct HMap*)o->data;
   for(m_uint i = a->capacity; --i;) {
     const HState state = *(HState*)(a->state + (i-1) * sizeof(HState));
     if(!state.set || state.deleted) continue;
-    fn(a, shred, hinfo, i-1);
+    clear_all(a, shred, hinfo, i-1);
   }
 }
 
@@ -174,14 +132,7 @@ static INSTR(hmap_iter_set) {
   HState *const state = (HState*)(hmap->state + sizeof(HState) * bucket);
   m_bit *const data = hmap->data + hinfo->sz * bucket;
   if (!state->set || state->deleted) {
-
-    if(hinfo->keyk) {
-      if(hinfo->keyk == HKIND_OBJ)
-        (*(M_Object*)REG(-instr->m_val))->ref++;
-      else
-        struct_addref(shred->info->vm->gwion, hinfo->key, REG(-instr->m_val));
-    }
-
+    compound_addref(hinfo->key, REG(-instr->m_val));
     state->set     = true;
     state->deleted = false;
     memcpy(data, REG(-instr->m_val), instr->m_val);
@@ -321,20 +272,12 @@ static INSTR(hmap_val) {
   memcpy(REG(-hinfo->val->size), new_data + hinfo->key->size, hinfo->val->size);
 }
 
-static INSTR(hmap_remove_clear) {
-  const M_Object o = *(M_Object*)(shred->reg - SZ_INT*2);
-  const HMap *hmap = (HMap*)o->data;
-  const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
-  const m_uint bucket = *(m_uint*)REG(0);
-  clear_fn *fn = (clear_fn*)instr->m_val;
-  fn(hmap, shred, hinfo, bucket);
-}
-
 static INSTR(hmap_remove) {
   const M_Object o = *(M_Object*)(shred->reg - SZ_INT*2);
   HMap *const hmap = (HMap*)o->data;
   const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
   const m_uint bucket = *(m_uint*)REG(0);
+  clear_all(hmap, shred, hinfo, bucket);
   m_bit *data = hmap->data + hinfo->sz * bucket;
   hmap->count--;
   HState *const state = (HState *)(hmap->state + bucket * sizeof(HState));
@@ -418,7 +361,8 @@ if(info->is_var) {
   emit_add_instr(emit, hmap_grow_dec);
   const Instr endgrow = emit_add_instr(emit, BranchNeqInt);
   CHECK_BB(emit_exp(emit, call.d.exp_call.func));
-  CHECK_BB(emit_exp_call1(emit, call.d.exp_call.func->type->info->func, true));
+  CHECK_BB(emit_exp_call1(emit, call.d.exp_call.func->type->info->func,
+    call.d.exp_call.func->type->info->func->def->base->ret_type->size, true));
   emit_add_instr(emit, hmap_find);
   const Instr regrow = emit_add_instr(emit, BranchEqInt);
   regrow->m_val = grow_pc;
@@ -484,12 +428,6 @@ static OP_EMIT(opem_dict_remove) {
 
   CHECK_BB(traverse_exp(env, &call));
   CHECK_BB(emit_dict_iter(emit, hinfo, &opi, &call, bin->lhs));
-  if(hinfo->keyk || hinfo->valk) {
-    clear_fn *const fn = clear[hinfo->keyk][hinfo->valk];
-    const Instr instr = emit_add_instr(emit, hmap_remove_clear);
-    instr->m_val = (m_uint)fn;
-  }
-
   const Instr pushval = emit_add_instr(emit, hmap_remove);
   pushval->m_val2 = hinfo->key->size;
   return GW_OK;
@@ -647,7 +585,7 @@ static OP_CHECK(opck_dict_scan) {
   }
   HMapInfo *const hinfo = (HMapInfo*)t->nspc->class_data;
   hmapinfo_init(hinfo, key, val);
-  if(hinfo->keyk + hinfo->valk) {
+  if(tflag(key, tflag_release) || tflag(val, tflag_release)) {
     t->nspc->dtor = new_vmcode(env->gwion->mp, NULL, NULL, "@dtor", SZ_INT, true, false);
     t->nspc->dtor->native_func = (m_uint)dict_clear_dtor;
     set_tflag(t, tflag_dtor);
index 5384f2cba8622928eff115fe917d022b9c57e332..992e4891423a8a5d7b49a56d614bb03741c2a4c8 100644 (file)
@@ -27,16 +27,22 @@ static OP_EMIT(opem_none) {
   return GW_OK;
 }
 
+static INSTR(UnionIndex) {
+  // probs exosts already
+  *(m_uint*)REG(-SZ_INT) = **(m_uint**)REG(-SZ_INT);
+}
 static OP_EMIT(opem_union_dot) {
   const Exp_Dot *member = (Exp_Dot *)data;
   const Map      map    = &member->base->type->nspc->info->value->map;
+  exp_setvar(member->base, true);
   CHECK_BB(emit_exp(emit, member->base));
   if (is_func(emit->gwion, exp_self(member)->type)) { // is_callable? can only be a func
     emit_pushimm(emit, (m_uint)exp_self(member)->type->info->func->code);
     return GW_OK;
   }
   if (!strcmp(s_name(member->xid), "index")) {
-    emit_add_instr(emit, DotMember);
+    //emit_add_instr(emit, DotMember);
+    emit_add_instr(emit, UnionIndex);
     return GW_OK;
   }
   for (m_uint i = 0; i < map_size(map); ++i) {
@@ -50,13 +56,13 @@ static OP_EMIT(opem_union_dot) {
   return GW_ERROR;
 }
 
-static DTOR(UnionDtor) {
-  const m_uint idx = *(m_uint *)o->data;
+ANN void union_release(const VM_Shred shred, const Type t, const m_bit *data) {
+  const m_uint idx = *(m_uint *)data;
   if (idx) {
-    const Map   map = &o->type_ref->nspc->info->value->map;
+    const Map   map = &t->nspc->info->value->map;
     const Value v   = (Value)map_at(map, idx - 1);
     if (tflag(v->type, tflag_compound))
-      compound_release(shred, v->type, (o->data + SZ_INT));
+      compound_release(shred, v->type, data + SZ_INT);
   }
 }
 
@@ -100,40 +106,54 @@ static MFUN(union_is) {
 }
 
 static MFUN(union_new) {
-  memcpy(o->data, MEM(SZ_INT*2), *(m_uint*)MEM(SZ_INT));
-  *(M_Object *)RETURN = o;
+  m_bit *data = *(m_bit**)MEM(0);
+  memcpy(data, MEM(SZ_INT*2), *(m_uint*)MEM(SZ_INT));
+  memcpy((m_bit*)RETURN, data, *(m_uint*)MEM(SZ_INT));
 }
-
+#include "parse.h"
+#undef insert_symbol
 static OP_CHECK(opck_union_new) {
   Exp_Call *call = (Exp_Call *)data;
   const Exp name = call->args;
-  if (!name || !name->next || name->next->next)
-    ERR_N(call->func->pos, "Union constructor takes two arguments, "
+  if (!name)
+    ERR_N(call->func->pos, "Union constructor takes one or two arguments, "
                            "'id' and 'value'");
   if (name->exp_type != ae_exp_primary || name->d.prim.prim_type != ae_prim_id)
-    return env->gwion->type[et_error];
+    ERR_N(call->func->pos, "Union constructor first argument me be an identifier");
   const Exp  val  = name->next;
   const Type base = call->func->d.exp_dot.base->type;
   const Map  map  = &base->nspc->info->value->map;
+
   for (m_uint i = 0; i < map_size(map); ++i) {
     if (VKEY(map, i) == (m_uint)name->d.prim.d.var) {
       const Value v          = (Value)VVAL(map, i);
       name->d.prim.prim_type = ae_prim_num;
       name->d.prim.d.num     = i;
       name->type             = env->gwion->type[et_int];
-      DECL_ON(const Type, t, = check_exp(env, val));
-      if (isa(t, v->type) < 0) {
-        ERR_N(val->pos, "Invalid type '%s' for '%s', should be '%s'", t->name,
-              v->name, v->type->name);
+      if(!val && v->type == env->gwion->type[et_none]) {
+        const Exp e = new_prim_int(env->gwion->mp, SZ_INT, name->pos);
+        e->next = name;
+        e->type = env->gwion->type[et_int];
+        name->next = new_prim_int(env->gwion->mp, 0, name->pos);
+        name->next->type = env->gwion->type[et_int];
+        call->args = e;
+      } else {
+        if (val->next)
+          ERR_N(call->func->pos, "too many arguments for union constructor");
+        DECL_ON(const Type, t, = check_exp(env, val));
+        if (check_implicit(env, val, v->type) < 0) { // add implicit
+          ERR_N(val->pos, "Invalid type '%s' for '%s', should be '%s'", t->name,
+                v->name, v->type->name);
+        }
+        const Exp e = new_prim_int(env->gwion->mp, t->size + SZ_INT, val->pos);
+        e->next = name;
+        e->type = env->gwion->type[et_int];
+        call->args = e;
       }
-      const Exp e = new_prim_int(env->gwion->mp, t->size + SZ_INT, val->pos);
-      e->next = name;
-      e->type = env->gwion->type[et_int];
-      call->args = e;
       return base;
     }
   }
-  return env->gwion->type[et_error];
+  ERR_N(name->pos, "%s has no member %s\n", base->name, s_name(name->d.prim.d.var));
 }
 
 ANN GWION_IMPORT(union) {
@@ -150,12 +170,16 @@ ANN GWION_IMPORT(union) {
   GWI_BB(gwi_oper_emi(gwi, opem_none))
   GWI_BB(gwi_oper_end(gwi, ":=>", NoOp))
 
-  const Type t_union = gwi_class_ini(gwi, "union", "Object");
-  gwi_class_xtor(gwi, NULL, UnionDtor);
+  const Type t_union = gwi_struct_ini(gwi, "union");
+  //gwi_class_xtor(gwi, NULL, UnionDtor);
   gwi->gwion->type[et_union] = t_union;
 
   GWI_BB(gwi_item_ini(gwi, "int", "index"))
   GWI_BB(gwi_item_end(gwi, ae_flag_const, num, 0))
+  /*
+  GWI_BB(gwi_func_ini(gwi, "void", "@ctor"))
+  GWI_BB(gwi_func_end(gwi, union_ctor, ae_flag_none))
+  */
   GWI_BB(gwi_func_ini(gwi, "bool", "is"))
   GWI_BB(gwi_func_arg(gwi, "int", "member"))
   GWI_BB(gwi_func_end(gwi, union_is, ae_flag_none))
@@ -164,9 +188,10 @@ ANN GWION_IMPORT(union) {
   GWI_BB(gwi_func_arg(gwi, "int", "id"))
   GWI_BB(gwi_func_arg(gwi, "T", "value"))
   GWI_BB(gwi_func_end(gwi, union_new, ae_flag_none))
+  
   GWI_BB(gwi_class_end(gwi))
 
-  const Func             f      = (Func)vector_front(&t_union->nspc->vtable);
+  const Func             f      = (Func)vector_at(&t_union->nspc->vtable, 0);
   const struct Op_Func   opfunc = {.ck = opck_union_is};
   const struct Op_Import opi    = {
       .rhs  = f->value_ref->type,
@@ -186,8 +211,6 @@ ANN GWION_IMPORT(union) {
       .op   = insert_symbol(gwi->gwion->st, "@func_check")};
   CHECK_BB(add_op(gwi->gwion, &opi1));
 
-  gwi->gwion->type[et_union] = t_union;
-
   GWI_BB(gwi_oper_ini(gwi, "union", (m_str)OP_ANY_TYPE, NULL))
   GWI_BB(gwi_oper_emi(gwi, opem_union_dot))
   GWI_BB(gwi_oper_end(gwi, ".", NULL))
index 681b255d87e70a39c83c51079442445f3464f49d..ee99d401dd0607549c846b3f39f0c2322947782c 100644 (file)
@@ -1542,7 +1542,7 @@ ANN static Symbol case_op(const Env env, const Type base, const Exp e) {
         return NULL;
       }
     }
-  } else if (isa(base, env->gwion->type[et_union]) > 0 &&
+  } else if (tflag(base, tflag_union) &&
              e->exp_type == ae_exp_call) {
     const Exp func = e->d.exp_call.func;
     if (func->d.prim.prim_type == ae_prim_id) {
index 6cfd30c15d67a162398d4ade30a56c4dfa256ba6..9334eafe36066bfe1df84bb3d235c6447bb6eaf6 100644 (file)
@@ -386,7 +386,8 @@ ANN m_bool operator_set_func(const struct Op_Import *opi) {
 ANN static m_bool handle_instr(const Emitter emit, const M_Operator *mo) {
   if (mo->func) {
     emit_pushfunc(emit, mo->func);
-    CHECK_BB(emit_exp_call1(emit, mo->func, true));
+    CHECK_BB(emit_exp_call1(emit, mo->func,
+          mo->func->def->base->ret_type->size, true));
     if (mo->func->def->base->xid ==
         insert_symbol(emit->gwion->st, "@conditional"))
       emit_add_instr(emit, BranchEqInt);
index a3546c612cc78234642789f1806252c1b0509a8a..83057805ab8043628819cd117e00c8a95ac68d06 100644 (file)
@@ -208,6 +208,51 @@ ANN m_bool scan0_enum_def(const Env env, const Enum_Def edef) {
   return GW_OK;
 }
 
+static INSTR(StructAssign) {
+  memcpy(*(m_bit**)REG(-SZ_INT), REG((m_int)instr->m_val), instr->m_val2);
+}
+
+static OP_EMIT(opem_struct_assign) {
+  const Exp_Binary *bin = data;
+  const Type t = bin->lhs->type;
+  const Exp e = exp_self(bin);
+
+  if(tflag(t, tflag_release)) {
+    const f_instr exec = !tflag(t, tflag_union)
+       ? StructReleaseRegAddr
+       : UnionReleaseRegAddr;
+    const Instr release = emit_add_instr(emit, exec);
+    release->m_val = -SZ_INT;
+    release->m_val2 = (m_uint)t;
+  }
+
+  const Instr instr = emit_add_instr(emit, StructAssign);
+  instr->m_val  = -t->size - SZ_INT;
+  instr->m_val2 = t->size;
+  emit_struct_addref(emit, t, -SZ_INT, true);
+  if(exp_getvar(e)) {
+    emit_regmove(emit, -t->size);
+    const Instr instr = emit_add_instr(emit, Reg2Reg);
+    instr->m_val = -SZ_INT;
+    instr->m_val2 = t->size - SZ_INT;
+  } else emit_regmove(emit, -SZ_INT);
+  return GW_OK;
+}
+
+ANN static OP_CHECK(opck_struct_assign) {
+  CHECK_NN(opck_rassign(env, data));
+  Exp_Binary *bin = data;
+  bin->rhs->ref = bin->lhs;
+  return bin->lhs->type;
+}
+
+ANN static void scan0_struct_assign(const Env env, const Type t) {
+  struct Op_Func   opfunc = {.ck = opck_struct_assign, .em = opem_struct_assign };
+  struct Op_Import opi    = {
+      .op = insert_symbol(":=>"), .lhs = t, .rhs = t, .ret = t, .func = &opfunc};
+  add_op(env->gwion, &opi);
+}
+
 ANN static Type union_type(const Env env, const Symbol s, const loc_t loc) {
   const m_str name = s_name(s);
   const Type  t    = new_type(env->gwion->mp, name, env->gwion->type[et_union]);
@@ -215,11 +260,13 @@ ANN static Type union_type(const Env env, const Symbol s, const loc_t loc) {
   t->nspc->parent  = env->curr;
   t->info->tuple   = new_tupleform(env->gwion->mp, NULL); // ???
   set_tflag(t, tflag_union);
+  set_tflag(t, tflag_struct);
   add_type(env, env->curr, t);
   mk_class(env, t, loc);
   SET_FLAG(t, final);
   set_tflag(t, tflag_compound);
-  if (strncmp(t->name, "Option", 6)) SET_FLAG(t, abstract);
+  SET_FLAG(t, abstract);
+  scan0_struct_assign(env,  t);
   return t;
 }
 
@@ -478,48 +525,6 @@ ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
 
 ANN Ast spread_class(const Env env, const Ast body);
 
-static INSTR(StructAssign) {
-  memcpy(*(m_bit**)REG(-SZ_INT), REG((m_int)instr->m_val), instr->m_val2);
-}
-
-static OP_EMIT(opem_struct_assign) {
-  const Exp_Binary *bin = data;
-  const Type t = bin->lhs->type;
-  const Exp e = exp_self(bin);
-
-  if(tflag(t, tflag_release)) {
-    const Instr release = emit_add_instr(emit, StructReleaseRegAddr);
-    release->m_val = -SZ_INT;
-    release->m_val2 = (m_uint)t;
-  }
-
-  const Instr instr = emit_add_instr(emit, StructAssign);
-  instr->m_val  = -t->size - SZ_INT;
-  instr->m_val2 = t->size;
-  emit_struct_addref(emit, t, -SZ_INT, true); // add ref on lhs
-  if(exp_getvar(e)) {
-    emit_regmove(emit, -t->size);
-    const Instr instr = emit_add_instr(emit, Reg2Reg);
-    instr->m_val = -SZ_INT;
-    instr->m_val2 = t->size - SZ_INT;
-  } else emit_regmove(emit, -SZ_INT);
-  return GW_OK;
-}
-
-ANN static OP_CHECK(opck_struct_assign) {
-  CHECK_NN(opck_rassign(env, data));
-  Exp_Binary *bin = data;
-  bin->rhs->ref = bin->lhs;
-  return bin->lhs->type;
-}
-
-ANN static void scan0_struct_assign(const Env env, const Type t) {
-  struct Op_Func   opfunc = {.ck = opck_struct_assign, .em = opem_struct_assign };
-  struct Op_Import opi    = {
-      .op = insert_symbol(":=>"), .lhs = t, .rhs = t, .ret = t, .func = &opfunc};
-  add_op(env->gwion, &opi);
-}
-
 ANN m_bool scan0_class_def(const Env env, const Class_Def c) {
   DECL_BB(const m_bool, global, = scan0_global(env, c->flag, c->pos));
   const Ast old_extend = env->context ? env->context->extend : NULL;
index e3b4f5add363ac7e4d3a3ac63443f5664231199c..a28d1c6731344aafeef6dc99eaca6104c36f2556 100644 (file)
@@ -525,6 +525,7 @@ ANN static inline m_bool scan1_union_def_inner_loop(const Env env,
     if (t->size > sz) sz = t->size;
   }
   udef->type->nspc->offset = SZ_INT + sz;
+  udef->type->size = SZ_INT + sz;
   return GW_OK;
 }
 
index fe6f73df88df393da8dde4a0133d7eeb692afc1f..cd5164325bdd4e6fa8a2e253807b9a5a41df56b7 100644 (file)
@@ -243,9 +243,7 @@ ANN m_bool driver_ini(const struct Gwion_ *gwion) {
   if (opt) *opt = '\0';
   for (m_uint i = 0; i < map_size(map); ++i) {
     const m_str name = (m_str)VKEY(map, i);
-    printf("%s %s\n", name, dname);
     if (!strcmp(name, dname)) {
-      puts("hey");
       const Plug     plug = (Plug)VVAL(map, i);
       const gwdriver_t drv  = plug->driver;
       if (!drv) break;
index 4cc46bcaefb0469b4413f99feb34071c43baf43c..c92b12f4e2652306ef3b0a43e555d31ce6b3ace2 100644 (file)
@@ -461,8 +461,11 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto]
       &&forkend, &&sporkend, &&brancheqint, &&branchneint, &&brancheqfloat,
       &&branchnefloat, &&unroll, &&arrayappend, &&autounrollinit, &&autoloop,
       &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&newobj, &&addref,
-      &&addrefaddr, &&structaddref, &&structaddrefaddr, &&objassign, &&assign,
+      &&addrefaddr, &&structaddref, &&structaddrefaddr,
+      &&unionaddref, &&unionaddrefaddr,
+      &&objassign, &&assign,
       &&_remref, &&_remref2, &&_structreleaseregaddr, &&structreleasemem,
+      &&_unionreleaseregaddr, &&unionreleasemem,
       &&_except,
       &&dotmembermem, &&dotmembermem2, /*&&dotmembermem3, */&&dotmembermem4,
       &&dotmember, &&dotfloat, &&dotother, &&dotaddr,
@@ -569,7 +572,8 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto]
       *(m_uint *)(reg + IVAL) = *(m_uint *)(reg + IVAL2);
       DISPATCH()
     regtoregother2:
-      memcpy(reg - VAL2, reg + IVAL, VAL2);
+      //memcpy(reg - VAL2, reg + IVAL, VAL2);
+      memmove(reg - VAL2, reg + IVAL, VAL2);
       DISPATCH()
     regtoregaddr:
       *(m_uint **)(reg + IVAL) = &*(m_uint *)(reg + IVAL2);
@@ -1066,10 +1070,16 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto]
     }
       DISPATCH()
     structaddref:
-      struct_addref(vm->gwion, (Type)VAL2, (reg + IVAL));
+      struct_addref((Type)VAL2, (reg + IVAL));
       DISPATCH()
     structaddrefaddr:
-      struct_addref(vm->gwion, (Type)VAL2, *(m_bit **)(reg + IVAL));
+      struct_addref((Type)VAL2, *(m_bit **)(reg + IVAL));
+      DISPATCH()
+    unionaddref:
+      union_addref((Type)VAL2, (reg + IVAL));
+      DISPATCH()
+    unionaddrefaddr:
+      union_addref((Type)VAL2, *(m_bit **)(reg + IVAL));
       DISPATCH()
     objassign : {
       const M_Object o = **(M_Object **)(reg - SZ_INT);
@@ -1095,6 +1105,12 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto]
     structreleasemem:
       struct_release(shred, (Type)VAL2, mem + IVAL);
       DISPATCH();
+    unionreleaseregaddr:
+      union_release(shred, (Type)VAL2, *(m_bit**)(reg + IVAL));
+      DISPATCH();
+    unionreleasemem:
+      union_release(shred, (Type)VAL2, mem + IVAL);
+      DISPATCH();
     except:
       /* TODO: Refactor except instruction             *
        * so that                                       *
@@ -1143,14 +1159,14 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto]
       DISPATCH()
 
 #define UNION_CHECK                                                            \
-  register const m_bit *data = (*(M_Object *)(reg - SZ_INT))->data;            \
+  register const m_bit *data = (*(m_bit**)(reg - SZ_INT));            \
   if (*(m_uint *)data != VAL) {                                                \
-    handle(shred, "invalid union acces");                                      \
+    handle(shred, "InvalidUnionAcces");                                      \
     continue;                                                                  \
   }
 
     unioncheck : {
-      if (*(m_uint *)(*(M_Object *)(reg - SZ_INT))->data != VAL2) {
+      if (*(m_uint *)(*(m_bit* *)(reg - SZ_INT)) != VAL2) {
         reg -= SZ_INT;
         PC_DISPATCH(VAL);
       }
@@ -1175,9 +1191,9 @@ vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto]
       DISPATCH()
     }
     unionaddr : {
-      *(m_uint *)(*(M_Object *)(reg - SZ_INT))->data = VAL;
-      *(m_bit **)(reg - SZ_INT) =
-          &*(m_bit *)((*(M_Object *)(reg - SZ_INT))->data + SZ_INT);
+      m_bit *data = *(m_bit**)(reg-SZ_INT);
+      *(m_uint*)data = VAL;
+      *(m_bit **)(reg - SZ_INT) = data + SZ_INT;
       DISPATCH()
     }
     staticint:
@@ -1313,8 +1329,10 @@ static void *_dispatch[] = {
       &&_sporkend, &&_brancheqint, &&_branchneint, &&_brancheqfloat,
       &&_branchnefloat, &&_unroll, &&_arrayappend, &&_autounrollinit, &&_autoloop,
       &&_arraytop, &&_arrayaccess, &&_arrayget, &&_arrayaddr, &&_newobj, &&_addref,
-      &&_addrefaddr, &&_structaddref, &&_structaddrefaddr, &&_objassign, &&_assign,
+      &&_addrefaddr, &&_structaddref, &&_structaddrefaddr,
+      &&_unionaddref, &&_unionaddrefaddr, &&_objassign, &&_assign,
       &&_remref, &&_remref2, &&_structreleaseregaddr, &&_structreleasemem,
+      &&_unionreleaseregaddr, &&_unionreleasemem,
       &&_except,
       &&_dotmembermem, &&_dotmembermem2, /*&&_dotmembermem3, */&&_dotmembermem4,
       &&_dotmember, &&_dotfloat, &&_dotother, &&_dotaddr,
@@ -1532,12 +1550,16 @@ return;
     PREPARE(addrefaddr);
     PREPARE(structaddref);
     PREPARE(structaddrefaddr);
+    PREPARE(unionaddref);
+    PREPARE(unionaddrefaddr);
     PREPARE(objassign);
     PREPARE(assign);
     PREPARE(remref);
     PREPARE(remref2);
     PREPARE(structreleaseregaddr);
     PREPARE(structreleasemem);
+    PREPARE(unionreleaseregaddr);
+    PREPARE(unionreleasemem);
     PREPARE(except);
     PREPARE(dotmembermem);
     PREPARE(dotmembermem2);
index 986551f2abf07d3c5537383bdee7e3a2b853baf1..d925a1665b84789c9be61308df6cbe4c74682540 100644 (file)
@@ -1,5 +1,5 @@
 class C {
-  1 :=> test;
+  1 => test;
   fun int test(int i) {
    13 :=> var int j;
    return j;
@@ -7,7 +7,7 @@ class C {
 }
 
 var C c;
-12 => c.test => var int ret;
+12 => c.test :=> var int ret;
 
 <<< 1394 >>>;
 <<<ret>>>;
diff --git a/tests/struct/struct_gack.gw b/tests/struct/struct_gack.gw
deleted file mode 100644 (file)
index 2d74c3c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-struct S {
-  13 :=> var int i;
-  operator void @gack () { <<< "test", i >>>; }
-  <<< this >>>;
-}
-
-var S s;
-<<< s >>>;
diff --git a/tests/struct/struct_global0.gw b/tests/struct/struct_global0.gw
deleted file mode 100644 (file)
index bd901ee..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-struct global GlobalStruct {
-  var int i;
-  var float f;
-  var string s;
-}
-
-struct global GlobalStructWithCtor {
-  var int i;
-  var float f;
-  var string s;
-}
-
-var global GlobalStruct global_s;
-var GlobalStructWithCtor sctor;
diff --git a/tests/struct/struct_global1.gw b/tests/struct/struct_global1.gw
deleted file mode 100644 (file)
index abb93aa..0000000
+++ /dev/null
@@ -1 +0,0 @@
-var GlobalStruct s;
index d073155aecd308a4ddfdda28e89ea211a747c16c..c69d815a87425b86032f980c9c0f79550922f2fb 100644 (file)
@@ -1,4 +1,3 @@
 #! [contains] 12
-var int? i;
-<<< 12 :=> i.val >>>;
+var int?(val, 12) i;
 <<< i.val >>>;
index 73e5dd66358edfd2a5831ce78d3c797a4e4bc77d..ef5572addb45bee4a4f0d01fb7ad25a329d127ae 100644 (file)
@@ -1,5 +1,5 @@
 #! [contains] val: 12
-var int? i;
+var int?(none) i;
 
 12 :=> i.val;
 if(i.is(val))
index b83406db9257baee8d31082a0f805a403cd948d6..dfe5c506d7eb235537be55ac43424b99b49cf0dc 100644 (file)
@@ -1,3 +1,3 @@
-#! [contains] invalid union acces
-var int? i;
+#! [contains] InvalidUnionAcces
+var int?(none) i;
 <<< i.val >>>;