From 7dedc7939a9b69a375c7ad62c69cb7100482c8c9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Tue, 29 Mar 2022 11:51:04 +0200 Subject: [PATCH] :art: Improve new semantics --- plug | 2 +- src/lib/lib_func.c | 2 +- src/lib/opfunc.c | 3 +++ src/parse/check.c | 6 +++++- src/parse/scan2.c | 1 + tests/ctor/missing.gw | 6 ++++++ tests/tree/inherit.gw | 14 ++++++++++++++ 7 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 tests/ctor/missing.gw create mode 100644 tests/tree/inherit.gw diff --git a/plug b/plug index 7fa0a948..3cdb9fee 160000 --- a/plug +++ b/plug @@ -1 +1 @@ -Subproject commit 7fa0a948f67335204cab7b72e4837b99699c2d32 +Subproject commit 3cdb9feede115e9c1728ebc93d6de7d08f0e7891 diff --git a/src/lib/lib_func.c b/src/lib/lib_func.c index f0af5559..dd20b8f1 100644 --- a/src/lib/lib_func.c +++ b/src/lib/lib_func.c @@ -588,7 +588,7 @@ static OP_CHECK(opck_op_impl) { // if (eff && !check_effect_overload(eff, func)) // ERR_N(impl->pos, _("`{+Y}%s{0}` has effects not present in `{+G}%s{0}`\n"), // s_name(impl->e->d.prim.d.var), func->name); - Value v = nspc_lookup_value0(opi.nspc, impl->e->d.prim.d.var); + const Value v = nspc_lookup_value0(opi.nspc, impl->e->d.prim.d.var); if (v) { const m_uint scope = env_push(env, NULL, opi.nspc); _lhs.next = &_rhs; diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index 9ec842fd..a3ca7f07 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -136,6 +136,9 @@ 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) && diff --git a/src/parse/check.c b/src/parse/check.c index a546b494..8cf11d70 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -1867,7 +1867,6 @@ ANN static inline bool type_is_recurs(const Type t, const Type tgt) { ANN static m_bool recursive_type_base(const Env env, const Type t); ANN static bool recursive_type(const Env env, const Type t, const Type tgt); ANN static bool recursive_value(const Env env, const Type t, const Value v) { -//if(!v->from->owner_class)exit(13); const Type tgt = array_base(v->type); if(type_is_recurs(t, tgt)) { env_err(env, v->from->loc, _("recursive type")); @@ -1949,6 +1948,11 @@ ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) { if (cflag(cdef, cflag_struct) || class_def_has_body(env, cdef->body)) set_tflag(t, tflag_ctor); } + if(t->info->parent->nspc && nspc_lookup_value0(t->info->parent->nspc, insert_symbol("new")) && !nspc_lookup_value0(t->nspc, insert_symbol("new"))) { + env_err(env, cdef->pos, "must define 'new' operator"); + env_warn(env, t->info->parent->info->value->from->loc, "defined here"); + return GW_ERROR; + } if (!GET_FLAG(cdef, abstract)) CHECK_BB(check_abstract(env, cdef)); if (cdef->traits) { ID_List list = cdef->traits; diff --git a/src/parse/scan2.c b/src/parse/scan2.c index f706fe69..993aca8a 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -568,6 +568,7 @@ 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}")); + SET_FLAG(env->class_def, abstract); if(!fdef->base->ret_type) // fdef->base->ret_type = env->class_def; fdef->base->ret_type = env->gwion->type[et_auto]; diff --git a/tests/ctor/missing.gw b/tests/ctor/missing.gw new file mode 100644 index 00000000..ff73ef54 --- /dev/null +++ b/tests/ctor/missing.gw @@ -0,0 +1,6 @@ +#! [contains] must define 'new' operator +class C { + operator new() {} +} +class D extends C {} +<<< "lol" >>>; diff --git a/tests/tree/inherit.gw b/tests/tree/inherit.gw new file mode 100644 index 00000000..bdd80d69 --- /dev/null +++ b/tests/tree/inherit.gw @@ -0,0 +1,14 @@ +class baseClass {} + +class childClass extends baseClass { + "test" => var string param; +} + +class testClass { + var static baseClass classHolder; +} + +var testClass tc; + +var childClass cc => tc.classHolder; +<<< cc.param >>>; -- 2.43.0