From: Jérémie Astor Date: Sun, 16 May 2021 11:44:50 +0000 (+0200) Subject: :art: Fix distinct and contracts X-Git-Tag: nightly~656 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=18aa0d9fbd1a4069bc84c13a0ae73230d472f3c0;p=gwion.git :art: Fix distinct and contracts --- diff --git a/include/operator.h b/include/operator.h index b376f828..d90afd79 100644 --- a/include/operator.h +++ b/include/operator.h @@ -45,6 +45,7 @@ struct TemplateScan { const Type_Decl *td; }; +ANN void op_cpy(const Env env, const struct Op_Import* opi); ANN m_bool add_op(const Gwion gwion, const struct Op_Import*); ANN Type op_check(const Env, struct Op_Import*); ANN m_bool op_emit(const Emitter, const struct Op_Import*); diff --git a/src/lib/engine.c b/src/lib/engine.c index 977ddc5f..28f6785b 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -73,9 +73,14 @@ static OP_CHECK(opck_basic_ctor) { ERR_N(exp_self(call)->pos, _("can't call a non-callable value")); } +static ID_CHECK(idck_predicate) { + set_fflag(env->func, fflag_return); + return exp_self(prim)->type; +} + static INSTR(PredicateCheck) { if(!*(m_uint*)REG(-SZ_INT)) - handle(shred, "predicate failed"); + handle(shred, "PredicateFail"); } ANN static m_bool import_core_libs(const Gwi gwi) { @@ -132,7 +137,7 @@ ANN static m_bool import_core_libs(const Gwi gwi) { gwi_specialid(gwi, "now", &spid); gwidoc(gwi, "internal predicate representation."); - struct SpecialId_ predicate = { .type=t_void, .exec=PredicateCheck, .is_const=1 }; + struct SpecialId_ predicate = { .type=t_void, .ck=idck_predicate, .exec=PredicateCheck, .is_const=1 }; gwi_specialid(gwi, "@predicate", &predicate); gwidoc(gwi, "internal base of all objects and structures."); diff --git a/src/parse/check.c b/src/parse/check.c index 1e26a028..ccaf3651 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -947,6 +947,8 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) { const Exp when = cpy_exp(env->gwion->mp, tdef->when); when->next = helper; const Stmt stmt = new_stmt_exp(env->gwion->mp, ae_stmt_exp, when, when->pos); +// const Stmt stmt_return = new_stmt_exp(env->gwion->mp, ae_stmt_return, new_prim_id(env->gwion->mp, insert_symbol("self"), when->pos), when->pos); +// const Stmt_List ret_list = new_stmt_list(env->gwion->mp, stmt_return, NULL);//ret_list); const Stmt_List body = new_stmt_list(env->gwion->mp, stmt, NULL);//ret_list); const Stmt code = new_stmt_code(env->gwion->mp, body, when->pos); const Func_Def fdef = new_func_def(env->gwion->mp, fb, code); @@ -980,6 +982,7 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) { ret_id->type = tdef->type; body->next = ret_list; tdef->when_def = fdef; + } return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ? check_class_def(env, tdef->type->info->cdef) : GW_OK; diff --git a/src/parse/operator.c b/src/parse/operator.c index 4f4a77b4..11fb0da3 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -148,7 +148,7 @@ ANN static inline Type op_parent(const Env env, const Type t) { array_type(env, array_base(t)->info->parent, depth); } -ANN static Type op_check_inner(struct OpChecker* ock, const uint i) { +ANN static Type op_check_inner(const Env env, struct OpChecker* ock, const uint i) { Type t, r = ock->opi->rhs; do { const M_Operator* mo; @@ -160,7 +160,7 @@ ANN static Type op_check_inner(struct OpChecker* ock, const uint i) { } else return mo->ret; } - } while(r && (r = r->info->parent)); + } while(r && (r = op_parent(env, r))); return NULL; } @@ -174,7 +174,7 @@ for(int i = 0; i < 2; ++i) { do { struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data }; struct OpChecker ock = { .env=env, .map=&nspc->info->op_map, .opi=&opi2 }; - const Type ret = op_check_inner(&ock, i); + const Type ret = op_check_inner(env, &ock, i); if(ret) { if(ret == env->gwion->type[et_error]) return NULL; @@ -252,3 +252,71 @@ ANN m_bool op_emit(const Emitter emit, const struct Op_Import* opi) { } return GW_ERROR; } + +#define CONVERT(t) t != from ? t : to +ANN static M_Operator* cpy_mo(MemPool p, M_Operator *const base, + const Type from, const Type to) { + M_Operator* mo = mp_calloc(p, M_Operator); + mo->lhs = CONVERT(base->lhs); + mo->rhs = CONVERT(base->rhs); + mo->ret = CONVERT(base->ret); + mo->instr = base->instr; + mo->func = base->func; + mo->ck = base->ck; + mo->em = base->em; + if(base->effect.ptr) { + vector_init(&mo->effect); + vector_copy2(&base->effect, &mo->effect); + } + return mo; +} +#undef CONVERT + +ANN static inline Map ensure_map(const Nspc nspc) { + const Map map = &nspc->info->op_map; + if(!map->ptr) + map_init(map); + return map; +} + +ANN static inline Vector ensure_vec(const MemPool mp, const Map map, const m_uint key) { + const Vector exists = (Vector)map_get(map, key); + if(exists) + return exists; + const Vector vec = new_vector(mp); + map_set(map, key, (m_uint)vec); + return vec; +} + +ANN static void op_visit(const MemPool mp, const Nspc nspc, const struct Op_Import* opi, const Vector visited) { + if(vector_find(visited, (m_uint)nspc) != -1) + return; + vector_add(visited, (m_uint)nspc); + if(nspc->info->op_map.ptr) { + const Map map = &nspc->info->op_map; + const Map base_map = ensure_map(opi->rhs->info->value->from->owner); + for(m_uint i = 0; i < map_size(map); i++) { + const Vector v = (Vector)map_at(map, i); + const m_uint sz = vector_size(v); + for(m_uint j = 0; j < sz; j++) { + M_Operator *const mo = (M_Operator*)vector_at(v, j); + if(opi->lhs == mo->lhs || opi->lhs == mo->rhs || opi->lhs == mo->ret) { + const M_Operator* tmp = cpy_mo(mp, mo, opi->lhs, opi->rhs); + const Vector target = ensure_vec(mp, base_map, VKEY(map, i)); + vector_add(target, (vtype)tmp); + } + } + } + } + if(nspc->parent) + op_visit(mp, nspc->parent, opi, visited); +} + +ANN void op_cpy(const Env env, const struct Op_Import* opi) { + struct Vector_ visited; + vector_init(&visited); + op_visit(env->gwion->mp, opi->rhs->info->value->from->owner, opi, &visited); + op_visit(env->gwion->mp, opi->lhs->info->value->from->owner, opi, &visited); + op_visit(env->gwion->mp, env->curr, opi, &visited); + vector_release(&visited); +} diff --git a/src/parse/scan0.c b/src/parse/scan0.c index a6c37acb..ff214eb5 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -108,6 +108,12 @@ ANN /*static */void scan0_implicit_similar(const Env env, const Type lhs, const add_op(env->gwion, &opi); } +ANN static void scan0_explicit_distinct(const Env env, const Type lhs, const Type rhs) { + struct Op_Func opfunc = { .ck=opck_cast_similar }; + struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .func=&opfunc }; + add_op(env->gwion, &opi); +} + ANN static void typedef_simple(const Env env, const Type_Def tdef, const Type base) { const Type t = scan0_type(env, s_name(tdef->xid), base); t->size = base->size; @@ -164,12 +170,20 @@ ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) { } else typedef_fptr(env, tdef, base); if(!tdef->distinct && !tdef->when) - scan0_implicit_similar(env, tdef->type, base); - if(tdef->distinct) + scan0_implicit_similar(env, base, tdef->type); + if(tdef->distinct) { + tdef->type->info->parent = base->info->parent; + if(base->info->gack) + vmcode_addref(tdef->type->info->gack = base->info->gack); set_tflag(tdef->type, tflag_distinct); + struct Op_Import opi = { .lhs=base, .rhs=tdef->type }; + 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 + set_tflag(tdef->type, tflag_typedef); if(global) env_pop(env, 0); - set_tflag(tdef->type, tflag_typedef); return GW_OK; } diff --git a/tests/pp/pragma.gw b/tests/pp/pragma.gw index 2a72b4f4..76812b5b 100644 --- a/tests/pp/pragma.gw +++ b/tests/pp/pragma.gw @@ -2,8 +2,7 @@ fun int recursive_fib(int n) { if (n < 2) return n; - else - return recursive_fib(n - 2) + recursive_fib(n - 1); + return recursive_fib(n - 2) + recursive_fib(n - 1); } <<< 6 => recursive_fib >>>; <<< 6 => recursive_fib >>>;