From 472805ec05746493309c715b65a0a446283e7ddc Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Thu, 18 Nov 2021 17:55:15 +0100 Subject: [PATCH] :art: Improve array semantics --- include/parse.h | 7 +++++++ src/emit/emit.c | 3 ++- src/lib/array.c | 9 +++++---- src/lib/opfunc.c | 9 +++++---- src/parse/scan1.c | 10 ++++++++-- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/include/parse.h b/include/parse.h index 0bd829e9..f70845fb 100644 --- a/include/parse.h +++ b/include/parse.h @@ -108,4 +108,11 @@ ANN static inline bool is_hole(const Env env, const Exp exp) { } return false; } + +static inline bool exp_is_zero(const Exp exp) { + return exp->exp_type == ae_exp_primary && + exp->d.prim.prim_type == ae_prim_num && + !exp->d.prim.d.num; +} + #endif diff --git a/src/emit/emit.c b/src/emit/emit.c index e0acdbad..37aa075a 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1103,7 +1103,8 @@ ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl *decl) { } set_late(emit->gwion, decl, list->self); if (!exp_self(decl)->emit_var && GET_FLAG(array_base_simple(v->type), abstract) && !GET_FLAG(decl->td, late) && - GET_FLAG(v, late) && late_array(decl->td, list->self)) { + GET_FLAG(v, late) && late_array(decl->td, list->self) + && GET_FLAG(v->type, abstract)) { env_warn(emit->env, decl->td->pos, _("Type '%s' is abstract, use {+G}late{0} instead of {G+}%s{0}"), v->type->name, !GET_FLAG(decl->td, const) ? "var" : "const"); } diff --git a/src/lib/array.c b/src/lib/array.c index 3d73d2f5..b26d4a27 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -668,14 +668,15 @@ static OP_CHECK(opck_array_scan) { base->info->value->from->owner); (void)scan0_class_def(env, cdef); const Type t = cdef->base.type; + if (GET_FLAG(base, abstract) && !tflag(base, tflag_union)) + SET_FLAG(t, abstract); + else + UNSET_FLAG(t, abstract); const m_bool ret = traverse_cdef(env, t); + UNSET_FLAG(t, abstract); env_pop(env, scope); env->context = ctx; if (ret == GW_ERROR) return NULL; - if (GET_FLAG(base, abstract)) - SET_FLAG(t, abstract); - else - UNSET_FLAG(t, abstract); set_tflag(t, tflag_emit); t->array_depth = base->array_depth + 1; t->info->base_type = array_base(base); diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index 1bcb49f5..751a9d20 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -116,6 +116,7 @@ ANN Type check_td(const Env env, Type_Decl *td); OP_CHECK(opck_new) { Exp_Unary *unary = (Exp_Unary *)data; + const Array_Sub array = unary->ctor.td->array; DECL_ON(const Type, t, = known_type(env, unary->ctor.td)); CHECK_BN(ensure_traverse(env, t)); if (type_ref(t)) @@ -123,12 +124,12 @@ OP_CHECK(opck_new) { if (tflag(t, tflag_infer)) ERR_N(unary->ctor.td->pos, _("can't use 'new' on '%s'\n"), t->name); - if (unary->ctor.td->array) CHECK_BN(check_subscripts(env, unary->ctor.td->array, 1)); + if (array) CHECK_BN(check_subscripts(env, array, 1)); if(unary->ctor.exp) { const Exp self = exp_self(unary); const Exp args = cpy_exp(env->gwion->mp, unary->ctor.exp); const Exp base = new_exp_unary2(env->gwion->mp, unary->op, unary->ctor.td, unary->ctor.exp, self->pos); -base->type = t; + base->type = t; 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; @@ -136,9 +137,9 @@ base->type = t; self->exp_type = ae_exp_call; CHECK_BN(traverse_exp(env, self)); return self->type; -// unarytype } - if (GET_FLAG(t, abstract)) + if (GET_FLAG(t, abstract) && + (!array || (array->exp && exp_is_zero(array->exp)))) ERR_N(unary->ctor.td->pos, _("can't use 'new' on abstract type '%s'\n"), t->name); if (isa(t, env->gwion->type[et_object]) < 0) diff --git a/src/parse/scan1.c b/src/parse/scan1.c index e1724fd8..1dd7988b 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -97,6 +97,10 @@ static inline uint array_ref(const Array_Sub array) { return array && !array->exp; } +static inline bool array_ref2(const Array_Sub array) { + return array && !(array->exp && exp_is_zero(array->exp)); +} + ANN static m_bool scan1_decl(const Env env, const Exp_Decl *decl) { Var_Decl_List list = decl->list; const uint decl_ref = array_ref(decl->td->array); @@ -110,11 +114,13 @@ ANN static m_bool scan1_decl(const Env env, const Exp_Decl *decl) { CHECK_OB((t = array_type(env, decl->type, var->array->depth))); } const Type base = array_base_simple(t); + if (GET_FLAG(base, abstract) && - ((var->array && var->array->exp) || - (decl->td->array && decl->td->array->exp))) + (array_ref2(var->array) || + array_ref2(decl->td->array))) ERR_B(var->pos, _("arrays of abstract type '%s' must be declared empty"), base->name); + const Value v = var->value = var->value ?: new_value(env->gwion->mp, t, s_name(var->xid)); nspc_add_value(env->curr, var->xid, v); -- 2.43.0