]> Nishi Git Mirror - gwion.git/commitdiff
:art: Fix distinct and contracts
authorJérémie Astor <fennecdjay@gmail.com>
Sun, 16 May 2021 11:44:50 +0000 (13:44 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Sun, 16 May 2021 11:44:50 +0000 (13:44 +0200)
include/operator.h
src/lib/engine.c
src/parse/check.c
src/parse/operator.c
src/parse/scan0.c
tests/pp/pragma.gw

index b376f8288e3bbd1cf6f0eb55c6cbc538d8debcd2..d90afd79e34ad822a93766c2ad0f4937aab3adf5 100644 (file)
@@ -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*);
index 977ddc5fc5bbcc515bb34895d51ab57391fbd171..28f6785b46c5a6164721450952cf2ce014db0e7d 100644 (file)
@@ -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.");
index 1e26a028347a5d150ae4126141bc969cdac3da8d..ccaf365130bc85484757c472f88d19d165996cf8 100644 (file)
@@ -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;
index 4f4a77b47a40ca47e9a4e0b17d996916b02932ca..11fb0da3ed584bd517748bc6e96bc507931138d1 100644 (file)
@@ -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);
+}
index a6c37acbbf6c6f6f0bcb7f89349bae36d599c0ba..ff214eb5a2ca168c59dfbc4a6aef624202d6329b 100644 (file)
@@ -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;
 }
 
index 2a72b4f4210ee93b78f35a7aec5fcceb6c58f395..76812b5b014cd75709b290f61623816fe175e772 100644 (file)
@@ -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 >>>;