From ca2390ffc329cf0ecb1f2ec8a6685d3f3c1cf5b2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Mon, 30 Mar 2020 17:30:18 +0200 Subject: [PATCH] :art: Introduce 'struct' --- ast | 2 +- examples/ptr_assign_class.gw | 5 +- examples/template_vararg.gw | 6 +- include/emit.h | 4 +- include/import/cdef.h | 2 +- include/import/checker.h | 1 - include/import/oper.h | 3 - include/opcode.h | 10 + include/operator.h | 16 +- include/specialid.h | 4 +- opcode.txt | 5 + src/emit/emit.c | 463 +++++++++++++++++++---------- src/env/nspc.c | 18 ++ src/env/type.c | 4 +- src/gwion.c | 2 + src/import/cdef.c | 6 +- src/import/oper.c | 7 +- src/lib/array.c | 28 +- src/lib/event.c | 1 - src/lib/func.c | 53 ++-- src/lib/gack.c | 11 +- src/lib/modules.c | 14 +- src/lib/object.c | 32 +- src/lib/object_op.c | 103 +++++-- src/lib/opfunc.c | 57 ++-- src/lib/prim.c | 16 +- src/lib/ptr.c | 36 +-- src/lib/string.c | 2 +- src/lib/ugen.c | 2 +- src/lib/vararg.c | 6 +- src/main.c | 4 +- src/parse/check.c | 145 ++++----- src/parse/operator.c | 138 ++++++--- src/parse/scan0.c | 15 +- src/parse/scan1.c | 13 +- src/parse/scan2.c | 6 +- src/parse/template.c | 2 +- src/vm/vm.c | 38 ++- tests/error/ptr_implicit_const.gw | 2 +- tests/import/gwi_oper_emit_var.c | 42 --- tests/import/gwi_oper_emit_var.gw | 5 - tests/import/test.log | 1 + tests/sh/import.sh | 2 +- tests/struct/member_func.gw | 11 + tests/struct/struct_gack.gw | 7 + tests/struct/struct_global0.gw | 14 + tests/struct/struct_global1.gw | 1 + tests/struct/struct_member.gw | 13 + tests/struct/struct_member_func.gw | 8 + tests/struct/struct_noctor.gw | 8 + tests/struct/struct_return.gw | 14 + tests/struct/struct_static.gw | 10 + tests/struct/struct_static_func.gw | 9 + tests/struct/t.gw | 7 + util | 2 +- 55 files changed, 928 insertions(+), 508 deletions(-) delete mode 100644 tests/import/gwi_oper_emit_var.c delete mode 100644 tests/import/gwi_oper_emit_var.gw create mode 100644 tests/import/test.log create mode 100644 tests/struct/member_func.gw create mode 100644 tests/struct/struct_gack.gw create mode 100644 tests/struct/struct_global0.gw create mode 100644 tests/struct/struct_global1.gw create mode 100644 tests/struct/struct_member.gw create mode 100644 tests/struct/struct_member_func.gw create mode 100644 tests/struct/struct_noctor.gw create mode 100644 tests/struct/struct_return.gw create mode 100644 tests/struct/struct_static.gw create mode 100644 tests/struct/struct_static_func.gw create mode 100644 tests/struct/t.gw diff --git a/ast b/ast index 318792cd..c16ad008 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit 318792cdc12f6b9632f89052c2d6cc258031b99c +Subproject commit c16ad0087304f84595aa4f901f2d71465e391192 diff --git a/examples/ptr_assign_class.gw b/examples/ptr_assign_class.gw index 68d635c8..913cc60a 100644 --- a/examples/ptr_assign_class.gw +++ b/examples/ptr_assign_class.gw @@ -1,8 +1,7 @@ -class C -{ +class C { typedef void Test(); fun void test1(){}; - Test test0; + Test test0; <<< test1 @=> test0 >>>; } diff --git a/examples/template_vararg.gw b/examples/template_vararg.gw index 564d0b80..57552d84 100644 --- a/examples/template_vararg.gw +++ b/examples/template_vararg.gw @@ -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); diff --git a/include/emit.h b/include/emit.h index ff00f7f8..21f6361b 100644 --- a/include/emit.h +++ b/include/emit.h @@ -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); } diff --git a/include/import/cdef.h b/include/import/cdef.h index f44f1855..d4bdd968 100644 --- a/include/import/cdef.h +++ b/include/import/cdef.h @@ -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); diff --git a/include/import/checker.h b/include/import/checker.h index 510943c6..52e8b7a3 100644 --- a/include/import/checker.h +++ b/include/import/checker.h @@ -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 { diff --git a/include/import/oper.h b/include/import/oper.h index 1bb02818..cf5bedcf 100644 --- a/include/import/oper.h +++ b/include/import/oper.h @@ -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 \ diff --git a/include/opcode.h b/include/opcode.h index e85a433d..1dc04395 100644 --- a/include/opcode.h +++ b/include/opcode.h @@ -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 diff --git a/include/operator.h b/include/operator.h index c7453f11..e6fc6c9d 100644 --- a/include/operator.h +++ b/include/operator.h @@ -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 { diff --git a/include/specialid.h b/include/specialid.h index 8deeb2fe..a2a81a77 100644 --- a/include/specialid.h +++ b/include/specialid.h @@ -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; } diff --git a/opcode.txt b/opcode.txt index 2c401589..8c1b8863 100644 --- a/opcode.txt +++ b/opcode.txt @@ -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 diff --git a/src/emit/emit.c b/src/emit/emit.c index 00a36785..06960591 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -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; } diff --git a/src/env/nspc.c b/src/env/nspc.c index e767d722..606ad597 100644 --- a/src/env/nspc.c +++ b/src/env/nspc.c @@ -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); diff --git a/src/env/type.c b/src/env/type.c index a3d1d886..a1264dc1 100644 --- a/src/env/type.c +++ b/src/env/type.c @@ -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; } diff --git a/src/gwion.c b/src/gwion.c index df61ac10..b8a73e6c 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -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; } diff --git a/src/import/cdef.c b/src/import/cdef.c index 1f6cd6c5..e8243b12 100644 --- a/src/import/cdef.c +++ b/src/import/cdef.c @@ -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); } diff --git a/src/import/oper.c b/src/import/oper.c index c810f096..79b41d8e 100644 --- a/src/import/oper.c +++ b/src/import/oper.c @@ -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; diff --git a/src/lib/array.c b/src/lib/array.c index fff75f3a..47383c79 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -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)) diff --git a/src/lib/event.c b/src/lib/event.c index 99718565..2f56dd16 100644 --- a/src/lib/event.c +++ b/src/lib/event.c @@ -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; } diff --git a/src/lib/func.c b/src/lib/func.c index c5ad8eda..09832140 100644 --- a/src/lib/func.c +++ b/src/lib/func.c @@ -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; } diff --git a/src/lib/gack.c b/src/lib/gack.c index 1f04a9f7..67a12565 100644 --- a/src/lib/gack.c +++ b/src/lib/gack.c @@ -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; } + diff --git a/src/lib/modules.c b/src/lib/modules.c index ff897dfa..76e20ae5 100644 --- a/src/lib/modules.c +++ b/src/lib/modules.c @@ -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; } diff --git a/src/lib/object.c b/src/lib/object.c index c421f141..6d008654 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -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; } diff --git a/src/lib/object_op.c b/src/lib/object_op.c index e0ccb8b0..8026bf66 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -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; } diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index 8a443967..122e7eff 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -10,19 +10,21 @@ #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); } diff --git a/src/lib/prim.c b/src/lib/prim.c index 5127bc62..e82f4669 100644 --- a/src/lib/prim.c +++ b/src/lib/prim.c @@ -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) diff --git a/src/lib/ptr.c b/src/lib/ptr.c index ab421ef1..86aee9b0 100644 --- a/src/lib/ptr.c +++ b/src/lib/ptr.c @@ -16,16 +16,17 @@ 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; } diff --git a/src/lib/string.c b/src/lib/string.c index 7f2f8070..a6cc6062 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -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); \ diff --git a/src/lib/ugen.c b/src/lib/ugen.c index d4c4dc18..73d8f79b 100644 --- a/src/lib/ugen.c +++ b/src/lib/ugen.c @@ -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) { diff --git a/src/lib/vararg.c b/src/lib/vararg.c index b6b37f2e..25fbb5fa 100644 --- a/src/lib/vararg.c +++ b/src/lib/vararg.c @@ -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")) } diff --git a/src/main.c b/src/main.c index 7ddc27d3..c1461968 100644 --- a/src/main.c +++ b/src/main.c @@ -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]; diff --git a/src/parse/check.c b/src/parse/check.c index dd6410d8..1298b859 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -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); diff --git a/src/parse/operator.c b/src/parse/operator.c index 85a87c1c..d74345e3 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -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); diff --git a/src/parse/scan0.c b/src/parse/scan0.c index b9fbc242..2b660dfb 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -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; diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 2dd7e817..d100f323 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -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) { diff --git a/src/parse/scan2.c b/src/parse/scan2.c index c692a813..90a2d202 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -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, diff --git a/src/parse/template.c b/src/parse/template.c index 0ae30a9f..cd5beb76 100644 --- a/src/parse/template.c +++ b/src/parse/template.c @@ -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); diff --git a/src/vm/vm.c b/src/vm/vm.c index 33ea94a2..2cb7dd0f 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -296,10 +296,11 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] static const void* dispatch[] = { &®setimm, &®pushimm, &®pushfloat, &®pushother, &®pushaddr, - &®pushmem, &®pushmemfloat, &®pushmemother, &®pushmemaddr, + &®pushmem, &®pushmemfloat, &®pushmemother, &®pushmemaddr, &®pushmemderef, &&pushnow, &&baseint, &&basefloat, &&baseother, &&baseaddr, - &®toreg, &®toregaddr, + &®toreg, &®toregaddr, &®toregderef, + &&structmember, &&structmemberaddr, &&memsetimm, &®pushme, &®pushmaybe, &&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); diff --git a/tests/error/ptr_implicit_const.gw b/tests/error/ptr_implicit_const.gw index 0cfbe996..ee0cb6fe 100644 --- a/tests/error/ptr_implicit_const.gw +++ b/tests/error/ptr_implicit_const.gw @@ -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 index ea28b4a6..00000000 --- a/tests/import/gwi_oper_emit_var.c +++ /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 index 31a9b502..00000000 --- a/tests/import/gwi_oper_emit_var.gw +++ /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 index 00000000..87ce6cd6 --- /dev/null +++ b/tests/import/test.log @@ -0,0 +1 @@ +op_already_imported.gw diff --git a/tests/sh/import.sh b/tests/sh/import.sh index c9f2ab76..e4b35b68 100644 --- a/tests/sh/import.sh +++ b/tests/sh/import.sh @@ -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 index 00000000..80de97ed --- /dev/null +++ b/tests/struct/member_func.gw @@ -0,0 +1,11 @@ +class C { + fun int test(int i) { + 13 => int j; + return j; + } +} +C c; +12 => c.test => int ret; + +<<< 1394 >>>; +<<>>; diff --git a/tests/struct/struct_gack.gw b/tests/struct/struct_gack.gw new file mode 100644 index 00000000..a5a4edd5 --- /dev/null +++ b/tests/struct/struct_gack.gw @@ -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 index 00000000..57abb9ed --- /dev/null +++ b/tests/struct/struct_global0.gw @@ -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 index 00000000..3199b2d5 --- /dev/null +++ b/tests/struct/struct_global1.gw @@ -0,0 +1 @@ +GlobalStruct s; diff --git a/tests/struct/struct_member.gw b/tests/struct/struct_member.gw new file mode 100644 index 00000000..5de8dc48 --- /dev/null +++ b/tests/struct/struct_member.gw @@ -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 index 00000000..a962263f --- /dev/null +++ b/tests/struct/struct_member_func.gw @@ -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 index 00000000..c08a62cf --- /dev/null +++ b/tests/struct/struct_noctor.gw @@ -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 index 00000000..25837e34 --- /dev/null +++ b/tests/struct/struct_return.gw @@ -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 index 00000000..3dec13be --- /dev/null +++ b/tests/struct/struct_static.gw @@ -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 index 00000000..e1ffa260 --- /dev/null +++ b/tests/struct/struct_static_func.gw @@ -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 index 00000000..3e91f487 --- /dev/null +++ b/tests/struct/t.gw @@ -0,0 +1,7 @@ +struct S { + int i; +} +S s; +<<< s.i >>>; +<<< 12 => s.i >>>; +<<< s.i >>>; diff --git a/util b/util index 360d8733..ca4eea2c 160000 --- a/util +++ b/util @@ -1 +1 @@ -Subproject commit 360d8733bbf2a1358ee4b82444711235388d4b81 +Subproject commit ca4eea2ca7862dcf66c3e230d2cd09142b84ebf7 -- 2.43.0