]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve Object
authorJérémie Astor <fennecdjay@gmail.com>
Thu, 16 Sep 2021 13:08:52 +0000 (15:08 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Thu, 16 Sep 2021 13:08:52 +0000 (15:08 +0200)
13 files changed:
include/env/type.h
include/env/value.h
include/object.h
src/env/value.c
src/lib/array.c
src/lib/object.c
src/lib/object_op.c
src/main.c
src/parse/check.c
src/parse/scan0.c
src/parse/scan1.c
tests/plug/enum.c
tests/plug/enum_fail3.c

index 6a68f18941fa374e0ad37c1c4b6d92451fb3e875..168d55e8ff3a71ed1cb0c9706cff68bf63e4b291 100644 (file)
@@ -37,6 +37,7 @@ enum tflag {
   tflag_noret    = 1 << 18,
   tflag_contract = 1 << 19,
   tflag_float    = 1 << 20,
+  tflag_union    = 1 << 21,
 } __attribute__((packed));
 
 struct Type_ {
index aa498b6d9e18f2eb137cc9eb98b07c2aef247a2a..9200096328026eff583478d71c473314694ca5a0 100644 (file)
@@ -18,7 +18,8 @@ enum vflag {
   vflag_builtin = 1 << 5,
   vflag_member  = 1 << 6,
   vflag_closed  = 1 << 7,
-  vflag_inner   = 1 << 8 // value is in a scope
+  vflag_inner   = 1 << 8, // value is in a scope
+  vflag_release = 1 << 9
   //  vflag_used = 1 << 3
 } __attribute__((packed));
 
index af933b4a787ed2fdbdf262d03d370a7b1303eecb..54745c565f520536921bccdfb760a75b2712ebd5 100644 (file)
@@ -2,10 +2,11 @@
 #define __OBJECT
 typedef struct M_Object_ *M_Object;
 struct M_Object_ {
-  m_bit *         data;
-  Type            type_ref;
-  struct Vector_  vtable;
-  volatile size_t ref;
+  Type                  type_ref;
+  struct Vector_        vtable;
+  /*volatile */uint32_t ref;
+  uint32_t              offset;
+  m_bit                 data[];
 };
 
 ANN void           instantiate_object(const VM_Shred, const Type);
@@ -60,7 +61,7 @@ static inline void struct_addref(const Gwion gwion, const Type type,
   }
 }
 
-static inline void compound_release(const VM_Shred shred, const Type t,
+ANN static inline void compound_release(const VM_Shred shred, const Type t,
                                     const m_bit *ptr) {
   if (!tflag(t, tflag_struct))
     object_release(shred, t, ptr);
index a82e2661ec9b070c91f85ab76d26121c16b68c93..e64a5cbfa68936158818d6e0c73bb42f1f16a7e8 100644 (file)
@@ -7,12 +7,16 @@
 #define MAX(a, b) (a >= b ? a : b)
 ANN void free_value(Value a, Gwion gwion) {
   const Type t = a->type;
+//  if(t) {
+
   if (t->size > SZ_INT && !vflag(a, vflag_func) && a->d.ptr)
     _mp_free(gwion->mp, t->size, a->d.ptr);
   else if (is_class(gwion, t))
     type_remref(t, gwion);
-  /* else */if (vflag(a, vflag_inner))
+  else if (vflag(a, vflag_inner))
     type_remref(t, gwion);
+//  }
+
   mp_free(gwion->mp, ValueFrom, a->from);
   mp_free(gwion->mp, Value, a);
 }
index fa41f106ba10ebe0feca727a0c3ee4d93d844f8a..aa8f32ee1b3c431f4ab89752a9bd6dd01431b0f7 100644 (file)
@@ -957,7 +957,7 @@ INSTR(ArrayAlloc) {
     return; // TODO make exception vararg
   }
   *(void **)(ref->data + SZ_INT) = aai.data;
-//  vector_add(&shred->gc, (m_uint)ref); // heyo
+  vector_add(&shred->gc, (m_uint)ref); // heyo
   if (!info->is_obj) {
     POP_REG(shred, SZ_INT * (info->depth - 1));
     *(M_Object *)REG(-SZ_INT) = ref;
index 2880c96fde2119285e910ca67f59c9d036aa1b6b..bd340374deae3cb0cc885123af6d1765d8241d41 100644 (file)
 #undef insert_symbol
 
 M_Object new_object(MemPool p, const VM_Shred shred, const Type t) {
-  const M_Object a = mp_calloc(p, M_Object);
+  const uint32_t offset = sizeof(struct M_Object_) + t->nspc->offset;
+  const M_Object a = _mp_calloc(p, offset);
   a->ref           = 1;
   a->type_ref      = t;
-  if (t->nspc) {
-    a->vtable.ptr = t->nspc->vtable.ptr;
-    if (t->nspc->offset)
-      a->data = (m_bit *)_mp_calloc(p, t->nspc->offset);
-  }
+  a->offset = t->nspc->offset;
+  a->vtable.ptr = t->nspc->vtable.ptr;
   if (shred) vector_add(&shred->gc, (vtype)a);
   return a;
 }
@@ -47,7 +45,8 @@ M_Object new_string2(const struct Gwion_ *gwion, const VM_Shred shred,
   return o;
 }
 
-ANN static void handle_dtor(const M_Object o, const VM_Shred shred) {
+ANN static void user_dtor(const M_Object o, const VM_Shred shred, const Type t) {
+  o->type_ref = t;
   const VM_Shred sh = new_vm_shred(shred->info->mp, o->type_ref->nspc->dtor);
   vmcode_addref(o->type_ref->nspc->dtor);
   sh->base             = shred->base;
@@ -56,39 +55,47 @@ ANN static void handle_dtor(const M_Object o, const VM_Shred shred) {
   ++sh->info->me->ref;
 }
 
-__attribute__((hot)) ANN void __release(const M_Object o,
-                                        const VM_Shred shred) {
-  vector_rem2(&shred->gc, (vtype)o);
-  MemPool p = shred->info->mp;
-  Type    t = o->type_ref;
-  do {
-    if (!t->nspc) continue;
-    if (isa(t, shred->info->vm->gwion->type[et_union]) < 0) {
-      struct scope_iter iter = {t->nspc->info->value, 0, 0};
-      Value             v;
-      while (scope_iter(&iter, &v) > 0) {
-        if (!GET_FLAG(v, static) &&
-            isa(v->type, shred->info->vm->gwion->type[et_compound]) > 0)
-          compound_release(shred, v->type, o->data + v->from->offset);
-      }
-    }
-    if (tflag(t, tflag_dtor)) {
-      if (t->nspc->dtor->builtin)
-        ((f_xtor)t->nspc->dtor->native_func)(o, NULL, shred);
-      else {
-        o->type_ref = t;
-        handle_dtor(o, shred);
-        return;
-      }
-    }
-  } while ((t = t->info->parent));
-  free_object(p, o);
+static DTOR(object_dtor) {
+  free_object(shred->info->mp, o);
+}
+
+ANN static inline Type next_type(Type t) {
+  do if(t->nspc) return t;
+  while((t = t->info->parent));
+  return NULL;
+}
+
+ANN static inline void release_not_union(const m_bit *data, const VM_Shred shred, const Scope s) {
+  const Map m = &s->map;
+  for(m_uint i = map_size(m) + 1; --i;) {
+    const Value v = (Value) VVAL(m, i-1);
+    if (vflag(v, vflag_release))
+      compound_release(shred, v->type, data + v->from->offset);
+  }
+}
+
+ANN static void do_release(const M_Object o,
+                                        const VM_Shred shred, const Type t) {
+  const Type next = next_type(t);
+  if(!next) return;
+  if (!tflag(t, tflag_union))
+    release_not_union(o->data, shred, t->nspc->info->value);
+  if (tflag(t, tflag_dtor)) {
+    if (t->nspc->dtor->builtin)
+      ((f_xtor)t->nspc->dtor->native_func)(o, NULL, shred);
+    else
+      return user_dtor(o, shred, t);
+  }
+  return do_release(o, shred, t->info->parent);
+}
+
+ANN void __release(const M_Object o, const VM_Shred shred) {
+//  vector_rem2(&shred->gc, (vtype)o);
+  do_release(o, shred, o->type_ref);
 }
 
 ANN void free_object(MemPool p, const M_Object o) {
-  if (o->type_ref->nspc && o->type_ref->nspc->offset)
-    mp_free2(p, o->type_ref->nspc->offset, o->data);
-  mp_free(p, M_Object, o);
+    mp_free2(p, o->offset, o);
 }
 
 static ID_CHECK(opck_this) {
@@ -119,6 +126,10 @@ static ID_EMIT(opem_this) {
 GWION_IMPORT(object) {
   const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, "@Compound");
   gwi_set_global_type(gwi, t_object, et_object);
+  t_object->nspc = new_nspc(gwi->gwion->mp, "Object");
+  t_object->nspc->dtor = new_vmcode(gwi->gwion->mp, NULL, NULL, "Object", SZ_INT, true, false);
+  t_object->nspc->dtor->native_func = (m_uint)object_dtor;
+  t_object->tflag |= tflag_dtor;
   struct SpecialId_ spid = {.ck = opck_this, .em = opem_this, .is_const = 1};
   gwi_specialid(gwi, "this", &spid);
   return GW_OK;
index 4e2a1b30b8a32820d6bbb5925ea84cc875f1a00e..f0d3937025b6afe85141d806106161c75a30a450 100644 (file)
@@ -229,7 +229,6 @@ OP_EMIT(opem_object_dot) {
   const Exp_Dot *member = (Exp_Dot *)data;
   const Type     t_base = actual_type(emit->gwion, member->base->type);
   const Value    value  = find_value(t_base, member->xid);
-
   if (is_class(emit->gwion, value->type)) {
     const Instr instr = emit_add_instr(emit, RegPushImm);
     instr->m_val      = (m_uint)value->type;
index d3a59b0f6563b170624369088b6556329c7086de..225f62546c8562ccc25f67ad90be513ba0ac74d9 100644 (file)
@@ -21,7 +21,8 @@ static void sig(int unused NUSED) {
 
 static void afl_run(const Gwion gwion) {
   __AFL_INIT();
-  while (__AFL_LOOP(128)) {
+//  while (__AFL_LOOP(128)) {
+  while (__AFL_LOOP(32)) {
     push_global(gwion, "[afl]");
     FILE *f = fdopen(0, "r");
     if (compile_file(gwion, "afl", f)) gwion_run(gwion);
index f6757c51fbe16aae19c9cdb86106b61ffd257fa7..07836089149320ada285d1d44f754d35ad210b3c 100644 (file)
@@ -163,13 +163,18 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl *decl) {
   }
   if (!decl->type) ERR_O(decl->td->pos, _("can't find type"));
   {
-    CHECK_BO(inferable(env, decl->type, decl->td->pos));
     CHECK_BO(ensure_check(env, decl->type));
+    if(inferable(env, decl->type, decl->td->pos) < 0) {
+      if(!tflag(decl->type, tflag_check) && decl->type->ref > 1 && env->class_def && !env->scope->depth)
+        type_remref(decl->type, env->gwion);
+      return NULL;
+   }
   }
   const m_bool global = GET_FLAG(decl->td, global);
   const m_uint scope  = !global ? env->scope->depth : env_push_global(env);
   const m_bool ret    = check_decl(env, decl);
   if (global) env_pop(env, scope);
+  env_weight(env, 1 + isa(decl->type, env->gwion->type[et_object]) > 0);
   return ret > 0 ? decl->list->self->value->type : NULL;
 }
 
@@ -209,6 +214,7 @@ ANN static Type check_prim_array(const Env env, const Array_Sub *data) {
   if (!e)
     ERR_O(prim_pos(data), _("must provide values/expressions for array [...]"))
   CHECK_OO(check_exp(env, e));
+  env_weight(env, 1);
   return array->type = prim_array_match(env, e);
 }
 
@@ -225,6 +231,7 @@ ANN static m_bool check_range(const Env env, Range *range) {
 ANN static Type check_prim_range(const Env env, Range **data) {
   Range *range = *data;
   CHECK_BO(check_range(env, range));
+  env_weight(env, 1);
   const Exp e = range->start ?: range->end;
   assert(e);
   const Symbol     sym = insert_symbol("@range");
@@ -288,6 +295,7 @@ ANN static Type check_dot(const Env env, const Exp_Dot *member) {
                           .lhs  = member->base->type,
                           .data = (uintptr_t)member,
                           .pos  = exp_self(member)->pos};
+  env_weight(env, 1);
   return op_check(env, &opi);
 }
 
@@ -367,17 +375,20 @@ ANN static Type check_prim_id(const Env env, const Symbol *data) {
 
 ANN static Type check_prim_perform(const Env env, const Symbol *data) {
   env_add_effect(env, *data, prim_pos(data));
+  env_weight(env, 1);
   return env->gwion->type[et_void];
 }
 
 ANN static Type check_prim_interp(const Env env, const Exp *exp) {
   CHECK_OO(check_exp(env, *exp));
+  env_weight(env, 1);
   return env->gwion->type[et_string];
 }
 
 ANN static Type check_prim_hack(const Env env, const Exp *data) {
   if (env->func) unset_fflag(env->func, fflag_pure);
   CHECK_OO(check_prim_interp(env, data));
+  env_weight(env, 1);
   return env->gwion->type[et_gack];
 }
 /*
@@ -452,6 +463,7 @@ static ANN Type check_exp_array(const Env env, const Exp_Array *array) {
 static ANN Type check_exp_slice(const Env env, const Exp_Slice *range) {
   CHECK_OO(check_exp(env, range->base));
   CHECK_BO(check_range(env, range->range));
+  env_weight(env, 1);
   const Symbol sym = insert_symbol("@slice");
   const Exp    e   = range->range->start ?: range->range->end;
   assert(e);
@@ -1801,6 +1813,78 @@ ANN static inline bool type_is_recurs(const Type t, const Type tgt) {
   return isa(tgt, t) > 0 || isa(t, tgt) > 0 || (tgt->info->tuple && vector_find(&tgt->info->tuple->contains, (m_uint)t) > -1);
 }
 
+ANN static m_bool recursive_type_base(const Env env, const Type t);
+ANN static bool recursive_type(const Env env, const Type t, const Type tgt);
+ANN static bool recursive_value(const Env env, const Type t, const Value v) {
+//if(!v->from->owner_class)exit(13);
+  const Type tgt = array_base(v->type);
+  if(type_is_recurs(t, tgt)) {
+    env_err(env, v->from->loc, _("recursive type"));
+    env->context->error = false;
+    gwerr_secondary("in class", t->name, t->info->cdef->base.pos);
+
+    const Type first = tgt->info->value->from->loc.first.line < t->info->value->from->loc.first.line ?
+//      tgt : t;
+      v->type : t;
+    const Type second = tgt->info->value->from->loc.first.line > t->info->value->from->loc.first.line ?
+//      tgt : t;
+      v->type : t;
+
+printf("%s %s\n", first->name, second->name);
+
+    if(first != second) {
+      const Map m1 = &first->info->value->from->owner->info->type->map;
+      map_remove(m1, (m_uint)insert_symbol(first->name));
+      const Map m2 = &second->info->value->from->owner->info->type->map;
+      map_remove(m2, (m_uint)insert_symbol(second->name));
+      if(first->ref > 2)
+        type_remref(first, env->gwion);
+      if(second->ref > 2)
+        type_remref(second, env->gwion);
+    if(tgt != t && v->type == tgt && strncmp(tgt->name, "Option:[", 8))
+      recursive_type_base(env, tgt);
+    }
+    set_tflag(t, tflag_infer);
+    set_tflag(tgt, tflag_infer);
+    unset_tflag(t, tflag_check);
+    unset_tflag(tgt, tflag_check);
+    return true;
+  }
+  if(v->type->nspc && !GET_FLAG(v, late) &&
+      isa(tgt, env->gwion->type[et_compound]) > 0)
+    return recursive_type(env, t, tgt);
+  return false;
+}
+
+ANN static bool recursive_type(const Env env, const Type t, const Type tgt) {
+  Value             v;
+  struct scope_iter inner = {tgt->nspc->info->value, 0, 0};
+  bool error = false;
+  while (scope_iter(&inner, &v) > 0) {
+    if(!GET_FLAG(v, late) && recursive_value(env, t, v)) {
+      error = true;
+    }
+  }
+  return error;
+}
+
+ANN static m_bool recursive_type_base(const Env env, const Type t) {
+  Value             value;
+  bool error = false;
+  struct scope_iter iter = {t->nspc->info->value, 0, 0};
+  while (scope_iter(&iter, &value) > 0) {
+    if (isa(value->type, env->gwion->type[et_compound]) < 0) continue;
+    if (value->type->nspc && !GET_FLAG(value, late)) {
+      if(recursive_type(env, t, value->type)) {
+        env_err(env, value->from->loc, _("recursive type"));
+        gw_err("use {+G}late{0} on one (or more) of the variables?\n");
+        error = true;
+      }
+    }
+  }
+  return error;
+}
+
 ANN bool check_trait_requests(const Env env, const Type t, const ID_List list);
 ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
   const Type t = cdef->base.type;
@@ -1826,48 +1910,7 @@ ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
       return GW_ERROR;
     }
   }
-
-  Value             value;
-  struct scope_iter iter = {t->nspc->info->value, 0, 0};
-  while (scope_iter(&iter, &value) > 0) {
-    if (isa(value->type, env->gwion->type[et_compound]) < 0) continue;
-//        const Type t = array_base(value->type);
-    if (value->type->nspc && !GET_FLAG(value, late)) {
-      Value             v;
-      struct scope_iter inner = {value->type->nspc->info->value, 0, 0};
-bool error = false;
-      while (scope_iter(&inner, &v) > 0) {
-        const Type tgt = array_base(v->type);
-//        if(isa(tgt, t) > 0 || isa(t, tgt) > 0 || (tgt->info->tuple && vector_find(&tgt->info->tuple->contains, (m_uint)t) > -1)) {
-        if(type_is_recurs(t, tgt)) {
-          env_err(env, v->from->loc, _("recursive type"));
-          env->context->error = false;
-          env_err(env, value->from->loc, _("recursive type"));
-          gw_err("use {+G}late{0} on one (or more) of the variables?\n");
-//          env_set_error(env);
-vector_rem2(&t->info->tuple->contains, (m_uint)tgt);
-vector_rem2(&tgt->info->tuple->contains, (m_uint)t);
-type_remref(t, env->gwion);
-//type_remref(tgt, env->gwion);
-//nspc_add_type_front(t->nspc, insert_symbol(tgt->name), tgt);
-//nspc_add_type_front(tgt->nspc, insert_symbol(tgt->name), t);
-          set_tflag(t, tflag_infer);
-          set_tflag(tgt, tflag_infer);
-          unset_tflag(t, tflag_check);
-          unset_tflag(tgt, tflag_check);
-//value->type =  env->gwion->type[et_error];
-//v->type =  env->gwion->type[et_error];
-//env->gwion->type[et_error]->ref += 2;
-
-error = true;
-//          return GW_OK;
-        }
-      }
-if(error)
-//          return GW_OK;
-          return GW_ERROR;
-    }
-  }
+  CHECK_BB(recursive_type_base(env, t));
   nspc_allocdata(env->gwion->mp, t->nspc);
   return GW_OK;
 }
index c25764c9797082af14811e92c0af2c8b1329ef20..fb9ec57ddff1f0b95d706c529a1381eec3676af8 100644 (file)
@@ -235,6 +235,7 @@ ANN static Type union_type(const Env env, const Symbol s, const loc_t loc) {
   t->nspc          = new_nspc(env->gwion->mp, name);
   t->nspc->parent  = env->curr;
   t->info->tuple   = new_tupleform(env->gwion->mp, NULL); // ???
+  set_tflag(t, tflag_union);
   add_type(env, env->curr, t);
   mk_class(env, t, loc);
   SET_FLAG(t, final);
@@ -380,7 +381,7 @@ ANN static Exp arglist2exp(MemPool p, Arg_List arg, const Exp default_arg) {
 }
 
 ANN2(1,2) static Ast scan0_func_def_default(const MemPool p, const Ast ast,
-                                      const Ast next) {
+                                            const Ast next) {
   const Func_Def base_fdef = ast->section->d.func_def;
   Arg_List       base_arg = base_fdef->base->args, former = NULL;
   while (base_arg) {
@@ -505,14 +506,14 @@ ANN m_bool scan0_class_def(const Env env, const Class_Def c) {
 }
 
 ANN m_bool scan0_ast(const Env env, Ast ast) {
+  Ast next;
   do {
+    next = ast->next;
     CHECK_BB(scan0_section(env, ast->section));
     if (ast->section->section_type != ae_section_func ||
         !fdef_defaults(ast->section->d.func_def))
       continue;
-    const Ast next = ast->next;
-    scan0_func_def_default(env->gwion->mp, ast, next);
-    if(!(ast = next))break;
-  } while ((ast = ast->next));
+    (void)scan0_func_def_default(env->gwion->mp, ast, ast->next);
+  } while ((ast = next));
   return GW_OK;
 }
index be0f4dfaeaf49fc97420c3b044a3b4be93afae17..4637ede97351f8793d88793138a3e6b52f45cbbf 100644 (file)
@@ -128,6 +128,8 @@ ANN static m_bool scan1_decl(const Env env, const Exp_Decl *decl) {
         if (env->class_def->info->tuple) tuple_contains(env, v);
         if (!GET_FLAG(decl->td, static)) {
           set_vflag(v, vflag_member);
+          if(isa(t, env->gwion->type[et_object]) > 0)
+            set_vflag(v, vflag_release);
           if (tflag(env->class_def, tflag_struct)) {
             v->from->offset = env->class_def->size;
             env->class_def->size += t->size;
@@ -508,9 +510,10 @@ ANN static inline m_bool scan1_union_def_inner_loop(const Env env,
     if (nspc_lookup_value0(env->curr, l->xid))
       ERR_B(l->pos, _("'%s' already declared in union"), s_name(l->xid))
     const Value v = new_value(env->gwion->mp, t, s_name(l->xid));
-    if (!tflag(t, tflag_scan1)) // ???
+//    if (!tflag(t, tflag_scan1)) // ???
       tuple_contains(env, v);   // ???
-    v->from->offset = SZ_INT;
+//    v->from->offset = SZ_INT;
+    v->from->offset = v->type->size;
     valuefrom(env, v->from, udef->pos);
     nspc_add_value_front(env->curr, l->xid, v);
     if (t->size > sz) sz = t->size;
index 898eec8adfb79fbf3caa056040f8e47669c7d2b5..cac4005bcccbb41df05c951ff6246c5a743f1048 100644 (file)
@@ -22,20 +22,6 @@ GWION_IMPORT(enum_test) {
   GWI_BB(gwi_enum_add(gwi, "TYPED_ENUM9", 9))
   GWI_OB(gwi_enum_end(gwi))
 
-  GWI_OB(gwi_class_ini(gwi, "Enum", NULL))
-  GWI_BB(gwi_enum_ini(gwi, "MyTest"))
-  GWI_BB(gwi_enum_add(gwi, "ENUM0", 0))
-  GWI_BB(gwi_enum_add(gwi, "ENUM1", 1))
-  GWI_BB(gwi_enum_add(gwi, "ENUM2", 2))
-  GWI_BB(gwi_enum_add(gwi, "ENUM3", 3))
-  GWI_BB(gwi_enum_add(gwi, "ENUM4", 4))
-  GWI_BB(gwi_enum_add(gwi, "ENUM5", 5))
-  GWI_BB(gwi_enum_add(gwi, "ENUM6", 6))
-  GWI_BB(gwi_enum_add(gwi, "ENUM7", 7))
-  GWI_BB(gwi_enum_add(gwi, "ENUM8", 8))
-  GWI_BB(gwi_enum_add(gwi, "ENUM9", 9))
-  GWI_OB(gwi_enum_end(gwi))
-
   GWI_OB(gwi_class_end(gwi))
 
   return GW_OK;
index a64d7199d380388687bbe565ed31e1bfc801f1fe..73453467dcbe8b1259bbcb1ff897bd1c25f197d8 100644 (file)
@@ -9,7 +9,7 @@
 #include "import.h"
 
 GWION_IMPORT(enum_test) {
-  GWI_BB(gwi_enum_ini(gwi, NULL))
+  GWI_BB(gwi_enum_ini(gwi, "test"))
   GWI_BB(gwi_enum_add(gwi, "adc", 0))
   GWI_BB(gwi_enum_ini(gwi, NULL))
   return GW_OK;