]> Nishi Git Mirror - gwion.git/commitdiff
:art: Allow fptr typedef
authorfennecdjay <astor.jeremie@wanadoo.fr>
Thu, 11 Jul 2019 13:59:16 +0000 (15:59 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Thu, 11 Jul 2019 13:59:16 +0000 (15:59 +0200)
src/emit/emit.c
src/lib/func.c
src/lib/instr.c
src/parse/check.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/template.c

index df309a90bb7f7d5df8af44f186c9e7edf0f7a995..e169d55efe01de85b9844115314374d823592d26 100644 (file)
@@ -693,8 +693,7 @@ 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 &&
-      is_fptr(v->type))
+  if(isa(v->type, t_class) > 0 && is_fptr(v->type))
     return emit->env->scope->depth;
   const m_uint scope = emit_push(emit, v->owner_class, v->owner);
   CHECK_BB(traverse_func_def(emit->env, f->def))
@@ -820,7 +819,9 @@ ANN static Instr get_prelude(const Emitter emit, const Func f) {
     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);
+      size_t slen = strlen(f->value_ref->owner->name);
+      assert(len > slen);
+      size_t sz = len - slen;
       char c[sz + 1];
       memcpy(c, f->name, sz);
       c[sz] = '\0';
index 4d8cc62b97818bacfcd9e1a256813ae9ea1b7c23..9fd775c814407c0ca41d7b9c16724d80e5e2e067 100644 (file)
@@ -197,6 +197,14 @@ ANN static m_bool fptr_do(const Env env, struct FptrInfo *info) {
 
 static OP_CHECK(opck_fptr_at) {
   Exp_Binary* bin = (Exp_Binary*)data;
+  if(bin->rhs->type->e->d.func->def->base->tmpl &&
+     bin->rhs->type->e->d.func->def->base->tmpl->call) {
+  struct FptrInfo info = { bin->lhs->type->e->d.func, bin->rhs->type->e->parent->e->d.func,
+      bin->lhs, exp_self(bin)->pos };
+  CHECK_BO(fptr_do(env, &info))
+  bin->rhs->emit_var = 1;
+  return bin->rhs->type;
+}
   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))
index 1963d9a01d18adfe1e0456b1a809afddc9641da9..9c0505916ee13e6daee5a601d105f804da299a48 100644 (file)
@@ -93,11 +93,14 @@ INSTR(GTmpl) {
   dt->owner = f->value_ref->owner;
   dt->owner_class = f->value_ref->owner_class;
   if(traverse_dot_tmpl(emit, dt) > 0) {
+    if(GET_FLAG(f, member)) // TODO: CHECK ME
+        shred->reg += SZ_INT; else
     if(GET_FLAG(def, static))
       shred->reg -= SZ_INT;
     *(VM_Code*)(shred->reg -SZ_INT) = def->base->func->code;
     return;
-  }
+  } else
+    Except(shred, "TemplateException");
 }
 
 INSTR(DotTmpl) {
index 495e1e2108669b312049d4e9674c648414536762..401ac5313e9834cfd37117777d550d893e027200 100644 (file)
@@ -451,7 +451,7 @@ ANN static Func _find_template_match(const Env env, const Value v, const Exp_Cal
   if(is_fptr(v->type)) {
   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;
+  Func_Def base = v->d.func_ref ? v->d.func_ref->def : exp->func->type->e->d.func->def;
   struct Func_Base_ *fbase = 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;
@@ -467,11 +467,10 @@ ANN static Func _find_template_match(const Env env, const Value v, const Exp_Cal
       m_func = find_func_match(env, fbase->func, exp->args);
       nspc_pop_type(env->gwion->mp, env->curr);
       if(!value && m_func) {
-printf("m_func %p\n", m_func);
-if(!m_func->def->base->ret_type)
-CHECK_BO(traverse_func_def(env, m_func->def))
+        if(!m_func->def->base->ret_type)
+          CHECK_BO(traverse_func_def(env, m_func->def))
         map_set(&v->owner->info->type->map, (vtype)sym, (vtype)actual_type(m_func->value_ref->type));
-}
+      }
     }
     free_stmt(env->gwion->mp, stmt);
   }
@@ -570,7 +569,7 @@ ANN static Func get_template_func(const Env env, const Exp_Call* func, const Val
   const Func f = find_template_match(env, v, func);
   if(f) {
     Tmpl* tmpl = new_tmpl_call(env->gwion->mp, func->tmpl->call);
-    tmpl->list = v->d.func_ref->def->base->tmpl->list;
+    tmpl->list = v->d.func_ref ? v->d.func_ref->def->base->tmpl->list : func->func->type->e->d.func->def->base->tmpl->list;
     ((Exp_Call*)func)->tmpl = tmpl;
     return ((Exp_Call*)func)->m_func = f;
   }
@@ -586,9 +585,29 @@ ANN static Type check_exp_call_template(const Env env, const Exp_Call *exp) {
   const Exp args = exp->args;
   m_uint args_number = 0;
   DECL_OO(const Value, value, = nspc_lookup_value1(call->type->e->owner, insert_symbol(call->type->name)))
-  const m_uint type_number = get_type_number(value->d.func_ref->def->base->tmpl->list);
+  Tmpl *tm = value->d.func_ref ? value->d.func_ref->def->base->tmpl : call->type->e->d.func->def->base->tmpl;
+  const m_uint type_number = get_type_number(tm->list);
   Type_List tl[type_number];
-  ID_List list = value->d.func_ref->def->base->tmpl->list;
+  ID_List list = tm->list;
+  if(tm->call) {
+    if(!value->d.func_ref) {
+      Tmpl tmpl = { .call=tm->call };
+      ((Exp_Call*)exp)->tmpl = &tmpl;
+      DECL_OO(const Func,func, = get_template_func(env, exp, value))
+      assert(func->def->base->ret_type);
+      value->d.func_ref = func;
+      return func->def->base->ret_type;
+    } else {
+      const Func func = value->d.func_ref;
+      if(!func->def->base->ret_type) { // template fptr
+        const m_uint scope = env_push(env, value->owner_class, value->owner);
+        CHECK_BO(traverse_func_def(env, func->def))
+        env_pop(env, scope);
+      }
+      ((Exp_Call*)exp)->m_func = func;
+      return func->def->base->ret_type;
+    }
+  }
   while(list) {
     Arg_List arg = value->d.func_ref->def->base->args;
     Exp template_arg = args;
@@ -614,7 +633,7 @@ ANN static Type check_exp_call_template(const Env env, const Exp_Call *exp) {
   DECL_OO(const Func,func, = get_template_func(env, exp, value))
   if(!func->def->base->ret_type) // template fptr
     CHECK_BO(traverse_func_def(env, func->def))
-    return func->def->base->ret_type;
+  return func->def->base->ret_type;
 }
 
 ANN static m_bool check_exp_call1_check(const Env env, const Exp exp) {
@@ -694,17 +713,32 @@ ANN static Type check_exp_post(const Env env, const Exp_Postfix* post) {
   return t;
 }
 
+ANN static m_bool predefined_call(const Env env, const Type t, const loc_t pos) {
+  const m_str str = tl2str(env, t->e->d.func->def->base->tmpl->call);
+  env_err(env, pos, _("Type '%s' has '%s' as pre-defined types."),
+      t->name, str);
+  free_mstr(env->gwion->mp, str);
+  if(GET_FLAG(t, typedef)) {
+    loc_header(t->e->d.func->def->pos, env->name);
+    gw_err(_("from definition:\n"));
+    loc_err(t->e->d.func->def->pos, env->name);
+  }
+  return GW_ERROR;
+}
+
 ANN static Type check_exp_call(const Env env, Exp_Call* exp) {
   if(exp->tmpl) {
     CHECK_OO(check_exp(env, exp->func))
     const Type t = actual_type(exp->func->type);
     const Value v = nspc_lookup_value1(t->e->owner, insert_symbol(t->name));
     if(!v)
-      ERR_O(exp_self(exp)->pos, _(" template call of non-existant function."))
-    if(!GET_FLAG(v, func))
+      ERR_O(exp_self(exp)->pos, _("template call of non-existant function."))
+    if(!GET_FLAG(v, func) && !GET_FLAG(exp->func->type, func))
       ERR_O(exp_self(exp)->pos, _("template call of non-function value."))
     if(!v->d.func_ref->def->base->tmpl)
       ERR_O(exp_self(exp)->pos, _("template call of non-template function."))
+    if(t->e->d.func->def->base->tmpl->call)
+      CHECK_BO(predefined_call(env, t, exp_self(exp)->pos))
     const Func ret = find_template_match(env, v, exp);
     CHECK_OO((exp->m_func = ret))
     return ret->def->base->ret_type;
@@ -772,7 +806,7 @@ ANN static Type check_exp_dot(const Env env, Exp_Dot* member) {
 }
 
 ANN m_bool check_stmt_type(const Env env, const Stmt_Type stmt) {
-  return stmt->type->e->def ? check_class_def(env, stmt->type->e->def) : 1;
+  return stmt->type->e->def ? check_class_def(env, stmt->type->e->def) : GW_OK;
 }
 ANN static Type check_exp_lambda(const Env env NUSED,
     const Exp_If* exp_if NUSED) { return t_lambda; }
index 463e22e21a6ad572fa7d2cb3e924583ba03c3519..b8de83a2a6d2eac82fabf9c057a1926311670222 100644 (file)
@@ -33,6 +33,17 @@ ANN static inline m_bool scan0_defined(const Env env, const Symbol s, const loc_
   return already_defined(env, s, pos);
 }
 
+static void fptr_def(const Env env, const Stmt_Fptr stmt) {
+  const Func_Def def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, stmt->base->td, stmt->base->xid, stmt->base->args),
+    NULL,stmt->base->td->flag, loc_cpy(env->gwion->mp, stmt_self(stmt)->pos));
+  stmt->base->func = new_func(env->gwion->mp, s_name(stmt->base->xid), def);
+  stmt->value->d.func_ref = stmt->base->func;
+  stmt->base->func->value_ref = stmt->value;
+  stmt->type->e->d.func = stmt->base->func;
+  def->base->tmpl = stmt->base->tmpl;
+  def->base->func = stmt->base->func;
+}
+
 ANN m_bool scan0_stmt_fptr(const Env env, const Stmt_Fptr stmt) {
   CHECK_BB(env_access(env, stmt->base->td->flag, stmt_self(stmt)->pos))
   CHECK_BB(scan0_defined(env, stmt->base->xid, td_pos(stmt->base->td)));
@@ -44,33 +55,57 @@ ANN m_bool scan0_stmt_fptr(const Env env, const Stmt_Fptr stmt) {
   t->flag = stmt->base->td->flag;
   stmt->type = t;
   stmt->value = mk_class(env, t);
+  stmt->value->owner = env->curr;
+  stmt->value->owner_class = env->class_def;
+  fptr_def(env, stmt);
+  SET_FLAG(stmt->value, func);
   add_type(env, t->e->owner, t);
   return GW_OK;
 }
 
+ANN static void typedef_simple(const Env env, const Stmt_Type stmt, const Type base) {
+  const Type t = new_type(env->gwion->mp, ++env->scope->type_xid, s_name(stmt->xid), base);
+  t->size = base->size;
+  const Nspc nspc = (!env->class_def && GET_FLAG(stmt->ext, global)) ?
+  env->global_nspc : env->curr;
+  add_type(env, nspc, t);
+  t->e->owner = nspc;
+  stmt->type = t;
+  t->flag = stmt->ext->flag | ae_flag_checked;
+  if(stmt->ext->array && !stmt->ext->array->exp)
+    SET_FLAG(t, empty);
+}
+
+ANN static void typedef_complex(const Env env, const Stmt_Type stmt, const Type base) {
+  const ae_flag flag = base->e->def ? base->e->def->flag : 0;
+  const Class_Def cdef = new_class_def(env->gwion->mp, flag, stmt->xid, stmt->ext, NULL,
+    loc_cpy(env->gwion->mp, td_pos(stmt->ext)));
+  CHECK_BB(scan0_class_def(env, cdef))
+  stmt->type = cdef->base.type;
+  cdef->base.tmpl = stmt->tmpl;
+}
+
+ANN static void typedef_fptr(const Env env, const Stmt_Type stmt, const Type base) {
+  stmt->type = type_copy(env->gwion->mp, base);
+  stmt->type->name = s_name(stmt->xid);
+  stmt->type->e->parent = base;
+  add_type(env, env->curr, stmt->type);
+  mk_class(env, stmt->type);
+  if(base->e->d.func->def->base->tmpl)
+    SET_FLAG(stmt->type, func);
+}
+
 ANN m_bool scan0_stmt_type(const Env env, const Stmt_Type stmt) {
   CHECK_BB(env_access(env, stmt->ext->flag, stmt_self(stmt)->pos))
   DECL_OB(const Type, base, = stmt->tmpl ? find_type(env, stmt->ext->xid) : known_type(env, stmt->ext))
   CHECK_BB(scan0_defined(env, stmt->xid, td_pos(stmt->ext)))
-  if(!stmt->ext->types && (!stmt->ext->array || !stmt->ext->array->exp)) {
-    const Type t = new_type(env->gwion->mp, ++env->scope->type_xid, s_name(stmt->xid), base);
-    t->size = base->size;
-    const Nspc nspc = (!env->class_def && GET_FLAG(stmt->ext, global)) ?
-      env->global_nspc : env->curr;
-    add_type(env, nspc, t);
-    t->e->owner = nspc;
-    stmt->type = t;
-    t->flag = stmt->ext->flag | ae_flag_checked;
-    if(stmt->ext->array && !stmt->ext->array->exp)
-      SET_FLAG(t, empty);
-  } else {
-    const ae_flag flag = base->e->def ? base->e->def->flag : 0;
-    const Class_Def cdef = new_class_def(env->gwion->mp, flag, stmt->xid, stmt->ext, NULL,
-      loc_cpy(env->gwion->mp, td_pos(stmt->ext)));
-    CHECK_BB(scan0_class_def(env, cdef))
-    stmt->type = cdef->base.type;
-    cdef->base.tmpl = stmt->tmpl;
-  }
+  if(isa(base, t_function) < 0) {
+    if(!stmt->ext->types && (!stmt->ext->array || !stmt->ext->array->exp))
+      typedef_simple(env, stmt, base);
+    else
+      typedef_complex(env, stmt, base);
+  } else
+    typedef_fptr(env, stmt, base);
   SET_FLAG(stmt->type, typedef);
   return GW_OK;
 }
index 2856ea9e235af859a05609bd2254ecd2d4df16e8..6b2684e2b95be424f6281eff8fb4c19112c2727a 100644 (file)
@@ -254,7 +254,7 @@ ANN m_bool scan1_stmt_fptr(const Env env, const Stmt_Fptr stmt) {
 ANN m_bool scan1_stmt_type(const Env env, const Stmt_Type stmt) {
   if(!stmt->type)
     CHECK_BB(scan0_stmt_type(env, stmt))
-  return stmt->type->e->def ? scan1_class_def(env, stmt->type->e->def) : 1;
+  return stmt->type->e->def ? scan1_class_def(env, stmt->type->e->def) : GW_OK;
 }
 
 ANN m_bool scan1_stmt_union(const Env env, const Stmt_Union stmt) {
index 2d0af075a753f2652402ee77e0117b1cdf3fb3fa..50fb06d415fa1a61dba481b09c112e9075796937 100644 (file)
@@ -14,7 +14,6 @@
 #include "nspc.h"
 #include "operator.h"
 
-//ANN /* static */ m_bool scan2_exp(const Env, const Exp);
 ANN static m_bool scan2_stmt(const Env, const Stmt);
 ANN static m_bool scan2_stmt_list(const Env, Stmt_List);
 
@@ -84,18 +83,12 @@ ANN static Value scan2_func_assign(const Env env, const Func_Def d,
 }
 
 ANN m_bool scan2_stmt_fptr(const Env env, const Stmt_Fptr ptr) {
-  const Func_Def def = new_func_def(env->gwion->mp, new_func_base(env->gwion->mp, ptr->base->td, ptr->base->xid, ptr->base->args),
-    NULL,ptr->base->td->flag, loc_cpy(env->gwion->mp, stmt_self(ptr)->pos));
-  def->base->ret_type = ptr->base->ret_type;
-  ptr->base->func = new_func(env->gwion->mp, s_name(ptr->base->xid), def);
-  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->tmpl)//
-  if(ptr->base->args)
-    CHECK_BB(scan2_args(env, def))
+  const Func_Def def = ptr->type->e->d.func->def;
+  if(!ptr->base->tmpl) {
+    def->base->ret_type = ptr->base->ret_type;
+    if(ptr->base->args)
+      CHECK_BB(scan2_args(env, def))
+  }
   if(env->class_def) {
     if(GET_FLAG(ptr->base->td, global)) {
       SET_FLAG(ptr->value, global);
@@ -118,7 +111,7 @@ if(!ptr->base->tmpl)//
 }
 
 ANN m_bool scan2_stmt_type(const Env env, const Stmt_Type stmt) {
-  return stmt->type->e->def ? scan2_class_def(env, stmt->type->e->def) : 1;
+  return stmt->type->e->def ? scan2_class_def(env, stmt->type->e->def) : GW_OK;
 }
 
 ANN static inline Value prim_value(const Env env, const Symbol s) {
index aac484502e5e93db8686b322669546562a15dde0..c9f66576a430830a2046401b6986f4d3edb94bb4 100644 (file)
@@ -5,6 +5,8 @@
 #include "vm.h"
 #include "env.h"
 #include "type.h"
+#include "func.h"
+#include "value.h"
 #include "nspc.h"
 #include "traverse.h"
 #include "template.h"
@@ -33,15 +35,15 @@ ANEW ANN static ID_List id_list_copy(MemPool p, ID_List src) {
   return list;
 }
 
-ANN static ID_List get_total_type_list(const Env env, const Type t) {
+ANN2(1,2) static ID_List get_total_type_list(const Env env, const Type t, const Tmpl *tmpl) {
   const Type parent = owner_type(env, t);
   if(!parent)
-    return t->e->def->base.tmpl ? t->e->def->base.tmpl->list : NULL;
+    return tmpl ? tmpl->list : NULL;
   const Vector v = get_types(env, parent);
   const ID_List base = (ID_List)vector_pop(v);
   if(!base) {
     free_vector(env->gwion->mp, v);
-    return t->e->def->base.tmpl ? t->e->def->base.tmpl->list : NULL;
+    return tmpl ? tmpl->list : NULL;
   }
   const ID_List types = id_list_copy(env->gwion->mp, base);
   ID_List list, tmp = types;
@@ -49,7 +51,7 @@ ANN static ID_List get_total_type_list(const Env env, const Type t) {
     list = (ID_List)vector_pop(v);
     tmp = (tmp->next = id_list_copy(env->gwion->mp, list));
   }
-  tmp->next = t->e->def->base.tmpl->list;
+  tmp->next = tmpl->list;
   free_vector(env->gwion->mp, v);
   return types;
 }
@@ -148,6 +150,12 @@ extern ANN m_bool scan1_class_def(const Env, const Class_Def);
 extern ANN m_bool traverse_func_def(const Env, const Func_Def);
 extern ANN m_bool traverse_class_def(const Env, const Class_Def);
 
+ANN Tmpl* mk_tmpl(const Env env, const Type t, const Tmpl *tm, const Type_List types) {
+  Tmpl *tmpl = new_tmpl(env->gwion->mp, get_total_type_list(env, t, tm), 0);
+  tmpl->call = types;
+  return tmpl;
+}
+
 ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) {
   if(GET_FLAG(t, template)) {
     if(GET_FLAG(t, ref))
@@ -161,8 +169,7 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) {
     SET_FLAG(a, ref);
     if(a->base.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;
+    a->base.tmpl = mk_tmpl(env, t, t->e->def->base.tmpl, type->types);
     if(isa(t, t_union) < 0) {
       CHECK_BO(scan0_class_def(env, a))
       map_set(&t->e->owner->info->type->map, (vtype)a->base.xid, (vtype)a->base.type);
@@ -186,8 +193,35 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) {
       ADD_REF(t->nspc->dtor)
     }
     return a->base.type;
-  } else if(type->types)
-      ERR_O(type->xid->pos,
-            _("type '%s' is not template. You should not provide template types"), t->name)
+  } else if(type->types) { // TODO: clean me
+    if(isa(t, t_function) > 0 && t->e->d.func->def->base->tmpl) {
+      const m_str tl_name = tl2str(env, type->types);
+      const Symbol sym = func_symbol(env, t->e->owner->name, t->e->d.func->name, tl_name, 0);
+      free_mstr(env->gwion->mp, tl_name);
+      const Type base_type = nspc_lookup_type1(t->e->owner, sym);
+      if(base_type)
+        return base_type;
+      const Type ret = type_copy(env->gwion->mp, t);
+      ret->e->parent = t;
+      ret->name = s_name(sym);
+      SET_FLAG(ret, func);
+      nspc_add_type(env->curr, sym, ret);
+      const Func_Def def = new_func_def(env->gwion->mp,
+        new_func_base(env->gwion->mp, t->e->d.func->def->base->td, sym, t->e->d.func->def->base->args),
+        NULL, type->flag, loc_cpy(env->gwion->mp, td_pos(type)));
+      const Func func = ret->e->d.func = new_func(env->gwion->mp, s_name(sym), def);
+      const Value value = new_value(env->gwion->mp, ret, s_name(sym));
+      value->d.func_ref = func;
+      value->owner = t->e->owner;
+      value->owner_class = t->e->d.func->value_ref->owner_class;
+      func->value_ref = value;
+      func->def->base->tmpl = mk_tmpl(env, t, t->e->d.func->def->base->tmpl, type->types);
+      def->base->func = func;
+      nspc_add_value(env->curr, sym, value);
+      return ret;
+    }
+    ERR_O(type->xid->pos,
+        _("type '%s' is not template. You should not provide template types"), t->name)
+  }
   return t;
 }