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