From: Jérémie Astor Date: Sun, 3 Apr 2022 21:38:06 +0000 (+0200) Subject: :art: Improve templates and typedefs X-Git-Tag: nightly~336 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=6b7092729cff03a744efb4a5f3fcb472396eb993;p=gwion.git :art: Improve templates and typedefs --- diff --git a/src/emit/emit.c b/src/emit/emit.c index 678eae0c..44c5bf6e 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -485,7 +485,7 @@ m_bool emit_instantiate_object(const Emitter emit, const Type type, if(!tflag(type, tflag_typedef)) { const Instr instr = emit_add_instr(emit, ObjectInstantiate); instr->m_val2 = (m_uint)type; - } + } // maybe we should instantiate the first actual type CHECK_BB(emit_pre_ctor(emit, type)); } return GW_OK; @@ -2546,6 +2546,11 @@ ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) { ANN static m_bool emit_type_def(const Emitter emit, const Type_Def tdef) { if (tdef->when) CHECK_BB(emit_func_def(emit, tdef->when_def)); + + if (!is_fptr(emit->gwion, tdef->type) && !tflag(tdef->type, tflag_cdef)) { + if(!tflag(tdef->type->info->parent, tflag_emit)) + return emit_class_def(emit, tdef->type->info->parent->info->cdef); + } return (!is_fptr(emit->gwion, tdef->type) && tdef->type->info->cdef) ? emit_class_def(emit, tdef->type->info->cdef) : GW_OK; diff --git a/src/env/type.c b/src/env/type.c index 599b0c04..8801e95e 100644 --- a/src/env/type.c +++ b/src/env/type.c @@ -22,6 +22,8 @@ ANN void free_type(const Type a, struct Gwion_ *const gwion) { else if (tflag(a, tflag_cdef)) class_def_cleaner(gwion, a->info->cdef); } + if (tflag(a, tflag_cdef) && a->info->parent) + type_remref(a->info->parent, gwion); if (a->effects.ptr) vector_release(&a->effects); if (a->nspc) nspc_remref(a->nspc, gwion); if (a->info->tuple) free_tupleform(a->info->tuple, gwion); diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index a3ca7f07..41fbf850 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -136,9 +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); +// 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 8cf11d70..d93ab1c6 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -1105,6 +1105,11 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) { ret_id->type = tdef->type; tdef->when_def = fdef; } + if (!is_fptr(env->gwion, tdef->type) && !tflag(tdef->type, tflag_cdef)) { + if(!tflag(tdef->type->info->parent, tflag_check)) + return check_class_def(env, tdef->type->info->parent->info->cdef); + } + return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ? check_class_def(env, tdef->type->info->cdef) : GW_OK; @@ -1948,11 +1953,14 @@ 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); } +/* + // enforce new to be defined in every child class 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/operator.c b/src/parse/operator.c index ec73bd33..4d98d223 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -216,7 +216,7 @@ ANN bool tmpl_match(const Env env, const struct Op_Import *opi, Specialized_List sl = base->tmpl->list; const Arg_List args = base->args; Arg *arg0 = mp_vector_at(args, Arg, 0); - Arg *arg1 = mp_vector_at(args, Arg, 1); + Arg *arg1 = args->len > 1 ? mp_vector_at(args, Arg, 1) : NULL; uint32_t idx = 0; if (opi->lhs) { if (!_tmpl_match(env, opi->lhs, arg0->td, mp_vector_at(sl, Specialized, idx), &idx)) return false; @@ -235,16 +235,20 @@ ANN bool tmpl_match(const Env env, const struct Op_Import *opi, } //! make template operator Func_def -ANN Type op_def(const Env env, struct Op_Import *const opi, +ANN static Type op_def(const Env env, struct Op_Import *const opi, const Func_Def fdef) { const Func_Def tmpl_fdef = cpy_func_def(env->gwion->mp, fdef); tmpl_fdef->base->tmpl->base = 0; tmpl_fdef->base->tmpl->call = new_mp_vector(env->gwion->mp, - sizeof(Type_Decl*), !!opi->lhs + !!opi->rhs); + sizeof(Type_Decl*), fdef->base->tmpl->list->len); if (opi->lhs) { - mp_vector_set(tmpl_fdef->base->tmpl->call, Type_Decl*, 0, type2td(env->gwion, opi->lhs, opi->pos)); - if(opi->rhs) - mp_vector_set(tmpl_fdef->base->tmpl->call, Type_Decl*, 1, type2td(env->gwion, opi->rhs, opi->pos)); + uint32_t idx = 0; + const Type lhs = find_type(env, mp_vector_at(fdef->base->args, Arg, 0)->td); + if(!lhs) + mp_vector_set(tmpl_fdef->base->tmpl->call, Type_Decl*, idx++, type2td(env->gwion, opi->lhs, opi->pos)); + const Type rhs = find_type(env, mp_vector_at(fdef->base->args, Arg, 1)->td); + if(!rhs) + mp_vector_set(tmpl_fdef->base->tmpl->call, Type_Decl*, idx, type2td(env->gwion, opi->rhs, opi->pos)); } else mp_vector_set(tmpl_fdef->base->tmpl->call, Type_Decl*, 0, type2td(env->gwion, opi->rhs, opi->pos)); if (traverse_func_def(env, tmpl_fdef) < 0) { diff --git a/src/parse/scan0.c b/src/parse/scan0.c index 9e1e5f77..1c8eb9c6 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -153,6 +153,7 @@ ANN static m_bool typedef_complex(const Env env, const Type_Def tdef, CHECK_BB(scan0_class_def(env, cdef)); tdef->type = cdef->base.type; cdef->base.tmpl = tdef->tmpl; // check cpy + set_tflag(tdef->type, tflag_cdef); mk_class(env, tdef->type, tdef->pos); return GW_OK; } @@ -180,14 +181,14 @@ ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) { env_push_global(env); } if (!is_func(env->gwion, base)) { - if (!tdef->ext->types && (!tdef->ext->array || !tdef->ext->array->exp)) + if (!tdef->ext->types && (!tdef->ext->array || !tdef->ext->array->exp)) { typedef_simple(env, tdef, base); - else + } else CHECK_BB(typedef_complex(env, tdef, base)); } else typedef_fptr(env, tdef, base); if (tdef->when) set_tflag(tdef->type, tflag_contract); - if (!tdef->distinct && !tdef->when) + if (tdef->type != base && !tdef->distinct && !tdef->when) scan0_implicit_similar(env, base, tdef->type); if (tdef->distinct || tdef->when) { // tdef->type->info->parent = base->info->parent; @@ -198,14 +199,15 @@ ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) { op_cpy(env, &opi); scan0_explicit_distinct(env, base, tdef->type); type_addref(tdef->type); // maybe because of scope_iter in nspc_free_values - } else + } else if(tdef->ext->array) set_tflag(tdef->type, tflag_typedef); if(tflag(base, tflag_ref)) { set_tflag(tdef->type, tflag_ref); set_tflag(tdef->type, tflag_infer); } if (global) env_pop(env, 0); - tdef->type->info->base_type = base; + if (tdef->type != base) + tdef->type->info->base_type = base; return GW_OK; } @@ -346,6 +348,7 @@ ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) { CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos)); const Type parent = cdef_parent(env, cdef); if (parent == (Type)GW_ERROR) return NULL; + if(parent) type_addref(parent); if (cdef->traits) CHECK_BO(find_traits(env, cdef->traits, cdef->pos)); const Type t = scan0_type(env, s_name(cdef->base.xid), parent); if (cflag(cdef, cflag_struct)) { diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 04b22415..a18ccf29 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -477,6 +477,13 @@ ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) { ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) { if (!tdef->type) tdef->type = nspc_lookup_type0(env->curr, tdef->xid); if (tdef->when) CHECK_BB(scan1_exp(env, tdef->when)); + if (!is_fptr(env->gwion, tdef->type) && !tflag(tdef->type, tflag_cdef)) { + if(!tflag(tdef->type->info->parent, tflag_scan1)) + return scan1_class_def(env, tdef->type->info->parent->info->cdef); + } + if (!is_fptr(env->gwion, tdef->type) && !tdef->type->info->cdef) { + if(!tflag(tdef->type->info->parent, tflag_scan1))exit(12); + } return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ? scan1_cdef(env, tdef->type) : GW_OK; diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 993aca8a..da9eff7e 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -89,6 +89,10 @@ ANN m_bool scan2_fptr_def(const Env env NUSED, const Fptr_Def fptr) { ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f); ANN m_bool scan2_type_def(const Env env, const Type_Def tdef) { if (tdef->when) CHECK_BB(scan2_exp(env, tdef->when)); + if (!is_fptr(env->gwion, tdef->type) && !tflag(tdef->type, tflag_cdef)) { + if(!tflag(tdef->type->info->parent, tflag_scan2)) + return scan2_class_def(env, tdef->type->info->parent->info->cdef); + } if (!tdef->type->info->cdef) return GW_OK; return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ? scan2_class_def(env, tdef->type->info->cdef) diff --git a/src/parse/template.c b/src/parse/template.c index 00392f10..eaf5b67b 100644 --- a/src/parse/template.c +++ b/src/parse/template.c @@ -20,7 +20,6 @@ ANN static m_bool _push_types(const Env env, const Nspc nspc, for(uint32_t i = 0; i < sl->len; i++) { if (i >= tl->len) return GW_OK; Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i); -// const Type t = td ? known_type(env, td) : NULL; const Type t = known_type(env, td); if (!t) return GW_OK; Specialized *spec = mp_vector_at(sl, Specialized, i); @@ -114,7 +113,7 @@ static ANN Type maybe_func(const Env env, const Type t, const Type_Decl *td) { t->name) } -ANN Type _scan_type(const Env env, const Type t, Type_Decl *td) { +ANN static Type _scan_type(const Env env, const Type t, Type_Decl *td) { if (tflag(t, tflag_tmpl) && !is_func(env->gwion, t)) { if (tflag(t, tflag_ntmpl) && !td->types) return t; if(!td->types) { diff --git a/tests/ctor/missing.gw b/tests/ctor/missing.gw deleted file mode 100644 index ff73ef54..00000000 --- a/tests/ctor/missing.gw +++ /dev/null @@ -1,6 +0,0 @@ -#! [contains] must define 'new' operator -class C { - operator new() {} -} -class D extends C {} -<<< "lol" >>>;