]> Nishi Git Mirror - gwion.git/commitdiff
:art: Towards late
authorJérémie Astor <fennecdjay@gmail.com>
Mon, 14 Dec 2020 20:38:29 +0000 (21:38 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Mon, 14 Dec 2020 20:38:29 +0000 (21:38 +0100)
src/emit/emit.c
src/lib/object_op.c
src/parse/check.c
src/vm/vm.c
tests/error/fptr_call_decl.gw [new file with mode: 0644]

index 7913a0d0c1872504fc031f2a6ba2e2024aca1962..7cb55f3f6dbeeb02721214389958772c571a6920 100644 (file)
@@ -434,9 +434,67 @@ ANN static VM_Code finalyze(const Emitter emit, const f_instr exec) {
   return code;
 }
 
+ANN static inline m_uint exp_size(const Exp e) {
+  if(exp_getvar(e))
+    return SZ_INT;
+  const Type type = e->info->cast_to ?: e->info->type;
+  return type->size;
+}
+
+
+ANN static inline m_uint exp_totalsize(Exp e) {
+  m_uint size = 0;
+  do size += exp_size(e);
+  while((e = e->next));
+  return size;
+}
+
+ANN static Instr emit_addref(const Emitter emit, const m_bool emit_var) {
+  const f_instr exec = !emit_var ? RegAddRef : RegAddRefAddr;
+  const Instr instr = emit_add_instr(emit, exec);
+  instr->m_val = -SZ_INT;
+  return instr;
+}
+
+ANN static void struct_addref(const Emitter emit, const Type type,
+    const m_int size, const m_bool offset, const m_bool emit_var) {
+  if(!type->info->tuple)
+    return;
+  for(m_uint i = 0; i < vector_size(&type->info->tuple->types); ++i) {
+    const Type t = (Type)vector_at(&type->info->tuple->types, i);
+    if(isa(t, emit->gwion->type[et_object]) > 0) {
+      const Instr instr = emit_addref(emit, emit_var);
+      instr->m_val = size;
+      instr->m_val2 = vector_at(&type->info->tuple->offset, i);
+    } else if(tflag(t, tflag_struct))
+      struct_addref(emit, t, size, offset + vector_at(&type->info->tuple->offset, i), emit_var);
+  }
+}
+
+ANN2(1) static void emit_exp_addref1(const Emitter emit, /* const */Exp exp, m_int size) {
+  if(isa(exp->info->type, emit->gwion->type[et_object]) > 0 &&
+        (exp->info->cast_to ? isa(exp->info->cast_to, emit->gwion->type[et_object]) > 0 : 1)) {
+    if(exp->exp_type == ae_exp_decl && GET_FLAG(exp->d.exp_decl.td, ref) && !exp_getvar(exp)) {
+      const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
+      instr->m_val = size;
+    }
+    const Instr instr = emit_addref(emit, exp_getvar(exp));
+    instr->m_val = size;
+  } else if(tflag(exp->info->type, tflag_struct)) // check cast_to ?
+    struct_addref(emit, exp->info->type, size, 0, exp_getvar(exp));
+}
+
+ANN2(1) static void emit_exp_addref(const Emitter emit, /* const */Exp exp, m_int size) {
+  do {
+    emit_exp_addref1(emit, exp, size);
+    size += exp_size(exp);
+  } while((exp = exp->next));
+}
+
 ANN static m_bool emit_prim_array(const Emitter emit, const Array_Sub *data) {
   Exp e = (*data)->exp;
   CHECK_BB(emit_exp(emit, e))
+  emit_exp_addref(emit, e, -exp_totalsize(e));
   m_uint count = 0;
   do ++count;
   while((e = e->next));
@@ -546,13 +604,6 @@ ANN static m_bool emit_prim_char(const Emitter emit, const m_str *str) {
   return GW_OK;
 }
 
-ANN static Instr emit_addref(const Emitter emit, const m_bool emit_var) {
-  const f_instr exec = !emit_var ? RegAddRef : RegAddRefAddr;
-  const Instr instr = emit_add_instr(emit, exec);
-  instr->m_val = -SZ_INT;
-  return instr;
-}
-
 ANN static m_bool emit_prim_str(const Emitter emit, const m_str *str) {
   char c[strlen(*str) + 1];
   if(strlen(*str)) {
@@ -796,8 +847,6 @@ ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) {
       CHECK_BB(emit_exp_decl_non_static(emit, decl, list->self, ref, var))
     else
       CHECK_BB(emit_exp_decl_global(emit, decl, list->self, ref, var))
-    if(!var && !decl->td->option && (GET_FLAG(decl->td, ref) || is_fptr(emit->gwion, list->self->value->type)))
-      ERR_B(list->self->pos, "kljlkj")
   } while((list = list->next));
   return GW_OK;
 }
@@ -837,16 +886,6 @@ ANN static void emit_func_arg_vararg(const Emitter emit, const Exp_Call* exp_cal
     free_vector(emit->gwion->mp, kinds);
 }
 
-ANN static inline m_uint exp_size(Exp e);
-ANN static inline m_uint exp_totalsize(Exp e) {
-  m_uint size = 0;
-  do size += exp_size(e);
-  while((e = e->next));
-  return size;
-}
-ANN static /*inline */void emit_exp_addref1(const Emitter emit, Exp, const m_int size);
-ANN static /*inline */void emit_exp_addref(const Emitter emit, Exp, const m_int size);
-
 ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call* exp_call) {
   if(exp_call->args) {
     CHECK_BB(emit_exp(emit, exp_call->args))
@@ -1149,11 +1188,13 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) {
   if(vector_size(&emit->code->instr) && vflag(f->value_ref, vflag_member) &&
         is_fptr(emit->gwion, f->value_ref->type)) {
     const Instr back = (Instr)vector_back(&emit->code->instr);
-    m_bit exec = back->opcode;
-    m_uint val = back->m_val;
-    m_uint val2 = back->m_val2;
-    back->opcode = eReg2Reg;
-    back->m_val2 = -SZ_INT;
+    const Instr base = back->opcode != eGWOP_EXCEPT ?
+      back : (Instr)vector_at(&emit->code->instr, vector_size(&emit->code->instr) -2);
+    const m_bit exec = base->opcode;
+    const m_uint val = base->m_val;
+    const m_uint val2 = base->m_val2;
+    base->opcode = eReg2Reg;
+    base->m_val2 = -SZ_INT;
     regpush(emit, SZ_INT);
     const Instr instr = emit_add_instr(emit, (f_instr)(m_uint)exec);
     instr->m_val = val;
@@ -1349,45 +1390,6 @@ ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If* exp_if) {
   return ret;
 }
 
-ANN static void struct_addref(const Emitter emit, const Type type,
-    const m_int size, const m_bool offset, const m_bool emit_var) {
-  if(!type->info->tuple)
-    return;
-  for(m_uint i = 0; i < vector_size(&type->info->tuple->types); ++i) {
-    const Type t = (Type)vector_at(&type->info->tuple->types, i);
-    if(isa(t, emit->gwion->type[et_object]) > 0) {
-      const Instr instr = emit_addref(emit, emit_var);
-      instr->m_val = size;
-      instr->m_val2 = vector_at(&type->info->tuple->offset, i);
-    } else if(tflag(t, tflag_struct))
-      struct_addref(emit, t, size, offset + vector_at(&type->info->tuple->offset, i), emit_var);
-  }
-}
-
-ANN static inline m_uint exp_size(const Exp e) {
-  if(exp_getvar(e))
-    return SZ_INT;
-  const Type type = e->info->cast_to ?: e->info->type;
-  return type->size;
-}
-
-ANN2(1) static void emit_exp_addref1(const Emitter emit, /* const */Exp exp, m_int size) {
-  if(isa(exp->info->type, emit->gwion->type[et_object]) > 0 &&
-    (exp->info->cast_to ? isa(exp->info->cast_to, emit->gwion->type[et_object]) > 0 : 1)) {
-    const Instr instr = emit_addref(emit, exp_getvar(exp));
-    instr->m_val = size;
-  } else if(tflag(exp->info->type, tflag_struct)) // check cast_to ?
-    struct_addref(emit, exp->info->type, size, 0, exp_getvar(exp));
-}
-
-ANN2(1) static void emit_exp_addref(const Emitter emit, /* const */Exp exp, m_int size) {
-  do {
-    emit_exp_addref1(emit, exp, size);
-    size += exp_size(exp);
-  } while((exp = exp->next));
-}
-
-
 ANN static inline m_bool emit_prim_novar(const Emitter emit, const Exp_Primary *prim) {
   const Exp e = exp_self(prim);
   const uint var = exp_getvar(e);
@@ -1404,7 +1406,6 @@ ANN static m_bool emit_upvalues(const Emitter emit, const Func func) {
     const Value v = prim->value;
     CHECK_BB(emit_prim_novar(emit, prim));
     if(isa(prim->value->type, emit->gwion->type[et_compound]) > 0) {
-       emit_exp_addref1(emit, exp_self(prim), -v->type->size);
        if(vflag(v, vflag_fglobal) && !vflag(v, vflag_closed))
          emit_exp_addref1(emit, exp_self(prim), -v->type->size);
        map_set(&func->code->closure->m, (vtype)v->type, VVAL(map, i));
index 519009c2f361382facd8afc67256bc1616cc5126..405313fa224c0f7bb19e514557c04c20fb5ce157 100644 (file)
@@ -207,6 +207,10 @@ OP_EMIT(opem_object_dot) {
     const Instr instr = emit_add_instr(emit, RegPushImm);
     instr->m_val = (m_uint)value->type;
   }
+  if(GET_FLAG(value, ref)) {
+    const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
+    instr->m_val = -SZ_INT;
+  }
   return (Instr)GW_OK;
 }
 
@@ -226,99 +230,6 @@ ANN static m_bool scantmpl_class_def(const Env env, struct tmpl_info *info) {
     free_class_def(env->gwion->mp, cdef);
   return ret;
 }
-/*
-ANN static OP_CHECK(opck_option_get) {
-  Exp_Binary *bin = (Exp_Binary*)data;
-  exp_setvar(bin->rhs, 1);
-  return bin->rhs->info->type;
-}
-
-static INSTR(OptionCheck) {
-  const M_Object o = *(M_Object*)REG(-SZ_INT*2);
-  if(*(m_uint*)(o->data) != instr->m_val2)
-    Except(shred, "invalid union access");
-  memcpy(*(m_bit**)REG(-SZ_INT), o->data + SZ_INT, instr->m_val);
-  POP_REG(shred, SZ_INT*2 - instr->m_val);
-  memcpy(&*(m_bit*)REG(-instr->m_val), o->data + SZ_INT, instr->m_val);
-}
-
-ANN static OP_EMIT(opem_option_get) {
-  Exp_Binary *bin = (Exp_Binary*)data;
-  const Instr instr = emit_add_instr(emit, OptionCheck);
-  instr->m_val = bin->rhs->info->type->size;
-  instr->m_val2 = 1;
-  return instr;
-}
-
-ANN static OP_CHECK(opck_option_set) {
-  Exp_Binary *bin = (Exp_Binary*)data;
-  CHECK_NN(opck_rassign(env, data, mut)) // check those two lines
-  exp_setvar(bin->rhs, 0);
-  const Type rhs = bin->rhs->info->type;
-  const Nspc nspc = bin->lhs->info->type->nspc;
-  for(m_uint i = 0; i < nspc->info->class_data_size; i += SZ_INT) {
-    if(rhs == *(Type*)(nspc->info->class_data + i))
-      return rhs;
-  }
-//  ERR_N(exp_self(data)->pos, _(
-//  const Value v = nspc_lookup_value0(bin->rhs->info->type->nspc, insert_symbol(env->gwion->st, "@val"));
-//  return v->type;
-}
-
-static INSTR(OptionSet) {
-  M_Object o = *(M_Object*)REG(-SZ_INT);
-  *(m_uint*)(o->data) = instr->m_val2;
-  *(m_bit**)(o->data + SZ_INT) = *(void**)REG(-instr->m_val);
-}
-
-ANN static OP_EMIT(opem_option_set) {
-  Exp_Binary *bin = (Exp_Binary*)data;
-  const Value v = nspc_lookup_value0(bin->rhs->info->type->nspc, insert_symbol(emit->gwion->st, "@val"));
-  const Instr set = emit_add_instr(emit, OptionSet);
-  set->m_val = SZ_INT + v->type->size;
-  set->m_val2 = 1;
-  const Instr pop = emit_add_instr(emit, RegPop);
-  pop->m_val = SZ_INT;
-  return set;
-}
-
-ANN static OP_CHECK(opck_option_setn) {
-  Exp_Binary *bin = (Exp_Binary*)data;
-  CHECK_NN(opck_rassign(env, data, mut))
-  exp_setvar(bin->rhs, 1);
-  return env->gwion->type[et_void];
-}
-
-ANN static OP_EMIT(opem_option_setn) {
-  Exp_Binary *bin = (Exp_Binary*)data;
-  const Instr instr = emit_add_instr(emit, OptionSet);
-  instr->m_val = bin->rhs->info->type->nspc->info->offset;
-  const Instr  pop2 = emit_add_instr(emit, RegPop);
-  pop2->m_val = SZ_INT * 2;
-  return instr;
-}
-
-ANN static OP_EMIT(opem_option_not) {
-  Exp_Unary *unary = (Exp_Unary*)data;
-  const Instr pop = emit_add_instr(emit, RegPop);
-  pop->m_val = unary->exp->info->type->size - SZ_INT;
-  return emit_add_instr(emit, IntNot);
-}
-
-ANN static OP_EMIT(opem_option_cond) {
-  Exp exp = (Exp)data;
-  const Instr pop = emit_add_instr(emit, RegPop);
-  pop->m_val = exp->info->type->size - SZ_INT;
-  return emit_add_instr(emit, BranchEqInt);
-}
-
-ANN static OP_EMIT(opem_option_uncond) {
-  Exp exp = (Exp)data;
-  const Instr pop = emit_add_instr(emit, RegPop);
-  pop->m_val = exp->info->type->size - SZ_INT;
-  return emit_add_instr(emit, BranchNeqInt);
-}
-*/
 
 ANN static m_bool scantmpl_union_def(const Env env, struct tmpl_info *info) {
   const Union_Def u = info->base->info->udef;
index 873240709ac30d124e8216a93c45305040d8426d..c0c6852b677651e871edab85992d8dcbc67d8da5 100644 (file)
@@ -120,6 +120,15 @@ ANN static m_bool check_var_td(const Env env, const Var_Decl var, Type_Decl *con
   return GW_OK;
 }
 
+ANN static void set_late(const Gwion gwion, const Exp_Decl *decl, const Value v) {
+  if(!exp_getvar(exp_self(decl)) &&
+      (GET_FLAG(decl->td, ref) || is_fptr(gwion, v->type))) {
+    SET_FLAG(decl->td, ref);
+    SET_FLAG(v, ref);
+  } else
+    UNSET_FLAG(v, ref);
+}
+
 ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
   Var_Decl_List list = decl->list;
   do {
@@ -128,6 +137,7 @@ ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
     CHECK_BB(check_var_td(env, var, decl->td))
     if(is_fptr(env->gwion, decl->type))
       CHECK_BB(check_fptr_decl(env, var))
+    set_late(env->gwion, decl, list->self->value);
     set_vflag(var->value, vflag_valid);
     //set_vflag(var->value, vflag_used));
     nspc_add_value(env->curr, var->xid, var->value);
@@ -686,6 +696,8 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
 
 ANN m_bool func_check(const Env env, const Exp_Call *exp) {
   CHECK_OB(check_exp(env, exp->func))
+  if(exp->func->exp_type == ae_exp_decl)
+    ERR_B(exp->func->pos, _("Can't call late function pointer at declaration site"))
   const Type t = actual_type(env->gwion, exp->func->info->type);
   const Exp e = exp_self(exp);
   struct Op_Import opi = { .op=insert_symbol("@func_check"),
index d9c2800289fc05337c3135b7bf05da95c7aa017a..c9032caea43aa41462b5ae0dd8044e5873e05b29 100644 (file)
@@ -765,7 +765,7 @@ newobj:
 addref:
   {
     const M_Object o = *((M_Object*)(reg+(m_int)VAL) + (m_int)VAL2);
-    if(o)
+//    if(o)
       ++o->ref;
   }
   DISPATCH()
@@ -797,7 +797,7 @@ except:
  *  VAL = offset (no default SZ_INT)             *
  *  VAL2 = error message                         *
  * grep for GWOP_EXCEPT and Except, exception... */
-  if(!*(M_Object*)(reg-SZ_INT-VAL)) {
+  if(!*(M_Object*)(reg-(m_int)VAL)) {
     shred->pc = PC;
     exception(shred, "NullPtrException");
     continue;
diff --git a/tests/error/fptr_call_decl.gw b/tests/error/fptr_call_decl.gw
new file mode 100644 (file)
index 0000000..9b66787
--- /dev/null
@@ -0,0 +1,3 @@
+#! [contains] Can't call late function pointer at declaration site
+funcdef void test(int);
+(var test t)(2);