From c5859b04fca6dfd49d30b2acac0ad69fdd475bc1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sat, 2 Oct 2021 11:42:14 +0200 Subject: [PATCH] :art: More on Ref and refinenemts --- include/env/type.h | 1 + include/import.h | 2 ++ src/emit/emit.c | 4 ++- src/lib/opfunc.c | 16 +++++++++++ src/lib/ref.c | 71 ++++++++++++++++++++++++++++++++++++++++++---- src/parse/check.c | 3 +- src/parse/scan0.c | 30 ++++++++++++++++---- 7 files changed, 113 insertions(+), 14 deletions(-) diff --git a/include/env/type.h b/include/env/type.h index 5efc523e..7d383e44 100644 --- a/include/env/type.h +++ b/include/env/type.h @@ -39,6 +39,7 @@ enum tflag { tflag_float = 1 << 20, tflag_union = 1 << 21, tflag_error = 1 << 22, + tflag_ref = 1 << 23, } __attribute__((packed)); struct Type_ { diff --git a/include/import.h b/include/import.h index e5e466a9..2de834d9 100644 --- a/include/import.h +++ b/include/import.h @@ -77,7 +77,9 @@ OP_CHECK(opck_unary); OP_CHECK(opck_post); OP_CHECK(opck_rassign); OP_CHECK(opck_basic_cast); +OP_CHECK(opck_similar_cast); OP_CHECK(opck_usr_implicit); +OP_EMIT(opem_contract_similar); OP_CHECK(opck_new); OP_EMIT(opem_new); diff --git a/src/emit/emit.c b/src/emit/emit.c index e4d6f0bf..2e61f74f 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -526,7 +526,9 @@ ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) { } return GW_OK; } - if (!strncmp(v->type->name, "Ref:[", 5) && (!prim_exp(data)->cast_to || strncmp(prim_exp(data)->cast_to->name, "Ref:[", 5))) { +// if (!strncmp(v->type->name, "Ref:[", 5) && (!prim_exp(data)->cast_to || strncmp(prim_exp(data)->cast_to->name, "Ref:[", 5))) { + if (tflag(v->type, tflag_ref) && !safe_tflag(prim_exp(data)->cast_to, tflag_ref)) { +//puts("here"); if (exp_getvar(exp_self(prim_self(data)))) { const Instr instr = emit_add_instr(emit, RegPushMem); instr->m_val = v->from->offset; diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index ad4960a5..e05348a9 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -18,6 +18,11 @@ OP_CHECK(opck_basic_cast) { : env->gwion->type[et_error]; } +OP_CHECK(opck_similar_cast) { + const Exp_Cast *cast = (Exp_Cast *)data; + return exp_self(cast)->type; +} + OP_CHECK(opck_usr_implicit) { struct Implicit *imp = (struct Implicit *)data; /* @@ -41,6 +46,17 @@ OP_CHECK(opck_usr_implicit) { return imp->t; } +//#include "emit.h" +// contracts only +OP_EMIT(opem_contract_similar) { + const Exp_Cast *cast = (Exp_Cast *)data; + const Env env = emit->env; + struct Implicit imp = { .t=exp_self(cast)->type, .e=cast->exp}; + struct Op_Import opi = { + .op = insert_symbol("@implicit"), .lhs = cast->exp->type, .rhs = exp_self(cast)->type, .data=(m_uint)&imp }; + return op_emit(emit, &opi); +} + OP_CHECK(opck_const_rhs) { const Exp_Binary *bin = (Exp_Binary *)data; const m_str access = exp_access(bin->rhs); diff --git a/src/lib/ref.c b/src/lib/ref.c index 1896241d..5bef6aa2 100644 --- a/src/lib/ref.c +++ b/src/lib/ref.c @@ -24,13 +24,37 @@ static m_bool ref_access(const Env env, const Exp e) { return GW_ERROR; } -static OP_CHECK(opck_implicit_similar) { +static OP_CHECK(opck_ref_implicit_similar) { const struct Implicit *imp = (struct Implicit *)data; CHECK_BN(ref_access(env, imp->e)); exp_setvar(imp->e, 1); return imp->t; } +static inline Type ref_base(Type t) { + do if(!tflag(t->info->parent, tflag_ref)) + return t; + while((t = t->info->parent)); + return NULL; +} + +static OP_EMIT(opem_ref_implicit_similar) { + const struct Implicit *imp = (struct Implicit *)data; + if(!tflag(imp->t, tflag_contract)) return GW_OK; + const Env env = emit->env; + const Type base = ref_base(imp->t); + struct Op_Import opi = {.op = insert_symbol("@implicit"), + .lhs = base, + .rhs = imp->t, + .data = (m_uint)imp}; + CHECK_BB(op_emit(emit, &opi)); + const Instr instr = emit_add_instr(emit, RegMove); + instr->m_val = -imp->e->type->size; + exp_setvar(imp->e, true); + imp->e->cast_to = NULL; + return emit_exp(emit, imp->e); +} + static OP_CHECK(opck_implicit_ref) { const struct Implicit *imp = (struct Implicit *)data; CHECK_BN(ref_access(env, imp->e)); @@ -39,13 +63,37 @@ static OP_CHECK(opck_implicit_ref) { return imp->t; } -static OP_CHECK(opck_cast_similar) { - const Exp_Cast *cast = (Exp_Cast *)data; - return exp_self(cast)->type; +static OP_CHECK(opck_ref_contract_similar) { + const struct Implicit *imp = (struct Implicit *)data; + CHECK_BN(ref_access(env, imp->e)); + const Type base = (Type)vector_front(&imp->t->info->tuple->contains); + struct Op_Import opi = {.op = insert_symbol("@implicit"), + .lhs = imp->e->type, + .rhs = base, + .data = (m_uint)imp}; + return op_check(env, &opi); +} + +static OP_EMIT(opem_ref_contract_similar) { + const struct Implicit *imp = (struct Implicit *)data; + const Env env = emit->env; + const Type base = (Type)vector_front(&imp->t->info->tuple->contains); + struct Exp_ cast = {.type=base, .d={.exp_cast={.exp=imp->e}}}; + struct Op_Import opi = {.op = insert_symbol("$"), + .lhs = imp->e->type, + .rhs = base, + .data = (m_uint)&cast}; + CHECK_BB(op_emit(emit, &opi)); + const Instr instr = emit_add_instr(emit, RegMove); + instr->m_val = -imp->e->type->size; + exp_setvar(imp->e, true); + imp->e->cast_to = NULL; + emit_exp(emit, imp->e); + return GW_OK; } ANN static void base2ref(Env env, const Type lhs, const Type rhs) { - struct Op_Func opfunc = {.ck = opck_cast_similar}; + struct Op_Func opfunc = {.ck = opck_similar_cast}; struct Op_Import opi = {.op = insert_symbol("$"), .lhs = lhs, .ret = rhs, @@ -53,9 +101,19 @@ ANN static void base2ref(Env env, const Type lhs, const Type rhs) { .func = &opfunc, .data = eNoOp}; add_op(env->gwion, &opi); - opfunc.ck = opck_implicit_similar; + opfunc.ck = opck_ref_implicit_similar; + opfunc.em = opem_ref_implicit_similar; opi.op = insert_symbol("@implicit"); add_op(env->gwion, &opi); + + if(tflag(lhs, tflag_contract)) { + opi.lhs = lhs->info->base_type; + opfunc.ck = opck_ref_contract_similar; + opfunc.em = opem_ref_contract_similar; + opi.op = insert_symbol("@implicit"); + add_op(env->gwion, &opi); + } + } ANN static void ref2base(Env env, const Type lhs, const Type rhs) { @@ -98,6 +156,7 @@ static OP_CHECK(opck_ref_scan) { set_tflag(t, tflag_scan2); set_tflag(t, tflag_check); set_tflag(t, tflag_emit); + set_tflag(t, tflag_ref); const m_uint scope = env_push(env, base->info->value->from->owner_class, base->info->value->from->owner); mk_class(env, t, (loc_t) {}); diff --git a/src/parse/check.c b/src/parse/check.c index 521a0161..9a7429b8 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -516,7 +516,8 @@ static Func find_func_match_actual(const Env env, Func func, const Exp args, while (e) { if (!e->type) // investigate return NULL; - if (!strncmp(e->type->name, "Ref:[", 5)) { +// if (!strncmp(e->type->name, "Ref:[", 5)) { + if (tflag(e->type, tflag_ref)) { if(!e->cast_to)e->cast_to = e->type; } if (!e1) { diff --git a/src/parse/scan0.c b/src/parse/scan0.c index fb9ec57d..b1bb1e1d 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -88,14 +88,20 @@ static OP_CHECK(opck_implicit_similar) { return imp->e->type; } -static OP_CHECK(opck_cast_similar) { +static OP_CHECK(opck_contract_similar) { const Exp_Cast *cast = (Exp_Cast *)data; - return exp_self(cast)->type; + if(tflag(exp_self(cast)->type, tflag_contract)) { + struct Implicit imp = { .t=exp_self(cast)->type, .e=cast->exp}; + struct Op_Import opi = { + .op = insert_symbol("@implicit"), .lhs = cast->exp->type, .rhs = exp_self(cast)->type, .data=(m_uint)&imp }; + CHECK_NN(op_check(env, &opi)); + } + return opck_similar_cast(env, data); } ANN /*static */ void scan0_implicit_similar(const Env env, const Type lhs, const Type rhs) { - struct Op_Func opfunc = {.ck = opck_cast_similar}; + struct Op_Func opfunc = {.ck = opck_similar_cast}; struct Op_Import opi = { .op = insert_symbol("$"), .lhs = lhs, .rhs = rhs, .func = &opfunc}; add_op(env->gwion, &opi); @@ -109,10 +115,17 @@ ANN /*static */ void scan0_implicit_similar(const Env env, const Type lhs, 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_Func opfunc = {.ck = opck_similar_cast}; + if(tflag(rhs, tflag_contract)) { + opfunc.ck = opck_contract_similar; + opfunc.em = opem_contract_similar; + } struct Op_Import opi = { .op = insert_symbol("$"), .lhs = lhs, .rhs = rhs, .func = &opfunc}; add_op(env->gwion, &opi); + opi.lhs = rhs; + opi.rhs = lhs; + add_op(env->gwion, &opi); } ANN static void typedef_simple(const Env env, const Type_Def tdef, @@ -174,10 +187,11 @@ ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) { 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) scan0_implicit_similar(env, base, tdef->type); - if (tdef->distinct) { - tdef->type->info->parent = base->info->parent; + if (tdef->distinct || tdef->when) { +// 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); @@ -187,6 +201,10 @@ ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) { type_addref(tdef->type); // maybe because of scope_iter in nspc_free_values } else 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; return GW_OK; -- 2.43.0