From: Jérémie Astor Date: Sat, 24 Jul 2021 18:52:46 +0000 (+0200) Subject: :bug: Constructor fixes X-Git-Tag: nightly~521 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=1afee8e0e27d2f34cae32d9ef8662ef8d1177d15;p=gwion.git :bug: Constructor fixes --- diff --git a/plug b/plug index d4786a23..b0fe6727 160000 --- a/plug +++ b/plug @@ -1 +1 @@ -Subproject commit d4786a23757fedd3e60624e1289229bd38377829 +Subproject commit b0fe67273876785e1282c6dc08f63bc6406c5cb1 diff --git a/src/emit/emit.c b/src/emit/emit.c index 0ef37ff6..6439c4a7 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -2659,8 +2659,8 @@ ANN m_bool emit_func_def(const Emitter emit, const Func_Def f) { if (func->code || tmpl_base(fdef->base->tmpl) || fflag(func, fflag_emit)) return GW_OK; set_fflag(func, fflag_emit); - if (vflag(func->value_ref, vflag_builtin) && - safe_tflag(emit->env->class_def, tflag_tmpl)) { + if ((vflag(func->value_ref, vflag_builtin) && + safe_tflag(emit->env->class_def, tflag_tmpl)) || (fdef->base->tmpl && !strcmp(s_name(f->base->xid), "new"))) { const Func base = nspc_lookup_func1(func->value_ref->from->owner, f->base->xid); builtin_func(emit->gwion->mp, func, (f_xfun)base->code->native_func); diff --git a/src/lib/object_op.c b/src/lib/object_op.c index db87b977..b7733607 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -37,9 +37,18 @@ static OP_CHECK(opck_object_at) { return bin->rhs->type; } +static bool is_new(const Exp exp) { + return exp->exp_type == ae_exp_call && + exp->d.exp_call.func->exp_type == ae_exp_dot && + !strcmp(s_name(exp->d.exp_call.func->type->info->func->def->base->xid), "new"); +} + static OP_EMIT(opem_object_at) { - const Instr addref = emit_add_instr(emit, RegAddRef); - addref->m_val = -SZ_INT * 2; + const Exp_Binary *bin = (Exp_Binary *)data; + if(!is_new(bin->lhs)) { + const Instr addref = emit_add_instr(emit, RegAddRef); + addref->m_val = -SZ_INT * 2; + } (void)emit_add_instr(emit, ObjectAssign); return GW_OK; } diff --git a/src/lib/union.c b/src/lib/union.c index 6cc7d0e6..369c331d 100644 --- a/src/lib/union.c +++ b/src/lib/union.c @@ -103,7 +103,12 @@ static MFUN(union_is) { *(m_uint *)RETURN = *(m_uint *)MEM(SZ_INT) == *(m_uint *)o->data; } -static OP_CHECK(opck_union_ctor) { +static MFUN(union_new) { + memcpy(o->data, MEM(SZ_INT*2), *(m_uint*)MEM(SZ_INT)); + *(M_Object *)RETURN = o; +} + +static OP_CHECK(opck_union_new) { Exp_Call *call = (Exp_Call *)data; const Exp name = call->args; if (!name || !name->next || name->next->next) @@ -112,7 +117,7 @@ static OP_CHECK(opck_union_ctor) { if (name->exp_type != ae_exp_primary || name->d.prim.prim_type != ae_prim_id) return NULL; const Exp val = name->next; - const Type base = actual_type(env->gwion, call->func->type); + const Type base = call->func->d.exp_dot.base->type; const Map map = &base->nspc->info->value->map; for (m_uint i = 0; i < map_size(map); ++i) { if (VKEY(map, i) == (m_uint)name->d.prim.d.var) { @@ -125,30 +130,16 @@ static OP_CHECK(opck_union_ctor) { ERR_N(val->pos, "Invalid type '%s' for '%s', should be '%s'", t->name, v->name, v->type->name); } + const Exp e = new_prim_int(env->gwion->mp, t->size + SZ_INT, val->pos); + e->next = name; + e->type = env->gwion->type[et_int]; + call->args = e; return base; } } return NULL; } -static INSTR(UnionCtor) { - POP_REG(shred, instr->m_val2); - const m_uint index = *(m_uint *)REG(-SZ_INT); - const M_Object o = *(M_Object *)REG(-SZ_INT) = - new_object(shred->info->mp, NULL, (Type)instr->m_val); - *(m_uint *)o->data = index; // + 1; - memcpy(o->data + SZ_INT, REG(0), instr->m_val2); -} - -static OP_EMIT(opem_union_ctor) { - Exp_Call *const call = (Exp_Call *)data; - const Type base = actual_type(emit->gwion, call->func->type); - const Instr instr = emit_add_instr(emit, UnionCtor); - instr->m_val = (m_uint)base; - instr->m_val2 = call->args->next->type->size; - return GW_OK; -} - ANN GWION_IMPORT(union) { const Type t_none = gwi_mk_type(gwi, "None", 0, NULL); GWI_BB(gwi_set_global_type(gwi, t_none, et_none)) @@ -165,18 +156,20 @@ ANN GWION_IMPORT(union) { const Type t_union = gwi_class_ini(gwi, "@Union", "Object"); gwi_class_xtor(gwi, NULL, UnionDtor); + gwi->gwion->type[et_union] = t_union; + GWI_BB(gwi_item_ini(gwi, "int", "@index")) GWI_BB(gwi_item_end(gwi, ae_flag_none, num, 0)) GWI_BB(gwi_func_ini(gwi, "bool", "is")) GWI_BB(gwi_func_arg(gwi, "int", "member")) GWI_BB(gwi_func_end(gwi, union_is, ae_flag_none)) + GWI_BB(gwi_func_ini(gwi, "auto", "new:[T]")) + GWI_BB(gwi_func_arg(gwi, "int", "size")) + GWI_BB(gwi_func_arg(gwi, "int", "id")) + GWI_BB(gwi_func_arg(gwi, "T", "value")) + GWI_BB(gwi_func_end(gwi, union_new, ae_flag_none)) GWI_BB(gwi_class_end(gwi)) - GWI_BB(gwi_oper_ini(gwi, NULL, "@Union", NULL)) - GWI_BB(gwi_oper_add(gwi, opck_union_ctor)) - GWI_BB(gwi_oper_emi(gwi, opem_union_ctor)) - GWI_BB(gwi_oper_end(gwi, "@ctor", NULL)) - const Func f = (Func)vector_front(&t_union->nspc->vtable); const struct Op_Func opfunc = {.ck = opck_union_is}; const struct Op_Import opi = { @@ -186,6 +179,18 @@ ANN GWION_IMPORT(union) { .pos = gwi->loc, .op = insert_symbol(gwi->gwion->st, "@func_check")}; CHECK_BB(add_op(gwi->gwion, &opi)); + + const Func f1 = (Func)vector_at(&t_union->nspc->vtable, 1); + const struct Op_Func opfunc1 = {.ck = opck_union_new}; + const struct Op_Import opi1 = { + .rhs = f1->value_ref->type, + .func = &opfunc1, + .data = (uintptr_t)f1, + .pos = gwi->loc, + .op = insert_symbol(gwi->gwion->st, "@func_check")}; + CHECK_BB(add_op(gwi->gwion, &opi1)); + +builtin_func(gwi->gwion->mp, f1, union_new); gwi->gwion->type[et_union] = t_union; GWI_BB(gwi_oper_ini(gwi, "@Union", (m_str)OP_ANY_TYPE, NULL)) diff --git a/src/parse/check.c b/src/parse/check.c index dba0fca7..06196e69 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -727,7 +727,8 @@ ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) { Tmpl tmpl = {.call = tl}; ((Exp_Call *)exp)->tmpl = &tmpl; DECL_OO(const Func, func, = get_template_func(env, exp, value)); - return func->def->base->ret_type; + return func->def->base->ret_type != env->gwion->type[et_auto] ? + func->def->base->ret_type : exp->func->d.exp_dot.base->type; } ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) { @@ -832,7 +833,8 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) { exp->func->type = func->value_ref->type; call_add_effect(env, func, exp->func->pos); if (func == env->func) set_fflag(env->func, fflag_recurs); - return func->def->base->ret_type; + return func->def->base->ret_type != env->gwion->type[et_auto] ? + func->def->base->ret_type : exp->func->d.exp_dot.base->type; } const loc_t pos = exp->args ? exp->args->pos : exp->func->pos; function_alternative(env, exp->func->type, exp->args, pos); diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 3d78ffa0..fb60fcb4 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -549,7 +549,8 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def fdef) { if(!strcmp(s_name(fdef->base->xid), "new")) { if(!env->class_def) ERR_B(fdef->base->pos, _("{G-}new{0} operator must be set inside {C+}class{0}")); - fdef->base->ret_type = env->class_def; + if(!fdef->base->ret_type) + fdef->base->ret_type = env->class_def; } if (GET_FLAG(fdef->base, global) && !env->class_def) env->context->global = 1; const Func_Def f = !is_cpy(fdef) ? fdef : scan2_cpy_fdef(env, fdef);