]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve array semantics
authorJérémie Astor <fennecdjay@gmail.com>
Thu, 18 Nov 2021 16:55:15 +0000 (17:55 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Thu, 18 Nov 2021 16:55:15 +0000 (17:55 +0100)
include/parse.h
src/emit/emit.c
src/lib/array.c
src/lib/opfunc.c
src/parse/scan1.c

index 0bd829e9381e7f483400321ff9b23b29740d5eb1..f70845fbd0465e7e25a7eecdd57febcf067aa148 100644 (file)
@@ -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
index e0acdbad191d2e20cb4983be1722e7698a0c2137..37aa075aee27a2629c1a2346acd9460672673cf8 100644 (file)
@@ -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");
     }
index 3d73d2f54dbbdffa5b1f796b33d2ea9485c7fc76..b26d4a2773f97def180a38240f7d2cd584a87c9d 100644 (file)
@@ -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);
index 1bcb49f52495f27c29580e12778e977b393608d0..751a9d2082a5dcc19250d9025e846ff23ca0ec0a 100644 (file)
@@ -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)
index e1724fd8d65209be96a5a5699546218691aa1679..1dd7988b3093442bc90e2ca015e4c3ceccdd39ce 100644 (file)
@@ -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);