]> Nishi Git Mirror - gwion.git/commitdiff
:art: Struct constructors
authorfennecdjay <fennecdjay@gmail.com>
Tue, 25 Oct 2022 23:47:36 +0000 (01:47 +0200)
committerfennecdjay <fennecdjay@gmail.com>
Tue, 25 Oct 2022 23:47:36 +0000 (01:47 +0200)
16 files changed:
include/emit.h
include/parse.h
src/emit/emit.c
src/lib/object_op.c
src/lib/opfunc.c
src/parse/check.c
src/parse/default_arg.c
src/parse/scan2.c
tests/struct_ctor/struct_ctor_assign_get.gw [new file with mode: 0644]
tests/struct_ctor/struct_ctor_assign_set.gw [new file with mode: 0644]
tests/struct_ctor/struct_ctor_decl_get.gw [new file with mode: 0644]
tests/struct_ctor/struct_ctor_decl_set.gw [new file with mode: 0644]
tests/struct_ctor/struct_ctor_new_get.gw [new file with mode: 0644]
tests/struct_ctor/struct_ctor_new_set.gw [new file with mode: 0644]
tests/struct_ctor/struct_ctor_simple_get.gw [new file with mode: 0644]
tests/struct_ctor/struct_ctor_simple_set.gw [new file with mode: 0644]

index 3f7980010e0bfc036b75fb928359eeffcd3886bd..89bc1ecc839f31c885ab01a402136989bdfeec67 100644 (file)
@@ -80,7 +80,7 @@ ANN m_uint emit_code_offset(const Emitter emit);
 ANN m_uint emit_local(const Emitter emit, const Type t);
 ANN m_uint emit_localn(const Emitter emit, const Type t);
 ANN void* emit_localx(const Emitter emit, const Type t);
-ANN void emit_local_exp(const Emitter emit, const Exp);
+ANN m_uint emit_local_exp(const Emitter emit, const Exp);
 ANN m_bool emit_exp_spork(const Emitter, const Exp_Unary *);
 ANN m_bool emit_exp(const Emitter, const Exp);
 
index 1041c2652494341ed7b31ee6fcaf33a6a97a123a..f2c96926e00d66b6cbf5d66e22b39a6a81518b14 100644 (file)
@@ -133,4 +133,6 @@ ANN static inline bool is_static_call(const Gwion gwion, const Exp e) {
          is_class(gwion, member->base->type) ||
          member->base->exp_type == ae_exp_cast;
 }
+
+#define is_new(a) !strcmp(s_name((a)->base->xid), "new")
 #endif
index dc978ff2552b874477f76c3bd983181eb481c0c1..41b55be48421993ea9a8726935212bc58dfb25cd 100644 (file)
@@ -320,10 +320,11 @@ ANN void* emit_localx(const Emitter emit, const Type t) {
   return l;
 }
 
-ANN void emit_local_exp(const Emitter emit, const Exp e) {
+ANN m_uint emit_local_exp(const Emitter emit, const Exp e) {
   Local *const l = emit_localx(emit, e->type);
   if(e->ref)
     e->ref->data = l;
+  return l->offset;
 }
 
 ANN m_uint emit_localn(const Emitter emit, const Type t) {
@@ -962,12 +963,31 @@ ANN static void decl_expand(const Emitter emit, const Type t) {
   emit_regmove(emit, t->size - SZ_INT);
 }
 
-ANN static void emit_struct_decl_finish(const Emitter emit, const Type t,
-                                        const bool emit_addr) {
-  emit->code->frame->curr_offset += t->size + SZ_INT;
-  emit_ext_ctor(emit, t);
-  if (!emit_addr) decl_expand(emit, t);
-  emit->code->frame->curr_offset -= t->size + SZ_INT;
+ANN static m_uint decl_non_static_offset(const Emitter emit, const Exp_Decl *decl, const Type t) {
+  if(!exp_self(decl)->data)
+    return emit_local(emit, t);
+  const Local *l = exp_self(decl)->data;
+  exp_self(decl)->data = (void*)-1;
+  return l->offset;
+}
+
+ANN static m_bool struct_finish(const Emitter emit, const Exp_Decl *decl) {
+  const Type t = decl->type;
+  const bool emit_addr = exp_getvar(exp_self(decl));
+  if (decl->args) {
+    const Instr instr = (Instr)vector_back(&emit->code->instr);
+    CHECK_BB(emit_exp(emit, decl->args));
+    if (emit_addr) {
+      emit_regmove(emit, -t->size);
+      vector_add(&emit->code->instr, (m_uint)instr);
+    }
+    return GW_OK;
+  }
+  if(tflag(t, tflag_ctor)) {
+    emit_ext_ctor(emit, t);
+    if (!emit_addr) decl_expand(emit, t);
+  }
+  return GW_OK;
 }
 
 ANN static m_bool emit_exp_decl_static(const Emitter emit, const Exp_Decl *decl,
@@ -978,7 +998,7 @@ ANN static m_bool emit_exp_decl_static(const Emitter emit, const Exp_Decl *decl,
   if (isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
     CHECK_BB(decl_static(emit, decl, var_decl, 0));
   CHECK_BB(emit_dot_static_data(emit, v, !struct_ctor(v) ? emit_addr : 1));
-  if (struct_ctor(v)) emit_struct_decl_finish(emit, v->type, emit_addr);
+  if (tflag(v->type, tflag_struct)) CHECK_BB(struct_finish(emit, decl));
   if (isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
   if(safe_tflag(emit->env->class_def, tflag_struct) && GET_FLAG(emit->env->class_def, global))
     emit_object_addref(emit, 0, emit_addr);
@@ -1011,14 +1031,6 @@ ANN void unset_local(const Emitter emit, Local *const l) {
   }
 }
 
-ANN static m_uint decl_non_static_offset(const Emitter emit, const Exp_Decl *decl, const Type t) {
-  if(!exp_self(decl)->data)
-    return emit_local(emit, t);
-  const Local *l = exp_self(decl)->data;
-  exp_self(decl)->data = (void*)-1;
-  return l->offset;
-}
-
 ANN static m_bool emit_exp_decl_non_static(const Emitter   emit,
                                            const Exp_Decl *decl,
                                            const Var_Decl *var_decl,
@@ -1060,8 +1072,11 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter   emit,
     }
     if(safe_tflag(emit->env->class_def, tflag_struct) && GET_FLAG(emit->env->class_def, global))
       emit_object_addref(emit, 0, emit_addr);
-  } else if (struct_ctor(v))
-    emit_struct_decl_finish(emit, v->type, emit_addr);
+  } else if (tflag(v->type, tflag_struct)) {
+//    if (!emit_var)
+//      decl->vd.value->from->offset = decl_non_static_offset(emit, decl, type);
+    CHECK_BB(struct_finish(emit, decl));
+  }
   return GW_OK;
 }
 
@@ -1087,8 +1102,8 @@ ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl,
     const Instr assign = emit_add_instr(emit, Assign);
     assign->m_val      = emit_var;
     (void)emit_object_addref(emit, -SZ_INT, emit_var);
-  } else if (struct_ctor(v)) {
-    emit_struct_decl_finish(emit, v->type, emit_addr);
+  } else if (tflag(v->type, tflag_struct)) {
+    struct_finish(emit, decl);
     (void)emit_struct_addref(emit, v->type, -v->type->size, emit_addr);
   }
   return GW_OK;
@@ -1137,7 +1152,7 @@ ANN static m_bool emit_decl(const Emitter emit, Exp_Decl *const decl) {
       const Vector vec = &v->type->nspc->vtable;
       for(m_uint i = 0; i < vector_size(vec); i++) {
         const Func f = (Func)vector_at(vec, i);
-        if(!strcmp(s_name(f->def->base->xid), "new")) {
+        if(is_new(f->def)) {
           gw_err(_("maybe use a constructor?\n"));
           break;
         }
@@ -1311,38 +1326,66 @@ ANN static inline m_bool emit_inline(const Emitter emit, const Func f,
 }
 #endif
 
-ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *exp_call) {
+
+ANN static inline bool is_new_struct(const Func f, const Type t) {
+    return is_new(f->def) && tflag(t, tflag_struct);
+}
+
+ANN static m_bool emit_new_struct(const Emitter emit,const Exp_Call *call)  {
+  const Exp self = exp_self(call);
+  const Type t =  self->type;
+  const m_int offset = self->ref ? emit->code->frame->curr_offset - t->size: emit_local(emit, t);
+  const Instr back = self->ref ? (Instr)vector_pop(&emit->code->instr) : NULL;
+  CHECK_BB(emit_func_args(emit, call));
+  if(back)
+    vector_add(&emit->code->instr, (m_uint)back);
+  else if(tflag(t, tflag_ctor)) {
+    const Instr instr = emit_add_instr(emit, RegPushMem4);
+    instr->m_val = offset;
+  }
+  if(tflag(t, tflag_ctor)) emit_ext_ctor(emit, t);
+  else if(!back)  {
+    emit_regmove(emit, -SZ_INT + t->size);
+    const Instr instr = emit_add_instr(emit, RegPushMem4);
+    instr->m_val = offset;
+  }
+  emit_add_instr(emit, NoOp);
+  return GW_OK;
+}
+
+ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *call) {
   #ifdef GWION_INLINE
-    const Func _f = is_inlinable(emit, exp_call);
+    const Func _f = is_inlinable(emit, call);
     if(_f) {
       const Func base = emit->env->func;
       emit->env->func = _f;
       const m_uint scope = emit_push(emit, _f->value_ref->from->owner_class, _f->value_ref->from->owner);
-      const m_bool ret = emit_inline(emit, _f, exp_call);
+      const m_bool ret = emit_inline(emit, _f, call);
       emit_pop(emit, scope);
       emit->env->func = base;
       return ret;
     }
   #endif
 
-  // skip when recursing
-  const Type t = actual_type(emit->gwion, exp_call->func->type);
-  const Func f = t->info->func;
-  if (strstr(emit->code->name, "ork~") ||
-      (f != emit->env->func || (f && f->value_ref->from->owner_class)))
-    CHECK_BB(prepare_call(emit, exp_call));
-  else
-    CHECK_BB(emit_func_args(emit, exp_call));
-  if (is_func(emit->gwion, t)) // is_callable needs type
-    CHECK_BB(emit_exp_call1(emit, t->info->func,
-                            is_static_call(emit->gwion, exp_call->func)));
-  else {
+  const Type t = call->func->type;
+
+  if(unlikely(!is_func(emit->gwion, t))) {
+    const Type t = actual_type(emit->gwion, call->func->type);
     struct Op_Import opi = {.op   = insert_symbol("@ctor"),
                             .rhs  = t,
-                            .data = (uintptr_t)exp_call,
-                            .pos  = exp_self(exp_call)->pos};
+                            .data = (uintptr_t)call,
+                            .pos  = exp_self(call)->pos};
     CHECK_BB(op_emit(emit, &opi));
   }
+
+  const Func f = t->info->func;
+  if(unlikely(is_new_struct(f, exp_self(call)->type)))
+    emit_new_struct(emit, call);
+  else if (strstr(emit->code->name, "ork~") ||  // skip when recursing
+      (f != emit->env->func || (f && f->value_ref->from->owner_class)))
+    CHECK_BB(prepare_call(emit, call));
+  else CHECK_BB(emit_func_args(emit, call));
+  CHECK_BB(emit_exp_call1(emit, f, is_static_call(emit->gwion, call->func)));
   return GW_OK;
 }
 
@@ -1362,8 +1405,6 @@ ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call *exp_call) {
              tflag(e->type, tflag_struct))
     emit_regmove(emit, -SZ_INT);
   }
-//  if(isa(e->type, emit->gwion->type[et_object]) > 0)
-//    emit_local_exp(emit, e);
   return GW_OK;
 }
 
@@ -1632,7 +1673,7 @@ ANN static void emit_fptr_call(const Emitter emit, const Func f) {
 ANN static void call_finish(const Emitter emit, const Func f,
                           const bool is_static) {
   const m_uint offset = emit_code_offset(emit);
-  if (f != emit->env->func || !is_static || strcmp(s_name(f->def->base->xid), "new"))
+  if (f != emit->env->func || !is_static || !is_new(f->def))
     emit_setimm(emit, offset, 0);
   const Instr instr   = emit_call(emit, f, is_static);
   instr->m_val        = f->def->base->ret_type->size;
@@ -2712,8 +2753,15 @@ 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);
+  if(is_new(func->def)) {
+    const Type t = func->value_ref->from->owner_class;
+    if(!tflag(t, tflag_struct))
+      emit_add_instr(emit, RegPushMem);
+    else  {
+      const Instr instr = emit_add_instr(emit, RegPushMemDeref);
+      instr->m_val2 = t->size;
+    }
+  }
   return !fbflag(func->def->base, fbflag_internal) ? finalyze(emit, FuncReturn)
                                                    : emit_internal(emit, func);
 }
@@ -2843,7 +2891,7 @@ ANN static m_bool _emit_func_def(const Emitter emit, const Func_Def f) {
     return GW_OK;
   }
   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"))) {
+      safe_tflag(emit->env->class_def, tflag_tmpl)) || (fdef->base->tmpl && is_new(f))) {
     const Func base =
         nspc_lookup_func1(func->value_ref->from->owner, f->base->xid);
     builtin_func(emit->gwion, func, (f_xfun)base->code->native_func);
index 9a9ba746c81920c3b09366c63856f1712c0e63e1..a91886d6297198ade4c37273c400befaacc5a0a1 100644 (file)
@@ -130,7 +130,7 @@ ANN static void emit_dottmpl(const Emitter emit, const Func f) {
 ANN static void emit_member_func(const Emitter emit, const Exp_Dot *member) {
   const Func f = exp_self(member)->type->info->func;
 
-  if(!strcmp(s_name(f->def->base->xid), "new")) {
+  if(is_new(f->def)) {
     if(f != emit->env->func) emit_pushfunc(emit, f);
     return;
   }
@@ -143,7 +143,7 @@ ANN static void emit_member_func(const Emitter emit, const Exp_Dot *member) {
       return;
     }
   } else if (is_static_call(emit->gwion, exp_self(member))) {
-    if (member->is_call && f == emit->env->func && strcmp(s_name(f->def->base->xid), "new")) return;
+    if (member->is_call && f == emit->env->func && !is_new(f->def)) return;
     return emit_pushfunc(emit, f);
   } else {
     if (tflag(member->base->type, tflag_struct))
@@ -171,6 +171,7 @@ ANN static inline void emit_struct_data(const Emitter emit, const Value v,
                                         const bool emit_addr) {
   const Instr instr = emit_structmember(emit, v->type->size, emit_addr);
   instr->m_val      = v->from->offset;
+  instr->m_val2     = 3;
   if (!emit_addr) emit_regmove(emit, v->type->size - SZ_INT);
 }
 
index ab43adcd378493ad4322ac3faedc6d4594665681..9818126312600b8c70998536b2f947fd57379682 100644 (file)
@@ -140,9 +140,6 @@ OP_CHECK(opck_new) {
     self->d.exp_call.tmpl = NULL;
     self->exp_type = ae_exp_call;
     CHECK_BN(traverse_exp(env, self));
-//    const Type tbase = func->type->info->value->from->owner_class;
-//    if(!tflag(base->type, tflag_union) && tbase != base->type)
-//      ERR_N(base->pos, "'%s' has no matching constructor", base->type->name);
     return self->type;
   }
   if (GET_FLAG(t, abstract) &&
@@ -156,7 +153,8 @@ OP_CHECK(opck_new) {
 
 OP_EMIT(opem_new) {
   const Exp_Unary *unary = (Exp_Unary *)data;
-  CHECK_BB(emit_instantiate_object(emit, exp_self(unary)->type,
+  if(!tflag(exp_self(unary)->type, tflag_struct))
+    CHECK_BB(emit_instantiate_object(emit, exp_self(unary)->type,
                                    unary->ctor.td->array, 0));
   if(!unary->ctor.exp)
     emit_local_exp(emit, exp_self(unary));
index 2117b11377af487a1972695f1d7cad338c49e421..9d3ee8d82ac444d0b975dba82de50ebc368b0ed6 100644 (file)
@@ -148,11 +148,11 @@ ANN static inline m_bool inferable(const Env env, const Type t,
 ANN Type check_exp_decl(const Env env, Exp_Decl *const decl) {
   if (decl->td->array && decl->td->array->exp)
     CHECK_OO(check_exp(env, decl->td->array->exp));
-//  if (decl->args && !decl->args->type) { // for some reason this can be parsed twice
   if (decl->args) {
     const Exp e = new_exp_unary2(env->gwion->mp, insert_symbol("new"), cpy_type_decl(env->gwion->mp, decl->td), decl->args, decl->td->pos);
     CHECK_OO(check_exp(env, e));
     decl->args = e;
+    e->ref = exp_self(decl);
   }
   if (decl->td->xid == insert_symbol("auto")) { // should be better
     CHECK_BO(scan1_exp(env, exp_self(decl)));
@@ -894,11 +894,15 @@ ANN void call_add_effect(const Env env, const Func func, const loc_t pos) {
 }
 
 ANN Type _check_exp_call1(const Env env, Exp_Call *const exp) {
-  /* const */Type t = exp->func->type;
+  Type t = exp->func->type;
   if (!is_func(env->gwion, t)) { // use func flag?
     if(isa(exp->func->type, env->gwion->type[et_closure]) > 0)
       t = closure_def(t)->base->func->value_ref->type;
-    else {
+    else if(is_class(env->gwion, t) && tflag(t->info->base_type, tflag_struct)) {
+      const Value v = nspc_lookup_value0(t->info->base_type->nspc, insert_symbol("new"));
+      if(v) t = exp->func->type = v->type;
+      else return NULL;
+    } else {
       struct Op_Import opi = {.op   = insert_symbol("@ctor"),
                               .rhs  = actual_type(env->gwion, exp->func->type),
                               .data = (uintptr_t)exp,
@@ -910,13 +914,6 @@ ANN Type _check_exp_call1(const Env env, Exp_Call *const exp) {
   if (t == env->gwion->type[et_op]) return check_op_call(env, exp);
   if (!t->info->func) // TODO: effects?
     return check_lambda_call(env, exp);
-/*
-  if (fflag(t->info->func, fflag_ftmpl)) {
-    const Value value = t->info->func->value_ref;
-    if (value->from->owner_class)
-      CHECK_BO(ensure_traverse(env, value->from->owner_class));
-  }
-*/
   if (exp->args) {
     CHECK_OO(check_exp(env, exp->args));
     Exp e = exp->args;
@@ -927,23 +924,13 @@ ANN Type _check_exp_call1(const Env env, Exp_Call *const exp) {
     return check_exp_call_template(env, (Exp_Call *)exp); // TODO: effects?
   const Func func = find_func_match(env, t->info->func, exp);
   if (func) {
-/*
-    if (func != env->func && func->def && !fflag(func, fflag_valid)) {
-      if(func->value_ref->from->owner_class)
-        CHECK_BO(ensure_check(env, func->value_ref->from->owner_class));
-      else {
-        const m_uint scope = env_push(env, NULL, func->value_ref->from->owner);
-        const m_bool ret = check_func_def(env, func->def);
-        env_pop(env, scope);
-        CHECK_BO(ret);
-      }
-    }
-*/
     exp->func->type = func->value_ref->type;
     call_add_effect(env, func, exp->func->pos);
-// used in new. why???
-    return func->def->base->ret_type != env->gwion->type[et_auto] ?
-      func->def->base->ret_type : exp->func->d.exp_dot.base->type;
+    if(func->def->base->ret_type != env->gwion->type[et_auto])
+      return func->def->base->ret_type;
+    if(tflag(func->value_ref->from->owner_class, tflag_struct))
+      return func->value_ref->from->owner_class;
+    return exp->func->d.exp_dot.base->type;
   }
   if(exp->func->exp_type == ae_exp_lambda) {
     const Type tt = partial_type(env, exp);
@@ -968,7 +955,8 @@ ANN static Type check_static(const Env env, const Exp e) {
 ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
   DECL_BO(const m_bool, ret, = func_check(env, exp));
   if (!ret) return exp_self(exp)->type;
-  const Type t = exp->func->type;
+//  const Type t = actual_type(env->gwion, exp->func->type);
+/*  const */Type t = exp->func->type;
   CHECK_OO(check_static(env, exp->func));
   const Type _ret = _check_exp_call1(env, exp);
   if(_ret) return _ret;
@@ -982,7 +970,17 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
       if(t) return t;
     }
   }
-  function_alternative(env, t, exp->args, exp->func->pos);
+//puts(t->name);
+//  if(!is_func(env->gwion, t)) {
+//    if(is_class(env->gwion, t)) {
+//      const Value v = nspc_lookup_value0(t->info->base_type->nspc, insert_symbol("new"));
+//      if(v) t = v->type;
+//    }
+// else
+//  }
+//exit(3);
+  if(is_func(env->gwion, exp->func->type))
+    function_alternative(env, exp->func->type, exp->args, exp->func->pos);
   return NULL;
 }
 
@@ -1131,7 +1129,7 @@ ANN static Type check_exp_call(const Env env, Exp_Call *exp) {
     }
 // check for closure and b ring it back
     if (!is_func(env->gwion, t)) return check_exp_call1(env, exp);
-    if(strcmp("new", s_name(t->info->func->def->base->xid)))
+    if(!is_new(t->info->func->def))
       return check_exp_call_tmpl(env, exp, t);
   }
   return check_exp_call1(env, exp);
@@ -1409,7 +1407,7 @@ stmt_func_xxx(loop, Stmt_Loop, env_inline_mult(env, 1.5); check_idx(env, stmt->i
 stmt_func_xxx(each, Stmt_Each, env_inline_mult(env, 1.5), do_stmt_each(env, stmt))
 
 ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) {
-  if (!strcmp(s_name(env->func->def->base->xid), "new")) {
+  if (is_new(env->func->def)) {
     if(stmt->val)
       ERR_B(stmt_self(stmt)->pos,
             _("'return' statement inside constructor function should have no expression"))
index 3d973831489401c94e02e39c81a9e856594723f9..eb0231c332ad2d742f07342bc66cbe4c7ffd1765 100644 (file)
@@ -64,7 +64,7 @@ ANN void default_args(const Env env, const Section *s, Ast *acc) {
     Arg *arg = mp_vector_at(args, Arg, args->len);
     if(!arg->exp) break;
     Func_Base *const base = cpy_func_base(p, base_fdef->base);
-    Stmt_List code = strcmp("new", s_name(base->xid))
+    Stmt_List code = strcmp(s_name(base->xid), "new")
         ? std_code(env->gwion->mp, base, args, len)
         : new_code(env, base, args, len);
 //    const Stmt      body  = new_stmt_code(p, slist, base->pos);
index c7aefd8f4427bcd96169b46b53eb277f3c2aec9a..48742541f652ed1c8974cf914d34381a1c08f39c 100644 (file)
@@ -552,7 +552,7 @@ 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(is_new(fdef)) {
     if(!env->class_def)
       ERR_B(fdef->base->pos, _("{G+}new{0} operator must be set inside {C+}class{0}"));
     SET_FLAG(env->class_def, abstract);
diff --git a/tests/struct_ctor/struct_ctor_assign_get.gw b/tests/struct_ctor/struct_ctor_assign_get.gw
new file mode 100644 (file)
index 0000000..72a6980
--- /dev/null
@@ -0,0 +1,12 @@
+#! [contains] 42
+
+struct S {
+  12 :=> var int i;
+  var float f;
+  operator new(int i, int j) {
+    <<< i + j :=> this.i >>>;
+  }
+}
+
+S(21,21) :=> var auto s;
+<<< s.i >>>;
diff --git a/tests/struct_ctor/struct_ctor_assign_set.gw b/tests/struct_ctor/struct_ctor_assign_set.gw
new file mode 100644 (file)
index 0000000..e845d72
--- /dev/null
@@ -0,0 +1,11 @@
+#! [contains] 42
+
+struct S {
+  12 :=> var int i;
+  var float f;
+  operator new(int i, int j) {
+    <<< i + j :=> this.i >>>;
+  }
+}
+
+<<< 12 :=> (S(21,21) :=> var auto s).i >>>;
diff --git a/tests/struct_ctor/struct_ctor_decl_get.gw b/tests/struct_ctor/struct_ctor_decl_get.gw
new file mode 100644 (file)
index 0000000..99a0168
--- /dev/null
@@ -0,0 +1,12 @@
+#! [contains] 42
+
+struct S {
+  12 :=> var int i;
+  var float f;
+  operator new(int i, int j) {
+    <<< i + j :=> this.i >>>;
+  }
+}
+
+var S(21,21) w;
+<<< w.i >>>;
diff --git a/tests/struct_ctor/struct_ctor_decl_set.gw b/tests/struct_ctor/struct_ctor_decl_set.gw
new file mode 100644 (file)
index 0000000..1af53ac
--- /dev/null
@@ -0,0 +1,12 @@
+#! [contains] 42
+
+struct S {
+  12 :=> var int i;
+  var float f;
+  operator new(int i, int j) {
+    <<< i + j :=> this.i >>>;
+  }
+}
+
+12 :=> (var S(21,21) w).i;
+<<< w.i >>>;
diff --git a/tests/struct_ctor/struct_ctor_new_get.gw b/tests/struct_ctor/struct_ctor_new_get.gw
new file mode 100644 (file)
index 0000000..ece50c8
--- /dev/null
@@ -0,0 +1,11 @@
+#! [contains] 42
+
+struct S {
+  12 :=> var int i;
+  var float f;
+  operator new(int i, int j) {
+    <<< i + j :=> this.i >>>;
+  }
+}
+
+(new S(21,21)).i;
diff --git a/tests/struct_ctor/struct_ctor_new_set.gw b/tests/struct_ctor/struct_ctor_new_set.gw
new file mode 100644 (file)
index 0000000..e6b1052
--- /dev/null
@@ -0,0 +1,11 @@
+#! [contains] 13
+
+struct S {
+  12 :=> var int i;
+  var float f;
+  operator new(int i, int j) {
+    <<< i + j :=> this.i >>>;
+  }
+}
+
+<<< 13 :=> (new S(21,21)).i >>>;
diff --git a/tests/struct_ctor/struct_ctor_simple_get.gw b/tests/struct_ctor/struct_ctor_simple_get.gw
new file mode 100644 (file)
index 0000000..d4ebecb
--- /dev/null
@@ -0,0 +1,11 @@
+#! [contains] 42
+
+struct S {
+  12 :=> var int i;
+  var float f;
+  operator new(int i, int j) {
+    <<< i + j :=> this.i >>>;
+  }
+}
+
+<<< (S(21,21)).i >>>;
diff --git a/tests/struct_ctor/struct_ctor_simple_set.gw b/tests/struct_ctor/struct_ctor_simple_set.gw
new file mode 100644 (file)
index 0000000..4e8c3f4
--- /dev/null
@@ -0,0 +1,11 @@
+#! [contains] 13
+
+struct S {
+  12 :=> var int i;
+  var float f;
+  operator new(int i, int j) {
+    <<< i + j :=> this.i >>>;
+  }
+}
+
+<<< 13 :=> (S(21,21)).i >>>;