}
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
}
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");
}
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);
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))
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;
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)
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);
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);