From 237b89aa5c0739a21fb18c083f3fa18a57b6868f Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sat, 27 Feb 2021 17:53:55 +0100 Subject: [PATCH] :art: Add 'Ref:[T]' --- ast | 2 +- include/lang_private.h | 2 +- src/emit/emit.c | 2 +- src/lib/engine.c | 2 +- src/lib/ref.c | 45 +++++++++++++++++++++++++++++++++++++++--- src/parse/check.c | 2 +- src/parse/scan0.c | 2 +- src/parse/type_decl.c | 12 ++++++++++- 8 files changed, 59 insertions(+), 10 deletions(-) diff --git a/ast b/ast index f6a44e51..82cf57a4 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit f6a44e51053e1e168322053cda0e6734911610f5 +Subproject commit 82cf57a4b02542e3a5528bd6fa362a47270ccb0f diff --git a/include/lang_private.h b/include/lang_private.h index 7bd61e45..4a84b6ed 100644 --- a/include/lang_private.h +++ b/include/lang_private.h @@ -14,5 +14,5 @@ ANN m_bool import_modules(const Gwi gwi); ANN m_bool import_object_op(const Gwi gwi); ANN m_bool import_values(const Gwi gwi); ANN m_bool import_union(const Gwi gwi); -ANN m_bool import_foreach(const Gwi gwi); +ANN m_bool import_ref(const Gwi gwi); #endif diff --git a/src/emit/emit.c b/src/emit/emit.c index e8aaebcf..178d1963 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -442,7 +442,7 @@ ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) { } if(vflag(v, vflag_builtin) || vflag(v, vflag_direct)) return emit_symbol_builtin(emit, data); - if(!strncmp(v->type->name, "@Foreach:[", 10)) { + if(!strncmp(v->type->name, "Ref:[", 5)) { 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/engine.c b/src/lib/engine.c index a4e6d336..14b2a7fe 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -144,7 +144,7 @@ ANN static m_bool import_core_libs(const Gwi gwi) { GWI_BB(import_string(gwi)) GWI_BB(import_shred(gwi)) GWI_BB(import_modules(gwi)) - GWI_BB(import_foreach(gwi)) + GWI_BB(import_ref(gwi)) GWI_BB(gwi_oper_ini(gwi, "@Class", "@Class", "int")) GWI_BB(gwi_oper_end(gwi, "==", int_eq)) diff --git a/src/lib/ref.c b/src/lib/ref.c index 3160d3ac..c3702df6 100644 --- a/src/lib/ref.c +++ b/src/lib/ref.c @@ -17,6 +17,41 @@ #include "gwi.h" #include "tmpl_info.h" +static m_bool ref_access(const Env env, const Exp e) { + const m_str access = exp_access(e); + if(!access) + return GW_OK; + ERR_B(e->pos, _("operand is %s"), access); +} + +static OP_CHECK(opck_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 OP_CHECK(opck_cast_similar) { + const Exp_Cast *cast = (Exp_Cast*)data; + return exp_self(cast)->type; +} + +ANN static void base2ref(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, .ret=rhs, .rhs=rhs, .func=&opfunc, .data=eNoOp }; + add_op(env->gwion, &opi); + opfunc.ck = opck_implicit_similar; + opi.op=insert_symbol("@implicit"); + add_op(env->gwion, &opi); +} + +ANN static void ref2base(Env env, const Type lhs, const Type rhs) { + struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .ret=rhs, .rhs=rhs, /*.func=&opfunc,*/ .data=eNoOp }; + add_op(env->gwion, &opi); + opi.op=insert_symbol("@implicit"); + add_op(env->gwion, &opi); +} + OP_CHECK(opck_foreach_scan) { struct TemplateScan *ts = (struct TemplateScan*)data; struct tmpl_info info = { .base=ts->t, .td=ts->td, .list=ts->t->info->cdef->base.tmpl->list }; @@ -25,16 +60,20 @@ OP_CHECK(opck_foreach_scan) { return exists != env->gwion->type[et_error] ? exists : NULL; const Type base = known_type(env, ts->td->types->td); 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); + base2ref(env, base, t); + ref2base(env, t, base); return t; } -GWION_IMPORT(foreach) { - const Type t_foreach = gwi_struct_ini(gwi, "@Foreach:[A]"); +GWION_IMPORT(ref) { + const Type t_foreach = gwi_struct_ini(gwi, "Ref:[A]"); set_tflag(t_foreach, tflag_infer); GWI_BB(gwi_item_ini(gwi, "@internal", "val")) GWI_BB(gwi_item_end(gwi, ae_flag_none, num, 0)) GWI_BB(gwi_struct_end(gwi)) - GWI_BB(gwi_oper_ini(gwi, "@Foreach", NULL, NULL)) + GWI_BB(gwi_oper_ini(gwi, "Ref", NULL, NULL)) GWI_BB(gwi_oper_add(gwi, opck_foreach_scan)) GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) return GW_OK; diff --git a/src/parse/check.c b/src/parse/check.c index 2c8b1f20..afc4f301 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -922,7 +922,7 @@ ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) { CHECK_BB(ensure_traverse(env, base)) const m_str basename = type2str(env->gwion, base, stmt->exp->pos); char c[15 + strlen(basename)]; - sprintf(c, "@Foreach:[%s]", basename); + sprintf(c, "Ref:[%s]", basename); const Type ret = str2type(env->gwion, c, stmt->exp->pos); if(base->array_depth) set_tflag(ret, tflag_typedef); diff --git a/src/parse/scan0.c b/src/parse/scan0.c index 9f9fc336..134c6425 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -99,7 +99,7 @@ static OP_CHECK(opck_cast_similar) { return exp_self(cast)->type; } -ANN static void scan0_implicit_similar(const Env env, const Type lhs, const Type rhs) { +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_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .func=&opfunc }; add_op(env->gwion, &opi); diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index a00a7fbe..98b0a84d 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -19,11 +19,21 @@ ANN static Type option(const Env env, Type_Decl* td) { return ret; } +ANN static inline Type ref(const Env env, Type_Decl* td) { + struct Type_List_ tl = { .td=td }; + td->ref = 0; + Type_Decl option_td = { .xid=insert_symbol("Ref"), .types=&tl, .pos=td->pos }; + const Type t = known_type(env, &option_td); + td->ref = 1; + return t; +} + ANN static Type resolve(const Env env, Type_Decl* td) { DECL_OO(const Type, base, = find_type(env, td)) if(base->info->ctx && base->info->ctx->error) ERR_O(td->pos, _("type '%s' is invalid"), base->name) - DECL_OO(const Type, t, = scan_type(env, base, td)) + DECL_OO(const Type, type, = scan_type(env, base, td)) + const Type t = !td->ref ? type : ref(env, td); const Type ret = !td->option ? t : option(env, td); return !td->array ? ret : array_type(env, ret, td->array->depth); } -- 2.43.0