]> Nishi Git Mirror - gwion.git/commitdiff
:bug: Constructor fixes
authorJérémie Astor <fennecdjay@gmail.com>
Sat, 24 Jul 2021 18:52:46 +0000 (20:52 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Sat, 24 Jul 2021 18:52:46 +0000 (20:52 +0200)
plug
src/emit/emit.c
src/lib/object_op.c
src/lib/union.c
src/parse/check.c
src/parse/scan2.c

diff --git a/plug b/plug
index d4786a23757fedd3e60624e1289229bd38377829..b0fe67273876785e1282c6dc08f63bc6406c5cb1 160000 (submodule)
--- a/plug
+++ b/plug
@@ -1 +1 @@
-Subproject commit d4786a23757fedd3e60624e1289229bd38377829
+Subproject commit b0fe67273876785e1282c6dc08f63bc6406c5cb1
index 0ef37ff678e0bda58d2f2e044128ecc0913fe5c0..6439c4a7cd62bee2cd313c5a1893e98f2d4c6d70 100644 (file)
@@ -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);
index db87b977eb73d6f660a6d837c307cf523d403038..b7733607564786cbc3c2101df5ce360e2138b02f 100644 (file)
@@ -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;
 }
index 6cc7d0e6e080afdbeabb2b16e19455ca5b68eaf1..369c331d38e9d535a20a9a508381c15587c99d8f 100644 (file)
@@ -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))
index dba0fca76c1c9eb6d2f837619c68d003ad5e6160..06196e69d98a8b61983c435ecf92fc7daff1d805 100644 (file)
@@ -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);
index 3d78ffa00434f09751b4ec8d8f9853687343a58d..fb60fcb484b375a5d7f52d49b51f044a011b07b9 100644 (file)
@@ -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);