]> Nishi Git Mirror - gwion.git/commitdiff
:art: More on Ref and refinenemts
authorJérémie Astor <fennecdjay@gmail.com>
Sat, 2 Oct 2021 09:42:14 +0000 (11:42 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Sat, 2 Oct 2021 09:42:14 +0000 (11:42 +0200)
include/env/type.h
include/import.h
src/emit/emit.c
src/lib/opfunc.c
src/lib/ref.c
src/parse/check.c
src/parse/scan0.c

index 5efc523ee7ebf97bb20e3dba4738e3c8c96f6703..7d383e4409eced6d6c672b43c2ae441ec97db4f9 100644 (file)
@@ -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_ {
index e5e466a99cf8096351c3427bb98ace0d2b53d35d..2de834d9b219158a5d0b7fe25f2c5f33aef8f001 100644 (file)
@@ -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);
 
index e4d6f0bf263fd33be34655fc18692b837299915d..2e61f74f314b85563ddee2286a161a6e0a10493e 100644 (file)
@@ -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;
index ad4960a564a98178c5354fdd2cf87237aa059e45..e05348a9cbe03698ecbb88b47c5f9c12441b8c89 100644 (file)
@@ -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);
index 1896241d0808e8cc9356bb2bec2410e3d9052b85..5bef6aa2047147e51fdc945fc2059aef5ef6f04f 100644 (file)
@@ -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) {});
index 521a0161ca897800b3297dcb556f30c23e9df1d5..9a7429b81ec0d1102cec3ad50ddb9603211efb79 100644 (file)
@@ -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) {
index fb9ec57ddff1f0b95d706c529a1381eec3676af8..b1bb1e1d5244c8c50486678c96f81700ecf7bb46 100644 (file)
@@ -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;