From b061320eff517ffd569855b204c73da20baf1739 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Thu, 29 Apr 2021 17:29:48 +0200 Subject: [PATCH] :art: More on effects --- include/env/env.h | 1 + include/env/type.h | 36 +++++++++++++++++---------------- src/lib/lib_func.c | 24 +++++++++++++++++++--- src/lib/ref.c | 1 + src/parse/check.c | 50 +++++++++++++++++++++++++++++++++++----------- src/parse/scan1.c | 12 ++++++++++- 6 files changed, 91 insertions(+), 33 deletions(-) diff --git a/include/env/env.h b/include/env/env.h index 4425fabb..8ff18c12 100644 --- a/include/env/env.h +++ b/include/env/env.h @@ -56,4 +56,5 @@ struct ScopeEffect { ANN void env_add_effect(const Env a, const Symbol effect, const loc_t pos); ANN void call_add_effect(const Env env, const Func func, const loc_t pos); +ANN bool check_effect_overload(const Vector base, const Func override); #endif diff --git a/include/env/type.h b/include/env/type.h index 6cc503f1..70e9a5fa 100644 --- a/include/env/type.h +++ b/include/env/type.h @@ -15,24 +15,25 @@ struct TypeInfo_ { }; enum tflag { - tflag_none = 1 << 0, - tflag_scan0 = 1 << 1,// - tflag_scan1 = 1 << 2,// - tflag_scan2 = 1 << 3,// - tflag_check = 1 << 4,// - tflag_emit = 1 << 5,// - tflag_infer = 1 << 6, - tflag_empty = 1 << 7, - tflag_ftmpl = 1 << 8, - tflag_ntmpl = 1 << 9, // do NOT need types - tflag_udef = 1 << 10, - tflag_cdef = 1 << 11, - tflag_struct = 1 << 12, - tflag_ctor = 1 << 13, - tflag_dtor = 1 << 14, - tflag_tmpl = 1 << 15, - tflag_typedef = 1 << 16, + tflag_none = 1 << 0, + tflag_scan0 = 1 << 1,// + tflag_scan1 = 1 << 2,// + tflag_scan2 = 1 << 3,// + tflag_check = 1 << 4,// + tflag_emit = 1 << 5,// + tflag_infer = 1 << 6, + tflag_empty = 1 << 7, + tflag_ftmpl = 1 << 8, + tflag_ntmpl = 1 << 9, // do NOT need types + tflag_udef = 1 << 10, + tflag_cdef = 1 << 11, + tflag_struct = 1 << 12, + tflag_ctor = 1 << 13, + tflag_dtor = 1 << 14, + tflag_tmpl = 1 << 15, + tflag_typedef = 1 << 16, tflag_distinct = 1 << 17, + tflag_noret = 1 << 17, } __attribute__((packed)); struct Type_ { @@ -41,6 +42,7 @@ struct Type_ { struct TypeInfo_ *info; size_t size; size_t array_depth; + struct Vector_ effects; // pre-ctor effects uint16_t ref; ae_flag flag; enum tflag tflag; diff --git a/src/lib/lib_func.c b/src/lib/lib_func.c index 244b8b30..8fb80a5c 100644 --- a/src/lib/lib_func.c +++ b/src/lib/lib_func.c @@ -427,9 +427,12 @@ static OP_CHECK(opck_op_impl){ self.d.exp_binary.op = impl->e->d.prim.d.var; struct Op_Import opi = { .op=impl->e->d.prim.d.var, .lhs=func->def->base->args->type, .rhs=func->def->base->args->next->type, .data=(uintptr_t)&self.d.exp_binary, .pos=impl->e->pos }; + vector_add(&env->scope->effects, 0); DECL_ON(const Type, t, = op_check(env, &opi)); - CHECK_BN(isa(t, func->def->base->ret_type)); - // Find if the function exists + CHECK_BN(isa(t, func->def->base->ret_type)); // error message? + const m_uint _eff = vector_back(&env->scope->effects); + if(!check_effect_overload((Vector)&_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); if(v) { const m_uint scope = env_push(env, NULL, opi.nspc); @@ -437,8 +440,14 @@ static OP_CHECK(opck_op_impl){ Exp_Call call = { .args=&_lhs }; const Func exists = (Func)find_func_match(env, v->d.func_ref, &call); env_pop(env, scope); - if(exists) + if(exists) { // improve me + if(_eff) { + const M_Vector eff = (M_Vector)&_eff; + m_vector_release(eff); + 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); + } return actual_type(env->gwion, func->value_ref->type); + } } const Arg_List args = cpy_arg_list(env->gwion->mp, func->def->base->args); // beware shadowing ? @@ -446,6 +455,15 @@ static OP_CHECK(opck_op_impl){ args->next->var_decl->xid = rhs_sym; Func_Base *base = new_func_base(env->gwion->mp, type2td(env->gwion, t, impl->e->pos), impl->e->d.prim.d.var, args, ae_flag_none, impl->e->pos); + if(_eff) { + const M_Vector eff = (M_Vector)&_eff; + for (m_uint i = 0; i < m_vector_size(eff); i++) { + struct ScopeEffect effect; + m_vector_get(eff, i, &effect); + vector_add(&base->effects, (m_uint)effect.sym); + } + m_vector_release(eff); + } const Exp lhs = new_prim_id(env->gwion->mp, args->var_decl->xid, impl->e->pos); const Exp rhs = new_prim_id(env->gwion->mp, args->next->var_decl->xid, impl->e->pos); const Exp bin = new_exp_binary(env->gwion->mp, lhs, impl->e->d.prim.d.var, rhs, impl->e->pos); diff --git a/src/lib/ref.c b/src/lib/ref.c index eabcb74d..e938b231 100644 --- a/src/lib/ref.c +++ b/src/lib/ref.c @@ -63,6 +63,7 @@ static OP_CHECK(opck_ref_scan) { const Type t = new_type(env->gwion->mp, s_name(info.name), base); SET_FLAG(t, abstract | ae_flag_final); set_tflag(t, tflag_infer); + set_tflag(t, tflag_noret); const m_uint scope = env_push(env, base->info->value->from->owner_class, base->info->value->from->owner); mk_class(env, t, (loc_t){}); base2ref(env, base, t); diff --git a/src/parse/check.c b/src/parse/check.c index f141fe98..e2fc0ce5 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -87,6 +87,11 @@ ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) { ANN static m_bool check_var(const Env env, const Var_Decl var) { if(env->class_def && !env->scope->depth && env->class_def->info->parent) CHECK_BB(check_exp_decl_parent(env, var)); + if(var->value->type->effects.ptr) { + const Vector v = &var->value->type->effects; + for(m_uint i = 0; i < vector_size(v); i++) + env_add_effect(env, (Symbol)vector_at(v, i), var->pos); + } if(var->array && var->array->exp) return check_subscripts(env, var->array, 1); return GW_OK; @@ -749,6 +754,7 @@ ANN void call_add_effect(const Env env, const Func func, const loc_t pos) { env_add_effect(env, (Symbol)vector_at(v, i), pos); } } + ANN Type check_exp_call1(const Env env, Exp_Call *const exp) { DECL_BO(const m_bool, ret, = func_check(env, exp)); if(!ret) @@ -1128,6 +1134,8 @@ ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) { } if(isa(ret_type, env->func->def->base->ret_type) > 0) return GW_OK; + if(tflag(ret_type, tflag_noret)) + ERR_B(stmt->val->pos, _("Can't use type `{+G}%s{+G}` for return")); if(stmt->val) { if(env->func->def->base->xid == insert_symbol("@implicit") && ret_type == env->func->def->base->args->type) ERR_B(stmt_self(stmt)->pos, _("can't use implicit casting while defining it")) @@ -1397,14 +1405,14 @@ ANN static m_bool check_func_overload(const Env env, const Func_Def fdef) { return GW_OK; } -ANN bool check_effect_overload(const Func_Base *base, const Value override) { - if(!base->effects.ptr) +ANN bool check_effect_overload(const Vector base, const Func override) { + if(!base->ptr) return true; - if(!override->d.func_ref->def->base->effects.ptr) + if(!override->def->base->effects.ptr) return false; // TODO: error message - const Vector v = &override->d.func_ref->def->base->effects; + const Vector v = &override->def->base->effects; for(m_uint i = 0; i < vector_size(v); i++) { - if(vector_find((Vector)&base->effects, vector_at(v, i)) == -1) + if(vector_find((Vector)base, vector_at(v, i)) == -1) return false; } return true; @@ -1462,8 +1470,10 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { } vector_add(&env->scope->effects, 0); const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)check_fdef); - const m_uint _v = vector_pop(&env->scope->effects); + const m_uint _v = vector_back(&env->scope->effects); if(_v) { + if(fdef->base->xid == insert_symbol("@dtor")) + ERR_B(fdef->base->pos, _("can't use effects in destructors")); const Vector v = (Vector)&_v; const Vector base = &fdef->base->effects; if(!base->ptr) @@ -1475,6 +1485,7 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { } vector_release(v); } + vector_pop(&env->scope->effects); if(fbflag(fdef->base, fbflag_op)) operator_resume(&opi); nspc_pop_value(env->gwion->mp, env->curr); @@ -1482,7 +1493,7 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { env->func = former; if(ret > 0) { set_fflag(fdef->base->func, fflag_valid); - if(env->class_def && !check_effect_overload(fdef->base, override)) + if(env->class_def && !check_effect_overload(&fdef->base->effects, override->d.func_ref)) ERR_B(fdef->base->pos, _("too much effects in override."), s_name(fdef->base->xid)) @@ -1548,26 +1559,25 @@ ANN m_bool check_abstract(const Env env, const Class_Def cdef) { return !err ? GW_OK : GW_ERROR; } -ANN static inline void check_unhandled(const Env env) { +ANN static inline void ctor_effects(const Env env) { const Vector v = &env->scope->effects; const m_uint _w = vector_back(v); if(!_w) return; + vector_init(&env->class_def->effects); const M_Vector w = (M_Vector)&_w; for(m_uint j = 0; j < m_vector_size(w); j++) { struct ScopeEffect eff; m_vector_get(w, j, &eff); - gwerr_secondary("Unhandled effect", env->name, eff.pos); - env->context->error = false; + vector_add(&env->class_def->effects, (m_uint)eff.sym); } m_vector_release(w); vector_pop(v); } - ANN static m_bool check_body(const Env env, Section *const section) { const m_bool ret = check_section(env, section); - check_unhandled(env); + ctor_effects(env); return ret; } @@ -1601,6 +1611,22 @@ ANN m_bool check_class_def(const Env env, const Class_Def cdef) { return _check_class_def(env, cdef); } +ANN static inline void check_unhandled(const Env env) { + const Vector v = &env->scope->effects; + const m_uint _w = vector_back(v); + if(!_w) + return; + const M_Vector w = (M_Vector)&_w; + for(m_uint j = 0; j < m_vector_size(w); j++) { + struct ScopeEffect eff; + m_vector_get(w, j, &eff); + gwerr_secondary("Unhandled effect", env->name, eff.pos); + env->context->error = false; + } + m_vector_release(w); + vector_pop(v); +} + ANN m_bool check_ast(const Env env, Ast ast) { do CHECK_BB(check_section(env, ast->section)); while((ast = ast->next)); diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 3eda9547..6d7d971f 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -383,6 +383,9 @@ ANN static m_bool _scan1_fdef_base_tmpl(const Env env, Func_Base *base) { do nspc_add_type(env->curr, id->xid, env->gwion->type[et_auto]); while((id = id->next)); CHECK_OB((base->ret_type = known_type(env, base->td))); + if(tflag(base->ret_type, tflag_noret)) + ERR_B(base->pos, _("Can't use type `{+G}%s{0}` for return"), + base->ret_type->name); if(base->args) { Arg_List arg = base->args; do CHECK_OB(known_type(env, arg->td)); @@ -407,6 +410,9 @@ ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) { } const Func_Def fdef = fptr->base->func->def; CHECK_OB((fdef->base->ret_type = scan1_type(env, fdef->base->td))); + if(tflag(fdef->base->ret_type, tflag_noret)) + ERR_B(fdef->base->pos, _("Can't use type `{+G}%s{0}` for return"), + fdef->base->ret_type->name); if(!fdef->base->args) return GW_OK; RET_NSPC(scan1_args(env, fdef->base->args)) @@ -566,8 +572,12 @@ ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) { } ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) { - if(fdef->base->td) + if(fdef->base->td) { CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td))); + if(tflag(fdef->base->ret_type, tflag_noret)) + ERR_B(fdef->base->pos, _("Can't use type `{+G}%s{0}` for return"), + fdef->base->ret_type->name); + } if(fbflag(fdef->base, fbflag_internal)) CHECK_BB(scan_internal(env, fdef->base)); else if(fbflag(fdef->base, fbflag_op) && env->class_def) -- 2.43.0