]> Nishi Git Mirror - gwion.git/commitdiff
:art: Introduce 'struct'
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Mon, 30 Mar 2020 15:30:18 +0000 (17:30 +0200)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Mon, 30 Mar 2020 15:30:48 +0000 (17:30 +0200)
55 files changed:
ast
examples/ptr_assign_class.gw
examples/template_vararg.gw
include/emit.h
include/import/cdef.h
include/import/checker.h
include/import/oper.h
include/opcode.h
include/operator.h
include/specialid.h
opcode.txt
src/emit/emit.c
src/env/nspc.c
src/env/type.c
src/gwion.c
src/import/cdef.c
src/import/oper.c
src/lib/array.c
src/lib/event.c
src/lib/func.c
src/lib/gack.c
src/lib/modules.c
src/lib/object.c
src/lib/object_op.c
src/lib/opfunc.c
src/lib/prim.c
src/lib/ptr.c
src/lib/string.c
src/lib/ugen.c
src/lib/vararg.c
src/main.c
src/parse/check.c
src/parse/operator.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/template.c
src/vm/vm.c
tests/error/ptr_implicit_const.gw
tests/import/gwi_oper_emit_var.c [deleted file]
tests/import/gwi_oper_emit_var.gw [deleted file]
tests/import/test.log [new file with mode: 0644]
tests/sh/import.sh
tests/struct/member_func.gw [new file with mode: 0644]
tests/struct/struct_gack.gw [new file with mode: 0644]
tests/struct/struct_global0.gw [new file with mode: 0644]
tests/struct/struct_global1.gw [new file with mode: 0644]
tests/struct/struct_member.gw [new file with mode: 0644]
tests/struct/struct_member_func.gw [new file with mode: 0644]
tests/struct/struct_noctor.gw [new file with mode: 0644]
tests/struct/struct_return.gw [new file with mode: 0644]
tests/struct/struct_static.gw [new file with mode: 0644]
tests/struct/struct_static_func.gw [new file with mode: 0644]
tests/struct/t.gw [new file with mode: 0644]
util

diff --git a/ast b/ast
index 318792cdc12f6b9632f89052c2d6cc258031b99c..c16ad0087304f84595aa4f901f2d71465e391192 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 318792cdc12f6b9632f89052c2d6cc258031b99c
+Subproject commit c16ad0087304f84595aa4f901f2d71465e391192
index 68d635c838194ba427c91f357ba15c5849be21bd..913cc60adc7bb723603cc6ba8928d8b9939dc352 100644 (file)
@@ -1,8 +1,7 @@
-class C
-{
+class C {
        typedef void Test();
        fun void test1(){};
-    Test test0;
+  Test test0;
        <<< test1 @=> test0 >>>;
 }
 
index 564d0b80b039b7397ee54bbab200e60b28dca4e9..57552d8486a476d00c6c5ee5b93d11c249106d46 100644 (file)
@@ -1,7 +1,7 @@
 fun void test<~A~>(...) {
-  vararg.start;
-  <<< vararg $ int >>>;
-  vararg.end;
+  varloop vararg {
+    <<< vararg $ int >>>;
+  }
 }
 test<~int~>(1, 2);
 test<~float~>(1, 2, 3);
index ff00f7f86ae4793f98de292507e8eeeffd9fb17b..21f6361b9ee2a6b5e3cf231a0bc4edcd21ad3c5a 100644 (file)
@@ -44,9 +44,9 @@ ANN void emit_ext_ctor(const Emitter, const VM_Code);
 ANN void emit_union_offset(Decl_List, const m_uint);
 ANN2(1,2) m_bool emit_instantiate_object(const Emitter, const Type, const Array_Sub, const m_bool);
 ANN m_uint emit_code_offset(const Emitter emit);
-ANN m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj);
+//ANN m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj);
 ANN Instr emit_exp_spork(const Emitter, const Exp_Unary*);
-ANN m_bool emit_exp(const Emitter, const Exp, const m_bool add_ref);
+ANN m_bool emit_exp(const Emitter, const Exp);
 ANN static inline void emit_except(const Emitter emit, const Type t) {
   emit_add_instr(emit, !GET_FLAG(t, nonnull) ? GWOP_EXCEPT : SetObj);
 }
index f44f185543b53a7038de3dad9698e9755b34ddf2..d4bdd9688f2d4995b7b17e416f6fb87ce77fcbf4 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __IMPORT_CLASS
 #define __IMPORT_CLASS
 ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str, const m_str parent);
-ANN2(1,2) Type gwi_class_spe(const Gwi gwi, const m_str, const m_uint size);
+ANN2(1,2) Type gwi_struct_ini(const Gwi gwi, const m_str, const m_uint size);
 ANN2(1) void gwi_class_xtor(const Gwi gwi, const f_xtor ctor, const f_xtor dtor);
 ANN m_int gwi_class_end(const Gwi gwi);
 ANN void inherit(const Type);
index 510943c6b559d512fdd26bcd400fdc826a33249d..52e8b7a39295c8670a4727a1a59f78d9f26db3ab 100644 (file)
@@ -41,7 +41,6 @@ typedef struct OperCK { // name_checker ?
   Instr  (*em)(Emitter, void*); // oper
   m_str lhs;// oper
   m_str rhs;// oper
-  m_uint emit_var;
 } OperCK;
 
 struct array_checker {
index 1bb02818c6999baa2f5d4ec4d32f9a7e4baec3db..cf5bedcff388ed69e5b4b3121b7885e35403ac3b 100644 (file)
@@ -7,9 +7,6 @@ ANN m_int gwi_oper_emi(const Gwi gwi, const opem);
 ANN2(1) m_int gwi_oper_end(const Gwi gwi, const m_str op, const f_instr f);
 ANN m_int gwi_oper_cond(const Gwi, const m_str,  const f_instr, const f_instr);
 
-//! use this with one if the right side operator's to emit_var is set
-ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset);
-
 #define _EQUALITY_OPER(sz, sign)                                 \
   POP_REG(shred, sz*2 - SZ_INT);                                 \
   *(m_uint*)REG(-SZ_INT) = sign                                  \
index e85a433dc8b95bda271fe9c3f8427ac1d0d287f5..1dc0439555fede0d31ccef6761667f7a04c62ff0 100644 (file)
@@ -10,6 +10,7 @@ enum {
   eRegPushMem2,
   eRegPushMem3,
   eRegPushMem4,
+  eRegPushMemDeref,
   eRegPushNow,
   eRegPushBase,
   eRegPushBase2,
@@ -17,6 +18,9 @@ enum {
   eRegPushBase4,
   eReg2Reg,
   eReg2RegAddr,
+  eReg2RegDeref,
+  eStructMember,
+  eStructMemberAddr,
   eMemSetImm,
   eRegPushMe,
   eRegPushMaybe,
@@ -146,6 +150,7 @@ enum {
   eArrayValid,
   eObjectInstantiate,
   eRegAddRef,
+  eRegAddRefAddr,
   eObjectAssign,
   eAssign,
   eObjectRelease,
@@ -183,6 +188,7 @@ enum {
 #define  RegPushMem2         (f_instr)eRegPushMem2
 #define  RegPushMem3         (f_instr)eRegPushMem3
 #define  RegPushMem4         (f_instr)eRegPushMem4
+#define  RegPushMemDeref     (f_instr)eRegPushMemDeref
 #define  RegPushNow          (f_instr)eRegPushNow
 #define  RegPushBase         (f_instr)eRegPushBase
 #define  RegPushBase2        (f_instr)eRegPushBase2
@@ -190,6 +196,9 @@ enum {
 #define  RegPushBase4        (f_instr)eRegPushBase4
 #define  Reg2Reg             (f_instr)eReg2Reg
 #define  Reg2RegAddr         (f_instr)eReg2RegAddr
+#define  Reg2RegDeref        (f_instr)eReg2RegDeref
+#define  StructMember        (f_instr)eStructMember
+#define  StructMemberAddr    (f_instr)eStructMemberAddr
 #define  MemSetImm           (f_instr)eMemSetImm
 #define  RegPushMe           (f_instr)eRegPushMe
 #define  RegPushMaybe        (f_instr)eRegPushMaybe
@@ -319,6 +328,7 @@ enum {
 #define  ArrayValid          (f_instr)eArrayValid
 #define  ObjectInstantiate   (f_instr)eObjectInstantiate
 #define  RegAddRef           (f_instr)eRegAddRef
+#define  RegAddRefAddr       (f_instr)eRegAddRefAddr
 #define  ObjectAssign        (f_instr)eObjectAssign
 #define  Assign              (f_instr)eAssign
 #define  ObjectRelease       (f_instr)eObjectRelease
index c7453f11f0fa24dd7d5bc42718caaaaeb63f569c..e6fc6c9da36767f1dd51587919edfe76c04ca9e3 100644 (file)
@@ -8,7 +8,7 @@
 #define DECL_NN(decl, f, exp) decl f exp; { if(f == env->gwion->type[et_null) return env->gwion->type[et_null]; }
 #define CHECK_ON(f) { if(!f)    return env->gwion->type[et_null]; }
 #define CHECK_BN(f) { if(f < 0) return env->gwion->type[et_null]; }
-#define CHECK_NN(f) { if(f == env->gwion->type[et_null] return env->gwion->type[et_null]; }
+#define CHECK_NN(f) { if(f == env->gwion->type[et_null]) return env->gwion->type[et_null]; }
 
 typedef Type (*opck)(const Env, void*, m_bool*);
 typedef struct Instr_* (*opem)(const Emitter, void*);
@@ -18,13 +18,25 @@ struct Op_Func {
   opem em;
 };
 
+enum op_type {
+  op_implicit,
+  op_exp,
+  op_dot,
+  op_array,
+  op_binary,
+  op_cast,
+  op_postfix,
+  op_unary,
+  op_scan
+};
+
 struct Op_Import {
   Type lhs, rhs, ret;
   const struct Op_Func *func;
   uintptr_t data;
   loc_t pos;
   Symbol op;
-  m_uint emit_var;
+  enum op_type op_type;
 };
 
 struct Implicit {
index 8deeb2fe48da816dbe7fb4031f71e36f68632dd6..a2a81a773b3dd96b8d6de9927a5c3e4d853a5b76 100644 (file)
@@ -18,9 +18,9 @@ struct SpecialId_ {
 
 ANN static inline Type specialid_type(const Env env,
     struct SpecialId_ *spid, const Exp_Primary* prim) {
-  exp_self(prim)->type = spid->type;
+  exp_self(prim)->info->type = spid->type;
   if(spid->is_const)
-    exp_self(prim)->meta = ae_meta_value;
+    exp_getmeta(exp_self(prim));
   return spid->ck ? spid->ck(env, prim) : spid->type;
 }
 
index 2c4015892ac8e6435b01793778fac47c6539d0a7..8c1b8863f269f644f6dc25b23a47f9fcc34724ed 100644 (file)
@@ -7,6 +7,7 @@ RegPushMem
 RegPushMem2
 RegPushMem3
 RegPushMem4
+RegPushMemDeref
 RegPushNow
 RegPushBase
 RegPushBase2
@@ -14,6 +15,9 @@ RegPushBase3
 RegPushBase4
 Reg2Reg
 Reg2RegAddr
+Reg2RegDeref
+StructMember
+StructMemberAddr
 MemSetImm
 RegPushMe
 RegPushMaybe
@@ -143,6 +147,7 @@ ArrayAddr
 ArrayValid
 ObjectInstantiate
 RegAddRef
+RegAddRefAddr
 ObjectAssign
 Assign
 ObjectRelease
index 00a36785658667278eb505e8e098674f78a54aaa..06960591b1e330f163bd6d8b4ff4f5c44ae67ad2 100644 (file)
@@ -29,9 +29,8 @@
 #define ERR_O(a, b, ...) { env_err(emit->env, (a), (b), ## __VA_ARGS__); return NULL; }
 
 typedef struct Local_ {
-  m_uint size;
+  Type type;
   m_uint offset;
-  m_bool is_obj;
 } Local;
 
 static inline void emit_pop(const Emitter emit, const m_uint scope) { env_pop(emit->env, scope); }
@@ -61,17 +60,16 @@ ANN static void free_frame(MemPool p, Frame* a) {
   mp_free(p, Frame, a);
 }
 
-ANN static Local* new_local(MemPool p, const m_uint size, const m_bool is_obj) {
+ANN static Local* new_local(MemPool p, const Type type) {
   Local* local  = mp_calloc(p, Local);
-  local->size   = size;
-  local->is_obj = is_obj;
+  local->type   = type;
   return local;
 }
 
-ANN static m_uint frame_local(MemPool p, Frame* frame, const m_uint size, const m_bool is_obj) {
-  Local* local = new_local(p, size, is_obj);
+ANN static m_uint frame_local(MemPool p, Frame* frame, const Type t) {
+  Local* local = new_local(p, t);
   local->offset = frame->curr_offset;
-  frame->curr_offset += size;
+  frame->curr_offset += t->size;
   vector_add(&frame->stack, (vtype)local);
   return local->offset;
 }
@@ -80,13 +78,29 @@ ANN static inline void frame_push(Frame* frame) {
   vector_add(&frame->stack, (vtype)NULL);
 }
 
-ANN static m_int frame_pop(Frame* frame) {
+ANN static void struct_pop(const Emitter emit, const Type type, const m_uint offset) {
+  for(m_uint i = 0; i < vector_size(&type->e->tuple->types); ++i) {
+    const Type t = (Type)vector_at(&type->e->tuple->types, i);
+    if(isa(t, emit->gwion->type[et_object]) > 0) {
+      const Instr instr = emit_add_instr(emit, ObjectRelease);
+      instr->m_val = offset + vector_at(&type->e->tuple->offset, i);
+    } else if(GET_FLAG(t, struct))
+      struct_pop(emit, t, offset + vector_at(&type->e->tuple->offset, i));
+  }
+}
+
+ANN static m_int frame_pop(const Emitter emit) {
+  Frame *frame = emit->code->frame;
   DECL_OB(const Local*, l, = (Local*)vector_pop(&frame->stack))
-  frame->curr_offset -= l->size;
-  return l->is_obj ? (m_int)l->offset : frame_pop(frame);
+  frame->curr_offset -= l->type->size;
+  if(GET_FLAG(l->type, struct)) {
+    struct_pop(emit, l->type, l->offset);
+    return frame_pop(emit);
+  }
+  return isa(l->type, emit->gwion->type[et_object]) > 0 ? (m_int)l->offset : frame_pop(emit);
 }
 
-ANN /*static */m_bool emit_exp(const Emitter emit, Exp exp, const m_bool add_ref);
+ANN /*static */m_bool emit_exp(const Emitter emit, Exp exp);
 ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop);
 ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List list);
 ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member);
@@ -115,7 +129,7 @@ ANN static void free_code(MemPool p, Code* code) {
 
 ANN static void emit_pop_scope(const Emitter emit) {
   m_int offset;
-  while((offset = frame_pop(emit->code->frame)) > -1) {
+  while((offset = frame_pop(emit)) > -1) {
     Instr instr = emit_add_instr(emit, ObjectRelease);
     instr->m_val = (m_uint)offset;
   }
@@ -140,8 +154,8 @@ ANN m_uint emit_code_offset(const Emitter emit) {
   return emit->code->frame->curr_offset;
 }
 
-ANN m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj) {
-  return frame_local(emit->gwion->mp, emit->code->frame, size, is_obj);
+ANN m_uint emit_local(const Emitter emit, const Type t) {
+  return frame_local(emit->gwion->mp, emit->code->frame, t);
 }
 
 ANN static inline void maybe_ctor(const Emitter emit, const Type type) {
@@ -185,7 +199,7 @@ ANN static void emit_pre_constructor_array(const Emitter emit, const Type type)
 
 ANN2(1) static m_bool extend_indices(const Emitter emit, Exp e, const m_uint depth) {
   if(e)
-    CHECK_BB(emit_exp(emit, e, 0))
+    CHECK_BB(emit_exp(emit, e))
   m_uint count = 0;
   while(e) {
     ++count;
@@ -292,7 +306,7 @@ static const f_instr allocword[]  = { AllocWord, AllocWord2, AllocWord3, RegPush
 ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data);
 ANN static m_bool emit_symbol_owned(const Emitter emit, const Symbol *data) {
   const Exp dot = symbol_owned_exp(emit->gwion, data);
-  dot->nspc = prim_exp(data)->nspc;
+  dot->info->nspc = prim_exp(data)->info->nspc;
   const m_bool ret = emit_exp_dot(emit, &dot->d.exp_dot);
   free_exp(emit->gwion->mp, dot);
   return ret;
@@ -302,12 +316,12 @@ ANN static m_bool emit_symbol_builtin(const Emitter emit, const Symbol *data) {
   const Value v = prim_self(data)->value;
   if(GET_FLAG(v, union)) {
     const m_uint size = v->type->size;
-    const Instr instr = emit_kind(emit, size, prim_exp(data)->emit_var, dotstatic);
+    const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), dotstatic);
     instr->m_val = (m_uint)v->d.ptr;
   } else {
     const m_uint size = v->type->size;
-    const Instr instr = emit_kind(emit, size, prim_exp(data)->emit_var, regpushimm);
-    if(!exp_self(data)->emit_var && size == SZ_INT) {
+    const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), regpushimm);
+    if(!exp_getvar(prim_exp(data)) && size == SZ_INT) {
       if(isa(v->type, emit->gwion->type[et_object]) > 0) {
         instr->opcode = eRegPushImm;
         instr->m_val = (m_uint)v->d.ptr;
@@ -333,12 +347,13 @@ ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) {
   if(GET_FLAG(v, builtin) || GET_FLAG(v, union) || GET_FLAG(v, enum))
     return emit_symbol_builtin(emit, data);
   const m_uint size = v->type->size;
-  const Instr instr = emit_kind(emit, size, prim_exp(data)->emit_var, !GET_FLAG(v, global) ? regpushmem : regpushbase);
+  const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), !GET_FLAG(v, global) ? regpushmem : regpushbase);
   instr->m_val  = v->from->offset;
   if(isa(v->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, v->type))
-    instr->m_val = prim_exp(data)->type->e->d.func->value_ref->from->offset;
+    instr->m_val = prim_exp(data)->info->type->e->d.func->value_ref->from->offset;
   return GW_OK;
 }
+
 ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary* prim) {
   return _emit_symbol(emit, &prim->d.var);
 }
@@ -353,7 +368,7 @@ ANN static VM_Code finalyze(const Emitter emit, const f_instr exec) {
 
 ANN static m_bool emit_prim_array(const Emitter emit, const Array_Sub *data) {
   Exp e = (*data)->exp;
-  CHECK_BB(emit_exp(emit, e, 0))
+  CHECK_BB(emit_exp(emit, e))
   m_uint count = 0;
   do ++count;
   while((e = e->next));
@@ -367,15 +382,15 @@ ANN static m_bool emit_prim_array(const Emitter emit, const Array_Sub *data) {
   return GW_OK;
 }
 
-ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e, const m_bool addref);
+ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e);
 
 ANN static m_bool emit_range(const Emitter emit, Range *range) {
   if(range->start)
-    CHECK_OB(emit_exp_pop_next(emit, range->start, 0))
+    CHECK_OB(emit_exp_pop_next(emit, range->start))
   else
     regpushi(emit, 0);
   if(range->end)
-    CHECK_OB(emit_exp_pop_next(emit, range->end, 0))
+    CHECK_OB(emit_exp_pop_next(emit, range->end))
   else
     regpushi(emit, -1);
   return GW_OK;
@@ -386,7 +401,8 @@ ANN static m_bool emit_prim_range(const Emitter emit, Range **data) {
   CHECK_BB(emit_range(emit, range))
   const Exp e = range->start ?: range->end;
   const Symbol sym = insert_symbol("@range");
-  struct Op_Import opi = { .op=sym, .rhs=e->type, .pos=e->pos, .data=(uintptr_t)prim_exp(data) };
+  struct Op_Import opi = { .op=sym, .rhs=e->info->type,
+    .pos=e->pos, .data=(uintptr_t)prim_exp(data), .op_type=op_exp };
   CHECK_OB(op_emit(emit, &opi))
   emit_add_instr(emit, GcAdd);
   return GW_OK;
@@ -397,33 +413,30 @@ ANN m_bool emit_array_access(const Emitter emit, struct ArrayAccessInfo *const i
     info->array.type = info->array.type->e->parent;
     return emit_array_access(emit, info);
   }
-  struct Op_Import opi = { .op=insert_symbol("@array"), .lhs=info->array.exp->type, .rhs=info->array.type, .data=(uintptr_t)info };
+  // look mum no pos
+  struct Op_Import opi = { .op=insert_symbol("@array"), .lhs=info->array.exp->info->type, .rhs=info->array.type,
+    .data=(uintptr_t)info, .op_type=op_array };
   return op_emit(emit, &opi) != (Instr)GW_ERROR ? GW_OK : GW_ERROR;
 }
 
 ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) {
-  CHECK_BB(emit_exp(emit, array->base, 0))
+  CHECK_BB(emit_exp(emit, array->base))
   const Exp e = exp_self(array);
-  struct ArrayAccessInfo info = { *array->array, e->type, e->emit_var };
+  struct ArrayAccessInfo info = { *array->array, e->info->type, exp_getvar(e) };
   return emit_array_access(emit, &info);
 }
 
 ANN static m_bool emit_exp_slice(const Emitter emit, const Exp_Slice* range) {
-  CHECK_BB(emit_exp(emit, range->base, 0))
+  CHECK_BB(emit_exp(emit, range->base))
   CHECK_BB(emit_range(emit, range->range))
   const Symbol sym = insert_symbol("@slice");
   const Exp e = range->range->start ?: range->range->end;
-  struct Op_Import opi = { .op=sym, .lhs=range->base->type, .rhs=e->type, .pos=e->pos, .data=(uintptr_t)exp_self(range) };
+  struct Op_Import opi = { .op=sym, .lhs=range->base->info->type, .rhs=e->info->type,
+    .pos=e->pos, .data=(uintptr_t)exp_self(range), .op_type=op_exp };
   CHECK_OB(op_emit(emit, &opi))
   return GW_OK;
 }
 
-ANN static void emit_vec_addr(const Emitter emit, const m_uint sz) {
-  regpop(emit, sz - SZ_INT);
-  const Instr cpy = emit_add_instr(emit, Reg2RegAddr);
-  cpy->m_val = -SZ_INT;
-}
-
 ANN static m_bool emit_prim_id(const Emitter emit, const Symbol *data) {
   struct SpecialId_ * spid = specialid_get(emit->gwion, *data);
   if(spid)
@@ -448,6 +461,13 @@ ANN static m_bool emit_prim_char(const Emitter emit, const m_str *str) {
   return GW_OK;
 }
 
+ANN static Instr emit_addref(const Emitter emit, const m_bool emit_var) {
+  const f_instr exec = !emit_var ? RegAddRef : RegAddRefAddr;
+  const Instr instr = emit_add_instr(emit, exec);
+  instr->m_val = -SZ_INT;
+  return instr;
+}
+
 ANN static m_bool emit_prim_str(const Emitter emit, const m_str *str) {
   char c[strlen(*str) + 1];
   if(strlen(*str)) {
@@ -459,24 +479,32 @@ ANN static m_bool emit_prim_str(const Emitter emit, const m_str *str) {
   if(!v->d.ptr)
     v->d.ptr = (m_uint*)new_string2(emit->gwion, NULL, s_name(sym));
   regpushi(emit, (m_uint)v->d.ptr);
-  emit_add_instr(emit, RegAddRef);
+  emit_addref(emit, 0);
   return GW_OK;
 }
 
 #define emit_prim_nil     (void*)dummy_func
 
+ANN static inline void struct_interp(const Emitter emit, const Exp e) {
+  if(GET_FLAG(e->info->type, struct)) {
+    exp_setvar(e, 1);
+    regpush(emit, e->info->type->size - SZ_INT);
+  }
+}
+
 ANN static m_bool emit_interp(const Emitter emit, const Exp exp) {
   regpushi(emit, 0);
   Exp e = exp, next = NULL;
   do {
     next = e->next;
     e->next = NULL;
-    if(emit_exp(emit, e, 0) < 0) {
+    struct_interp(emit, e);
+    if(emit_exp(emit, e) < 0) {
       e->next = next;
       return GW_ERROR;
     }
-    regseti(emit, (m_uint)e->type);
-    if(isa(e->type, emit->gwion->type[et_object]) > 0 && !GET_FLAG(e->type, force))
+    regseti(emit, (m_uint)e->info->type);
+    if(isa(e->info->type, emit->gwion->type[et_object]) > 0 && !GET_FLAG(e->info->type, force))
       emit_add_instr(emit, GackType);
     const Instr instr = emit_add_instr(emit, Gack);
     instr->m_val = emit_code_offset(emit);
@@ -511,17 +539,41 @@ ANN static m_bool decl_static(const Emitter emit, const Var_Decl var_decl, const
   CHECK_BB(emit_instantiate_object(emit, v->type, var_decl->array, is_ref))
   CHECK_BB(emit_dot_static_data(emit, v, 1))
   emit_add_instr(emit, Assign);
-  emit_add_instr(emit, RegAddRef);
+  (void)emit_addref(emit, 0);
   regpop(emit, SZ_INT);
   emit->code = code;
   return GW_OK;
 }
 
+ANN static inline int struct_ctor(const Value v) {
+  return GET_FLAG(v->type, struct) && v->type->nspc->pre_ctor;
+}
+
+ANN static void emit_struct_decl_finish(const Emitter emit, const Value v) {
+  emit_ext_ctor(emit, v->type->nspc->pre_ctor);
+  const Instr instr = emit_add_instr(emit, Reg2RegDeref);
+  instr->m_val = -SZ_INT;
+  instr->m_val2 = v->type->size;
+  regpush(emit, v->type->size - SZ_INT);
+}
+
 ANN static m_bool emit_exp_decl_static(const Emitter emit, const Var_Decl var_decl, const uint is_ref, const uint emit_addr) {
-  const Value value = var_decl->value;
-  if(isa(value->type, emit->gwion->type[et_object]) > 0 && !is_ref)
+  const Value v = var_decl->value;
+  if(isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
     CHECK_BB(decl_static(emit, var_decl, 0))
-  return emit_dot_static_data(emit, value, emit_addr);
+  CHECK_BB(emit_dot_static_data(emit, v, !struct_ctor(v) ? emit_addr : 1))
+  if(!emit_addr && struct_ctor(v))
+    emit_struct_decl_finish(emit, v);
+  return GW_OK;
+}
+
+ANN static Instr emit_struct_decl(const Emitter emit, const Value v, const m_bool emit_addr) {
+  emit_add_instr(emit, RegPushMem);
+  const Instr instr = emit_add_instr(emit, !emit_addr ? StructMember : StructMemberAddr);
+  instr->m_val2 = v->from->offset;
+  if(!emit_addr)
+    regpush(emit, v->type->size - SZ_INT);
+  return instr; // m_val set after but ignored
 }
 
 ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl,
@@ -537,15 +589,16 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Exp_Decl *d
     CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
   f_instr *exec = (f_instr*)allocmember;
   if(!GET_FLAG(v, member)) {
-    v->from->offset = emit_local(emit, v->type->size, is_obj);
+    v->from->offset = emit_local(emit, type);
     exec = (f_instr*)(allocword);
-    if(GET_FLAG(var_decl->value, ref)) {
+    if(GET_FLAG(var_decl->value, ref)) { // ref or emit_var ?
       const Instr clean = emit_add_instr(emit, MemSetImm);
       clean->m_val = v->from->offset;
     }
   }
-  const Instr instr = emit_kind(emit, v->type->size, emit_addr, exec);
-  if(emit_addr || !GET_FLAG(v, member))
+  const Instr instr = !(SAFE_FLAG(emit->env->class_def, struct) && !emit->env->scope->depth) ?
+    emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, exec) : emit_struct_decl(emit, v, emit_addr);
+  if((emit_addr || !GET_FLAG(v, member)))
     instr->m_val = v->from->offset;
   if(is_obj && (is_array || !is_ref)) {
     emit_add_instr(emit, Assign);
@@ -554,11 +607,12 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Exp_Decl *d
       const Instr push = emit_add_instr(emit, Reg2Reg);
       push->m_val = -(missing_depth) * SZ_INT;
     }
-  }
+  } else if(!emit_addr && struct_ctor(v))
+    emit_struct_decl_finish(emit, v);
   return GW_OK;
 }
 
-ANN static m_bool emit_exp_decl_global(const Emitter emit, const Var_Decl var_decl,
+ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl,
   const uint is_ref, const uint emit_var) {
   const Value v = var_decl->value;
   const Type type = v->type;
@@ -569,17 +623,23 @@ ANN static m_bool emit_exp_decl_global(const Emitter emit, const Var_Decl var_de
     emit_var : 1;
   if(is_obj && (is_array || !is_ref))
     CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
-  const Instr instr = emit_kind(emit, v->type->size, emit_addr, dotstatic);
+//  const Instr instr = emit_kind(emit, v->type->size, emit_addr, dotstatic);
+  const Instr instr = emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, dotstatic);
   v->d.ptr = mp_calloc2(emit->gwion->mp, v->type->size);
   SET_FLAG(v, union);
   instr->m_val = (m_uint)v->d.ptr;
   instr->m_val2 = v->type->size;
   if(is_obj && (is_array || !is_ref)) {
     const Instr assign = emit_add_instr(emit, Assign);
+    const size_t missing_depth = type->array_depth - (array ? array->depth : 0);
+    if(missing_depth && !GET_FLAG(decl->td, force)) {
+      const Instr push = emit_add_instr(emit, Reg2Reg);
+      push->m_val = -(missing_depth) * SZ_INT;
+    }
     assign->m_val = emit_var;
-    const Instr instr = emit_add_instr(emit, RegAddRef);
-    instr->m_val = emit_var;
-  }
+    (void)emit_addref(emit, emit_var);
+  } else if(!emit_var && struct_ctor(v))
+    emit_struct_decl_finish(emit, v);
   return GW_OK;
 }
 
@@ -593,7 +653,7 @@ ANN static inline m_bool emit_exp_decl_template(const Emitter emit, const Exp_De
 
 ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) {
   const m_bool global = GET_FLAG(decl->td, global);
-  const uint var = exp_self(decl)->emit_var;
+  const uint var = exp_getvar(exp_self(decl));
   const uint ref = GET_FLAG(decl->td, ref) || type_ref(decl->type);
   Var_Decl_List list = decl->list;
   do {
@@ -603,7 +663,7 @@ ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) {
     else if(!global)
       CHECK_BB(emit_exp_decl_non_static(emit, decl, list->self, r, var))
     else
-      CHECK_BB(emit_exp_decl_global(emit, list->self, r, var))
+      CHECK_BB(emit_exp_decl_global(emit, decl, list->self, r, var))
     if(GET_FLAG(list->self->value->type, nonnull))
       emit_add_instr(emit, GWOP_EXCEPT);
   } while((list = list->next));
@@ -627,8 +687,8 @@ ANN static m_uint vararg_size(const Exp_Call* exp_call, const Vector kinds) {
   m_uint size = 0;
   while(e) {
     if(!l) {
-      size += e->type->size;
-      vector_add(kinds, (vtype)e->type); // ->size
+      size += e->info->type->size;
+      vector_add(kinds, (vtype)e->info->type); // ->size
     } else
       l = l->next;
     e = e->next;
@@ -647,9 +707,20 @@ ANN static void emit_func_arg_vararg(const Emitter emit, const Exp_Call* exp_cal
   }
 }
 
+ANN static inline m_uint exp_size(Exp e);
+ANN static inline m_uint exp_totalsize(Exp e) {
+  m_uint size = 0;
+  do size += exp_size(e);
+  while((e = e->next));
+  return size;
+}
+ANN static /*inline */void emit_exp_addref(const Emitter emit, Exp, const m_int size);
+
 ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call* exp_call) {
-  if(exp_call->args)
-    CHECK_BB(emit_exp(emit, exp_call->args, 1))
+  if(exp_call->args) {
+    CHECK_BB(emit_exp(emit, exp_call->args))
+    emit_exp_addref(emit, exp_call->args, -exp_totalsize(exp_call->args));
+  }
   if(GET_FLAG(exp_call->m_func->def, variadic))
     emit_func_arg_vararg(emit, exp_call);
   return GW_OK;
@@ -657,21 +728,25 @@ ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call* exp_call) {
 
 ANN static m_bool prepare_call(const Emitter emit, const Exp_Call* exp_call) {
   CHECK_BB(emit_func_args(emit, exp_call))
-  return emit_exp(emit, exp_call->func, 0);
+  return emit_exp(emit, exp_call->func);
 }
 
 ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call* exp_call) {
-  if(exp_call->m_func) {
-    CHECK_BB(prepare_call(emit, exp_call))
-    return emit_exp_call1(emit, exp_call->m_func) ? GW_OK : GW_ERROR;
+  CHECK_BB(prepare_call(emit, exp_call))
+  if(exp_call->m_func)
+    CHECK_OB(emit_exp_call1(emit, exp_call->m_func))
+  else {
+    struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp_call->func->info->type->e->d.base_type,
+      .data=(uintptr_t)exp_call, .pos=exp_self(exp_call)->pos, .op_type=op_exp };
+    CHECK_OB(op_emit(emit, &opi))
   }
-  if(exp_call->args)
-    CHECK_BB(emit_exp(emit, exp_call->args, 1))
-  struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp_call->func->type->e->d.base_type, .data=(uintptr_t)exp_call, .pos=exp_self(exp_call)->pos };
-  CHECK_OB(op_emit(emit, &opi))
   const Exp e = exp_self(exp_call);
-  if(e->emit_var)
-    emit_vec_addr(emit, e->type->size);
+  if(exp_getvar(e)) {
+    regpop(emit, exp_self(exp_call)->info->type->size - SZ_INT);
+    const Instr instr = emit_add_instr(emit, Reg2RegAddr);
+    instr->m_val = -SZ_INT;
+    instr->m_val2 = -SZ_INT;
+  }
   return GW_OK;
 }
 
@@ -685,9 +760,9 @@ ANN static m_uint get_decl_size(Var_Decl_List a) {
 
 ANN static m_uint pop_exp_size(Exp e) {
   m_uint size = 0;
-  do {
+  do { // account for emit_var ?
     size += (e->exp_type == ae_exp_decl ?
-        get_decl_size(e->d.exp_decl.list) : e->type->size);
+        get_decl_size(e->d.exp_decl.list) : e->info->type->size);
   } while((e = e->next));
   return size;
 }
@@ -698,8 +773,8 @@ ANN static inline void pop_exp(const Emitter emit, Exp e) {
    regpop(emit, size);
 }
 
-ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e, const m_bool addref) {
-  CHECK_BB(emit_exp(emit, e, addref))
+ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e) {
+  CHECK_BB(emit_exp(emit, e))
   if(e->next)
     pop_exp(emit, e->next);
   return GW_OK;
@@ -713,22 +788,31 @@ ANN static inline m_bool op_emit_bool(const Emitter emit, const struct Op_Import
 ANN static m_bool emit_exp_binary(const Emitter emit, const Exp_Binary* bin) {
   const Exp lhs = bin->lhs;
   const Exp rhs = bin->rhs;
-  struct Op_Import opi = { .op=bin->op, .lhs=lhs->type, .rhs=rhs->type, .pos=exp_self(bin)->pos, .data = (uintptr_t)bin };
-  CHECK_BB(emit_exp_pop_next(emit, lhs, 1))
-  CHECK_BB(emit_exp_pop_next(emit, rhs, 1))
+  struct Op_Import opi = { .op=bin->op, .lhs=lhs->info->type, .rhs=rhs->info->type,
+    .pos=exp_self(bin)->pos, .data=(uintptr_t)bin, .op_type=op_binary };
+  CHECK_BB(emit_exp_pop_next(emit, lhs))
+  CHECK_BB(emit_exp_pop_next(emit, rhs))
+  const m_int size = exp_totalsize(rhs);
+  emit_exp_addref(emit, lhs, -exp_totalsize(lhs) - size);
+  emit_exp_addref(emit, rhs, -size);
   return op_emit_bool(emit, &opi);
 }
 
 ANN static m_bool emit_exp_cast(const Emitter emit, const Exp_Cast* cast) {
-  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=cast->exp->type, .rhs=exp_self(cast)->type, .data=(uintptr_t)cast};
-  CHECK_BB(emit_exp(emit, cast->exp, 0))
+  // no pos ?
+  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=cast->exp->info->type, .rhs=exp_self(cast)->info->type,
+    .data=(uintptr_t)cast, .op_type=op_cast};
+  CHECK_BB(emit_exp(emit, cast->exp))
   (void)op_emit(emit, &opi);
   return GW_OK;
 }
 
 ANN static m_bool emit_exp_post(const Emitter emit, const Exp_Postfix* post) {
-  struct Op_Import opi = { .op=post->op, .lhs=post->exp->type, .data=(uintptr_t)post };
-  CHECK_BB(emit_exp(emit, post->exp, 1))
+  // no pos ?
+  struct Op_Import opi = { .op=post->op, .lhs=post->exp->info->type,
+    .data=(uintptr_t)post, .op_type=op_postfix };
+  CHECK_BB(emit_exp(emit, post->exp))
+  emit_exp_addref(emit, post->exp, -exp_totalsize(post->exp));
   return op_emit_bool(emit, &opi);
 }
 
@@ -811,7 +895,6 @@ ANN static Instr get_prelude(const Emitter emit, const Func f) {
     emit_except(emit, t);
     if(f->def->base->tmpl)
       tmpl_prelude(emit, f);
-
   }
   const Instr instr = emit_add_instr(emit, SetCode);
   instr->m_val2 = 1;
@@ -847,8 +930,10 @@ ANN static Instr me_push(const MemoizeEmitter *me, const m_uint sz) {
 static m_bool me_cmp(MemoizeEmitter *me, const Arg_List arg) {
   const Emitter emit = me->emit;
   const Symbol sym = insert_symbol("==");
-  struct Exp_ exp = { .nspc=me->fdef->base->func->value_ref->from->owner };
-  struct Op_Import opi = { .op=sym, .lhs=arg->type, .rhs=arg->type, .pos=me->fdef->pos, .data=(uintptr_t)&exp.d };
+  struct ExpInfo_ info = { .nspc=me->fdef->base->func->value_ref->from->owner };
+  struct Exp_ exp = { .info=&info };
+  struct Op_Import opi = { .op=sym, .lhs=arg->type, .rhs=arg->type,
+    .pos=me->fdef->pos, .data=(uintptr_t)&exp.d, .op_type=op_binary };
   CHECK_BB(op_emit_bool(emit, &opi))
   const Instr instr = emit_add_instr(emit, BranchEqInt);
   vector_add(&me->branch, (vtype)instr);
@@ -935,8 +1020,8 @@ ANN static void emit_exp_spork_finish(const Emitter emit, const m_uint depth) {
   spork->m_val2 = -SZ_INT;
 }
 
-static inline void stack_alloc(const Emitter emit) {
-  emit_local(emit, SZ_INT, 0);
+static inline void stack_alloc(const Emitter emit) { // maybe vararg could use t_vararg instead
+  emit_local(emit, emit->gwion->type[et_int]); // hiding the fact it is an object
   emit->code->stack_depth += SZ_INT;
 }
 
@@ -979,11 +1064,11 @@ ANN static m_bool call_spork_func(const Emitter emit, const Exp_Call *exp) {
 }
 
 struct Sporker {
-  const m_bool is_spork;
   const Stmt code;
   const Exp  exp;
   VM_Code vm_code;
   const m_bool emit_var;
+  const m_bool is_spork;
 };
 
 ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
@@ -995,6 +1080,7 @@ ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
     CHECK_BO(scoped_stmt(emit, sp->code, 0))
   } else {
     CHECK_BO(prepare_call(emit, &sp->exp->d.exp_call))
+//    emit_exp_addref(emit, &sp->exp->d.exp_call, -exp_totalsize(&sp->exp->d.exp_call);
     push_spork_code(emit, sp->is_spork ? SPORK_FUNC_PREFIX : FORK_CODE_PREFIX, sp->exp->pos);
     CHECK_BO(call_spork_func(emit, &sp->exp->d.exp_call))
   }
@@ -1033,10 +1119,10 @@ ANN static Instr spork_ini(const Emitter emit, const struct Sporker *sp) {
 
 ANN Instr emit_exp_spork(const Emitter emit, const Exp_Unary* unary) {
   struct Sporker sporker = {
-    .is_spork=(unary->op == insert_symbol("spork")),
     .exp=unary->exp,
     .code=unary->code,
-    .emit_var=exp_self(unary)->emit_var
+    .is_spork=(unary->op == insert_symbol("spork")),
+    .emit_var=exp_getvar(exp_self(unary))
   };
   CHECK_OO((sporker.vm_code = spork_prepare(emit, &sporker)))
   const Instr ini = spork_ini(emit, &sporker);
@@ -1045,10 +1131,14 @@ ANN Instr emit_exp_spork(const Emitter emit, const Exp_Unary* unary) {
 }
 
 ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary* unary) {
-  struct Op_Import opi = { .op=unary->op, .data=(uintptr_t)unary };
+// no pos ?
+  struct Op_Import opi = { .op=unary->op, .data=(uintptr_t)unary, .op_type=op_unary };
   if(unary->op != insert_symbol("spork") && unary->op != insert_symbol("fork") && unary->exp) {
-    CHECK_BB(emit_exp_pop_next(emit, unary->exp, 1))
-    opi.rhs = unary->exp->type;
+    CHECK_BB(emit_exp_pop_next(emit, unary->exp))
+const Exp next = unary->exp->next;
+    emit_exp_addref(emit, unary->exp, -exp_size(unary->exp));
+unary->exp->next = next;
+    opi.rhs = unary->exp->info->type;
   }
   return op_emit_bool(emit, &opi);
 }
@@ -1056,14 +1146,19 @@ ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary* unary) {
 ANN static m_bool emit_implicit_cast(const Emitter emit,
     const restrict Exp  from, const restrict Type to) {
   const struct Implicit imp = { from, to, from->pos };
-  struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=from->type, .rhs=to, .data=(m_uint)&imp };
+  // no pos
+  struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=from->info->type, .rhs=to,
+    .data=(m_uint)&imp, .op_type=op_implicit };
   return op_emit_bool(emit, &opi);
 }
 
 ANN static Instr _flow(const Emitter emit, const Exp e, const m_bool b) {
-  CHECK_BO(emit_exp_pop_next(emit, e, 1))
+    CHECK_BO(emit_exp_pop_next(emit, e))
+const Exp next = e->next;
+    emit_exp_addref(emit, e, -exp_size(e));
+e->next = next;
   struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"),
-                           .rhs=e->type, .pos=e->pos, .data=(uintptr_t)e};
+                           .rhs=e->info->type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp };
   const Instr instr = op_emit(emit, &opi);
   assert(instr != (Instr)GW_OK);
   return instr;
@@ -1072,17 +1167,17 @@ ANN static Instr _flow(const Emitter emit, const Exp e, const m_bool b) {
 
 ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If* exp_if) {
   const Instr op = emit_flow(emit, exp_if->cond);
-  CHECK_BB(emit_exp(emit, exp_if->if_exp ?: exp_if->cond, 0))
+  CHECK_BB(emit_exp(emit, exp_if->if_exp ?: exp_if->cond))
   const Instr op2 = emit_add_instr(emit, Goto);
   op->m_val = emit_code_size(emit);
-  const m_bool ret = emit_exp(emit, exp_if->else_exp, 0);
+  const m_bool ret = emit_exp(emit, exp_if->else_exp);
   op2->m_val = emit_code_size(emit);
   return ret;
 }
 
 ANN static m_bool emit_lambda(const Emitter emit, const Exp_Lambda * lambda) {
   CHECK_BB(emit_func_def(emit, lambda->def))
-  if(GET_FLAG(lambda->def, member) && !exp_self(lambda)->emit_var)
+  if(GET_FLAG(lambda->def, member) && !exp_getvar(exp_self(lambda)))
     emit_add_instr(emit, RegPushMem);
   regpushi(emit, (m_uint)lambda->def->base->func->code);
   return GW_OK;
@@ -1102,10 +1197,10 @@ ANN static m_bool emit_exp_lambda(const Emitter emit, const Exp_Lambda * lambda)
 }
 
 ANN static m_bool emit_exp_typeof(const Emitter emit, const Exp_Typeof *exp) {
-  if(!exp->exp->type->array_depth)
-    regpushi(emit, (m_uint)(actual_type(emit->gwion, exp->exp->type)));
+  if(!exp->exp->info->type->array_depth)
+    regpushi(emit, (m_uint)(actual_type(emit->gwion, exp->exp->info->type)));
   else
-    regpushi(emit, (m_uint)exp->exp->type);
+    regpushi(emit, (m_uint)exp->exp->info->type);
   return GW_OK;
 }
 
@@ -1118,15 +1213,47 @@ ANN static m_bool emit_exp_interp(const Emitter emit, const Exp_Interp *exp) {
 
 DECL_EXP_FUNC(emit, m_bool, Emitter)
 
-ANN2(1) /*static */m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) {
+
+ANN static void struct_addref(const Emitter emit, const Type type,
+    const m_int size, const m_bool offset, const m_bool emit_var) {
+  for(m_uint i = 0; i < vector_size(&type->e->tuple->types); ++i) {
+    const Type t = (Type)vector_at(&type->e->tuple->types, i);
+    if(isa(t, emit->gwion->type[et_object]) > 0) {
+      const Instr instr = emit_addref(emit, emit_var);
+      instr->m_val = size;
+      instr->m_val2 = vector_at(&type->e->tuple->offset, i);
+    } else if(GET_FLAG(t, struct))
+      struct_addref(emit, t, size, offset + vector_at(&type->e->tuple->offset, i), emit_var);
+  }
+}
+
+ANN static inline m_uint exp_size(const Exp e) {
+  if(exp_getvar(e))
+    return SZ_INT;
+  const Type type = e->info->cast_to ?: e->info->type;
+  return type->size;
+}
+
+ANN2(1) static void emit_exp_addref(const Emitter emit, /* const */Exp exp, m_int size) {
   do {
-   CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d))
-   if(ref && isa(exp->type, emit->gwion->type[et_object]) > 0) {
-      const Instr instr = emit_add_instr(emit, RegAddRef);
-      instr->m_val = exp->emit_var;
-    }
-    if(exp->cast_to)
-      CHECK_BB(emit_implicit_cast(emit, exp, exp->cast_to))
+    if(isa(exp->info->type, emit->gwion->type[et_object]) > 0 &&
+      (exp->info->cast_to ? isa(exp->info->cast_to, emit->gwion->type[et_object]) > 0 : 1)) {
+      const Instr instr = emit_addref(emit, exp_getvar(exp));
+      instr->m_val = size;
+    } else if(GET_FLAG(exp->info->type, struct)) // check cast_to ?
+      struct_addref(emit, exp->info->type, size, 0, exp_getvar(exp));
+    size += exp_size(exp);
+  } while((exp = exp->next));
+}
+
+ANN2(1) /*static */m_bool emit_exp(const Emitter emit, /* const */Exp e) {
+  Exp exp = e;
+  do {
+    CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d))
+    if(exp_getnonnull(exp))
+      emit_except(emit, exp->info->type);
+    if(exp->info->cast_to)
+      CHECK_BB(emit_implicit_cast(emit, exp, exp->info->cast_to))
   } while((exp = exp->next));
   return GW_OK;
 }
@@ -1158,7 +1285,7 @@ ANN static m_bool emit_stmt_code(const Emitter emit, const Stmt_Code stmt) {
 
 ANN static m_bool optimize_taill_call(const Emitter emit, const Exp_Call* e) {
   if(e->args) {
-    CHECK_BB(emit_exp(emit, e->args, 0))
+    CHECK_BB(emit_exp(emit, e->args))
     regpop(emit, e->m_func->def->stack_depth);
     emit_args(emit, e->m_func);
   }
@@ -1170,9 +1297,9 @@ ANN static m_bool emit_stmt_return(const Emitter emit, const Stmt_Exp stmt) {
   if(stmt->val) {
     if(stmt->val->exp_type == ae_exp_call && emit->env->func == stmt->val->d.exp_call.m_func)
       return optimize_taill_call(emit, &stmt->val->d.exp_call);
-    CHECK_BB(emit_exp_pop_next(emit, stmt->val, 0))
-    if(isa(stmt->val->type, emit->gwion->type[et_object]) > 0)
-      emit_add_instr(emit, RegAddRef);
+    CHECK_BB(emit_exp_pop_next(emit, stmt->val))
+    if(isa(stmt->val->info->type, emit->gwion->type[et_object]) > 0)
+        (void)emit_addref(emit, 0);
   }
   vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto));
   return GW_OK;
@@ -1228,7 +1355,7 @@ ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
 
 ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, const m_uint status) {
   regpushi(emit, status);
-  CHECK_BB(emit_exp(emit, stmt->exp, 0))
+  CHECK_BB(emit_exp(emit, stmt->exp))
   emit_add_instr(emit, SetObj);
   const Instr member = emit_add_instr(emit, DotMember4);
   member->m_val = SZ_INT;
@@ -1239,11 +1366,11 @@ ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, co
 
 ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt) {
   CHECK_BB(variadic_state(emit, stmt, 1))
-  CHECK_BB(emit_exp(emit, stmt->exp, 0))
+  CHECK_BB(emit_exp(emit, stmt->exp))
   const Instr instr = emit_add_instr(emit, BranchEqInt);
   const m_uint pc = emit_code_size(emit);
   emit_stmt(emit, stmt->body, 1);
-  CHECK_BB(emit_exp(emit, stmt->exp, 0))
+  CHECK_BB(emit_exp(emit, stmt->exp))
   emit_vararg_end(emit, pc);
   instr->m_val = emit_code_size(emit);
   CHECK_BB(variadic_state(emit, stmt, 0))
@@ -1259,7 +1386,7 @@ ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
   CHECK_BB(scoped_stmt(emit, stmt->body, 1))
   const m_uint action_index = emit_code_size(emit);
   if(stmt->c3) {
-    CHECK_BB(emit_exp(emit, stmt->c3, 0))
+    CHECK_BB(emit_exp(emit, stmt->c3))
     pop_exp(emit, stmt->c3);
   }
   const Instr _goto = emit_add_instr(emit, Goto);
@@ -1272,22 +1399,24 @@ ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
 ANN static Instr emit_stmt_autoptr_init(const Emitter emit, const Type type) {
   const Instr new_obj = emit_add_instr(emit, ObjectInstantiate);
   new_obj->m_val2 = (m_uint)type;
-  emit_add_instr(emit, RegAddRef);
+  (void)emit_addref(emit, 0);
   regpop(emit, SZ_INT);
   return emit_add_instr(emit, Reg2Mem);
 }
 
 // scope push problem
 ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) {
-  CHECK_BB(emit_exp(emit, stmt->exp, 0))
+  CHECK_BB(emit_exp(emit, stmt->exp))
   const Instr s1 = emit_add_instr(emit, MemSetImm);
   emit_push_stack(emit);
   Instr cpy = stmt->is_ptr ? emit_stmt_autoptr_init(emit, stmt->v->type) : NULL;
   const m_uint ini_pc  = emit_code_size(emit);
-  emit_except(emit, stmt->exp->type);
+  emit_except(emit, stmt->exp->info->type);
   const Instr loop = emit_add_instr(emit, stmt->is_ptr ? AutoLoopPtr : AutoLoop);
   const Instr end = emit_add_instr(emit, BranchEqInt);
-  const m_uint offset = emit_local(emit, SZ_INT + stmt->v->type->size, 0);
+//  (void)emit_addref(emit, 0);
+  emit_local(emit, stmt->exp->info->type);
+  const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
   stmt->v->from->offset = offset + SZ_INT;
   CHECK_BB(emit_stmt(emit, stmt->body, 1))
   const m_uint end_pc = emit_code_size(emit);
@@ -1307,7 +1436,7 @@ ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) {
 // scope push problem
 ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
   emit_push_stack(emit);
-  CHECK_BB(emit_exp_pop_next(emit, stmt->cond, 0))
+  CHECK_BB(emit_exp_pop_next(emit, stmt->cond))
   const m_uint index = emit_code_size(emit);
   const Instr cpy = emit_add_instr(emit, Reg2RegAddr);
   cpy->m_val2 = -SZ_INT;
@@ -1352,7 +1481,7 @@ ANN static m_bool emit_enum_def(const Emitter emit, const Enum_Def edef) {
     const Value v = (Value)vector_at(&edef->values, i);
     if(!emit->env->class_def) {
       ALLOC_PTR(emit->gwion->mp, addr, m_uint, i);
-      v->from->offset = emit_local(emit, SZ_INT, 0);
+      v->from->offset = emit_local(emit, emit->gwion->type[et_int]);
       v->d.ptr = addr;
     } else
       *(m_bit*)(emit->env->class_def->nspc->info->class_data + v->from->offset) = i;
@@ -1425,20 +1554,25 @@ ANN static m_bool emit_union_def(const Emitter emit, const Union_Def udef) {
 }
 
 ANN static m_bool emit_stmt_exp(const Emitter emit, const struct Stmt_Exp_* exp) {
-  return exp->val ? emit_exp(emit, exp->val, 0) : 1;
+  return exp->val ? emit_exp(emit, exp->val) : 1;
 }
 
 ANN static m_bool emit_case_head(const Emitter emit, const Exp base,
     const Exp e, const Symbol op, const Vector v) {
-  CHECK_BB(emit_exp(emit, base, 1))
+  CHECK_BB(emit_exp(emit, base))
   const Exp next = e->next;
-  e->next = NULL;
-  const m_bool ret = emit_exp(emit, e, 1);
-  e->next = next;
+//  e->next = NULL;
+  const m_bool ret = emit_exp_pop_next(emit, e);
+  const m_int size = -exp_size(e);
+  emit_exp_addref(emit, base, -exp_totalsize(base) - size);
+  emit_exp_addref(emit, e, -size);
+//  e->next = next;
   CHECK_BB(ret)
   const Exp_Binary bin = { .lhs=base, .rhs=e, .op=op };
-  struct Exp_ ebin = { .d={.exp_binary=bin}, .nspc=e->nspc};
-  struct Op_Import opi = { .op=op, .lhs=base->type, .rhs=e->type, .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos };
+  struct ExpInfo_ info = { .nspc=e->info->nspc };
+  struct Exp_ ebin = { .d={.exp_binary=bin}, .info=&info };
+  struct Op_Import opi = { .op=op, .lhs=base->info->type, .rhs=e->info->type,
+    .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos, .op_type=op_binary };
   CHECK_BB(op_emit_bool(emit, &opi))
   const Instr instr = emit_add_instr(emit, BranchEqInt);
   vector_add(v, (vtype)instr);
@@ -1459,12 +1593,13 @@ ANN static m_bool emit_case_body(const Emitter emit, const struct Stmt_Match_* s
 
 ANN static m_bool case_value(const Emitter emit, const Exp base, const Exp e) {
   const Value v = e->d.prim.value;
-  v->from->offset = emit_local(emit, base->type->size, isa(base->type, emit->gwion->type[et_object]) > 0);
-  CHECK_BB(emit_exp(emit, base, 1))
-  regpop(emit, base->type->size);
+  v->from->offset = emit_local(emit, base->info->type);
+  CHECK_BB(emit_exp(emit, base))
+  emit_exp_addref(emit, base, -exp_totalsize(base));
+  regpop(emit, base->info->type->size);
   const Instr instr = emit_add_instr(emit, Reg2Mem4);
   instr->m_val = v->from->offset;
-  instr->m_val2 = base->type->size;
+  instr->m_val2 = base->info->type->size;
   return GW_OK;
 }
 
@@ -1580,7 +1715,7 @@ ANN static inline m_bool ensure_emit(const Emitter emit, const Type type) {
 ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) {
   CHECK_BB(ensure_emit(emit, member->t_base))
   struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base,
-  .rhs=exp_self(member)->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos };
+    .rhs=exp_self(member)->info->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos, .op_type=op_dot };
   return op_emit_bool(emit, &opi);
 }
 
@@ -1599,11 +1734,9 @@ ANN static void emit_func_def_init(const Emitter emit, const Func func) {
 
 ANN static void emit_func_def_args(const Emitter emit, Arg_List a) {
   do {
-    const Value  value = a->var_decl->value;
-    const m_uint size = value->type->size;
-    const m_bool obj = isa(value->type, emit->gwion->type[et_object]) > 0;
-    emit->code->stack_depth += size;
-    value->from->offset = emit_local(emit, size, obj);
+    const Type type = a->var_decl->value->type;
+    emit->code->stack_depth += type->size;
+    a->var_decl->value->from->offset = emit_local(emit, type);
   } while((a = a->next));
 }
 
@@ -1741,15 +1874,20 @@ ANN static m_bool emit_func_def(const Emitter emit, const Func_Def fdef) {
   if(SAFE_FLAG(emit->env->class_def, builtin) && GET_FLAG(emit->env->class_def, template))
     return GW_OK;
   if(!emit->env->class_def && !GET_FLAG(fdef, global) && !fdef->base->tmpl && !emit->env->scope->depth)
-    func->value_ref->from->offset = emit_local(emit, SZ_INT, 0);
+    func->value_ref->from->offset = emit_local(emit, emit->gwion->type[et_int]);
   emit_func_def_init(emit, func);
   if(GET_FLAG(func, member))
     stack_alloc_this(emit);
+
   emit->env->func = func;
   emit_push_scope(emit);
+  if(!strcmp(s_name(fdef->base->xid), "@gack") &&
+      SAFE_FLAG(func->value_ref->from->owner_class, struct))
+    regpop(emit, func->value_ref->from->owner_class->size - SZ_INT);
   const m_bool ret = scanx_fdef(emit->env, emit, fdef, (_exp_func)emit_fdef);
   emit_pop_scope(emit);
   emit->env->func = former;
+
   if(ret > 0)
     emit_fdef_finish(emit, fdef);
   return ret;
@@ -1791,20 +1929,47 @@ ANN static m_bool cdef_parent(const Emitter emit, const Class_Def cdef) {
   return ret;
 }
 
+ANN static inline int no_ctor(const Emitter emit, const Class_Def cdef) {
+  if(isa(cdef->base.type, emit->gwion->type[et_object]) > 0)
+    return 0;
+  Ast ast = cdef->body;
+  do {
+    if(ast->section->section_type == ae_section_stmt) {
+      Stmt_List list = ast->section->d.stmt_list;
+      do {
+        if(list->stmt->stmt_type != ae_stmt_exp ||
+           !list->stmt->d.stmt_exp.val || list->stmt->d.stmt_exp.val->exp_type != ae_exp_decl)
+          return 0;
+      } while((list = list->next));
+    }
+  } while((ast = ast->next));
+  return 1;
+}
+
+ANN static m_bool emit_struct_body2(const Emitter emit, Section *const section) {
+  return section->section_type != ae_section_stmt ?
+    emit_section(emit, section) : GW_OK;
+}
+
 ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
   if(tmpl_base(cdef->base.tmpl))
     return GW_OK;
-if(GET_FLAG(cdef->base.type, emit))return GW_OK;
+  if(GET_FLAG(cdef->base.type, emit))
+    return GW_OK;
   const Type type = cdef->base.type;
   const Nspc nspc = type->nspc;
-  if(cdef->base.ext && cdef->base.type->e->parent->e->def && !GET_FLAG(cdef->base.type->e->parent, emit))
+  if(cdef->base.ext && type->e->parent->e->def && !GET_FLAG(type->e->parent, emit))
     CHECK_BB(cdef_parent(emit, cdef))
   SET_FLAG(type, emit);
   nspc_allocdata(emit->gwion->mp, nspc);
-  emit_class_code(emit, type->name);
-  if(cdef->body)
-    CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit))
-  emit_class_finish(emit, nspc);
+  if(cdef->body) {
+    if(!no_ctor(emit, cdef)) {
+      emit_class_code(emit, type->name);
+      CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit))
+      emit_class_finish(emit, nspc);
+    } else
+      CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_struct_body2, emit))
+  }
   SET_FLAG(type, emit);
   return GW_OK;
 }
index e767d722e9dae104e46b68c62eb949158eba6b67..606ad5972b24079ad30ee8a6cdc11dccec6e491b 100644 (file)
@@ -5,6 +5,7 @@
 #include "object.h"
 #include "gwion.h"
 #include "operator.h"
+#include "tuple.h"
 
 ANN void nspc_commit(const Nspc nspc) {
   scope_commit(nspc->info->value);
@@ -21,12 +22,29 @@ ANN static inline void nspc_release_object(const Nspc a, Value value, Gwion gwio
   }
 }
 
+ANN2(1,3) static inline void nspc_release_struct(const Nspc a, Value value, Gwion gwion) {
+  if(!SAFE_FLAG(value, pure) && ((SAFE_FLAG(value, static) && a->info->class_data) ||
+    (SAFE_FLAG(value, builtin) && value->d.ptr))) {
+    const m_bit *ptr = (value && value->d.ptr) ? (m_bit*)value->d.ptr:
+        (m_bit*)(a->info->class_data + value->from->offset);
+    for(m_uint i = 0; i < vector_size(&value->type->e->tuple->types); ++i) {
+      const Type t = (Type)vector_at(&value->type->e->tuple->types, i);
+      if(isa(t, gwion->type[et_object]) > 0)
+        release(*(M_Object*)(ptr + vector_at(&value->type->e->tuple->offset, i)), gwion->vm->cleaner_shred);
+      else if(GET_FLAG(t, struct))
+        nspc_release_struct(t->nspc, NULL, gwion);
+    }
+  }
+}
+
 ANN static void free_nspc_value(const Nspc a, Gwion gwion) {
   struct scope_iter iter = { a->info->value, 0, 0 };
   Value v;
   while(scope_iter(&iter, &v) > 0) {
     if(isa(v->type, gwion->type[et_object]) > 0)
       nspc_release_object(a, v, gwion);
+    else if(GET_FLAG(v->type, struct))
+      nspc_release_struct(a, v, gwion);
     REM_REF(v, gwion);
   }
   free_scope(gwion->mp, a->info->value);
index a3d1d8860b34aa170a898f669bbbac41ae13a765..a1264dc127ad7cbebdd94b74bf2910f34397a5a4 100644 (file)
@@ -50,10 +50,8 @@ Type new_type(MemPool p, const m_uint xid, const m_str name, const Type parent)
   type->name   = name;
   type->e = mp_calloc(p, TypeInfo);
   type->e->parent = parent;
-  if(parent) {
+  if(parent)
     type->size = parent->size;
-    type->e->tuple = new_tupleform(p);
-  }
   type->ref = new_refcount(p, free_type);
   return type;
 }
index df61ac104066d0ee028df960d33100bbafdbf618..b8a73e6c693bb795be349247cb1f422cb8657aac 100644 (file)
@@ -152,6 +152,7 @@ ANN static void env_header(const Env env) {
 ANN void env_err(const Env env, const loc_t pos, const m_str fmt, ...) {
   if(env->context && env->context->error)
       return;
+#ifndef __AFL_HAVE_MANUAL_CONTROL
   env_header(env);
   loc_header(pos, env->name);
   va_list arg;
@@ -160,6 +161,7 @@ ANN void env_err(const Env env, const loc_t pos, const m_str fmt, ...) {
   va_end(arg);
   fprintf(stderr, "\n");
   loc_err(pos, env->name);
+#endif
   if(env->context)
     env->context->error = 1;
 }
index 1f6cd6c592619bc566d5a4a08407b595bb3d42b5..e8243b12ee453760ad2a753ecd5f64e502d004a1 100644 (file)
@@ -16,6 +16,7 @@
 #include "mpool.h"
 #include "specialid.h"
 #include "template.h"
+#include "tuple.h"
 
 ANN static m_bool mk_xtor(MemPool p, const Type type, const m_uint d, const ae_flag e) {
   VM_Code* code = e == ae_flag_ctor ? &type->nspc->pre_ctor : &type->nspc->dtor;
@@ -48,6 +49,7 @@ ANN void inherit(const Type t) {
 ANN2(1,2) static void import_class_ini(const Env env, const Type t) {
   t->nspc = new_nspc(env->gwion->mp, t->name);
   t->nspc->parent = env->curr;
+  if(isa(t, env->gwion->type[et_object]) > 0)
   inherit(t);
   t->e->owner = env->curr;
   SET_FLAG(t, checked);
@@ -87,6 +89,7 @@ ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str name, const m_str parent
   t->e->def = new_class_def(gwi->gwion->mp, 0, ck.sym, td, NULL, loc(gwi));
   t->e->def->base.tmpl = tmpl;
   t->e->def->base.type = t;
+  t->e->tuple = new_tupleform(gwi->gwion->mp);
   t->e->parent = p;
   if(td->array)
     SET_FLAG(t, typedef);
@@ -97,11 +100,12 @@ ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str name, const m_str parent
   return type_finish(gwi, t);
 }
 
-ANN Type gwi_class_spe(const Gwi gwi, const m_str name, const m_uint size) {
+ANN Type gwi_struct_ini(const Gwi gwi, const m_str name, const m_uint size) {
   CHECK_OO(str2sym(gwi, name))
   const Type t = new_type(gwi->gwion->mp, ++gwi->gwion->env->scope->type_xid, name, NULL);
   t->size = size;
   gwi_type_flag(t);
+  SET_FLAG(t, struct);
   return type_finish(gwi, t);
 }
 
index c810f09655d8a522dba6c9f61c821df05b09eb6c..79b41d8e7d2257f62dca4e8525b36356b3adb338 100644 (file)
@@ -36,7 +36,7 @@ ANN2(1,2) static int import_op(const Gwi gwi, const struct OperCK* op,
              ret = get_type(gwi, op->ret);
   const struct Op_Func opfunc = { .ck=op->ck, .em=op->em };
   const struct Op_Import opi = { .lhs=lhs, .rhs=rhs, .ret=ret,
-    .func=&opfunc, .data=(uintptr_t)f, .pos=gwi->loc, .op=op->sym, .emit_var=op->emit_var };
+    .func=&opfunc, .data=(uintptr_t)f, .pos=gwi->loc, .op=op->sym };
   return add_op(gwi->gwion, &opi);
 }
 
@@ -54,11 +54,6 @@ ANN m_int gwi_oper_add(const Gwi gwi, Type (*ck)(Env, void*, m_bool*)) {
   return GW_OK;
 }
 
-ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset) {
-  gwi->oper->emit_var = offset;
-  return GW_OK;
-}
-
 ANN m_int gwi_oper_emi(const Gwi gwi, const opem em) {
   gwi->oper->em = em;
   return GW_OK;
index fff75f3a0f363510117a558c8cd5e6016fe1aba7..47383c7966d38a77af32f89303498cb45a24b720 100644 (file)
@@ -133,8 +133,8 @@ ANN static Type get_array_type(Type t) {
 
 #define ARRAY_OPCK                                        \
   const Exp_Binary* bin = (Exp_Binary*)data;              \
-  const Type l = get_array_type(bin->lhs->type);          \
-  const Type r = get_array_type(bin->rhs->type);          \
+  const Type l = get_array_type(bin->lhs->info->type);    \
+  const Type r = get_array_type(bin->rhs->info->type);    \
   if(isa(l, r) < 0)                                       \
     ERR_N(exp_self(bin)->pos, _("array types do not match."))
 
@@ -142,27 +142,27 @@ static OP_CHECK(opck_array_at) {
   ARRAY_OPCK
   if(opck_const_rhs(env, data, mut) == env->gwion->type[et_null])
     return env->gwion->type[et_null];
-  if(bin->lhs->type->array_depth != bin->rhs->type->array_depth)
+  if(bin->lhs->info->type->array_depth != bin->rhs->info->type->array_depth)
     ERR_N(exp_self(bin)->pos, _("array depths do not match."))
   if(bin->rhs->exp_type == ae_exp_decl) {
     if(bin->rhs->d.exp_decl.list->self->array &&
           bin->rhs->d.exp_decl.list->self->array->exp)
       ERR_N(exp_self(bin)->pos, _("do not provide array for 'xxx @=> declaration'."))
   }
-  bin->rhs->emit_var = 1;
-  return bin->rhs->type;
+  exp_setvar(bin->rhs, 1);
+  return bin->rhs->info->type;
 }
 
 static OP_CHECK(opck_array_shift) {
   ARRAY_OPCK
-  if(bin->lhs->type->array_depth != bin->rhs->type->array_depth + 1)
+  if(bin->lhs->info->type->array_depth != bin->rhs->info->type->array_depth + 1)
     ERR_N(exp_self(bin)->pos, "array depths do not match for '<<'.");
-  return bin->lhs->type;
+  return bin->lhs->info->type;
 }
 
 static OP_EMIT(opem_array_shift) {
   const Exp_Binary* bin = (Exp_Binary*)data;
-  const Type type = bin->rhs->type;
+  const Type type = bin->rhs->info->type;
   const Instr pop = emit_add_instr(emit, RegPop);
   pop->m_val = type->size;
   return emit_add_instr(emit, ArrayAppend);
@@ -171,20 +171,20 @@ static OP_EMIT(opem_array_shift) {
 // check me. use common ancestor maybe
 static OP_CHECK(opck_array_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
-  Type l = cast->exp->type;
-  Type r = exp_self(cast)->type;
+  Type l = cast->exp->info->type;
+  Type r = exp_self(cast)->info->type;
   while(!l->e->d.base_type)
     l = l->e->parent;
   while(!r->e->d.base_type)
     r = r->e->parent;
-  if(get_depth(cast->exp->type) == get_depth(exp_self(cast)->type) && isa(l->e->d.base_type, r->e->d.base_type) > 0)
+  if(get_depth(cast->exp->info->type) == get_depth(exp_self(cast)->info->type) && isa(l->e->d.base_type, r->e->d.base_type) > 0)
     return l;
   return env->gwion->type[et_null];
 }
 
 static OP_CHECK(opck_array_slice) {
   const Exp e = (Exp)data;
-  return e->d.exp_slice.base->type;
+  return e->d.exp_slice.base->info->type;
 }
 
 static inline m_bool bounds(const M_Vector v, const m_int i) {
@@ -274,7 +274,7 @@ ANN static void array_finish(const Emitter emit, const m_uint depth,
 
 ANN static inline m_bool array_do(const  Emitter emit, const Array_Sub array, const m_bool is_var) {
   emit_add_instr(emit, GcAdd);
-  CHECK_BB(emit_exp(emit, array->exp, 0))
+  CHECK_BB(emit_exp(emit, array->exp))
   array_loop(emit, array->depth);
   array_finish(emit, array->depth, array->type->size, is_var);
   return GW_OK;
@@ -335,9 +335,9 @@ GWION_IMPORT(array) {
   GWI_BB(gwi_oper_emi(gwi, opem_basic_cast))
   GWI_BB(gwi_oper_end(gwi, "$", NULL))
   GWI_BB(gwi_oper_ini(gwi, "nonnull @Array", "int", "int"))
+//  GWI_BB(gwi_oper_ini(gwi, "@Array", "int", "int"))
   GWI_BB(gwi_oper_add(gwi, opck_array_slice))
   GWI_BB(gwi_oper_emi(gwi, opem_array_slice))
-  GWI_BB(gwi_oper_var(gwi, SZ_INT*2))
   GWI_BB(gwi_oper_end(gwi, "@slice", NULL))
   GWI_BB(gwi_oper_ini(gwi, "int", (m_str)OP_ANY_TYPE, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_not_array))
index 99718565ff05a1b91f3a3e59033c9787f418abe7..2f56dd16abba165d8be2ec677bc7db505946a78a 100644 (file)
@@ -65,7 +65,6 @@ GWION_IMPORT(event) {
   GWI_BB(gwi_func_end(gwi, event_broadcast, ae_flag_none))
   GWI_BB(gwi_class_end(gwi))
   GWI_BB(gwi_oper_ini(gwi, "nonnull Event", "@now", "int"))
-  GWI_BB(gwi_oper_var(gwi, -SZ_FLOAT))
   _CHECK_OP("=>", eventwait, EventWait)
   return GW_OK;
 }
index c5ad8eda4e2e3cce7b04174ea6ea7f6be947aab9..098321406b4dc52da3529f3f6e16e7d1630918ea 100644 (file)
@@ -36,10 +36,11 @@ static inline void fptr_instr(const Emitter emit, const Func f, const m_uint i)
 
 static OP_EMIT(opem_func_assign) {
   Exp_Binary* bin = (Exp_Binary*)data;
-  if(bin->rhs->type->e->d.func->def->base->tmpl)
-    fptr_instr(emit, bin->lhs->type->e->d.func, 2);
+  if(bin->rhs->info->type->e->d.func->def->base->tmpl)
+    fptr_instr(emit, bin->lhs->info->type->e->d.func, 2);
   const Instr instr = emit_add_instr(emit, int_r_assign);
-  if(!is_fptr(emit->gwion, bin->lhs->type) && GET_FLAG(bin->rhs->type->e->d.func, member)) {
+  if(!is_fptr(emit->gwion, bin->lhs->info->type) && GET_FLAG(bin->rhs->info->type->e->d.func, member)) {
+//exit(3);
     const Instr pop = emit_add_instr(emit, LambdaAssign);
     pop->m_val = SZ_INT;
   }
@@ -173,7 +174,7 @@ ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner,
     env_pop(env, scope);
   if(ret < 0)
     return GW_ERROR;
-  exp_self(l)->type = l->def->base->func->value_ref->type;
+  exp_self(l)->info->type = l->def->base->func->value_ref->type;
   return GW_OK;
 }
 
@@ -184,11 +185,11 @@ ANN static m_bool fptr_lambda(const Env env, struct FptrInfo *info) {
 }
 
 ANN static m_bool fptr_do(const Env env, struct FptrInfo *info) {
-  if(isa(info->exp->type, env->gwion->type[et_lambda]) < 0) {
-    m_bool nonnull = GET_FLAG(info->exp->type, nonnull);
+  if(isa(info->exp->info->type, env->gwion->type[et_lambda]) < 0) {
+    m_bool nonnull = GET_FLAG(info->exp->info->type, nonnull);
     CHECK_BB(fptr_check(env, info))
     DECL_OB(const Type, t, = fptr_type(env, info))
-    info->exp->type = !nonnull ? t : type_nonnull(env, t);
+    info->exp->info->type = !nonnull ? t : type_nonnull(env, t);
     return GW_OK;
   }
   return fptr_lambda(env, info);
@@ -196,28 +197,28 @@ ANN static m_bool fptr_do(const Env env, struct FptrInfo *info) {
 
 static OP_CHECK(opck_fptr_at) {
   Exp_Binary* bin = (Exp_Binary*)data;
-  if(bin->rhs->type->e->d.func->def->base->tmpl &&
-     bin->rhs->type->e->d.func->def->base->tmpl->call) {
-    struct FptrInfo info = { bin->lhs->type->e->d.func, bin->rhs->type->e->parent->e->d.func,
+  if(bin->rhs->info->type->e->d.func->def->base->tmpl &&
+     bin->rhs->info->type->e->d.func->def->base->tmpl->call) {
+    struct FptrInfo info = { bin->lhs->info->type->e->d.func, bin->rhs->info->type->e->parent->e->d.func,
       bin->lhs, exp_self(bin)->pos };
     CHECK_BO(fptr_do(env, &info))
-    bin->rhs->emit_var = 1;
-    return bin->rhs->type;
+    exp_setvar(bin->rhs, 1);
+    return bin->rhs->info->type;
   }
-  struct FptrInfo info = { bin->lhs->type->e->d.func, bin->rhs->type->e->d.func,
+  struct FptrInfo info = { bin->lhs->info->type->e->d.func, bin->rhs->info->type->e->d.func,
       bin->lhs, exp_self(bin)->pos };
   CHECK_BO(fptr_do(env, &info))
-  bin->rhs->emit_var = 1;
-  return bin->rhs->type;
+  exp_setvar(bin->rhs, 1);
+  return bin->rhs->info->type;
 }
 
 static OP_CHECK(opck_fptr_cast) {
   Exp_Cast* cast = (Exp_Cast*)data;
-  const Type t = exp_self(cast)->type;
-  struct FptrInfo info = { cast->exp->type->e->d.func, t->e->d.func,
+  const Type t = exp_self(cast)->info->type;
+  struct FptrInfo info = { cast->exp->info->type->e->d.func, t->e->d.func,
      cast->exp, exp_self(cast)->pos };
   CHECK_BO(fptr_do(env, &info))
-  cast->func = cast->exp->type->e->d.func;
+  cast->func = cast->exp->info->type->e->d.func;
   return t;
 }
 
@@ -231,29 +232,29 @@ static void member_fptr(const Emitter emit) {
 static OP_EMIT(opem_fptr_cast) {
   CHECK_OO(opem_basic_cast(emit, data))
   Exp_Cast* cast = (Exp_Cast*)data;
-  if(exp_self(cast)->type->e->d.func->def->base->tmpl)
-    fptr_instr(emit, cast->exp->type->e->d.func, 1);
-  if(GET_FLAG(cast->exp->type->e->d.func, member) &&
-    !(GET_FLAG(cast->exp->type, nonnull) || GET_FLAG(exp_self(cast)->type, nonnull)))
+  if(exp_self(cast)->info->type->e->d.func->def->base->tmpl)
+    fptr_instr(emit, cast->exp->info->type->e->d.func, 1);
+  if(GET_FLAG(cast->exp->info->type->e->d.func, member) &&
+    !(GET_FLAG(cast->exp->info->type, nonnull) || GET_FLAG(exp_self(cast)->info->type, nonnull)))
     member_fptr(emit);
   return (Instr)GW_OK;
 }
 
 static OP_CHECK(opck_fptr_impl) {
   struct Implicit *impl = (struct Implicit*)data;
-  struct FptrInfo info = { impl->e->type->e->d.func, impl->t->e->d.func,
+  struct FptrInfo info = { impl->e->info->type->e->d.func, impl->t->e->d.func,
       impl->e, impl->e->pos };
   CHECK_BO(fptr_do(env, &info))
-  return ((Exp)impl->e)->cast_to = impl->t;
+  return ((Exp)impl->e)->info->cast_to = impl->t;
 }
 
 static OP_EMIT(opem_fptr_impl) {
   struct Implicit *impl = (struct Implicit*)data;
   if(GET_FLAG(impl->t->e->d.func, member) &&
-    !(GET_FLAG(impl->e->type, nonnull) || GET_FLAG(impl->t, nonnull)))
+    !(GET_FLAG(impl->e->info->type, nonnull) || GET_FLAG(impl->t, nonnull)))
     member_fptr(emit);
   if(impl->t->e->d.func->def->base->tmpl)
-    fptr_instr(emit, ((Exp)impl->e)->type->e->d.func, 1);
+    fptr_instr(emit, ((Exp)impl->e)->info->type->e->d.func, 1);
   return (Instr)GW_OK;
 }
 
index 1f04a9f7418aaf3b887c33834594618a9a725130..67a12565f2bb953fb5a860789a74af4306d6da03 100644 (file)
@@ -54,12 +54,12 @@ ANN static inline VM_Code get_gack(Type t) {
   return NULL; // unreachable
 }
 
-ANN static void prepare_call(const VM_Shred shred, m_uint offset) {
+ANN static void prepare_call(const VM_Shred shred, const m_uint offset) {
   shred->mem += offset;
-  *(m_uint*)(shred->mem+ SZ_INT) = offset + SZ_INT;
-  *(VM_Code*)(shred->mem+ SZ_INT*2) = shred->code;
-  *(m_uint*)(shred->mem+ SZ_INT*3) = shred->pc;
-  *(m_uint*)(shred->mem+ SZ_INT*4) = SZ_INT;
+  *(m_uint*)(shred->mem  + SZ_INT) = offset + SZ_INT;
+  *(VM_Code*)(shred->mem + SZ_INT*2) = shred->code;
+  *(m_uint*)(shred->mem  + SZ_INT*3) = shred->pc;
+  *(m_uint*)(shred->mem  + SZ_INT*4) = SZ_INT;
   shred->mem += SZ_INT*5;
   *(M_Object*)(shred->mem)= *(M_Object*)(shred->reg - SZ_INT);
   shred->pc = 0;
@@ -80,3 +80,4 @@ ANN void gack(const VM_Shred shred, const Instr instr) {
   }
   return;
 }
+
index ff897dfa4bf6966d4b1a7e4e3c69eb37a51f0822..76e20ae5a6bdec0f12135827c68080bd1981a0a5 100644 (file)
@@ -207,17 +207,17 @@ static DTOR(usrugen_dtor) {
 
 static OP_CHECK(opck_usrugen) {
   Exp_Binary *bin = (Exp_Binary*)data;
-  const Arg_List arg = bin->lhs->type->e->d.func->def->base->args;
+  const Arg_List arg = bin->lhs->info->type->e->d.func->def->base->args;
   if(!arg || arg->next)
     ERR_N(exp_self(bin)->pos, _("Tick function take one and only one argument"))
   if(isa(arg->type, env->gwion->type[et_float]) < 0)
     ERR_N(exp_self(bin)->pos, _("Tick functions argument must be of type float"))
-  if(isa(bin->lhs->type->e->d.func->def->base->ret_type, env->gwion->type[et_float]) < 0)
+  if(isa(bin->lhs->info->type->e->d.func->def->base->ret_type, env->gwion->type[et_float]) < 0)
     ERR_N(exp_self(bin)->pos, _("Tick function must return float"))
-  if(bin->lhs->type->e->d.func->value_ref->from->owner_class)
-    CHECK_BN(isa(bin->lhs->type->e->d.func->value_ref->from->owner_class,
-      bin->rhs->type))
-  return bin->rhs->type;
+  if(bin->lhs->info->type->e->d.func->value_ref->from->owner_class)
+    CHECK_BN(isa(bin->lhs->info->type->e->d.func->value_ref->from->owner_class,
+      bin->rhs->info->type))
+  return bin->rhs->info->type;
 }
 
 static INSTR(UURet) {
@@ -270,7 +270,7 @@ static INSTR(UsrUGenTick) {
 static OP_EMIT(opem_usrugen) {
   Exp_Binary *bin = (Exp_Binary*)data;
   const Instr instr = emit_add_instr(emit, UsrUGenTick);
-  instr->m_val = !!bin->lhs->type->e->d.func->value_ref->from->owner_class;
+  instr->m_val = !!bin->lhs->info->type->e->d.func->value_ref->from->owner_class;
   return instr;
 }
 
index c421f141faf132e47f2d9adf6a775e45f28b80f9..6d008654d5adea7f91e3cd5cb0aea6f611a437e0 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "gwi.h"
 #include "gack.h"
+#include "tuple.h"
 
 #undef insert_symbol
 ANN void exception(const VM_Shred shred, const m_str c) {
@@ -75,6 +76,18 @@ ANN void __release(const M_Object o, const VM_Shred shred) {
       if(!GET_FLAG(v, static) && !GET_FLAG(v, pure) &&
           isa(v->type, shred->info->vm->gwion->type[et_object]) > 0)
         release(*(M_Object*)(o->data + v->from->offset), shred);
+else if(GET_FLAG(v->type, struct) &&
+       !GET_FLAG(v, static) && !GET_FLAG(v, pure)) {
+const TupleForm tf = v->type->e->tuple;
+for(m_uint i = 0; i < vector_size(&tf->types); ++i) {
+  const Type t = (Type)vector_at(&tf->types, i);
+  if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
+    release(*(M_Object*)(o->data + v->from->offset + vector_at(&tf->offset, i)), shred);
+}
+
+//exit(77);
+
+}
     }
     if(GET_FLAG(t, dtor) && t->nspc->dtor) {
       if(GET_FLAG(t->nspc->dtor, builtin))
@@ -95,14 +108,26 @@ ANN void free_object(MemPool p, const M_Object o) {
   mp_free(p, M_Object, o);
 }
 
-static ID_CHECK(check_this) {
+static ID_CHECK(opck_this) {
   if(!env->class_def)
     ERR_O(exp_self(prim)->pos, _("keyword 'this' can be used only inside class definition..."))
   if(env->func && !GET_FLAG(env->func, member))
-    ERR_O(exp_self(prim)->pos, _("keyword 'this' cannot be used inside static functions..."))
+      ERR_O(exp_self(prim)->pos, _("keyword 'this' cannot be used inside static functions..."))
+  if(env->func && !strcmp(s_name(env->func->def->base->xid), "@gack") &&
+GET_FLAG(env->class_def, struct))
+  ERR_O(exp_self(prim)->pos, _("can't use 'this' in struct @gack"))
   return env->class_def;
 }
 
+static ID_EMIT(opem_this) {
+  if(!exp_getvar(exp_self(prim)) && GET_FLAG(exp_self(prim)->info->type, struct)) {
+    const Instr instr = emit_add_instr(emit, RegPushMemDeref);
+    instr->m_val2 = emit->env->class_def->size;
+    return (Instr)GW_OK;
+  }
+  return emit_add_instr(emit, RegPushMem);
+}
+
 static GACK(gack_object) {
   INTERP_PRINTF("%p", *(M_Object*)VALUE);
 }
@@ -113,7 +138,8 @@ GWION_IMPORT(object) {
   GWI_BB(gwi_gack(gwi, t_object, gack_object))
   SET_FLAG(t_object, checked); // should be set by gwi_add_type
   gwi->gwion->type[et_object] = t_object;
-  struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 };
+//  struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 };
+  struct SpecialId_ spid = { .ck=opck_this, .em=opem_this, .is_const=1 };
   gwi_specialid(gwi, "this", &spid);
   return GW_OK;
 }
index e0ccb8b0c3a65003017b3448ef6ff29c7584fc63..8026bf665df5340c82c8829c3522b45eb5d3cf93 100644 (file)
@@ -20,7 +20,7 @@
 #undef insert_symbol
 
 #define describe_logical(name, op)               \
-static INSTR(name##Object) {\
+static INSTR(name##Object) {                     \
   POP_REG(shred, SZ_INT);                        \
   const M_Object lhs = *(M_Object*)REG(-SZ_INT); \
   const M_Object rhs = *(M_Object*)REG(0);       \
@@ -51,8 +51,8 @@ static inline Type check_nonnull(const Env env, const Type l, const Type r,
 
 static OP_CHECK(at_object) {
   const Exp_Binary* bin = (Exp_Binary*)data;
-  const Type l = bin->lhs->type;
-  const Type r = bin->rhs->type;
+  const Type l = bin->lhs->info->type;
+  const Type r = bin->rhs->info->type;
   if(opck_rassign(env, data, mut) == env->gwion->type[et_null])
     return env->gwion->type[et_null];
   if(check_nonnull(env, l, r, "assign", exp_self(bin)->pos) == env->gwion->type[et_null])
@@ -61,14 +61,14 @@ static OP_CHECK(at_object) {
     SET_FLAG(bin->rhs->d.exp_decl.td, ref);
     SET_FLAG(bin->rhs->d.exp_decl.list->self->value, ref);
   }
-  bin->rhs->emit_var = 1;
+  exp_setvar(bin->rhs, 1);
   return r;
 }
 
 static OP_EMIT(opem_at_object) {
   const Exp_Binary* bin = (Exp_Binary*)data;
-  const Type l = bin->lhs->type;
-  const Type r = bin->rhs->type;
+  const Type l = bin->lhs->info->type;
+  const Type r = bin->rhs->info->type;
   if(nonnull_check(l, r)) {
     const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
     instr->m_val = SZ_INT;
@@ -100,8 +100,8 @@ static Type get_force_type(const Env env, const Type t) {
 
 static OP_CHECK(opck_object_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
-  const Type l = cast->exp->type;
-  const Type r = exp_self(cast)->type;
+  const Type l = cast->exp->info->type;
+  const Type r = exp_self(cast)->info->type;
   if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null])
     return env->gwion->type[et_null];
   return get_force_type(env, r);
@@ -109,8 +109,8 @@ static OP_CHECK(opck_object_cast) {
 
 static OP_EMIT(opem_object_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
-  const Type l = cast->exp->type;
-  const Type r = exp_self(cast)->type;
+  const Type l = cast->exp->info->type;
+  const Type r = exp_self(cast)->info->type;
   if(nonnull_check(l, r))
     emit_add_instr(emit, GWOP_EXCEPT);
   return (Instr)GW_OK;
@@ -118,17 +118,17 @@ static OP_EMIT(opem_object_cast) {
 
 static OP_CHECK(opck_implicit_null2obj) {
   const struct Implicit* imp = (struct Implicit*)data;
-  const Type l = imp->e->type;
+  const Type l = imp->e->info->type;
   const Type r = imp->t;
   if(check_nonnull(env, l, r, "implicitly cast", imp->e->pos) == env->gwion->type[et_null])
     return env->gwion->type[et_null];
-  imp->e->cast_to = r;
+  imp->e->info->cast_to = r;
   return imp->t;
 }
 
 static OP_EMIT(opem_implicit_null2obj) {
   const struct Implicit* imp = (struct Implicit*)data;
-  const Type l = imp->e->type;
+  const Type l = imp->e->info->type;
   const Type r = imp->t;
   if(nonnull_check(l, r))
     emit_add_instr(emit, GWOP_EXCEPT);
@@ -168,8 +168,8 @@ ANN static void emit_dot_static_import_data(const Emitter emit, const Value v, c
 static const f_instr dotmember[]  = { DotMember, DotMember2, DotMember3, DotMember4 };
 
 ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) {
-  const Func f = exp_self(member)->type->e->d.func;
-  if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) {
+  const Func f = exp_self(member)->info->type->e->d.func;
+  if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->info->type, force)) {
     const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
     func_i->m_val = (m_uint)f->code;
     return;
@@ -177,6 +177,15 @@ ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) {
   if(f->def->base->tmpl)
     emit_add_instr(emit, DotTmplVal);
   else {
+    if(GET_FLAG(member->t_base, struct)) {
+      if(!GET_FLAG(f->def, static)) {
+        exp_setvar(member->base, 1);
+        emit_exp(emit, member->base);
+      }
+      const Instr instr = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
+      instr->m_val = (m_uint)f->code;
+      return;
+    }
     const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc);
     instr->m_val = f->vt_index;
   }
@@ -190,6 +199,33 @@ ANN static inline void emit_member(const Emitter emit, const Value v, const uint
   instr->m_val2 = size;
 }
 
+ANN static inline void emit_struct_addr(const Emitter emit, const Value v) {
+  const Instr set = emit_add_instr(emit, StructMemberAddr);
+  set->m_val = v->from->owner_class->size - v->type->size;
+  set->m_val2 = v->from->offset;
+}
+
+ANN static inline void emit_struct_var(const Emitter emit, const Value v) {
+  for(m_uint i = 0; i < v->type->size; i += SZ_INT) {
+    const Instr set = emit_add_instr(emit, Reg2Reg);
+    set->m_val = -v->type->size + i;
+    set->m_val2 = -v->type->size + v->from->offset + i;
+  }
+}
+
+ANN static inline void emit_struct_data(const Emitter emit, const Value v, const uint emit_addr) {
+  if(emit_addr) {
+    emit_struct_addr(emit, v);
+    return;
+  }
+  const Instr push = emit_add_instr(emit, RegPush);
+  push->m_val = v->type->size - v->from->owner_class->size;
+  if(v->from->offset)
+    emit_struct_var(emit, v);
+//  const Instr push = emit_add_instr(emit, RegPush);
+//  push->m_val = v->type->size - SZ_INT;
+}
+
 ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
 OP_CHECK(opck_object_dot) {
   const Exp_Dot *member = (Exp_Dot*)data;
@@ -217,29 +253,42 @@ OP_CHECK(opck_object_dot) {
       ERR_O(exp_self(member)->pos,
           _("can't access private '%s' outside of class..."), value->name)
     else if(GET_FLAG(value, protect))
-      exp_self(member)->meta = ae_meta_protect;
+      exp_setprot(exp_self(member), 1);
   }
   if(base_static && GET_FLAG(value, member))
     ERR_O(exp_self(member)->pos,
           _("cannot access member '%s.%s' without object instance..."),
           the_base->name, str)
   if(GET_FLAG(value, const) || GET_FLAG(value, enum))
-    exp_self(member)->meta = ae_meta_value;
+    exp_setmeta(exp_self(member), 1);
   return value->type;
 }
 
 OP_EMIT(opem_object_dot) {
   const Exp_Dot *member = (Exp_Dot*)data;
-  const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid);
+  const Type t_base = actual_type(emit->gwion, member->t_base);
+  const Value value = find_value(t_base, member->xid);
   if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
-       (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 &&
-       !is_fptr(emit->gwion, exp_self(member)->type)))) {
-    CHECK_BO(emit_exp(emit, member->base, 0))
-    emit_except(emit, member->t_base);
+       (isa(exp_self(member)->info->type, emit->gwion->type[et_function]) > 0 &&
+       !is_fptr(emit->gwion, exp_self(member)->info->type)))) {
+  if(!GET_FLAG(t_base, struct))
+    CHECK_BO(emit_exp(emit, member->base))
+    if(isa(member->t_base, emit->env->gwion->type[et_object]) > 0)
+      emit_except(emit, member->t_base);
   }
-  if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type))
+  if(isa(exp_self(member)->info->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->info->type))
          emit_member_func(emit, member);
-  else (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data)(emit, value, exp_self(member)->emit_var);
+  else if(GET_FLAG(value, member)) {
+    if(!GET_FLAG(t_base, struct))
+      emit_member(emit, value, exp_getvar(exp_self(member)));
+    else {
+      exp_setvar(member->base, exp_getvar(exp_self(member)));
+      CHECK_BO(emit_exp(emit, member->base))
+      emit_struct_data(emit, value, exp_getvar(exp_self(member)));
+    }
+  }
+  else if(GET_FLAG(value, static))
+    emit_dot_static_import_data(emit, value, exp_getvar(exp_self(member)));
   return (Instr)GW_OK;
 }
 
@@ -376,9 +425,9 @@ ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data) {
   const Value v = prim_self(data)->value;
   const Exp base = new_prim_id(gwion->mp, dot_symbol(gwion->st, v), loc_cpy(gwion->mp, prim_pos(data)));
   const Exp dot = new_exp_dot(gwion->mp, base, *data);
-  dot->d.exp_dot.t_base = dot->d.exp_dot.base->type = dot_type(gwion->st, v);
-  dot->type = prim_exp(data)->type;
-  dot->emit_var = prim_exp(data)->emit_var;
+  dot->d.exp_dot.t_base = dot->d.exp_dot.base->info->type = dot_type(gwion->st, v);
+  dot->info->type = prim_exp(data)->info->type;
+  exp_setvar(dot, exp_getvar(prim_exp(data)));
   return dot;
 }
 
index 8a443967f45bd6e3d672d2c902df040ca3b4f586..122e7eff315e4a4d9c9de0f335cbb9607fdd257b 100644 (file)
 #include "operator.h"
 #include "import.h"
 
-static inline m_str access(ae_Exp_Meta meta) {
-  return meta == ae_meta_value ? "non-mutable" : "protected";
+static inline m_str get_access(const Exp e) {
+  if(exp_getmeta(e))
+    return "non-mutable";
+  return !exp_getprot(e) ? NULL : "protected";
 }
 
 OP_CHECK(opck_basic_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
-  return isa(cast->exp->type, exp_self(cast)->type) > 0 ?
-     exp_self(cast)->type : env->gwion->type[et_null];
+  return isa(cast->exp->info->type, exp_self(cast)->info->type) > 0 ?
+     exp_self(cast)->info->type : env->gwion->type[et_null];
 }
 
 OP_CHECK(opck_usr_implicit) {
   struct Implicit* imp = (struct Implicit*)data;
-  imp->e->cast_to = imp->t;
+  imp->e->info->cast_to = imp->t;
   return imp->t;
 }
 
@@ -32,59 +34,60 @@ OP_EMIT(opem_basic_cast) {
 
 OP_CHECK(opck_const_rhs) {
   const Exp_Binary* bin = (Exp_Binary*)data;
-  if(bin->rhs->meta != ae_meta_var)
+  const m_str access = get_access(bin->rhs);
+  if(access)
     ERR_N(bin->rhs->pos, _("cannot assign '%s' on types '%s' and '%s'.\n"
          "  ...  (reason: --- right-side operand is %s.)"),
-         s_name(bin->op), bin->lhs->type->name, bin->rhs->type->name,
-         access(bin->rhs->meta))
-  return bin->rhs->type;
+         s_name(bin->op), bin->lhs->info->type->name, bin->rhs->info->type->name,
+         access)
+  return bin->rhs->info->type;
 }
 
 OP_CHECK(opck_rhs_emit_var) {
   const Exp_Binary* bin = (Exp_Binary*)data;
-  bin->rhs->emit_var = 1;
-  return bin->rhs->type;
+  exp_setvar(bin->rhs, 1);
+  return bin->rhs->info->type;
 }
 
 OP_CHECK(opck_rassign) {
   const Exp_Binary* bin = (Exp_Binary*)data;
   if(opck_const_rhs(env, data, mut) == env->gwion->type[et_null])
     return env->gwion->type[et_null];
-  bin->rhs->emit_var = 1;
-  return bin->rhs->type;
+  exp_setvar(bin->rhs, 1);
+  return bin->rhs->info->type;
 }
 
 OP_CHECK(opck_unary_meta) {
   const Exp_Unary* unary = (Exp_Unary*)data;
-  exp_self(unary)->meta = ae_meta_value;
-  return unary->exp->type;
+  exp_setmeta(exp_self(unary), 1);
+  return unary->exp->info->type;
 }
 
 OP_CHECK(opck_unary_meta2) {
   const Exp_Unary* unary = (Exp_Unary*)data;
-  exp_self(unary)->meta = ae_meta_value;
+  exp_setmeta(exp_self(unary), 1);
   return env->gwion->type[et_bool];
 }
 
 OP_CHECK(opck_unary) {
   const Exp_Unary* unary = (Exp_Unary*)data;
-  if(unary->exp->meta != ae_meta_var)
+  const m_str access = get_access(unary->exp);
+  if(access)
     ERR_N(unary->exp->pos,
           _("unary operator '%s' cannot be used on %s data-types."),
-          s_name(unary->op), access(unary->exp->meta))
-  unary->exp->emit_var = 1;
-  exp_self(unary)->meta = ae_meta_value;
-  return unary->exp->type;
+          s_name(unary->op), access);
+  exp_setvar(unary->exp, 1);
+  return unary->exp->info->type;
 }
 
 OP_CHECK(opck_post) {
   const Exp_Postfix* post = (Exp_Postfix*)data;
-  if(post->exp->meta != ae_meta_var)
+  const m_str access = get_access(post->exp);
+  if(access)
     ERR_N(post->exp->pos, _("post operator '%s' cannot be used on %s data-type."),
-          s_name(post->op), access(post->exp->meta))
-  post->exp->emit_var = 1;
-  exp_self(post)->meta = ae_meta_value;
-  return post->exp->type;
+          s_name(post->op), access)
+  exp_setvar(post->exp, 1);
+  return post->exp->info->type;
 }
 
 OP_CHECK(opck_new) {
@@ -105,7 +108,7 @@ OP_CHECK(opck_new) {
 
 OP_EMIT(opem_new) {
   const Exp_Unary* unary = (Exp_Unary*)data;
-  CHECK_BO(emit_instantiate_object(emit, exp_self(unary)->type,
+  CHECK_BO(emit_instantiate_object(emit, exp_self(unary)->info->type,
     unary->td->array, GET_FLAG(unary->td, ref)))
   return emit_add_instr(emit, GcAdd);
 }
index 5127bc6284b82cb42403d3b28bee769875207629..e82f46697bf56b09c21e7d171ba1f399ae83d955 100644 (file)
@@ -75,27 +75,27 @@ static OP_CHECK(opck_int_range) {
   const Exp exp = (Exp)data;
   const Range *range = exp->d.prim.d.range;
   const Exp e = range->start ?: range->end;
-  return array_type(env, e->type, 1);
+  return array_type(env, e->info->type, 1);
 }
 
 static OP_EMIT(opem_int_range) {
   const Exp exp = (Exp)data;
   const Instr instr = emit_add_instr(emit, IntRange);
-  instr->m_val = (m_uint)exp->type;
+  instr->m_val = (m_uint)exp->info->type;
   return instr;
 }
 
 static GWION_IMPORT(int_unary) {
   GWI_BB(gwi_oper_ini(gwi, NULL, "int", "int"))
-  GWI_BB(gwi_oper_add(gwi,  opck_unary_meta))
-  GWI_BB(gwi_oper_end(gwi,  "-",       int_negate))
+  GWI_BB(gwi_oper_add(gwi, opck_unary_meta))
+  GWI_BB(gwi_oper_end(gwi, "-", int_negate))
   CHECK_OP("++", unary, pre_inc)
   CHECK_OP("--", unary, pre_dec)
   GWI_BB(gwi_oper_end(gwi,  "~", int_cmp))
   GWI_BB(gwi_oper_ini(gwi, NULL, "int", NULL))
-  GWI_BB(gwi_oper_add(gwi,  opck_int_range))
-  GWI_BB(gwi_oper_emi(gwi,  opem_int_range))
-  GWI_BB(gwi_oper_end(gwi,  "@range", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_int_range))
+  GWI_BB(gwi_oper_emi(gwi, opem_int_range))
+  GWI_BB(gwi_oper_end(gwi, "@range", NULL))
   GWI_BB(gwi_oper_ini(gwi, "int", NULL, "int"))
   CHECK_OP("++", post, post_inc)
   GWI_BB(gwi_oper_add(gwi, opck_post))
@@ -139,7 +139,7 @@ static OP_CHECK(opck_implicit_f2i) {
 
 static OP_CHECK(opck_implicit_i2f) {
   struct Implicit* imp = (struct Implicit*)data;
-  return imp->e->cast_to = env->gwion->type[et_float];
+  return imp->e->info->cast_to = env->gwion->type[et_float];
 }
 
 #define CHECK_FF(op, check, func) _CHECK_OP(op, check, float_##func)
index ab421ef1205de190037641fb9a0ee3db4f237bd1..86aee9b0e0eecde1282e8078d147f944debfd4c0 100644 (file)
 
 static OP_CHECK(opck_ptr_assign) {
   const Exp_Binary* bin = (Exp_Binary*)data;
-  if(bin->lhs->meta != ae_meta_var)
-    ERR_N(exp_self(bin)->pos, _("left side operand is constant"));
-  bin->lhs->emit_var = 1;
-  Type t = bin->lhs->type;
+  const m_str access = exp_access(exp_self(bin));
+  if(access)
+    ERR_N(exp_self(bin)->pos, _("left side operand is %s"), access);
+  exp_setvar(bin->lhs, 1);
+  Type t = bin->lhs->info->type;
   do {
-    Type u = bin->rhs->type;
+    Type u = bin->rhs->info->type;
     do {
       const m_str str = get_type_name(env, u->name, 1);
       if(str && !strcmp(t->name, str))
-        return bin->lhs->type;
+        return bin->lhs->info->type;
     } while((u = u->e->parent));
   } while((t = t->e->parent));
   return env->gwion->type[et_null];
@@ -39,8 +40,8 @@ static INSTR(instr_ptr_assign) {
 
 static OP_CHECK(opck_ptr_deref) {
   const Exp_Unary* unary = (Exp_Unary*)data;
-  DECL_ON(const m_str, str, = get_type_name(env, unary->exp->type->name, 1))
-  return exp_self(unary)->type = nspc_lookup_type1(env->curr, insert_symbol(str));
+  DECL_ON(const m_str, str, = get_type_name(env, unary->exp->info->type->name, 1))
+  return exp_self(unary)->info->type = nspc_lookup_type1(env->curr, insert_symbol(str));
 }
 
 static OP_CHECK(opck_ptr_cast) {
@@ -49,7 +50,7 @@ static OP_CHECK(opck_ptr_cast) {
   if(!GET_FLAG(t, check))
     CHECK_BN(traverse_class_def(env, t->e->def))
   const Type to = known_type(env, cast->td->types->td);
-  if(isa(cast->exp->type, to) > 0)
+  if(isa(cast->exp->info->type, to) > 0)
     return t;
   ERR_N(exp_self(cast)->pos, "invalid pointer cast")
 }
@@ -57,11 +58,12 @@ static OP_CHECK(opck_ptr_cast) {
 static OP_CHECK(opck_ptr_implicit) {
   const struct Implicit* imp = (struct Implicit*)data;
   const Exp e = imp->e;
-  if(!strcmp(get_type_name(env, imp->t->name, 1), e->type->name)) {
-    if(e->meta == ae_meta_value)
-      ERR_N(e->pos, _("can't cast constant to Ptr"));
-    e->cast_to = imp->t;
-    e->emit_var = 1;
+  if(!strcmp(get_type_name(env, imp->t->name, 1), e->info->type->name)) {
+    const m_str access = exp_access(e);
+    if(access)
+      ERR_N(e->pos, _("can't cast %s value to Ptr"), access);
+    e->info->cast_to = imp->t;
+    exp_setvar(e, 1);
     if(!GET_FLAG(imp->t, check))
       CHECK_BN(traverse_class_def(env, imp->t->e->def))
     return imp->t;
@@ -90,7 +92,7 @@ static INSTR(Cast2Ptr) {
 static OP_EMIT(opem_ptr_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
   const Instr instr = emit_add_instr(emit, Cast2Ptr);
-  instr->m_val = (m_uint)exp_self(cast)->type;
+  instr->m_val = (m_uint)exp_self(cast)->info->type;
   return instr;
 }
 
@@ -104,8 +106,8 @@ static OP_EMIT(opem_ptr_implicit) {
 static OP_EMIT(opem_ptr_deref) {
   const Exp_Unary* unary = (Exp_Unary*)data;
   const Instr instr = emit_add_instr(emit, instr_ptr_deref);
-  instr->m_val = exp_self(unary)->type->size;
-  instr->m_val2 = exp_self(unary)->emit_var;
+  instr->m_val = exp_self(unary)->info->type->size;
+  instr->m_val2 = exp_getvar(exp_self(unary));
   return instr;
 }
 
index 7f2f8070804cc327f44a82ce56f03c4787d4037a..a6cc60625582d2de8438899f38bfb610ee9399b7 100644 (file)
@@ -22,7 +22,7 @@ ANN static void push_string(const VM_Shred shred, const M_Object obj, const m_st
 }
 
 #define describe_string_logical(name, action)    \
-static INSTR(String_##name) {\
+static INSTR(String_##name) {                    \
   POP_REG(shred, SZ_INT);                        \
   const M_Object lhs = *(M_Object*)REG(-SZ_INT); \
   const M_Object rhs = *(M_Object*)REG(0);       \
index d4c4dc182acee94f09816daebd07b20a8ed10dd2..73d8f79b0b91e152dec001b63546d78570348867 100644 (file)
@@ -316,7 +316,7 @@ static GWION_IMPORT(global_ugens) {
 
 static OP_CHECK(opck_chuck_ugen) {
   const Exp_Binary* bin = (Exp_Binary*)data;
-  return bin->rhs->type;
+  return bin->rhs->info->type;
 }
 
 GWION_IMPORT(ugen) {
index b6b37f2ed5a2d7c9ef6e92e43ee2a43c9cfcfe39..25fbb5faeb3beed54ee3e8dce85e64273f4b062a 100644 (file)
@@ -107,9 +107,9 @@ static INSTR(VarargCast) {
 static OP_EMIT(opem_vararg_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
   const Instr instr = emit_add_instr(emit, VarargCast);
-  instr->m_val = (m_uint)exp_self(cast)->type;
+  instr->m_val = (m_uint)exp_self(cast)->info->type;
   const Instr push = emit_add_instr(emit, RegPush);
-  push->m_val = exp_self(cast)->type->size - SZ_INT;
+  push->m_val = exp_self(cast)->info->type->size - SZ_INT;
   return instr;
 }
 
@@ -120,7 +120,7 @@ static FREEARG(freearg_vararg) {
 
 static ID_CHECK(idck_vararg) {
   if(env->func && GET_FLAG(env->func->def, variadic))
-    return type_nonnull(env, exp_self(prim)->type);
+    return type_nonnull(env, exp_self(prim)->info->type);
   ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function"))
 }
 
index 7ddc27d36c087e1ee341ba653eec4399ffea1d36..c14619689df2d7ce0cf89a3d4c30a9811d764954 100644 (file)
@@ -18,12 +18,12 @@ static void sig(int unused NUSED) {
 #ifdef __AFL_HAVE_MANUAL_CONTROL
 
 ANN static void gwion_reset(const Gwion gwion) {
-  release_ctx(gwion->env->scope, gwion);
   pop_global(gwion);
   push_global(gwion, "[user]");
 }
 
-#define BUFSIZE 1024
+//#define BUFSIZE 1024
+#define BUFSIZE 256
 
 static void afl_run(const Gwion gwion) {
   char buf[BUFSIZE];
index dd6410d8ad3ee68c2d4ac87708663c745fedbfee..1298b859abe8f601dd5540140c6b19f441ccad33 100644 (file)
@@ -21,15 +21,15 @@ ANN m_bool check_class_def(const Env env, const Class_Def class_def);
 ANN static m_bool check_internal(const Env env, const Symbol sym,
       const Exp e, const Type t) {
   struct Implicit imp = { .e=e, .t=t, .pos=e->pos };
-  struct Op_Import opi = { .op=sym, .lhs=e->type,
-        .rhs=t, .data=(uintptr_t)&imp, .pos=e->pos };
+  struct Op_Import opi = { .op=sym, .lhs=e->info->type,
+        .rhs=t, .data=(uintptr_t)&imp, .pos=e->pos, .op_type=op_implicit };
   CHECK_OB(op_check(env, &opi))
   assert(e->nspc);
   return GW_OK;
 }
 
 ANN m_bool check_implicit(const Env env, const Exp e, const Type t) {
-  if(e->type == t)
+  if(e->info->type == t)
     return GW_OK;
   const Symbol sym = insert_symbol("@implicit");
   return check_internal(env, sym, e, t);
@@ -93,7 +93,7 @@ ANN Type check_td(const Env env, Type_Decl *td) {
   CHECK_BO(scan1_exp(env, td->exp))
   CHECK_BO(scan2_exp(env, td->exp))
   CHECK_OO(check_exp(env, td->exp))
-  const Type t = actual_type(env->gwion, td->exp->type);
+  const Type t = actual_type(env->gwion, td->exp->info->type);
   assert(t);
   if(GET_FLAG(t, template) && !GET_FLAG(t, ref))
     ERR_O(td_pos(td), _("type '%s' needs template types"), t->name)
@@ -130,10 +130,10 @@ ANN static m_bool check_var_td(const Env env, const Var_Decl var, Type_Decl *con
   if(env->class_def)  {
     if(GET_FLAG(td, member)) {
       decl_member(env, v);
-      if(isa(env->class_def, env->gwion->type[et_object]) > 0)
+      if(env->class_def->e->tuple)
         tuple_info(env, td, var);
     } else if(GET_FLAG(td, static))
-      decl_static(env, v);
+        decl_static(env, v);
   } else if(GET_FLAG(td, global) || (env->func && GET_FLAG(env->func->def, global)))
     SET_FLAG(v, abstract);
   return GW_OK;
@@ -181,12 +181,12 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
 
 
 ANN static inline void set_cast(const Env env, Type type, const Exp e) {
-  e->cast_to = type;
-  e->nspc = env->curr;
+  e->info->cast_to = type;
+  e->info->nspc = env->curr;
 }
 
 ANN static m_bool prim_array_inner(const Env env, Type type, const Exp e) {
-  const Type common = find_common_anc(e->type, type);
+  const Type common = find_common_anc(e->info->type, type);
   if(common)
     return GW_OK;
   if(check_implicit(env, e, type) < 0)
@@ -196,7 +196,7 @@ ANN static m_bool prim_array_inner(const Env env, Type type, const Exp e) {
 }
 
 ANN static inline Type prim_array_match(const Env env, Exp e) {
-  const Type type = e->type;
+  const Type type = e->info->type;
   do CHECK_BO(prim_array_inner(env, type, e))
   while((e = e->next));
   return array_type(env, type->array_depth ? array_base(type) : type, type->array_depth + 1);
@@ -217,7 +217,7 @@ ANN static m_bool check_range(const Env env, Range *range) {
   if(range->end)
     CHECK_OB(check_exp(env, range->end))
   if(range->start && range->end) {
-    if(isa(range->end->type, range->start->type) < 0)
+    if(isa(range->end->info->type, range->start->info->type) < 0)
       ERR_B(range->start->pos, _("range types do not match"))
   }
   return GW_OK;
@@ -228,7 +228,7 @@ ANN static Type check_prim_range(const Env env, Range **data) {
   CHECK_BO(check_range(env, range))
   const Exp e = range->start ?: range->end;
   const Symbol sym = insert_symbol("@range");
-  struct Op_Import opi = { .op=sym, .rhs=e->type, .pos=e->pos, .data=(uintptr_t)prim_exp(data) };
+  struct Op_Import opi = { .op=sym, .rhs=e->info->type, .pos=e->pos, .data=(uintptr_t)prim_exp(data), .op_type=op_exp };
   return op_check(env, &opi);
 }
 
@@ -266,7 +266,8 @@ ANN static Value check_non_res_value(const Env env, const Symbol *data) {
 ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data);
 
 ANN static Type check_dot(const Env env, const Exp_Dot *member) {
-  struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, .data=(uintptr_t)member, .pos=exp_self(member)->pos };
+  struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, .data=(uintptr_t)member,
+    .pos=exp_self(member)->pos, .op_type=op_dot };
   return op_check(env, &opi);
 }
 
@@ -284,11 +285,11 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) {
   SET_FLAG(v, used);
   prim_self(data)->value = v;
   if(GET_FLAG(v, const))
-    prim_exp(data)->meta = ae_meta_value;
+    exp_setmeta(prim_exp(data), 1);
   if(v->from->owner_class) {
     const Exp exp  = symbol_owned_exp(env->gwion, data);
     const Type ret = check_dot(env, &exp->d.exp_dot);
-    prim_exp(data)->nspc = exp->nspc;
+    prim_exp(data)->info->nspc = exp->info->nspc;
     free_exp(env->gwion->mp, exp);
     CHECK_OO(ret);
   }
@@ -330,12 +331,13 @@ describe_prim_xxx(nil, env->gwion->type[et_void])
 DECL_PRIM_FUNC(check, Type, Env);
 
 ANN static Type check_prim(const Env env, Exp_Primary *prim) {
-  return exp_self(prim)->type = check_prim_func[prim->prim_type](env, &prim->d);
+  return exp_self(prim)->info->type = check_prim_func[prim->prim_type](env, &prim->d);
 }
 
 ANN Type check_array_access(const Env env, const Array_Sub array) {
   const Symbol sym = insert_symbol("@array");
-  struct Op_Import opi = { .op=sym, .lhs=array->exp->type, .rhs=array->type, .pos=array->exp->pos, .data=(uintptr_t)array };
+  struct Op_Import opi = { .op=sym, .lhs=array->exp->info->type, .rhs=array->type,
+    .pos=array->exp->pos, .data=(uintptr_t)array, .op_type=op_array };
   return op_check(env, &opi);
 }
 
@@ -350,7 +352,8 @@ static ANN Type check_exp_slice(const Env env, const Exp_Slice* range) {
   CHECK_BO(check_range(env, range->range))
   const Symbol sym = insert_symbol("@slice");
   const Exp e = range->range->start ?: range->range->end;
-  struct Op_Import opi = { .op=sym, .lhs=range->base->type, .rhs=e->type, .pos=e->pos, .data=(uintptr_t)exp_self(range) };
+  struct Op_Import opi = { .op=sym, .lhs=range->base->info->type, .rhs=e->info->type,
+    .pos=e->pos, .data=(uintptr_t)exp_self(range), .op_type=op_exp };
   return op_check(env, &opi);
 }
 
@@ -381,15 +384,15 @@ ANN static Type_List mk_type_list(const Env env, const Type type, const loc_t po
 
 ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t,
   const m_bool implicit, const m_bool specific) {
-  const m_bool match = (specific ? e->type == t : isa(e->type, t) > 0) &&
-    e->type->array_depth == t->array_depth &&
-    array_base(e->type) == array_base(t);
+  const m_bool match = (specific ? e->info->type == t : isa(e->info->type, t) > 0) &&
+    e->info->type->array_depth == t->array_depth &&
+    array_base(e->info->type) == array_base(t);
     if(!match) {
-      if(e->type == env->gwion->type[et_lambda] && is_fptr(env->gwion, t)) {
+      if(e->info->type == env->gwion->type[et_lambda] && is_fptr(env->gwion, t)) {
         const Type owner = nspc_lookup_type1(t->e->owner->parent,
           insert_symbol(t->e->owner->name));
         const m_bool ret = check_lambda(env, owner, &e->d.exp_lambda, t->e->d.func->def);
-//        e->emit_var = 1;
+//        exp_setvar(e, 1);
         return ret;
       }
       if(implicit)
@@ -432,7 +435,7 @@ ANN2(1,2) static Func find_func_match_actual(const Env env, Func func, const Exp
 
 ANN2(1, 2) static Func find_func_match(const Env env, const Func up, const Exp exp) {
   Func func;
-  const Exp args = (exp && isa(exp->type, env->gwion->type[et_void]) < 0) ? exp : NULL;
+  const Exp args = (exp && isa(exp->info->type, env->gwion->type[et_void]) < 0) ? exp : NULL;
   if((func = find_func_match_actual(env, up, args, 0, 1)) ||
      (func = find_func_match_actual(env, up, args, 1, 1)) ||
      (func = find_func_match_actual(env, up, args, 0, 0)) ||
@@ -500,7 +503,7 @@ ANN static Func _find_template_match(const Env env, const Value v, const Exp_Cal
     if(exists)
       m_func = exists->e->d.func;
     else {
-      Func_Def base = v->d.func_ref ? v->d.func_ref->def : exp->func->type->e->d.func->def;
+      Func_Def base = v->d.func_ref ? v->d.func_ref->def : exp->func->info->type->e->d.func->def;
       Func_Base *fbase = cpy_func_base(env->gwion->mp, base->base);
       fbase->xid = sym;
       fbase->tmpl->base = 0;
@@ -584,7 +587,7 @@ next_arg(Arg_List)
 
 ANN static void print_current_args(Exp e) {
   gw_err(_("and not\n  "));
-  do gw_err(" \033[32m%s\033[0m", e->type->name);
+  do gw_err(" \033[32m%s\033[0m", e->info->type->name);
   while((e = next_arg_Exp(e)));
   gw_err("\n");
 }
@@ -624,7 +627,7 @@ ANN static Func get_template_func(const Env env, const Exp_Call* func, const Val
   const Func f = find_template_match(env, v, func);
   if(f) {
     Tmpl* tmpl = new_tmpl_call(env->gwion->mp, func->tmpl->call);
-    tmpl->list = v->d.func_ref ? v->d.func_ref->def->base->tmpl->list : func->func->type->e->d.func->def->base->tmpl->list;
+    tmpl->list = v->d.func_ref ? v->d.func_ref->def->base->tmpl->list : func->func->info->type->e->d.func->def->base->tmpl->list;
     ((Exp_Call*)func)->tmpl = tmpl;
     return ((Exp_Call*)func)->m_func = f;
   }
@@ -668,7 +671,7 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp, const Tmp
       char path[id_list_len(arg->td->xid)];
       type_path(path, arg->td->xid);
       if(!strcmp(s_name(list->xid), path)) {
-        tl[args_number] = mk_type_list(env, template_arg->type, fdef->pos);
+        tl[args_number] = mk_type_list(env, template_arg->info->type, fdef->pos);
         if(args_number)
           tl[args_number - 1]->next = tl[args_number];
         ++args_number;
@@ -685,7 +688,7 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp, const Tmp
 }
 
 ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) {
-  const Type t = exp->func->type;
+  const Type t = exp->func->info->type;
   DECL_OO(const Value, value, = nspc_lookup_value1(t->e->owner, insert_symbol(t->name)))
   const Func_Def fdef = value->d.func_ref ? value->d.func_ref->def : t->e->d.func->def;
   Tmpl *tm = fdef->base->tmpl;
@@ -705,7 +708,7 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
   Arg_List arg = l->def->base->args;
   Exp e = exp->args;
   while(arg && e) {
-    arg->type = e->type;
+    arg->type = e->info->type;
     arg = arg->next;
     e = e->next;
   }
@@ -720,34 +723,35 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
 
 ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
   CHECK_OO(check_exp(env, exp->func))
-  if(isa(exp->func->type, env->gwion->type[et_function]) < 0) {
+  if(isa(exp->func->info->type, env->gwion->type[et_function]) < 0) {
     // use func flag?
-    if(isa(exp->func->type, env->gwion->type[et_class]) < 0)
+    if(isa(exp->func->info->type, env->gwion->type[et_class]) < 0)
       ERR_O(exp->func->pos, _("function call using a non-function value"))
 //    if(exp->args)
 //      CHECK_OO(check_exp(env, exp->args))
-    struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp->func->type->e->d.base_type, .data=(uintptr_t)exp, .pos=exp_self(exp)->pos };
+    struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp->func->info->type->e->d.base_type,
+      .data=(uintptr_t)exp, .pos=exp_self(exp)->pos, .op_type=op_exp };
     const Type t = op_check(env, &opi);
-    exp_self(exp)->nspc = t ? t->e->owner : NULL;
+    exp_self(exp)->info->nspc = t ? t->e->owner : NULL;
     return t;
   }
-  if(exp->func->type == env->gwion->type[et_lambda])
+  if(exp->func->info->type == env->gwion->type[et_lambda])
     return check_lambda_call(env, exp);
-  if(GET_FLAG(exp->func->type->e->d.func, ref)) {
-    const Value value = exp->func->type->e->d.func->value_ref;
+  if(GET_FLAG(exp->func->info->type->e->d.func, ref)) {
+    const Value value = exp->func->info->type->e->d.func->value_ref;
     if(value->from->owner_class && !GET_FLAG(value->from->owner_class, check))
       CHECK_BO(traverse_class_def(env, value->from->owner_class->e->def))
   }
   if(exp->args)
     CHECK_OO(check_exp(env, exp->args))
-  if(GET_FLAG(exp->func->type, func))
+  if(GET_FLAG(exp->func->info->type, func))
     return check_exp_call_template(env, (Exp_Call*)exp);
-  const Func func = find_func_match(env, exp->func->type->e->d.func, exp->args);
+  const Func func = find_func_match(env, exp->func->info->type->e->d.func, exp->args);
   if((exp_self(exp)->d.exp_call.m_func = func)) {
-    exp->func->type = func->value_ref->type;
+    exp->func->info->type = func->value_ref->type;
     return func->def->base->ret_type;
   }
-  function_alternative(env, exp->func->type, exp->args, exp_self(exp)->pos);
+  function_alternative(env, exp->func->info->type, exp->args, exp_self(exp)->pos);
   return NULL;
 }
 
@@ -755,10 +759,10 @@ ANN static Type check_exp_binary(const Env env, const Exp_Binary* bin) {
   CHECK_OO(check_exp(env, bin->lhs))
   const m_bool is_auto = bin->rhs->exp_type == ae_exp_decl && bin->rhs->d.exp_decl.type == env->gwion->type[et_auto];
   if(is_auto)
-     bin->rhs->type = bin->rhs->d.exp_decl.type = bin->lhs->type;
+     bin->rhs->info->type = bin->rhs->d.exp_decl.type = bin->lhs->info->type;
   CHECK_OO(check_exp(env, bin->rhs))
-  struct Op_Import opi = { .op=bin->op, .lhs=bin->lhs->type,
-    .rhs=bin->rhs->type, .data=(uintptr_t)bin, .pos=exp_self(bin)->pos };
+  struct Op_Import opi = { .op=bin->op, .lhs=bin->lhs->info->type,
+    .rhs=bin->rhs->info->type, .data=(uintptr_t)bin, .pos=exp_self(bin)->pos, .op_type=op_binary };
   const Type ret = op_check(env, &opi);
   if(!ret && is_auto)
     bin->rhs->d.exp_decl.list->self->value->type = env->gwion->type[et_auto];
@@ -767,17 +771,19 @@ ANN static Type check_exp_binary(const Env env, const Exp_Binary* bin) {
 
 ANN static Type check_exp_cast(const Env env, const Exp_Cast* cast) {
   DECL_OO(const Type, t, = check_exp(env, cast->exp))
-  CHECK_OO((exp_self(cast)->type = cast->td->xid ? known_type(env, cast->td) : check_td(env, cast->td)))
-  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=t, .rhs=exp_self(cast)->type, .data=(uintptr_t)cast, .pos=exp_self(cast)->pos };
+  CHECK_OO((exp_self(cast)->info->type = cast->td->xid ? known_type(env, cast->td) : check_td(env, cast->td)))
+  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=t, .rhs=exp_self(cast)->info->type,
+    .data=(uintptr_t)cast, .pos=exp_self(cast)->pos, .op_type=op_cast };
   return op_check(env, &opi);
 }
 
 ANN static Type check_exp_post(const Env env, const Exp_Postfix* post) {
-  struct Op_Import opi = { .op=post->op, .lhs=check_exp(env, post->exp), .data=(uintptr_t)post, .pos=exp_self(post)->pos };
+  struct Op_Import opi = { .op=post->op, .lhs=check_exp(env, post->exp),
+    .data=(uintptr_t)post, .pos=exp_self(post)->pos, .op_type=op_postfix };
   CHECK_OO(opi.lhs)
   const Type t = op_check(env, &opi);
   if(t && isa(t, env->gwion->type[et_object]) < 0)
-    exp_self(post)->meta = ae_meta_value;
+    exp_setmeta(exp_self(post), 1);
   return t;
 }
 
@@ -797,10 +803,10 @@ ANN static m_bool predefined_call(const Env env, const Type t, const loc_t pos)
 ANN static Type check_exp_call(const Env env, Exp_Call* exp) {
   if(exp->tmpl) {
     CHECK_OO(check_exp(env, exp->func))
-    const Type t = actual_type(env->gwion, !GET_FLAG(exp->func->type, nonnull) ?
-       exp->func->type : exp->func->type->e->parent);
+    const Type t = actual_type(env->gwion, !GET_FLAG(exp->func->info->type, nonnull) ?
+       exp->func->info->type : exp->func->info->type->e->parent);
     const Value v = nspc_lookup_value1(t->e->owner, insert_symbol(t->name));
-    if(!GET_FLAG(v, func) && !GET_FLAG(exp->func->type, func) )
+    if(!GET_FLAG(v, func) && !GET_FLAG(exp->func->info->type, func) )
       ERR_O(exp_self(exp)->pos, _("template call of non-function value."))
     if(!v->d.func_ref || !v->d.func_ref->def->base->tmpl)
       ERR_O(exp_self(exp)->pos, _("template call of non-template function."))
@@ -822,7 +828,7 @@ ANN static Type check_exp_call(const Env env, Exp_Call* exp) {
 
 ANN static Type check_exp_unary(const Env env, const Exp_Unary* unary) {
   struct Op_Import opi = { .op=unary->op, .rhs=unary->exp ? check_exp(env, unary->exp) : NULL,
-    .data=(uintptr_t)unary, .pos=exp_self(unary)->pos };
+    .data=(uintptr_t)unary, .pos=exp_self(unary)->pos, .op_type=op_unary };
   if(unary->exp && !opi.rhs)
     return NULL;
   return op_check(env, &opi);
@@ -831,7 +837,7 @@ ANN static Type check_exp_unary(const Env env, const Exp_Unary* unary) {
 ANN static Type _flow(const Env env, const Exp e, const m_bool b) {
   DECL_OO(const Type, type, = check_exp(env, e))
   struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"),
-    .rhs=type, .pos=e->pos, .data=(uintptr_t)e };
+    .rhs=type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp };
   return op_check(env, &opi);
 }
 #define check_flow(emit,b) _flow(emit, b, 1)
@@ -875,12 +881,12 @@ DECL_EXP_FUNC(check, Type, Env)
 ANN Type check_exp(const Env env, const Exp exp) {
   Exp curr = exp;
   do {
-    CHECK_OO((curr->type = check_exp_func[curr->exp_type](env, &curr->d)))
-    if(env->func && isa(curr->type, env->gwion->type[et_lambda]) < 0 && isa(curr->type, env->gwion->type[et_function]) > 0 &&
-        !GET_FLAG(curr->type->e->d.func, pure))
+    CHECK_OO((curr->info->type = check_exp_func[curr->exp_type](env, &curr->d)))
+    if(env->func && isa(curr->info->type, env->gwion->type[et_lambda]) < 0 && isa(curr->info->type, env->gwion->type[et_function]) > 0 &&
+        !GET_FLAG(curr->info->type->e->d.func, pure))
       UNSET_FLAG(env->func, pure);
   } while((curr = curr->next));
-  return exp->type;
+  return exp->info->type;
 }
 
 ANN m_bool check_enum_def(const Env env, const Enum_Def edef) {
@@ -899,9 +905,9 @@ ANN static m_bool check_stmt_code(const Env env, const Stmt_Code stmt) {
 
 ANN static m_bool check_stmt_varloop(const Env env, const Stmt_VarLoop stmt) {
   CHECK_OB(check_exp(env, stmt->exp))
-  if(isa(stmt->exp->type, env->gwion->type[et_vararg]) < 0)
+  if(isa(stmt->exp->info->type, env->gwion->type[et_vararg]) < 0)
     ERR_B(stmt->exp->pos, "varloop expression type must be '%s', not '%s'",
-      env->gwion->type[et_vararg]->name, stmt->exp->type->name)
+      env->gwion->type[et_vararg]->name, stmt->exp->info->type->name)
   return check_stmt(env, stmt->body);
 }
 
@@ -939,7 +945,7 @@ ANN static m_bool do_stmt_auto(const Env env, const Stmt_Auto stmt) {
   const m_uint depth = t->array_depth - 1;
   if(!ptr || isa(t, env->gwion->type[et_array]) < 0)
     ERR_B(stmt_self(stmt)->pos, _("type '%s' is not array.\n"
-          " This is not allowed in auto loop"), stmt->exp->type->name)
+          " This is not allowed in auto loop"), stmt->exp->info->type->name)
   if(stmt->is_ptr) {
     struct ID_List_   id0, id;
     struct Type_List_ tl;
@@ -1057,8 +1063,8 @@ ANN m_bool check_union_decl(const Env env, const Union_Def udef) {
     Var_Decl_List list = l->self->d.exp_decl.list;
     do SET_FLAG(list->self->value, pure);
     while((list = list->next));
-    if(l->self->type->size > udef->s)
-      udef->s = l->self->type->size;
+    if(l->self->info->type->size > udef->s)
+      udef->s = l->self->info->type->size;
   } while((l = l->next));
   return GW_OK;
 }
@@ -1095,7 +1101,7 @@ ANN static m_bool check_stmt_exp(const Env env, const Stmt_Exp stmt) {
 ANN static Value match_value(const Env env, const Exp_Primary* prim, const m_uint i) {
   const Symbol sym = prim->d.var;
   const Value v = new_value(env->gwion->mp,
-     ((Exp)VKEY(&env->scope->match->map, i))->type, s_name(sym));
+     ((Exp)VKEY(&env->scope->match->map, i))->info->type, s_name(sym));
   SET_FLAG(v, checked);
   nspc_add_value(env->curr, sym, v);
   VVAL(&env->scope->match->map, i) = (vtype)v;
@@ -1123,10 +1129,12 @@ ANN static m_bool match_case_exp(const Env env, Exp e) {
       const Exp base = (Exp)VKEY(&env->scope->match->map, i);
       CHECK_OB(check_exp(env, e))
       Exp_Binary bin = { .lhs=base, .rhs=e, .op=op };
-      struct Exp_ ebin = { .d={.exp_binary=bin}, .nspc=env->curr};
-      struct Op_Import opi = { .op=op, .lhs=base->type, .rhs=e->type, .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos };
+      struct ExpInfo_ info = { .nspc=env->curr };
+      struct Exp_ ebin = { .d={.exp_binary=bin}, .info=&info };
+      struct Op_Import opi = { .op=op, .lhs=base->info->type, .rhs=e->info->type,
+        .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos, .op_type=op_binary };
       CHECK_OB(op_check(env, &opi))
-      e->nspc= ebin.nspc;
+      e->info->nspc= info.nspc;
       return GW_OK;
     }
   }
@@ -1335,8 +1343,9 @@ if(GET_FLAG(cdef->base.type, checked))return GW_OK;
   SET_FLAG(type, check);
   if(cdef->base.ext)
     CHECK_BB(cdef_parent(env, cdef))
-  assert(type->e->parent);
-  inherit(type);
+  assert(type->e->parent || GET_FLAG(cdef, struct));
+  if(!GET_FLAG(cdef, struct))
+    inherit(type);
   if(cdef->body)
     CHECK_BB(env_body(env, cdef, check_section))
   SET_FLAG(type, checked);
index 85a87c1c459284c4c99334e6114196ff22b24e91..d74345e3d8acc3d617b9d8706dbc37a0dc35a815 100644 (file)
@@ -95,7 +95,6 @@ ANN static M_Operator* new_mo(MemPool p, const struct Op_Import* opi) {
     mo->ck     = opi->func->ck;
     mo->em     = opi->func->em;
   }
-  mo->emit_var = opi->emit_var;
   return mo;
 }
 
@@ -148,28 +147,84 @@ ANN m_bool add_op(const Gwion gwion, const struct Op_Import* opi) {
   return GW_OK;
 }
 
-ANN static void set_nspc(struct OpChecker* ock, const Nspc nspc) {
-  if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@array")) {
-    Array_Sub array = (Array_Sub)ock->opi->data;
-    array->exp->nspc = nspc;
+ANN static void set_nspc(struct Op_Import *opi, const Nspc nspc) {
+  if(opi->op_type == op_implicit) {
+    struct Implicit* imp = (struct Implicit*)opi->data;
+    imp->e->info->nspc = nspc;
     return;
-
   }
-  if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@implicit")) {
-    struct Implicit* imp = (struct Implicit*)ock->opi->data;
-    imp->e->nspc = nspc;
+  if(opi->op_type == op_array) {
+    Array_Sub array = (Array_Sub)opi->data;
+    array->exp->info->nspc = nspc;
     return;
   }
-  if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@slice")        ||
-     ock->opi->op == insert_symbol(ock->env->gwion->st, "@range")   ||
-     ock->opi->op == insert_symbol(ock->env->gwion->st, "@conditionnal") ||
-     ock->opi->op == insert_symbol(ock->env->gwion->st, "@unconditionnal")) {
-    ((Exp)ock->opi->data)->nspc = nspc;
+  if(opi->op_type == op_exp) {
+    ((Exp)opi->data)->info->nspc = nspc;
     return;
   }
-// use .mut
-  if(ock->opi->op != insert_symbol(ock->env->gwion->st, "@scan"))
-    exp_self((union exp_data*)ock->opi->data)->nspc = nspc;
+  if(opi->op_type != op_scan)
+    exp_self((union exp_data*)opi->data)->info->nspc = nspc;
+}
+
+ANN static void set_nonnull(const Type t, const Exp exp) {
+  if(t != OP_ANY_TYPE && GET_FLAG(t, nonnull))
+    exp_setnonnull(exp, 1);
+}
+
+ANN static void opi_nonnull(const M_Operator *mo, const struct Op_Import *opi) {
+  switch(opi->op_type) {
+    case op_implicit:
+    {
+      const struct Implicit *a = (struct Implicit*)opi->data;
+      set_nonnull(mo->lhs, a->e);
+      break;
+    }
+    case op_exp:
+    {
+      const Exp a = (Exp)opi->data;
+      set_nonnull(mo->rhs, a); // rhs ???
+      break;
+    }
+    case op_dot:
+    {
+      const Exp_Dot *a = (Exp_Dot*)opi->data;
+      set_nonnull(mo->lhs, a->base);
+      break;
+    }
+    case op_array:
+    {
+      const Array_Sub a = (Array_Sub)opi->data;
+      set_nonnull(mo->lhs, a->exp);
+      break;
+    }
+    case op_binary:
+    {
+      const Exp_Binary *a = (Exp_Binary*)opi->data;
+      set_nonnull(mo->lhs, a->lhs);
+      set_nonnull(mo->rhs, a->rhs);
+      break;
+    }
+    case op_cast:
+    {
+      const Exp_Cast *a = (Exp_Cast*)opi->data;
+      set_nonnull(mo->lhs, a->exp);
+      break;
+    }
+    case op_postfix:
+    {
+      const Exp_Postfix *a = (Exp_Postfix*)opi->data;
+      set_nonnull(mo->lhs, a->exp);
+      break;
+    }
+    case op_unary:
+    {
+      const Exp_Unary *a = (Exp_Unary*)opi->data;
+      set_nonnull(mo->rhs, a->exp);
+      break;
+    }
+    case op_scan:
+      break;
+  }
 }
 
 ANN static Type op_check_inner(struct OpChecker* ock) {
@@ -178,6 +233,7 @@ ANN static Type op_check_inner(struct OpChecker* ock) {
     const M_Operator* mo;
     const Vector v = (Vector)map_get(ock->map, (vtype)ock->opi->op);
     if(v && (mo = operator_find(v, ock->opi->lhs, r))) {
+      opi_nonnull(mo, ock->opi);
       if((mo->ck && (t = mo->ck(ock->env, (void*)ock->opi->data, &ock->mut))))
         return t;
       else
@@ -193,14 +249,14 @@ ANN Type op_check(const Env env, struct Op_Import* opi) {
     if(nspc->info->op_map.ptr) {
       Type l = opi->lhs;
       do {
-        struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data };
+        struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data, .op_type=opi->op_type };
         struct OpChecker ock = { env, &nspc->info->op_map, &opi2, 0 };
         const Type ret = op_check_inner(&ock);
         if(ret) {
           if(ret == env->gwion->type[et_null])
             break;
           if(!ock.mut)
-            set_nspc(&ock, nspc);
+            set_nspc(&opi2, nspc);
           return ret;
         }
       } while(l && (l = op_parent(env, l)));
@@ -236,52 +292,38 @@ ANN static Instr handle_instr(const Emitter emit, const M_Operator* mo) {
   return emit_add_instr(emit, mo->instr);
 }
 
-ANN static Nspc get_nspc(SymTable *st, const struct Op_Import* opi) {
-  if(opi->op == insert_symbol(st, "@array")) {
-    struct ArrayAccessInfo *info = (struct ArrayAccessInfo*)opi->data;
-    return info->array.exp->nspc;
-  }
-  if(opi->op == insert_symbol(st, "@implicit")) {
+ANN static Nspc get_nspc(const struct Op_Import* opi) {
+  if(opi->op_type == op_implicit) {
     struct Implicit* imp = (struct Implicit*)opi->data;
-    return imp->e->nspc;
+    return imp->e->info->nspc;
   }
-  if(opi->op == insert_symbol(st, "@range")   ||
-     opi->op == insert_symbol(st, "@slice")        ||
-     opi->op == insert_symbol(st, "@conditionnal") ||
-     opi->op == insert_symbol(st, "@unconditionnal"))
-    return ((Exp)opi->data)->nspc;
-  return exp_self((union exp_data*)opi->data)->nspc;
+  if(opi->op_type == op_array) {
+    struct ArrayAccessInfo *info = (struct ArrayAccessInfo*)opi->data;
+    return info->array.exp->info->nspc;
+  }
+  if(opi->op_type == op_exp)
+    return ((Exp)opi->data)->info->nspc;
+  return exp_self((union exp_data*)opi->data)->info->nspc;
 }
 
-ANN static inline Nspc ensure_nspc(SymTable *st, const struct Op_Import* opi) {
-  DECL_OO(Nspc, nspc, = get_nspc(st, opi))
+ANN static inline Nspc ensure_nspc(const struct Op_Import* opi) {
+  DECL_OO(Nspc, nspc, = get_nspc(opi))
   while(!nspc->info->op_map.ptr)
     nspc = nspc->parent;
   return nspc;
 }
 
-ANN2(1) void op_emit_nonnull(const Emitter emit, const Type mo, const Type opi, const m_uint offset) {
-  if(!mo || mo == OP_ANY_TYPE)
-    return;
-  if(GET_FLAG(mo, nonnull) && !GET_FLAG(opi, nonnull)) {
-    const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
-    instr->m_val = offset;
-   }
-}
-
 ANN Instr op_emit(const Emitter emit, const struct Op_Import* opi) {
-  DECL_OO(Nspc, nspc, = ensure_nspc(emit->gwion->st, opi))
+  DECL_OO(Nspc, nspc, = ensure_nspc(opi))
   Type l = opi->lhs;
   do {
     Type r = opi->rhs;
     do {
       const Vector v = (Vector)map_get(&nspc->info->op_map, (vtype)opi->op);
-      if(!v)continue;
+      if(!v)
+        continue;
       const M_Operator* mo = operator_find(v, l, r);
       if(mo) {
-        const m_uint sz = opi->rhs ? opi->rhs->size : 0;
-        op_emit_nonnull(emit, mo->lhs, opi->lhs, mo->emit_var ?: sz);
-        op_emit_nonnull(emit, mo->rhs, opi->rhs, 0);
         if(mo->em)
           return mo->em(emit, (void*)opi->data);
         return handle_instr(emit, mo);
index b9fbc2425f7084d95d049201e9e020e3dd97d8d9..2b660dfb5d6696fbf23a7c675227cb1e735ef8f3 100644 (file)
@@ -11,6 +11,7 @@
 #include "instr.h"
 #include "operator.h"
 #include "import.h"
+#include "tuple.h"
 
 static inline void add_type(const Env env, const Nspc nspc, const Type t) {
   nspc_add_type_front(nspc, insert_symbol(t->name), t);
@@ -109,13 +110,13 @@ if(fptr->base->tmpl && fptr->base->args) {
 }
 
 static OP_CHECK(opck_implicit_similar) {
-  const Exp_Binary *bin = (Exp_Binary*)data;
-  return bin->rhs->type;
+  const struct Implicit *imp = (struct Implicit*)data;
+  return imp->e->info->type;
 }
 
 static OP_CHECK(opck_cast_similar) {
   const Exp_Cast *cast = (Exp_Cast*)data;
-  return exp_self(cast)->type;
+  return exp_self(cast)->info->type;
 }
 
 ANN static void scan0_implicit_similar(const Env env, const Type lhs, const Type rhs) {
@@ -313,7 +314,13 @@ ANN static void inherit_tmpl(const Env env, const Class_Def cdef) {
 
 ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
   CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos))
-  const Type t = scan0_type(env, ++env->scope->type_xid, s_name(cdef->base.xid), env->gwion->type[et_object]);
+  const Type parent = !GET_FLAG(cdef, struct) ? env->gwion->type[et_object] : NULL;
+  const Type t = scan0_type(env, ++env->scope->type_xid, s_name(cdef->base.xid), parent);
+  if(GET_FLAG(cdef, struct)) {
+    SET_FLAG(t, struct);
+    t->e->gack = env->gwion->type[et_object]->e->gack;
+  }
+  t->e->tuple = new_tupleform(env->gwion->mp);
   t->e->owner = env->curr;
   t->nspc = new_nspc(env->gwion->mp, t->name);
   t->nspc->parent = env->curr;
index 2dd7e81705784079c6ef12d4df5d3a4179f04292..d100f32316ad942a465c4765c46359be09b4dd1b 100644 (file)
@@ -37,7 +37,7 @@ ANN static m_bool type_recursive(const Env env, const Type_Decl *td, const Type
 ANN static Type void_type(const Env env, const Type_Decl* td) {
   DECL_OO(const Type, type, = known_type(env, td))
   const Type t = get_type(type);
-  if(isa(t, env->gwion->type[et_object]) > 0)
+  if(isa(t, env->gwion->type[et_object]) > 0 || GET_FLAG(t, struct))
     CHECK_BO(type_recursive(env, td, t))
   if(type->size)
     return type;
@@ -86,6 +86,10 @@ ANN static m_bool scan1_decl(const Env env, const Exp_Decl* decl) {
     if(env->class_def)
       type_contains(env->class_def, t);
     const Value v = var->value = former ?: new_value(env->gwion->mp, t, s_name(var->xid));
+    if(SAFE_FLAG(env->class_def, struct) && !GET_FLAG(decl->td, static)) {
+      v->from->offset = env->class_def->size;
+      env->class_def->size += t->size;
+    }
     nspc_add_value(env->curr, var->xid, v);
     v->flag = decl->td->flag;
     v->type = t;
@@ -106,7 +110,7 @@ ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) {
   ((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl);
   CHECK_OB(decl->type)
   if(GET_FLAG(decl->type, const))
-    exp_self(decl)->meta = ae_meta_value;
+    exp_setmeta(exp_self(decl), 1);
 //    SET_FLAG(decl->td, const);
   const m_bool global = GET_FLAG(decl->td, global);
   if(global && decl->type->e->owner != env->global_nspc)
@@ -159,10 +163,11 @@ ANN static inline m_bool scan1_exp_cast(const Env env, const Exp_Cast* cast) {
 
 ANN static m_bool scan1_exp_post(const Env env, const Exp_Postfix* post) {
   CHECK_BB(scan1_exp(env, post->exp))
-  if(post->exp->meta == ae_meta_var)
+  const m_str access = exp_access(post->exp);
+  if(access)
     return GW_OK;
   ERR_B(post->exp->pos, _("post operator '%s' cannot be used"
-      " on non-mutable data-type..."), s_name(post->op));
+      " on %S data-type..."), s_name(post->op), access);
 }
 
 ANN static m_bool scan1_exp_call(const Env env, const Exp_Call* exp_call) {
index c692a813c3431f3555395c474c6521589ac80354..90a2d202c23ad1498e02693789475da570743066 100644 (file)
@@ -9,7 +9,6 @@
 #include "object.h"
 #include "instr.h"
 #include "import.h"
-#include "tuple.h"
 
 ANN static m_bool scan2_stmt(const Env, const Stmt);
 ANN static m_bool scan2_stmt_list(const Env, Stmt_List);
@@ -325,16 +324,13 @@ ANN static Func scan_new_func(const Env env, const Func_Def f, const m_str name)
 ANN static Type func_type(const Env env, const Func func) {
   const Type t = type_copy(env->gwion->mp, env->gwion->type[func->def->base->td ? et_function : et_lambda]);
   t->xid = ++env->scope->type_xid;
-// = type_copy(env->gwion->mp, env->gwion->type[func->def->base->td ? et_function : et_lambda]);
   t->e->parent = env->gwion->type[func->def->base->td ? et_function : et_lambda];
   t->name = func->name;
   t->e->owner = env->curr;
   if(GET_FLAG(func, member))
     t->size += SZ_INT;
   t->e->d.func = func;
-  if(t->e->tuple)
-    free_tupleform(env->gwion->mp, t->e->tuple);
-  t->e->tuple = NULL;
+//  t->e->tuple = NULL;
   return t;
 }
 ANN2(1,2) static Value func_value(const Env env, const Func f,
index 0ae30a9fe2a51e2fa356ee5f06aad06489cf3d93..cd5beb766efdab389f6f0e3f2d5d678b08372434 100644 (file)
@@ -80,7 +80,7 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* td) {
     if(GET_FLAG(t, ref))
       return t;
     struct TemplateScan ts = { .t=t, .td=td };
-    struct Op_Import opi = { .op=insert_symbol("@scan"), .lhs=t, .data=(uintptr_t)&ts, .pos=td_pos(td) };
+    struct Op_Import opi = { .op=insert_symbol("@scan"), .lhs=t, .data=(uintptr_t)&ts, .pos=td_pos(td), .op_type=op_scan };
     return op_check(env, &opi);
   } else if(td->types)
     return maybe_func(env, t, td);
index 33ea94a271f4e6070859caff29561994ecc41b5d..2cb7dd0f467a4e94a8a0825222e54c2d6d992b3f 100644 (file)
@@ -296,10 +296,11 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
   static const void* dispatch[] = {
     &&regsetimm,
     &&regpushimm, &&regpushfloat, &&regpushother, &&regpushaddr,
-    &&regpushmem, &&regpushmemfloat, &&regpushmemother, &&regpushmemaddr,
+    &&regpushmem, &&regpushmemfloat, &&regpushmemother, &&regpushmemaddr, &&regpushmemderef,
     &&pushnow,
     &&baseint, &&basefloat, &&baseother, &&baseaddr,
-    &&regtoreg, &&regtoregaddr,
+    &&regtoreg, &&regtoregaddr, &&regtoregderef,
+    &&structmember, &&structmemberaddr,
     &&memsetimm,
     &&regpushme, &&regpushmaybe,
     &&funcreturn,
@@ -335,7 +336,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
     &&sporkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&forkend, &&sporkend,
     &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat,
     &&arrayappend, &&autoloop, &&autoloopptr, &&autoloopcount, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid,
-    &&newobj, &&addref, &&objassign, &&assign, &&remref,
+    &&newobj, &&addref, &&addrefaddr, &&objassign, &&assign, &&remref,
     &&setobj, &&except, &&allocmemberaddr, &&dotmember, &&dotfloat, &&dotother, &&dotaddr,
     &&staticint, &&staticfloat, &&staticother,
     &&dotfunc, &&dotstaticfunc, &&pushstaticcode,
@@ -400,6 +401,10 @@ regpushmemaddr:
   *(m_bit**)reg = &*(m_bit*)(mem + (m_int)VAL);
   reg += SZ_INT;
   DISPATCH()
+regpushmemderef:
+  memcpy(reg, *(m_uint**)(mem+(m_int)VAL), VAL2);
+  reg += VAL2;
+  DISPATCH()
 pushnow:
   *(m_float*)reg = vm->bbq->pos;
   reg += SZ_FLOAT;
@@ -419,7 +424,7 @@ baseother:
   reg += VAL2;
   DISPATCH();
 baseaddr:
-  *(m_bit**)reg = (shred->base + VAL);
+  *(m_uint**)reg = &*(m_uint*)(shred->base + (m_int)VAL);
   reg += SZ_INT;
   DISPATCH();
 regtoreg:
@@ -428,6 +433,15 @@ regtoreg:
 regtoregaddr:
   *(m_uint**)(reg + (m_int)VAL) = &*(m_uint*)(reg + (m_int)VAL2);
   DISPATCH()
+regtoregderef:
+  memcpy(*(m_bit**)(reg - SZ_INT), *(m_bit**)(reg + (m_int)VAL), VAL2);
+  DISPATCH()
+structmember:
+  *(m_bit**)(reg-SZ_INT) =  *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL2);
+  DISPATCH()
+structmemberaddr:
+  *(m_bit**)(reg-SZ_INT) =  &*(*(m_bit**)(reg-SZ_INT) + (m_int)VAL2);
+  DISPATCH()
 memsetimm:
   *(m_uint*)(mem+VAL) = VAL2;
   DISPATCH();
@@ -627,7 +641,7 @@ regpush:
   reg += VAL;
   DISPATCH();
 regtomem:
-  *(m_uint*)(mem+VAL) = *(m_uint*)(reg+VAL2);
+  *(m_uint*)(mem+VAL) = *(m_uint*)(reg+(m_int)VAL2);
   DISPATCH()
 regtomemother:
   memcpy(mem+VAL, reg, VAL2);
@@ -747,8 +761,12 @@ newobj:
   reg += SZ_INT;
   DISPATCH()
 addref:
-  if((a.obj = VAL ? **(M_Object**)(reg-SZ_INT) :
-    *(M_Object*)(reg-SZ_INT)))
+  a.obj = *((M_Object*)(reg+(m_int)VAL) + (m_int)VAL2);
+  goto addrefcommon;
+addrefaddr:
+  a.obj = *(*(M_Object**)(reg+(m_int)VAL) + (m_int)VAL2);
+addrefcommon:
+  if(a.obj)
     ++a.obj->ref;
   DISPATCH()
 objassign:
@@ -759,8 +777,10 @@ objassign:
   }
 assign:
   reg -= SZ_INT;
-  a.obj = *(M_Object*)(reg-SZ_INT);
-  **(M_Object**)reg = a.obj;
+//  a.obj = *(M_Object*)(reg-SZ_INT);
+//  **(M_Object**)reg = a.obj;
+//  a.obj = 
+  **(M_Object**)reg = *(M_Object*)(reg-SZ_INT);
   DISPATCH()
 remref:
   release(*(M_Object*)(mem + VAL), shred);
index 0cfbe996d6a94b430df0a20576bbcb701dae689e..ee0cb6fe3c71e745700e9a75e240bd663245a994 100644 (file)
@@ -1,3 +1,3 @@
-#! [contains] can't cast constant to Ptr
+#! [contains] can't cast non-mutable value to Ptr
 fun void test(<~int~>Ptr i) { <<< *i>>>; }
 1 => test;
diff --git a/tests/import/gwi_oper_emit_var.c b/tests/import/gwi_oper_emit_var.c
deleted file mode 100644 (file)
index ea28b4a..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "gwion_env.h"
-#include "vm.h"
-#include "object.h"
-#include "instr.h"
-#include "gwion.h"
-#include "operator.h"
-#include "import.h"
-
-static OP_CHECK(opck_ptrext_assign) {
-  const Exp_Binary* bin = (Exp_Binary*)data;
-  if(bin->rhs->meta != ae_meta_var)
-    ERR_N(exp_self(bin)->pos, _("left side operand is constant"));
-  bin->rhs->emit_var = 1;
-  Type t = bin->rhs->type;
-  do {
-    Type u = bin->lhs->type;
-    do {
-      const m_str str = get_type_name(env, u->name, 1);
-      if(str && !strcmp(t->name, str))
-      return bin->lhs->type;
-    } while((u = u->e->parent));
-  } while((t = t->e->parent));
-  return env->gwion->type[et_null];
-}
-
-static INSTR(instr_ptrext_assign) {
-  POP_REG(shred, SZ_INT)
-  const M_Object o = *(M_Object*)REG(-SZ_INT);
-  *(m_float**)o->data = *(m_float**)REG(0);
-}
-
-GWION_IMPORT(typedef_test) {
-  GWI_OB(gwi_class_ini(gwi, "PtrExt", "Ptr<~float~>"))
-  GWI_BB(gwi_class_end(gwi))
-  GWI_BB(gwi_oper_ini(gwi, "nonnull PtrExt", "float", NULL))
-  GWI_BB(gwi_oper_var(gwi, SZ_INT))
-  GWI_BB(gwi_oper_add(gwi, opck_ptrext_assign))
-  GWI_BB(gwi_oper_end(gwi, "<=:", instr_ptrext_assign))
-  return GW_OK;
-}
diff --git a/tests/import/gwi_oper_emit_var.gw b/tests/import/gwi_oper_emit_var.gw
deleted file mode 100644 (file)
index 31a9b50..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-1234.5 => float f;
-PtrExt ref ptr;
-<<< ptr >>>;
-ptr <=: f;
-<<< f >>>;
diff --git a/tests/import/test.log b/tests/import/test.log
new file mode 100644 (file)
index 0000000..87ce6cd
--- /dev/null
@@ -0,0 +1 @@
+op_already_imported.gw 
index c9f2ab760c9b20f6a997267d930a514949222da8..e4b35b689dd623e5f626acb05f36873540c9af94 100644 (file)
@@ -1,5 +1,5 @@
 #!/bin/bash
-# [test] #75
+# [test] #74
 
 n=0
 [ "$1" ] && n="$1"
diff --git a/tests/struct/member_func.gw b/tests/struct/member_func.gw
new file mode 100644 (file)
index 0000000..80de97e
--- /dev/null
@@ -0,0 +1,11 @@
+class C {
+  fun int test(int i) {
+   13 => int j;
+   return j;
+  }
+}
+C c;
+12 => c.test => int ret;
+
+<<< 1394 >>>;
+<<<ret>>>;
diff --git a/tests/struct/struct_gack.gw b/tests/struct/struct_gack.gw
new file mode 100644 (file)
index 0000000..a5a4edd
--- /dev/null
@@ -0,0 +1,7 @@
+struct S {
+  13 => int i;
+  operator @gack void() { <<< "test", i >>>; }
+  <<< this >>>;
+}
+S s;
+<<< s >>>;
diff --git a/tests/struct/struct_global0.gw b/tests/struct/struct_global0.gw
new file mode 100644 (file)
index 0000000..57abb9e
--- /dev/null
@@ -0,0 +1,14 @@
+struct global GlobalStruct {
+  int i;
+  float f;
+  string s;
+}
+
+struct global GlobalStructWithCtor {
+  int i;
+  float f;
+  string s;
+}
+
+global GlobalStruct s;
+GlobalStructWithCtor sctor;
diff --git a/tests/struct/struct_global1.gw b/tests/struct/struct_global1.gw
new file mode 100644 (file)
index 0000000..3199b2d
--- /dev/null
@@ -0,0 +1 @@
+GlobalStruct s;
diff --git a/tests/struct/struct_member.gw b/tests/struct/struct_member.gw
new file mode 100644 (file)
index 0000000..5de8dc4
--- /dev/null
@@ -0,0 +1,13 @@
+class C {
+  struct S {
+    string s;
+    float a;
+    11 => int i;
+    13 => float f;
+  }
+  S s;
+  <<< "after ctor" >>>;
+}
+C c;
+<<< c.s.i >>>;
+
diff --git a/tests/struct/struct_member_func.gw b/tests/struct/struct_member_func.gw
new file mode 100644 (file)
index 0000000..a962263
--- /dev/null
@@ -0,0 +1,8 @@
+struct S {
+  4 => int i;
+  12 => int j;
+  fun int test() { <<< "test", i >>>; }
+  test();
+}
+S s;
+s.test();
diff --git a/tests/struct/struct_noctor.gw b/tests/struct/struct_noctor.gw
new file mode 100644 (file)
index 0000000..c08a62c
--- /dev/null
@@ -0,0 +1,8 @@
+struct S {
+  float f;
+  fun void test() { <<< __func__, f >>>; }
+}
+
+S s;
+12.3 => s.f;
+s.test();
diff --git a/tests/struct/struct_return.gw b/tests/struct/struct_return.gw
new file mode 100644 (file)
index 0000000..25837e3
--- /dev/null
@@ -0,0 +1,14 @@
+struct S {
+  int i;
+  float f;
+}
+
+fun S test() {
+  S s;
+  12 => s.i;
+  12 => s.f;
+  return s;
+}
+
+<<< test().i >>>;
+<<< test().f >>>;
diff --git a/tests/struct/struct_static.gw b/tests/struct/struct_static.gw
new file mode 100644 (file)
index 0000000..3dec13b
--- /dev/null
@@ -0,0 +1,10 @@
+class C {
+  struct S {
+    12 => int i;
+    "testing::" => string s;
+    13 => float f;
+    <<< __func__ >>>;
+  }
+  static S s;
+}
+C c;
diff --git a/tests/struct/struct_static_func.gw b/tests/struct/struct_static_func.gw
new file mode 100644 (file)
index 0000000..e1ffa26
--- /dev/null
@@ -0,0 +1,9 @@
+struct S {
+  int i;
+  int j;
+  12 => static int si;
+  fun static void test() { <<< __func__, si >>>; }
+  test();
+}
+S s;
+s.test();
diff --git a/tests/struct/t.gw b/tests/struct/t.gw
new file mode 100644 (file)
index 0000000..3e91f48
--- /dev/null
@@ -0,0 +1,7 @@
+struct S {
+  int i;
+}
+S s;
+<<< s.i >>>;
+<<< 12 => s.i >>>;
+<<< s.i >>>;
diff --git a/util b/util
index 360d8733bbf2a1358ee4b82444711235388d4b81..ca4eea2ca7862dcf66c3e230d2cd09142b84ebf7 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 360d8733bbf2a1358ee4b82444711235388d4b81
+Subproject commit ca4eea2ca7862dcf66c3e230d2cd09142b84ebf7