]> Nishi Git Mirror - gwion.git/commitdiff
:art: Add 'Ref:[T]'
authorJérémie Astor <fennecdjay@gmail.com>
Sat, 27 Feb 2021 16:53:55 +0000 (17:53 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Sat, 27 Feb 2021 16:53:55 +0000 (17:53 +0100)
ast
include/lang_private.h
src/emit/emit.c
src/lib/engine.c
src/lib/ref.c
src/parse/check.c
src/parse/scan0.c
src/parse/type_decl.c

diff --git a/ast b/ast
index f6a44e51053e1e168322053cda0e6734911610f5..82cf57a4b02542e3a5528bd6fa362a47270ccb0f 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit f6a44e51053e1e168322053cda0e6734911610f5
+Subproject commit 82cf57a4b02542e3a5528bd6fa362a47270ccb0f
index 7bd61e45e4c884a20178342764d994d4876dbf9f..4a84b6ed662a8608414ae57916500c798e72e2a7 100644 (file)
@@ -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
index e8aaebcf17cd00c95225aafa4d2ac8c5d35cd8d6..178d19633bc1d7b6ecfaf3dc899bc8bc9d436e75 100644 (file)
@@ -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;
index a4e6d33672d24a03a5ea9c6403d195799bf52a46..14b2a7fe43f857b16eade7f4f81c3928303c5d65 100644 (file)
@@ -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))
index 3160d3ac01c58edfe1d7904625223e6bea1feb4b..c3702df6e2d3132815220422b93462b3247cf846 100644 (file)
 #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;
index 2c8b1f203e14b7e316820c0941f22f7367f3851e..afc4f3012dca3dc6bc9d6d3ccc2a4d18b304bf4d 100644 (file)
@@ -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);
index 9f9fc336d45ec890e6e7b1c8a0370c496ceda0a4..134c642548dafa486feae36a2c6facf05de496fd 100644 (file)
@@ -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);
index a00a7fbe9a084a2edd97b2aee2dd2c9c0c3b17d2..98b0a84d81b792ec66ceca2f5f643ec16a4f5d19 100644 (file)
@@ -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);
 }