]> Nishi Git Mirror - gwion.git/commitdiff
:art: A Better type system
authorfennecdjay <astor.jeremie@wanadoo.fr>
Thu, 6 Jun 2019 15:56:51 +0000 (17:56 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Thu, 6 Jun 2019 15:56:51 +0000 (17:56 +0200)
17 files changed:
include/instr.h
include/type.h
src/emit/emit.c
src/lib/func.c
src/lib/gack.c
src/lib/instr.c
src/lib/opfunc.c
src/oo/context.c
src/oo/type.c
src/parse/check.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/template.c
src/parse/traverse.c
src/parse/traverse_template.c
src/vm/vm.c
tests/error/ptr_assign_other.gw

index f311e2b50c92b91a0de8f2159b2d2c3b57241c88..a84f8d4a4870bdb494b8239947ce84f6af6a6337 100644 (file)
@@ -61,13 +61,15 @@ INSTR(VecMember);
 INSTR(PopArrayClass);
 
 INSTR(DotTmpl);
+INSTR(GTmpl);
 
 struct dottmpl_ {
   size_t len;
   m_str name;
   Func_Def base, def;
-  Type owner;
-  size_t overload; // => vtindex ?
+  Type owner_class;
+  Nspc owner;
+  size_t vt_index;
   Type_List tl;
 };
 ANN void free_dottmpl(struct dottmpl_*);
index f286ca8d2c26169cf35f2c88b9ad3e725a72f2a1..e9cc2a3492b0544505bd5f12940e08b235844c72 100644 (file)
@@ -1,15 +1,16 @@
 #ifndef __TYPE
 #define __TYPE
 
-  struct TypeInfo_ {
-    Type      parent;
-    Nspc      owner;
-    Class_Def def;
-    union type_data {
-      Func      func;
-      Type      base_type;
-    } d;
-  };
+struct TypeInfo_ {
+  Type      parent;
+  Nspc      owner;
+  Class_Def def;
+  union type_data {
+    Func      func;
+    Type      base_type;
+  } d;
+  struct Vector_ contains;
+};
 
 struct Type_ {
   m_str     name;
index d64392d29c4caecfb79ac499002536690e4064af..44487123e7fd36f6e19fe644fcc370e53e0086b3 100644 (file)
@@ -305,7 +305,7 @@ ANN static inline Exp dot_static_exp(const Emitter emit, const Exp_Primary* prim
 ANN static m_bool emit_symbol_owned(const Emitter emit, const Exp_Primary* prim) {
   const Value v = prim->value;
   const Exp dot = (!GET_FLAG(v, static) ? dot_this_exp : dot_static_exp)(emit, prim, v->owner_class);
-  dot->type = v->type;
+  dot->type = exp_self(prim)->type;
   dot->emit_var = exp_self(prim)->emit_var;
   const m_bool ret = emit_exp_dot(emit, &dot->d.exp_dot);
   free_exp(emit->gwion->mp, dot);
@@ -349,6 +349,8 @@ ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary* prim) {
   const m_uint size = v->type->size;
   const Instr instr = emit_kind(emit, size, exp_self(prim)->emit_var, !GET_FLAG(v, global) ? regpushmem : regpushbase);
   instr->m_val  = v->offset;
+  if(isa(v->type, t_function) > 0 && isa(v->type, t_fptr) < 0)
+    instr->m_val = exp_self(prim)->type->e->d.func->value_ref->offset;
   return GW_OK;
 }
 
@@ -684,6 +686,9 @@ ANN static m_bool prepare_call(const Emitter emit, const Exp_Call* exp_call) {
 
 ANN static inline m_int push_tmpl_func(const Emitter emit, const Func f) {
   const Value v = f->value_ref;
+  if(isa(v->type, t_class) > 0 &&
+      isa(actual_type(v->type), t_fptr) > 0)
+    return emit->env->scope->depth;
   const m_uint scope = emit_push(emit, v->owner_class, v->owner);
   CHECK_BB(traverse_func_template(emit->env, f->def))
   return (m_int)scope;
@@ -751,10 +756,11 @@ ANN static Type_List tmpl_tl(const Env env, const m_str name) {
 }
 
 ANN m_bool traverse_dot_tmpl(const Emitter emit, const struct dottmpl_ *dt) {
-  const m_uint scope = emit_push_type(emit, dt->owner);
+  const m_uint scope = dt->owner_class ?
+      emit_push_type(emit, dt->owner_class) : emit_push(emit, NULL, dt->owner);
   m_bool ret = GW_ERROR;
   dt->def->base->tmpl->call = dt->tl;// in INSTR
-  if(traverse_func_template(emit->env, dt->def) > 0) {
+  if(!dt->def->base->func &&traverse_func_template(emit->env, dt->def) > 0) {
     ret = emit_func_def(emit, dt->def);
     nspc_pop_type(emit->gwion->mp, emit->env->curr);
   }
@@ -773,7 +779,7 @@ static inline m_bool push_func_code(const Emitter emit, const Func f) {
     c[sz] = '\0';
     struct dottmpl_ *dt = mp_calloc(emit->gwion->mp, dottmpl);
     dt->name = s_name(insert_symbol(c));
-    dt->overload = f->def->base->tmpl->base;
+    dt->vt_index = f->def->base->tmpl->base;
     dt->tl = tmpl_tl(emit->env, c);
     dt->base = f->def;
     instr->opcode = eOP_MAX;
@@ -782,11 +788,11 @@ static inline m_bool push_func_code(const Emitter emit, const Func f) {
     instr->execute = DotTmpl;
     return GW_OK;
   }
-if(vector_size(&emit->code->instr)) {
-  const Instr instr = (Instr)vector_back(&emit->code->instr);
-  instr->opcode = eRegPushImm;
-  instr->m_val = (m_uint)f->code;
-}
+  if(vector_size(&emit->code->instr)) {
+    const Instr instr = (Instr)vector_back(&emit->code->instr);
+    instr->opcode = eRegPushImm;
+    instr->m_val = (m_uint)f->code;
+  }
   return GW_OK;
 }
 
@@ -807,6 +813,23 @@ ANN static Instr get_prelude(const Emitter emit, const Func f) {
     instr = emit_add_instr(emit, !GET_FLAG(f, builtin) ? FuncUsr : SetCode);
   else {
     emit_add_instr(emit, GWOP_EXCEPT);
+    if(f->def->base->tmpl) { // TODO: put in func
+      struct dottmpl_ *dt = (struct dottmpl_*)mp_calloc(emit->gwion->mp, dottmpl);
+      size_t len = strlen(f->name);
+      size_t sz = len - strlen(f->value_ref->owner->name);
+      char c[sz + 1];
+      memcpy(c, f->name, sz);
+      c[sz] = '\0';
+      dt->tl = tmpl_tl(emit->env, c);
+      dt->name = s_name(insert_symbol(c));
+      dt->vt_index = f->def->base->tmpl->base;
+      dt->base = f->def;
+      dt->owner = f->value_ref->owner;
+      dt->owner_class = f->value_ref->owner_class;
+      const Instr gtmpl = emit_add_instr(emit, GTmpl);
+      gtmpl->m_val = (m_uint)dt;
+      gtmpl->m_val2 = strlen(c);
+    }
     instr = emit_add_instr(emit, FuncPtr);
   }
   instr->m_val2 = 1;
@@ -842,7 +865,8 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) {
     if(GET_FLAG(f, template) && emit->env->func != f)
       CHECK_BB(emit_template_code(emit, f))
   } else if((f->value_ref->owner_class && is_special(f->value_ref->owner_class) > 0) ||
-  !f->value_ref->owner_class || GET_FLAG(f, template))
+        !f->value_ref->owner_class || (GET_FLAG(f, template) &&
+        isa(f->value_ref->type, t_fptr) < 0))
     push_func_code(emit, f);
   else if(vector_size(&emit->code->instr)){
     const Instr back = (Instr)vector_back(&emit->code->instr);
@@ -975,8 +999,9 @@ ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary* unary) {
 }
 
 ANN static m_bool emit_implicit_cast(const Emitter emit,
-    const restrict Type from, const restrict Type to) {
-  struct Op_Import opi = { .op=op_impl, .lhs=from, .rhs=to, .data=(m_uint)from };
+    const restrict Exp  from, const restrict Type to) {
+  const struct Implicit imp = { from, to };
+  struct Op_Import opi = { .op=op_impl, .lhs=from->type, .rhs=to, .data=(m_uint)&imp };
   return op_emit(emit, &opi);
 }
 
@@ -1024,7 +1049,7 @@ ANN2(1) static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) {
   do {
     CHECK_BB(exp_func[exp->exp_type](emit, &exp->d))
     if(exp->cast_to)
-      CHECK_BB(emit_implicit_cast(emit, exp->type, exp->cast_to))
+      CHECK_BB(emit_implicit_cast(emit, exp, exp->cast_to))
     if(ref && isa(exp->type, t_object) > 0 && isa(exp->type, t_shred) < 0 ) { // beware fork
       const Instr instr = emit_add_instr(emit, RegAddRef);
       instr->m_val = exp->emit_var;
@@ -1563,7 +1588,7 @@ ANN static m_bool emit_member_func(const Emitter emit, const Exp_Dot* member, co
     emit_add_instr(emit, DotTmplVal);
   else {
     const Instr instr = emit_add_instr(emit, GET_FLAG(func, member) ? DotFunc : DotStaticFunc);
-    instr->m_val = func->vt_index;
+    instr->m_val = exp_self(member)->type->e->d.func->vt_index;
   }
   return GW_OK;
 }
@@ -1651,6 +1676,8 @@ ANN static void emit_func_def_code(const Emitter emit, const Func func) {
     instr->m_val = (m_uint)emit->gwion->mp;
     ADD_REF(func->code)
   }
+  // TODO: find why we need this
+  func->def->stack_depth = func->code->stack_depth;
 }
 
 ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def func_def) {
@@ -1658,7 +1685,7 @@ ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def func_def
     emit_func_def_args(emit, func_def->base->args);
   if(GET_FLAG(func_def, variadic))
     stack_alloc(emit);
-  if(func_def->d.code->d.stmt_code.stmt_list)
+  if(func_def->d.code)
     CHECK_BB(emit_stmt_code(emit, &func_def->d.code->d.stmt_code))
   emit_func_def_ensure(emit, func_def);
   return GW_OK;
index a757862ccc56567a2cee38800f437a8b4460d992..ca08dcdb3506c6d298cd6722997a2a52d3e7eedc 100644 (file)
@@ -36,30 +36,113 @@ static OP_CHECK(opck_func_call) {
   return check_exp_call1(env, &e->d.exp_call) ?: t_null;
 }
 
+static inline void fptr_instr(const Emitter emit, const Func f, const m_uint i) {
+  const Instr set = emit_add_instr(emit, RegSetImm);
+  set->m_val = (m_uint)f;
+  set->m_val2 = -SZ_INT*i;
+}
+
 static OP_EMIT(opem_func_assign) {
   Exp_Binary* bin = (Exp_Binary*)data;
+  if(bin->rhs->type->e->d.func->def->base->tmpl)
+    fptr_instr(emit, bin->lhs->type->e->d.func, 2);
   emit_add_instr(emit, int_r_assign);
-  if((bin->lhs->type != t_lambda && isa(bin->lhs->type, t_fptr) < 0) && GET_FLAG(bin->rhs->type->e->d.func, member)) {
+  if((bin->lhs->type != t_lambda && isa(bin->lhs->type, t_fptr) < 0) &&
+      GET_FLAG(bin->rhs->type->e->d.func, member)) {
     const Instr instr = emit_add_instr(emit, LambdaAssign);
     instr->m_val = SZ_INT;
   }
   return GW_OK;
 }
 
-ANN static Type fptr_type(const Env env, Exp_Binary* bin) {
-  const Func l_func = bin->lhs->type->e->d.func;
-  const Func r_func = bin->rhs->type->e->d.func;
-  const Nspc nspc = l_func->value_ref->owner;
-  const m_str c = s_name(l_func->def->base->xid);
-  const Value v = l_func->value_ref;
-  for(m_uint i = 0; i <= v->offset; ++i) {
-    const Symbol sym = func_symbol(env, nspc->name, c, NULL, i);
-    const Func f = nspc_lookup_func1(nspc, sym); // was lookup2
-    CHECK_OO(f)
-    if(compat_func(r_func->def, f->def) > 0)
-      return r_func->value_ref->type->e->d.base_type;
+struct FptrInfo {
+        Func  lhs;
+  const Func  rhs;
+  const Exp   exp;
+  const loc_t pos;
+};
+
+ANN static m_bool fptr_tmpl_push(const Env env, struct FptrInfo *info) {
+  if(!info->rhs->def->base->tmpl)
+    return GW_OK;
+  ID_List t0 = info->lhs->def->base->tmpl->list,
+          t1 = info->rhs->def->base->tmpl->list;
+  nspc_push_type(env->gwion->mp, env->curr);
+  while(t0) {
+    CHECK_OB(t1)
+    nspc_add_type(env->curr, t0->xid, t_undefined);
+    nspc_add_type(env->curr, t1->xid, t_undefined);
+    t0 = t0->next;
+    t1 = t1->next;
   }
-  return NULL;
+  return GW_OK;
+}
+
+ANN static m_bool fptr_args(const Env env, struct Func_Base_ *base[2]) {
+  Arg_List arg0 = base[0]->args, arg1 = base[1]->args;
+  while(arg0) {
+    CHECK_OB(arg1)
+    const Type t0 = known_type(env, base[0]->td);
+    CHECK_OB(t0)
+    const Type t1 = known_type(env, base[1]->td);
+    CHECK_OB(t1)
+    CHECK_BB(isa(t0, t1))
+    arg0 = arg0->next;
+    arg1 = arg1->next;
+  }
+  return !arg1 ? GW_OK : GW_ERROR;
+}
+
+ANN static m_bool fptr_check(const Env env, struct FptrInfo *info) {
+  const Type l_type = info->lhs->value_ref->owner_class;
+  const Type r_type = info->rhs->value_ref->owner_class;
+  if(!r_type && l_type)
+    ERR_B(info->pos, "can't assign member function to non member function pointer")
+  else if(!l_type && r_type) {
+    if(!GET_FLAG(info->rhs, global))
+      ERR_B(info->pos, "can't assign non member function to member function pointer")
+  } else if(l_type && isa(r_type, l_type) < 0)
+      ERR_B(info->pos, "can't assign member function to a pointer of an other class")
+  if(GET_FLAG(info->rhs, member)) {
+    if(!GET_FLAG(info->lhs, member))
+      ERR_B(info->pos, "can't assign static function to member function pointer")
+  } else if(GET_FLAG(info->lhs, member))
+      ERR_B(info->pos, "can't assign member function to static function pointer")
+  return GW_OK;
+}
+
+ANN static m_bool fptr_rettype(const Env env, struct FptrInfo *info) {
+  const Type t0 = known_type(env, info->lhs->def->base->td);
+  CHECK_OB(t0)
+  const Type t1 = known_type(env, info->rhs->def->base->td);
+  CHECK_OB(t1)
+  return isa(t0, t1);
+}
+
+ANN static inline m_bool fptr_arity(struct FptrInfo *info) {
+  return GET_FLAG(info->lhs->def, variadic) ==
+         GET_FLAG(info->rhs->def, variadic);
+}
+
+ANN static Type fptr_type(const Env env, struct FptrInfo *info) {
+  const Value v = info->lhs->value_ref;
+  const Nspc nspc = v->owner;
+  const m_str c = s_name(info->lhs->def->base->xid),
+    stmpl = !info->rhs->def->base->tmpl ? NULL : "template";
+  Type type = NULL;
+  for(m_uint i = 0; i <= v->offset && !type; ++i) {
+    const Symbol sym = (!info->lhs->def->base->tmpl || i != 0) ?
+        func_symbol(env, nspc->name, c, stmpl, i) : info->lhs->def->base->xid;
+    info->lhs = nspc_lookup_func1(nspc, sym);
+    assert(info->lhs);
+    struct Func_Base_ *base[2] =  { info->lhs->def->base, info->rhs->def->base };
+    if(fptr_tmpl_push(env, info) > 0 && fptr_rettype(env, info) > 0 &&
+       fptr_arity(info) && fptr_args(env, base) > 0)
+      type = info->lhs->value_ref->type;
+    if(info->rhs->def->base->tmpl)
+      nspc_pop_type(env->gwion->mp, env->curr);
+  }
+  return type;
 }
 
 ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner,
@@ -74,8 +157,9 @@ ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner,
   }
   if(base || arg)
     ERR_B(exp_self(l)->pos, "argument number does not match for lambda")
-  l->def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, def->base->td, l->name, l->args), l->code, def->flag,
-    loc_cpy(env->gwion->mp, def->pos));
+  l->def = new_func_def(env->gwion->mp,
+    new_func_base(env->gwion->mp, def->base->td, l->name, l->args),
+    l->code, def->flag, loc_cpy(env->gwion->mp, def->pos));
   CHECK_BB(traverse_func_def(env, l->def))
   arg = l->args;
   while(arg) {
@@ -87,63 +171,44 @@ ANN2(1,3,4) m_bool check_lambda(const Env env, const Type owner,
   return GW_OK;
 }
 
+ANN static m_bool fptr_lambda(const Env env, struct FptrInfo *info) {
+  Exp_Lambda *l = &info->exp->d.exp_lambda;
+  const Type owner = info->rhs->value_ref->owner_class;
+  return check_lambda(env, owner, l, info->rhs->def);
+}
+
+ANN static m_bool fptr_do(const Env env, struct FptrInfo *info) {
+  if(isa(info->exp->type, t_lambda) < 0) {
+    CHECK_BB(fptr_check(env, info))
+    return (info->exp->type = fptr_type(env, info)) ? GW_OK : GW_ERROR;
+  }
+  return fptr_lambda(env, info);
+}
+
 static OP_CHECK(opck_fptr_at) {
   Exp_Binary* bin = (Exp_Binary*)data;
+  struct FptrInfo info = { bin->lhs->type->e->d.func, bin->rhs->type->e->d.func,
+      bin->lhs, exp_self(bin)->pos };
+  CHECK_BO(fptr_do(env, &info))
   bin->rhs->emit_var = 1;
-  if(isa(bin->lhs->type, t_lambda) > 0) {
-    Exp_Lambda *l = &bin->lhs->d.exp_lambda;
-    const Type owner = nspc_lookup_type1(bin->rhs->type->e->owner->parent,
-       insert_symbol(bin->rhs->type->e->owner->name));
-    CHECK_BO(check_lambda(env, owner, l, bin->rhs->type->e->d.func->def))
-    return bin->rhs->type;
-  }
-  const Func l_func = bin->lhs->type->e->d.func;
-  const Func_Def l_fdef = l_func->def;
-  const Type l_type = l_func->value_ref->owner_class;
-  const Func r_func = bin->rhs->type->e->d.func;
-  const Func_Def r_fdef = r_func->def;
-  const Type r_type = r_func->value_ref->owner_class;
-  if(!r_type && l_type)
-    ERR_N(exp_self(bin)->pos, "can't assign member function to non member function pointer")
-  else if(r_type && !l_type) {
-    if(!GET_FLAG(r_func, global))
-      ERR_N(exp_self(bin)->pos, "can't assign non member function to member function pointer")
-  } else if(r_type && isa(r_type, l_type) < 0)
-      ERR_N(exp_self(bin)->pos, "can't assign member function to member function pointer"
-            " of an other class")
-  if(GET_FLAG(r_func, member)) {
-    if(!GET_FLAG(l_func, member))
-      ERR_N(exp_self(bin)->pos, "can't assign static function to member function pointer")
-  } else if(GET_FLAG(l_func, member))
-      ERR_N(exp_self(bin)->pos, "can't assign member function to static function pointer")
-  if(isa(r_fdef->base->ret_type, l_fdef->base->ret_type) < 0)
-    ERR_N(exp_self(bin)->pos, "return type '%s' does not match '%s'\n\t... in pointer assignement",
-         r_fdef->base->ret_type->name, l_fdef->base->ret_type->name)
-  if(GET_FLAG(l_fdef, variadic) != GET_FLAG(r_fdef, variadic))
-    ERR_N(exp_self(bin)->pos, "function must be of same argument kind.",
-         r_fdef->base->ret_type->name, l_fdef->base->ret_type->name)
-  if(isa(bin->lhs->type, t_fptr) > 0 && isa(bin->lhs->type, bin->rhs->type) > 0)
-    return bin->rhs->type;
-  return fptr_type(env, bin);
+  return bin->rhs->type;
 }
 
 static OP_CHECK(opck_fptr_cast) {
   Exp_Cast* cast = (Exp_Cast*)data;
   const Type t = exp_self(cast)->type;
-  const Value v = nspc_lookup_value1(env->curr, cast->exp->d.exp_primary.d.var);
-  CHECK_OO(v)
-  const Func f = isa(v->type, t_fptr) > 0 ?
-            v->type->e->d.func :
-            nspc_lookup_func1(env->curr, insert_symbol(v->name));
-  CHECK_OO(f)
-  CHECK_BO(compat_func(t->e->d.func->def, f->def))
-  cast->func = f;
+  struct FptrInfo info = { cast->exp->type->e->d.func, t->e->d.func,
+     cast->exp, exp_self(cast)->pos };
+  CHECK_BO(fptr_do(env, &info))
+  cast->func = cast->exp->type->e->d.func;
   return t;
 }
 
 static OP_EMIT(opem_fptr_cast) {
   CHECK_BB(opem_basic_cast(emit, data))
   Exp_Cast* cast = (Exp_Cast*)data;
+  if(exp_self(cast)->type->e->d.func->def->base->tmpl)
+    fptr_instr(emit, cast->exp->type->e->d.func, 1);
   if(GET_FLAG(cast->exp->type->e->d.func, member)) {
     const Instr instr = emit_add_instr(emit, RegPop);
     instr->m_val = SZ_INT*2;
@@ -153,6 +218,25 @@ static OP_EMIT(opem_fptr_cast) {
   return GW_OK;
 }
 
+static OP_CHECK(opck_fptr_impl) {
+  struct Implicit *impl = (struct Implicit*)data;
+  struct FptrInfo info = { ((Exp)impl->e)->type->e->d.func, impl->t->e->d.func,
+      (Exp)impl->e, ((Exp)impl->e)->pos };
+  CHECK_BO(fptr_do(env, &info))
+  return ((Exp)impl->e)->cast_to = impl->t;
+}
+
+static OP_EMIT(opem_fptr_impl) {
+  struct Implicit *impl = (struct Implicit*)data;
+  if(GET_FLAG(impl->t->e->d.func, member)) {
+    const Instr pop = emit_add_instr(emit, RegPop);
+    pop->m_val = SZ_INT;
+  }
+  if(impl->t->e->d.func->def->base->tmpl)
+    fptr_instr(emit, ((Exp)impl->e)->type->e->d.func, 1);
+  return GW_OK;
+}
+
 ANN Type check_exp_unary_spork(const Env env, const Stmt code);
 
 static OP_CHECK(opck_spork) {
@@ -163,10 +247,10 @@ static OP_CHECK(opck_spork) {
   if(unary->exp && unary->exp->exp_type == ae_exp_call)
     return unary->op == op_spork ? t_shred : t_fork;
   else if(unary->code) {
-    ++env->scope->depth;        \
-    nspc_push_value(env->gwion->mp, env->curr); \
+    ++env->scope->depth;
+    nspc_push_value(env->gwion->mp, env->curr);
     const m_bool ret = check_stmt(env, unary->code);
-    nspc_pop_value(env->gwion->mp, env->curr);  \
+    nspc_pop_value(env->gwion->mp, env->curr);
     --env->scope->depth;
     CHECK_BO(ret)
     return unary->op == op_spork ? t_shred : t_fork;
@@ -202,6 +286,9 @@ GWION_IMPORT(func) {
   CHECK_BB(gwi_oper_add(gwi, opck_fptr_cast))
   CHECK_BB(gwi_oper_emi(gwi, opem_fptr_cast))
   CHECK_BB(gwi_oper_end(gwi, op_cast, NULL))
+  CHECK_BB(gwi_oper_add(gwi, opck_fptr_impl))
+  CHECK_BB(gwi_oper_emi(gwi, opem_fptr_impl))
+  CHECK_BB(gwi_oper_end(gwi, op_impl, NULL))
   CHECK_BB(gwi_oper_ini(gwi, NULL, (m_str)OP_ANY_TYPE, NULL))
   CHECK_BB(gwi_oper_add(gwi, opck_spork))
   CHECK_BB(gwi_oper_emi(gwi, opem_spork))
index a80e1ccd4a3ad089509a148d404c1600ab2bdd50..775a0a09aadfd8627736ad71d67ad66760346f17 100644 (file)
@@ -15,7 +15,7 @@ static void print_type(const Type type) {
   const m_bool is_func = isa(type, t_function) > 0 && isa(type, t_fptr) < 0;
   const m_str name = is_func ? strdup("@function") : strdup(type->name);
   gw_out("(%s) ", name);
-  free(name);
+  xfree(name);
   if(GET_FLAG(type, typedef)) {
     gw_out(" aka ");
     print_type(type->e->parent);
@@ -76,12 +76,14 @@ ANN2(1) static inline void print_object(const Type type, const M_Object obj) {
 }
 
 ANN static inline void print_func(const Type type, const m_bit* stack) {
-  if(type->e->d.func) {
-    const VM_Code code = isa(type, t_fptr) > 0 ?
-      *(VM_Code*)stack : type->e->d.func->code;
-    gw_out("%s %s %p", type->name, (void*)code ? code->name : NULL, code);
-  } else
-    gw_out("%s %p", type->name, NULL);
+  if(isa(type, t_fptr) > 0 && type->e->d.func->def->base->tmpl) {
+    const Func f = *(Func*)stack;
+    gw_out("%s", f ? f->name : "(nil)");
+    return;
+  }
+  const VM_Code code = isa(type, t_fptr) > 0 ?
+    *(VM_Code*)stack : type->e->d.func->code;
+  gw_out("%s %s %p", type->name, (void*)code ? code->name : NULL, code);
 }
 
 ANN static void print_prim(const Type type, const m_bit* stack) {
index 8529b8cdfe783a77f08b7dda67b231bf657aedd2..cac9c0403231155d892fe50e6eb164ef8fb59980 100644 (file)
@@ -58,21 +58,58 @@ INSTR(PopArrayClass) {
   ADD_REF(obj->type_ref) // add ref to typedef array type
 }
 
-ANN static Func_Def from_base(const Env env, const struct dottmpl_ *dt, const Type t) {
-  const Symbol sym = func_symbol(env, t->name, s_name(dt->base->base->xid),
-    "template", dt->overload);
-  const Value v = nspc_lookup_value1(t->nspc, sym);
+ANN static Func_Def from_base(const Env env, const struct dottmpl_ *dt, const Nspc nspc) {
+  const Func_Def fdef = dt->def ?: dt->base;
+  const Symbol sym = func_symbol(env, nspc->name, s_name(fdef->base->xid),
+    "template", dt->vt_index);
+  const Value v = nspc_lookup_value1(nspc, sym);
   CHECK_OO(v)
   const Func_Def base = v->d.func_ref->def;
-  const Func_Def def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, base->base->td, insert_symbol(env->gwion->st, v->name),
-            base->base->args), base->d.code, base->flag, loc_cpy(env->gwion->mp, base->pos));
-  def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, dt->overload);
+  const Func_Def def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, fdef->base->td, insert_symbol(env->gwion->st, v->name),
+            fdef->base->args), fdef->d.code, fdef->flag, loc_cpy(env->gwion->mp, base->pos));
+  def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, dt->vt_index);
   SET_FLAG(def, template);
   return def;
 }
 
+INSTR(GTmpl) {
+  struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val;
+  const Func f = *(Func*)REG(-SZ_INT);
+  const m_str name = f->name;
+  const Emitter emit = shred->info->vm->gwion->emit;
+  emit->env->name = "runtime";
+  m_str tmpl_name = tl2str(emit->env, dt->tl);
+  for(m_uint i = 0 ; i <= f->value_ref->offset; ++i) {
+    const Symbol sym = func_symbol(emit->env, f->value_ref->owner->name,
+      name, tmpl_name, i);
+    const Func base = nspc_lookup_func1(f->value_ref->owner, sym);
+    if(base) {
+      xfree(tmpl_name);
+      assert(base->code);
+      if(GET_FLAG(base->def, static))
+        shred->reg -= SZ_INT;
+      *(VM_Code*)(shred->reg -SZ_INT) = base->code;
+      return;
+    }
+  }
+  xfree(tmpl_name);
+  dt->def = f->def;
+  const Func_Def def = from_base(emit->env, dt, f->value_ref->owner);
+  if(!def)
+    Except(shred, "MissigTmplPtrException[internal]");
+  dt->def = def;
+  dt->owner = f->value_ref->owner;
+  dt->owner_class = f->value_ref->owner_class;
+  if(traverse_dot_tmpl(emit, dt) > 0) {
+    if(GET_FLAG(def, static))
+      shred->reg -= SZ_INT;
+    *(VM_Code*)(shred->reg -SZ_INT) = def->base->func->code;
+    return;
+  }
+}
+
 INSTR(DotTmpl) {
-  struct dottmpl_ * dt = (struct dottmpl_*)instr->m_val;
+  struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val;
   const m_str name = dt->name;
   const M_Object o = *(M_Object*)REG(-SZ_INT);
   Type t = o->type_ref;
@@ -86,7 +123,7 @@ INSTR(DotTmpl) {
     if(f) {
       if(!f->code) {
         dt->def = f->def;//
-        dt->owner = t; //
+        dt->owner_class = t; //
         if(traverse_dot_tmpl(emit, dt) < 0)
           continue;
       }
@@ -96,11 +133,11 @@ INSTR(DotTmpl) {
       shred->reg += SZ_INT;
       return;
     } else {
-      const Func_Def def = from_base(emit->env, dt, t);
+      const Func_Def def = from_base(emit->env, dt, t->nspc);
       if(!def)
         continue;
       dt->def = def; //
-      dt->owner = t; //
+      dt->owner_class = t; //
       if(traverse_dot_tmpl(emit, dt) > 0) {
         if(GET_FLAG(def, static))
           shred->reg -= SZ_INT;
index 9d02745fcd2009dccf94294e1dcac61d4b94af48..b186ea720f8b4ebce78072dd31e32d36f3fdb476 100644 (file)
@@ -65,7 +65,8 @@ OP_CHECK(opck_unary_meta2_uniq) {
   const Exp_Unary* unary = (Exp_Unary*)data;
   CHECK_OO(opck_unary_meta2(env, data))
   if(unary->exp->next)
-    ERR_N(exp_self(unary)->pos, "fuck!!")
+    ERR_N(exp_self(unary)->pos,
+      "'%s' must be applied to a unique expression", op2str(unary->op))
   return t_int;
 }
 
index a923085018d83e4e4c97082cbec3686c5e2749ef..98486df1db68b8e02ba35c9ee56475fb133875f3 100644 (file)
@@ -1,4 +1,5 @@
 #include <stdlib.h>
+#include <string.h>
 #include "gwion_util.h"
 #include "gwion_ast.h"
 #include "oo.h"
index 2505fab7a4c8e9f8d38396e9b10e15a3fb2838da..41926714727ffd9e95525f095203e58a7e31f5e6 100644 (file)
 ANN static void free_type(Type a, Gwion gwion) {
   if(GET_FLAG(a, template)) {
     if(GET_FLAG(a, union)) {
-      if(a->e->def->stmt) {
-      if(GET_FLAG(a, pure))
-        free_decl_list(gwion->mp, a->e->def->list);
-      else {
+      if(a->e->def->stmt && !GET_FLAG(a, pure))  { // <=> decl_list
           UNSET_FLAG(&a->e->def->stmt->d.stmt_union, global);
           free_stmt(gwion->mp, a->e->def->stmt);
-        }
       }
       a->e->def->stmt = NULL;
     }
@@ -27,6 +23,10 @@ ANN static void free_type(Type a, Gwion gwion) {
   }
   if(a->nspc)
     REM_REF(a->nspc, gwion);
+  if(a->e->contains.ptr)
+    vector_release(&a->e->contains);
+// TODO: commenting this should not happen
+//  mp_free(gwion->mp, TypeInfo, a->e);
   mp_free(gwion->mp, Type, a);
 }
 
index 8ec65bec0dc2e1a3d853d0d1e1fb927890da26cf..3b5a745c03bd8301bc94e972c7ac7127c92c2def 100644 (file)
@@ -367,6 +367,13 @@ ANN2(1,2) static Func find_func_match_actual(const Env env, Func func, const Exp
         CHECK_OO(func->next);
         return find_func_match_actual(env, func->next, args, implicit, specific);
       }
+      if(e1->type == t_undefined) {
+        if(func->value_ref->owner_class)
+          CHECK_BO(template_push_types(env, func->value_ref->owner_class->e->def->base.tmpl))
+        e1->type = known_type(env, e1->td);
+        if(func->value_ref->owner_class)
+          nspc_pop_type(env->gwion->mp, env->curr);
+      }
       if(func_match_inner(env, e, e1->type, implicit, specific) < 0)
         break;
       e = e->next;
@@ -394,7 +401,7 @@ ANN static m_bool check_call(const Env env, const Exp_Call* exp) {
   if(et != ae_exp_primary && et != ae_exp_dot && et != ae_exp_cast)
     ERR_B(exp->func->pos, "invalid expression for function call.")
   CHECK_OB(check_exp(env, exp->func))
-  return exp->args ? !!check_exp(env, exp->args) : -1;
+  return exp->args ? !!check_exp(env, exp->args) : GW_OK;
 }
 
 ANN static inline Value template_get_ready(const Env env, const Value v, const m_str tmpl, const m_uint i) {
@@ -403,69 +410,111 @@ ANN static inline Value template_get_ready(const Env env, const Value v, const m
       nspc_lookup_value1(v->owner, sym);
 }
 
+static Func ensure_tmpl(const Env env, const Func f, const Exp_Call *exp) {
+  nspc_pop_type(env->gwion->mp, env->curr);
+  if(check_call(env, exp) > 0) {
+    const Func next = f->next;
+    f->next = NULL;
+    const Func func = find_func_match(env, f, exp->args);
+    f->next = next;
+    if(func) {
+      SET_FLAG(func, checked | ae_flag_template);
+      return func;
+    }
+  }
+  return NULL;
+}
+ANN static m_bool check_func_args(const Env env, Arg_List arg_list) {
+  do {
+    const Var_Decl decl = arg_list->var_decl;
+    const Value v = decl->value;
+    if(arg_list->td && !arg_list->td->xid)
+      arg_list->type = v->type = check_td(env, arg_list->td);
+    if(isa(v->type, t_object) > 0 || isa(v->type, t_function) > 0)
+      UNSET_FLAG(env->func, pure);
+    CHECK_BB(already_defined(env, decl->xid, decl->pos))
+    SET_FLAG(v, checked);
+    nspc_add_value(env->curr, decl->xid, v);
+  } while((arg_list = arg_list->next));
+  return GW_OK;
+}
+
 ANN static Func _find_template_match(const Env env, const Value v, const Exp_Call* exp) {
-  const Exp args = exp->args;
   const Type_List types = exp->tmpl->call;
-  Func m_func = exp->m_func, former = env->func;
-if(types->td->types)exit(12);
+  Func m_func = NULL, former = env->func;
   const m_str tmpl_name = tl2str(env, types);
-  const m_uint sz = vector_size((Vector)env->curr->info->type);
   const m_uint scope = env_push(env, v->owner_class, v->owner);
+  if(isa(actual_type(v->type), t_fptr) > 0) {
+  const Symbol sym = func_symbol(env, v->owner->name, v->name, tmpl_name, 0);
+  const Value value = nspc_lookup_value1(v->owner, sym);
+  Func_Def base = v->d.func_ref->def;
+  struct Func_Base_ *fbase = /*value ? value->type->e->d.func->def :*/
+      new_func_base(env->gwion->mp, base->base->td, sym, base->base->args);
+  fbase->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, 0);
+  fbase->tmpl->call = types;
+  CHECK_BO(template_push_types(env, fbase->tmpl))
+  const Stmt stmt = new_stmt_fptr(env->gwion->mp, fbase, base->flag);
+  if(value) {
+    stmt->d.stmt_fptr.type = actual_type(value->type);
+    stmt->d.stmt_fptr.value = value;
+  }
+  CHECK_BO(traverse_stmt_fptr(env, &stmt->d.stmt_fptr))
+  free_stmt(env->gwion->mp, stmt);
+  CHECK_OO((base->base->ret_type = known_type(env, base->base->td)))
+  if(exp->args)
+    CHECK_OO(check_exp(env, exp->args))
+  const Func func = find_func_match(env, fbase->func, exp->args);
+  //  nspc_pop_type(env->gwion->mp, env->curr);
+  //  env_pop(env, scope);
+  if(!value)
+    map_set(&v->owner->info->type->map, (vtype)sym, (vtype)actual_type(func->value_ref->type));
+  xfree(tmpl_name);
+  env->func = former;
+  return func;
+  }
   for(m_uint i = 0; i < v->offset + 1; ++i) {
-    Func_Def def = NULL;
+    Func_Def fdef = NULL;
     Func_Def base = NULL;
     Value value = template_get_ready(env, v, tmpl_name, i);
     if(value) {
       if(env->func == value->d.func_ref) {
-        free(tmpl_name);
         CHECK_BO(check_call(env, exp))
-        return env->func;
+        m_func = env->func;
+        break;
       }
-      base = def = value->d.func_ref->def;
-      if(!def->base->tmpl) {
+      base = fdef = value->d.func_ref->def;
+      if(!fdef->base->tmpl) {
         if(!(value = template_get_ready(env, v, "template", i)))
           continue;
         base = value->d.func_ref->def;
-        def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i);
+        fdef->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i);
       }
     } else {
       if(!(value = template_get_ready(env, v, "template", i)))
         continue;
       base = value->d.func_ref->def;
-      def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, base->base->td, insert_symbol(v->name),
+      fdef = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, base->base->td, insert_symbol(v->name),
                 base->base->args), base->d.code, base->flag, loc_cpy(env->gwion->mp, base->pos));
-      def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i);
-      SET_FLAG(def, template);
-    }
-    def->base->tmpl->call = types;
-    if(traverse_func_template(env, def) > 0) {
-      nspc_pop_type(env->gwion->mp, env->curr);
-      if(check_call(env, exp) > 0) {
-        const Func next = def->base->func->next;
-        def->base->func->next = NULL;
-        m_func = find_func_match(env, def->base->func, args);
-        def->base->func->next = next;
-        if(m_func) {
-          SET_FLAG(m_func, checked | ae_flag_template);
-          goto end;
-        }
-      }
+      fdef->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i);
+      SET_FLAG(fdef, template);
     }
-    if(sz != vector_size((Vector)env->curr->info->type))
-     nspc_pop_type(env->gwion->mp, env->curr);
-    SET_FLAG(base, template);
+    fdef->base->tmpl->call = types;
+    if(traverse_func_template(env, fdef) > 0 &&
+        (m_func = ensure_tmpl(env, fdef->base->func, exp)))
+      break;
   }
-end:
-  free(tmpl_name);
+  xfree(tmpl_name);
   env_pop(env, scope);
   env->func = former;
   return m_func;
 }
+
 ANN Func find_template_match(const Env env, const Value value, const Exp_Call* exp) {
   Type t = value->owner_class;
   const Func f = _find_template_match(env, value, exp);
-  if(f)
+  if(f) {
     return f;
+  }
   while(t) {
    Value v = nspc_lookup_value1(t->nspc, value->d.func_ref->def->base->xid);
    if(!v)
@@ -963,7 +1012,7 @@ ANN m_bool check_stmt_union(const Env env, const Stmt_Union stmt) {
     if(isa(l->self->type, t_object) > 0) {
         if(!GET_FLAG(l->self->d.exp_decl.td, ref) && !GET_FLAG(stmt->type, template))
       ERR_B(l->self->pos, "In union, Objects must be declared as reference (use '@')")
-      SET_FLAG(l->self->d.exp_decl.td, ref);
+//      SET_FLAG(l->self->d.exp_decl.td, ref);
       Var_Decl_List list = l->self->d.exp_decl.list;
       do SET_FLAG(list->self->value, pure);
       while((list = list->next));
@@ -1046,21 +1095,6 @@ ANN static m_bool check_parent_match(const Env env, const Func_Def f) {
   return GW_OK;
 }
 
-ANN static m_bool check_func_args(const Env env, Arg_List arg_list) {
-  do {
-    const Var_Decl decl = arg_list->var_decl;
-    const Value v = decl->value;
-    if(arg_list->td && !arg_list->td->xid)
-      arg_list->type = v->type = check_td(env, arg_list->td);
-    if(isa(v->type, t_object) > 0 || isa(v->type, t_function) > 0)
-      UNSET_FLAG(env->func, pure);
-    CHECK_BB(already_defined(env, decl->xid, decl->pos))
-    SET_FLAG(v, checked);
-    nspc_add_value(env->curr, decl->xid, v);
-  } while((arg_list = arg_list->next));
-  return GW_OK;
-}
-
 ANN static inline Func get_overload(const Env env, const Func_Def def, const m_uint i) {
   const Symbol sym = func_symbol(env, env->curr->name, s_name(def->base->xid), NULL, i);
   return nspc_lookup_func1(env->curr, sym);
@@ -1136,7 +1170,8 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) {
     ret = check_func_args(env, f->base->args);
   if(ret > 0) {
     const Value variadic = GET_FLAG(f, variadic) ? set_variadic(env) : NULL;
-    if(!GET_FLAG(f, builtin) && check_stmt_code(env, &f->d.code->d.stmt_code) < 0)
+    if(!GET_FLAG(f, builtin) && f->d.code &&
+        check_stmt_code(env, &f->d.code->d.stmt_code) < 0)
       ret = GW_ERROR;
     if(variadic)
       REM_REF(variadic, env->gwion)
index bad133388a34204e818fe4cbd520ee1bc54ef88d..106390d0718bb52581641641f7d71f35d88a8545 100644 (file)
@@ -15,9 +15,6 @@ ANN static m_bool scan1_stmt_list(const Env env, Stmt_List list);
 ANN static m_bool scan1_stmt(const Env env, Stmt stmt);
 
 ANN static Type void_type(const Env env, const Type_Decl* td) {
-// could be more precise
-  if(SAFE_FLAG(env->class_def, template) && td->types)
-    return t_undefined;
   const Type t = known_type(env, td);
   CHECK_OO(t)
   if(t->size)
@@ -25,25 +22,47 @@ ANN static Type void_type(const Env env, const Type_Decl* td) {
   ERR_O(td_pos(td), "cannot declare variables of size '0' (i.e. 'void')...")
 }
 
+
+ANN static inline Type get_base_type(const Env env, const Type t) {
+  const m_str decl_name = get_type_name(env, t->name, 0);
+  return nspc_lookup_type1(env->curr, insert_symbol(decl_name));
+}
+
+ANN static m_bool type_recursive(const Env env, Exp_Decl* decl, const Type t) {
+  const Type decl_base = get_base_type(env, t);
+  const Type base = get_base_type(env, env->class_def);
+  if(decl_base && base) {
+    if(!base->e->contains.ptr)
+      vector_init(&base->e->contains);
+    vector_add(&base->e->contains, (vtype)decl_base);
+    if(decl_base->e->contains.ptr) {
+      for(m_uint i = 0; i < vector_size(&decl_base->e->contains); ++i) {
+        if(base == (Type)vector_at(&decl_base->e->contains, i) && !GET_FLAG(decl->td, ref))
+          ERR_B(exp_self(decl)->pos, "%s declared inside %s\n. (make it a ref ?)",
+              decl_base->name, decl_base == base ? "itself" : base->name);
+      }
+    }
+  }
+   return GW_OK;
+}
+
 ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) {
   const Type t = void_type(env, decl->td);
   CHECK_OO(t);
   if(decl->td->xid && decl->td->xid->xid == insert_symbol("auto") && decl->type)
     return decl->type;
+  if(!env->scope->depth && env->class_def) {
+    if(isa(t, t_object) > 0)
+      CHECK_BO(type_recursive(env, decl, t))
+    if(!GET_FLAG(decl->td, static))
+      SET_FLAG(decl->td, member);
+  }
   if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref))
     ERR_O(exp_self(decl)->pos, "Type '%s' is abstract, declare as ref. (use @)", t->name)
   if(GET_FLAG(t, private) && t->e->owner != env->curr)
     ERR_O(exp_self(decl)->pos, "can't use private type %s", t->name)
   if(GET_FLAG(t, protect) && (!env->class_def || isa(t, env->class_def) < 0))
     ERR_O(exp_self(decl)->pos, "can't use protected type %s", t->name)
-  if(env->class_def) {
-    if(!env->scope->depth) {
-      if(!GET_FLAG(decl->td, ref) && t == env->class_def)
-        ERR_O(exp_self(decl)->pos, "...(note: object of type '%s' declared inside itself)", t->name)
-      if(!GET_FLAG(decl->td, static))
-        SET_FLAG(decl->td, member);
-    }
-  }
   decl->base = t->e->def;
   return decl->type = t;
 }
@@ -303,7 +322,7 @@ ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
     CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td)))
   if(fdef->base->args)
     CHECK_BB(scan1_args(env, fdef->base->args))
-  if(!GET_FLAG(fdef, builtin))
+  if(!GET_FLAG(fdef, builtin) && fdef->d.code)
     CHECK_BB(scan1_stmt_code(env, &fdef->d.code->d.stmt_code))
   env->func = former;
   --env->scope->depth;
index bc4e999ec46ff967a27124062160e2b582ea18f5..7fba103e1ea5b40a2901269b9a5f6d3252711c7d 100644 (file)
@@ -20,22 +20,21 @@ ANN static m_bool scan2_stmt_list(const Env, Stmt_List);
 
 ANN static m_bool scan2_exp_decl_template(const Env env, const Exp_Decl* decl) {
   CHECK_BB(scan1_cdef(env, decl->type->e->def))
-  CHECK_BB(scan2_cdef(env, decl->type->e->def))
-  return GW_OK;
+  return scan2_cdef(env, decl->type->e->def);
 }
 
 ANN m_bool scan2_exp_decl(const Env env, const Exp_Decl* decl) {
-  Var_Decl_List list = decl->list;
+  const m_bool global = GET_FLAG(decl->td, global);
+  const m_uint scope = !global ? env->scope->depth : env_push_global(env);
   const Type type = decl->type;
   if(GET_FLAG(type, template) && !GET_FLAG(type, scan2))
     CHECK_BB(scan2_exp_decl_template(env, decl))
-  const m_bool global = GET_FLAG(decl->td, global);
-  const m_uint scope = !global ? env->scope->depth : env_push_global(env);
+  Var_Decl_List list = decl->list;
   do {
     const Var_Decl var = list->self;
-    const Array_Sub array = var->array;
-    if(array && array->exp)
-      CHECK_BB(scan2_exp(env, array->exp))
+    const Exp array = var->array ? var->array->exp : NULL;
+    if(array)
+      CHECK_BB(scan2_exp(env, array))
     nspc_add_value(env->curr, var->xid, var->value);
   } while((list = list->next));
   if(global)
@@ -92,6 +91,7 @@ ANN m_bool scan2_stmt_fptr(const Env env, const Stmt_Fptr ptr) {
   ptr->value->d.func_ref = ptr->base->func;
   ptr->base->func->value_ref = ptr->value;
   ptr->type->e->d.func = ptr->base->func;
+  def->base->tmpl = ptr->base->tmpl;
   SET_FLAG(ptr->value, func | ae_flag_checked);
   if(ptr->base->args)
     CHECK_BB(scan2_args(env, def))
@@ -301,8 +301,10 @@ ANN static m_bool scan2_stmt_list(const Env env, Stmt_List list) {
 ANN static m_bool scan2_func_def_overload(const Env env, const Func_Def f, const Value overload) {
   const m_bool base = tmpl_base(f->base->tmpl);
   const m_bool tmpl = GET_FLAG(overload, template);
-  if(isa(overload->type, t_function) < 0 || isa(overload->type, t_fptr) > 0)
+  if(isa(overload->type, t_function) < 0 || isa(overload->type, t_fptr) > 0) {
+  if(isa(actual_type(overload->type), t_function) < 0)
     ERR_B(f->pos, "function name '%s' is already used by another value", overload->name)
+}
   if((!tmpl && base) || (tmpl && !base && !GET_FLAG(f, template)))
     ERR_B(f->pos, "must overload template function with template")
   return GW_OK;
@@ -387,6 +389,7 @@ ANN2(1, 2) static m_bool scan2_func_def_template(const Env env, const Func_Def f
     func->vt_index = i;
     ADD_REF(value)
     nspc_add_value(env->curr, f->base->xid, value);
+    nspc_add_func(env->curr, f->base->xid, func);
   } else
     func->vt_index = ++overload->offset;
   return GW_OK;
@@ -467,7 +470,7 @@ ANN static m_str func_tmpl_name(const Env env, const Func_Def f) {
 }
 
 
-ANN2(1,2,4) static Value func_create(const Env env, const Func_Def f,
+ANN2(1,2,4) /*static */Value func_create(const Env env, const Func_Def f,
      const Value overload, const m_str name) {
   const Func func = scan_new_func(env, f, name);
   nspc_add_func(env->curr, insert_symbol(func->name), func);
@@ -531,7 +534,7 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def f) {
 // body
   if(f->base->args)
     CHECK_BB(scan2_args(env, f))
-  if(!GET_FLAG(f, builtin) && f->d.code->d.stmt_code.stmt_list)
+  if(!GET_FLAG(f, builtin) && f->d.code)
     CHECK_BB(scan2_func_def_code(env, f))
 // gpop
   if(GET_FLAG(f, global))
index b1e7d1786b758fa9599a7bcba20b62f5273b8346..081a4bd6539ff48dce423eef0178e756d7461067 100644 (file)
@@ -73,8 +73,11 @@ ANN static size_t template_size(const Env env, struct tmpl_info* info) {
   ID_List base = info->cdef->base.tmpl->list;
   Type_List call = info->call;
   size_t size = tmpl_set(info, info->cdef->base.type);
-  do size += tmpl_set(info, type_decl_resolve(env, call->td));
-  while((call = call->next) && (base = base->next) && ++size);
+  do {
+    const Type t = type_decl_resolve(env, call->td);
+    CHECK_OB(t)
+    size += tmpl_set(info, t);
+  } while((call = call->next) && (base = base->next) && ++size);
   return size + 16 + 3;
 }
 
@@ -114,6 +117,8 @@ ANN m_bool template_match(ID_List base, Type_List call) {
 
 ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) {
   const Symbol name = template_id(env, def, call);
+  if(env->class_def && name == insert_symbol(env->class_def->name))
+     return env->class_def->e->def;
   const Type t = nspc_lookup_type1(env->curr, name);
   return t ? t->e->def : new_class_def(env->gwion->mp, def->flag, name, def->base.ext, def->body,
     loc_cpy(env->gwion->mp, def->pos));
@@ -157,9 +162,11 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) {
       return a->base.type;
     a->base.tmpl = new_tmpl(env->gwion->mp, get_total_type_list(env, t), 0);
     a->base.tmpl->call = type->types;
-    if(isa(t, t_union) < 0)
+    if(isa(t, t_union) < 0) {
       CHECK_BO(scan0_class_def(env, a))
-    else {
+    map_set(&t->e->owner->info->type->map, (vtype)insert_symbol(a->base.type->name),
+      (vtype)a->base.type);
+    } else {
       a->stmt = new_stmt_union(env->gwion->mp, (Decl_List)a->body, t->e->def->pos);
       a->stmt->d.stmt_union.type_xid = a->base.xid;
       CHECK_BO(scan0_stmt_union(env, &a->stmt->d.stmt_union))
@@ -177,8 +184,6 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) {
       SET_FLAG(a->base.type, dtor);
       ADD_REF(t->nspc->dtor)
     }
-//    nspc_add_type(t->e->owner, insert_symbol(a->base.type->name), a->base.type);
-    map_set(&t->e->owner->info->type->map, insert_symbol(a->base.type->name), a->base.type);
     return a->base.type;
   } else if(type->types)
       ERR_O(type->xid->pos,
index 637d93e3b7d2740837047e94f1adf04b2439ac57..00ee4ce5b875225e0ec3af470b1a5d8e94b0ad2e 100644 (file)
@@ -40,7 +40,7 @@ ANN m_bool traverse_stmt_enum(const Env env, const Stmt_Enum def) {
 }
 
 ANN m_bool traverse_stmt_fptr(const Env env, const Stmt_Fptr def) {
-  CHECK_BB(scan0_stmt_fptr(env, def))
+//  CHECK_BB(scan0_stmt_fptr(env, def))
   CHECK_BB(scan1_stmt_fptr(env, def))
   return scan2_stmt_fptr(env, def);
 // CHECK_BB(check_stmt_fptr(env, def))
index 8b32476febd7b66345b175dbee5a1bd14f2de26d..1a49596a19c9d142563b044912bce6c62f6acafd 100644 (file)
@@ -10,5 +10,8 @@
 
 ANN m_bool traverse_func_template(const Env env, const Func_Def def) {
   CHECK_BB(template_push_types(env, def->base->tmpl))
-  return traverse_func_def(env, def);
+  if(traverse_func_def(env, def) > 0)
+    return GW_OK;
+  nspc_pop_type(env->gwion->mp, env->curr);
+  return GW_ERROR;
 }
index 5123753979844ec324bd6d0651a66255fddaa58e..11610db16a3de66ef25f64938807062eb4f8227f 100644 (file)
@@ -301,7 +301,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
   do {
     register Instr instr; DISPATCH();
 regsetimm:
-  *(m_uint*)reg = instr->m_val;
+  *(m_uint*)(reg + (m_int)instr->m_val2) = instr->m_val;
   DISPATCH();
 regpushimm:
   *(m_uint*)reg = instr->m_val;
index cdbf537d86abed04dbe57724f5f74d9df9dd0489..7f18d51a2deb713367b4dc818dfd0fa527d635a0 100644 (file)
@@ -1,4 +1,4 @@
-// [contains] can't assign member function to member function pointer of an other class
+// [contains] can't assign member function to a pointer of an other class
 class C {
   typedef void Test();
   Test test;