]> Nishi Git Mirror - gwion.git/commitdiff
:art: Constructors
authorJérémie Astor <fennecdjay@gmail.com>
Sat, 17 Jul 2021 18:44:59 +0000 (20:44 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Sat, 17 Jul 2021 18:47:24 +0000 (20:47 +0200)
ast
fmt
src/clean.c
src/emit/emit.c
src/lib/opfunc.c
src/parse/check.c
src/parse/scan2.c
tests/ctor/ctor_outside.gw [new file with mode: 0644]
tests/ctor/ctor_overload.gw [new file with mode: 0644]

diff --git a/ast b/ast
index 7492fddf76bd861aea16e16f6cc66ac257c3c647..68044023ce834c80ff2992487835b91e139a467c 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 7492fddf76bd861aea16e16f6cc66ac257c3c647
+Subproject commit 68044023ce834c80ff2992487835b91e139a467c
diff --git a/fmt b/fmt
index d78297aacc14071b97ae22e47f9e1c06054c15de..30bff4e9845b15c3af3f8caee300134a4d6fbd27 160000 (submodule)
--- a/fmt
+++ b/fmt
@@ -1 +1 @@
-Subproject commit d78297aacc14071b97ae22e47f9e1c06054c15de
+Subproject commit 30bff4e9845b15c3af3f8caee300134a4d6fbd27
index fb4dee1a8ef1999a919e775fee2c9e56b5eac7bf..3adaf1d9e51a8478f7ae8c3dfa3dac172c637882 100644 (file)
@@ -75,7 +75,9 @@ ANN static void clean_exp_unary(Clean *a, Exp_Unary *b) {
     clean_exp(a, b->exp);
     break;
   case unary_td:
-    clean_type_decl(a, b->td);
+    clean_type_decl(a, b->ctor.td);
+    if(b->ctor.exp)
+      clean_exp(a, b->ctor.exp);
     break;
   case unary_code:
     clean_stmt(a, b->code);
index d2da91156c0f0e24550813497f5f6e5dad6efcb8..5f9091c654a6b1b5c8a1d086f5819204e6fb3a5f 100644 (file)
@@ -2560,6 +2560,8 @@ ANN static VM_Code emit_internal(const Emitter emit, const Func f) {
 
 ANN static inline VM_Code _emit_func_def_code(const Emitter emit,
                                               const Func    func) {
+  if(!strcmp(s_name(func->def->base->xid), "new"))
+    emit_add_instr(emit, RegPushMem);
   return !fbflag(func->def->base, fbflag_internal) ? finalyze(emit, FuncReturn)
                                                    : emit_internal(emit, func);
 }
index 195bb2b9f659d46c25b1e3f5bb5cc8414601ca6a..ac3c17f9560e53d3bfddb6a52a7b879a483ec103 100644 (file)
@@ -97,23 +97,36 @@ OP_CHECK(opck_post) {
 ANN Type check_td(const Env env, Type_Decl *td);
 
 OP_CHECK(opck_new) {
-  const Exp_Unary *unary = (Exp_Unary *)data;
-  DECL_ON(const Type, t, = known_type(env, unary->td));
+  Exp_Unary *unary = (Exp_Unary *)data;
+  DECL_ON(const Type, t, = known_type(env, unary->ctor.td));
+  if(unary->ctor.exp) {
+    const Exp self   = exp_self(unary);
+    const Exp args   = unary->ctor.exp;
+    const Exp base   = new_exp_unary2(env->gwion->mp, unary->op, unary->ctor.td, NULL, self->pos);
+    const Exp func   = new_exp_dot(env->gwion->mp, base, insert_symbol("new"), self->pos);
+    self->d.exp_call.func = func;
+    self->d.exp_call.args = args;
+    self->d.exp_call.tmpl = NULL;
+    self->exp_type = ae_exp_call;
+    CHECK_BN(traverse_exp(env, self));
+    return self->type;
+//    unarytype
+  }
   if (isa(t, env->gwion->type[et_object]) < 0)
     ERR_N(exp_self(unary)->pos, _("can't use 'new' on non-object types...\n"));
   if (type_ref(t))
-    ERR_N(unary->td->pos, _("can't use 'new' on ref type '%s'\n"), t->name);
+    ERR_N(unary->ctor.td->pos, _("can't use 'new' on ref type '%s'\n"), t->name);
   if (GET_FLAG(t, abstract))
-    ERR_N(unary->td->pos, _("can't use 'new' on abstract type '%s'\n"),
+    ERR_N(unary->ctor.td->pos, _("can't use 'new' on abstract type '%s'\n"),
           t->name);
-  if (unary->td->array) CHECK_BN(check_subscripts(env, unary->td->array, 1));
+  if (unary->ctor.td->array) CHECK_BN(check_subscripts(env, unary->ctor.td->array, 1));
   return t;
 }
 
 OP_EMIT(opem_new) {
   const Exp_Unary *unary = (Exp_Unary *)data;
   CHECK_BB(emit_instantiate_object(emit, exp_self(unary)->type,
-                                   unary->td->array, 0));
+                                   unary->ctor.td->array, 0));
   emit_gc(emit, -SZ_INT);
   return GW_OK;
 }
index fbe0614489554dbee877fad824ebd6bac425e516..58952baa9267e1da10965aefdcb96ca8b2bc802f 100644 (file)
@@ -1551,7 +1551,8 @@ ANN m_bool check_fdef(const Env env, const Func_Def fdef) {
     CHECK_BB(check_stmt_code(env, &fdef->d.code->d.stmt_code));
     env->scope->depth++;
   }
-  if (fdef->base->ret_type &&
+  // check fdef->base->td for `new`
+  if (fdef->base->td && fdef->base->ret_type &&
       fdef->base->ret_type != env->gwion->type[et_void] && fdef->d.code &&
       !fflag(fdef->base->func, fflag_return))
     ERR_B(fdef->base->td->pos,
index 1350c178f6a314afd63eb06e655a4b87490ea168..3d78ffa00434f09751b4ec8d8f9853687343a58d 100644 (file)
@@ -546,6 +546,11 @@ static inline int is_cpy(const Func_Def fdef) {
 ANN m_bool scan2_func_def(const Env env, const Func_Def fdef) {
   if (tmpl_base(fdef->base->tmpl) && fbflag(fdef->base, fbflag_op))
     return GW_OK;
+  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 (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);
   const m_uint   scope =
diff --git a/tests/ctor/ctor_outside.gw b/tests/ctor/ctor_outside.gw
new file mode 100644 (file)
index 0000000..a7343cd
--- /dev/null
@@ -0,0 +1,5 @@
+#! [contains] new operator must be set inside class
+var int i;
+operator new(int arg) {
+  arg => i;
+}
diff --git a/tests/ctor/ctor_overload.gw b/tests/ctor/ctor_overload.gw
new file mode 100644 (file)
index 0000000..3e22ad4
--- /dev/null
@@ -0,0 +1,14 @@
+#! [contains] 42
+class C {
+  var int i;
+  operator new(int arg) {
+    arg => i;
+  }
+  operator new() {}
+}
+
+new C() => var auto c;
+new C(2) => var auto d;
+<<< "c:${c.i}, d:${d.i}" >>>;
+
+<<< "the answer: ${(new C(42)).i}" >>>;