]> Nishi Git Mirror - gwion.git/commitdiff
:art: Type alias templating
authorfennecdjay <astor.jeremie@wanadoo.fr>
Mon, 20 May 2019 22:15:59 +0000 (00:15 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Mon, 20 May 2019 22:15:59 +0000 (00:15 +0200)
14 files changed:
ast
include/parse.h
src/emit/emit.c
src/lib/import.c
src/lib/instr.c
src/parse/check.c
src/parse/func.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/scanx.c
src/parse/template.c
src/parse/traverse_template.c
util

diff --git a/ast b/ast
index c902b1888ae8aadcb2cdf6000308e0d55043b8ed..2f8759c59db171ce3d4737c7912b3b57d1d6dec6 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit c902b1888ae8aadcb2cdf6000308e0d55043b8ed
+Subproject commit 2f8759c59db171ce3d4737c7912b3b57d1d6dec6
index c3ef0eb65839e345d6e5e8cbb798d9caea9a9880..42dbcd68fb777201fd6a45e9593f6d3e416e672d 100644 (file)
@@ -69,4 +69,14 @@ static inline ANN m_bool env_body(const Env env, const Class_Def cdef, const _ex
   return scanx_body(env, cdef, f, env);
 }
 #define env_body(a,b,c) env_body(a,b,(_exp_func)c)
+
+ANN m_bool scanx_ext(const Env e, const Class_Def c, const _exp_func f, void* d);
+static inline ANN m_bool env_ext(const Env env, const Class_Def cdef, const _exp_func f) {
+  return scanx_ext(env, cdef, f, env);
+}
+#define env_ext(a,b,c) env_ext(a, b, (_exp_func)c)
+#define scanx_ext(a,b,c,d) scanx_ext(a, b, (_exp_func)c, d)
+
+ANN m_bool scanx_parent(const Type t, const _exp_func f, void *d);
+#define scanx_parent(a,b,c) scanx_parent(a, (_exp_func)b, c)
 #endif
index 7926d6feea3a63a235d76afcb0821b878aab9940..5bb689f28bf9afab13447f575bcf533343d0915c 100644 (file)
@@ -608,10 +608,14 @@ ANN static m_bool emit_exp_decl_global(const Emitter emit, const Var_Decl var_de
 
 ANN static m_bool emit_class_def(const Emitter, const Class_Def);
 
+ANN static m_bool emit_parent_inner(const Emitter emit, const Class_Def cdef) {
+  CHECK_BB(traverse_class_def(emit->env, cdef))
+  return emit_class_def(emit, cdef);
+}
+
 ANN static inline m_bool emit_exp_decl_template(const Emitter emit, const Exp_Decl* decl) {
-  const Type t = typedef_base(decl->type);
-  CHECK_BB(traverse_class_def(emit->env, t->e->def))
-  return !GET_FLAG(t, emit) ? emit_class_def(emit, t->e->def) : GW_OK;
+  const Type t = decl->type;
+  return !GET_FLAG(t, emit) ? emit_parent_inner(emit, t->e->def) : GW_OK;
 }
 
 ANN static m_bool emit_exp_decl(const Emitter emit, const Exp_Decl* decl) {
@@ -687,7 +691,7 @@ ANN static inline m_int push_tmpl_func(const Emitter emit, const Func f) {
 ANN static m_bool emit_exp_call_template(const Emitter emit, const Exp_Call* exp_call) {
   if(emit->env->func && emit->env->func == exp_call->m_func)
     return prepare_call(emit, exp_call);
-  exp_call->m_func->def->tmpl->call = exp_call->tmpl->call;
+  exp_call->m_func->def->base->tmpl->call = exp_call->tmpl->call;
   const m_int scope = push_tmpl_func(emit, exp_call->m_func);
   CHECK_BB(scope);
   CHECK_BB(prepare_call(emit, exp_call))
@@ -748,7 +752,7 @@ 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);
   m_bool ret = GW_ERROR;
-  dt->def->tmpl->call = dt->tl;// in INSTR
+  dt->def->base->tmpl->call = dt->tl;// in INSTR
   if(traverse_func_template(emit->env, dt->def) > 0) {
     ret = emit_func_def(emit, dt->def);
     nspc_pop_type(emit->gwion->mp, emit->env->curr);
@@ -768,7 +772,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->tmpl->base;
+    dt->overload = f->def->base->tmpl->base;
     dt->tl = tmpl_tl(emit->env, c);
     dt->base = f->def;
     instr->opcode = eOP_MAX;
@@ -1552,7 +1556,7 @@ ANN static m_bool emit_member_func(const Emitter emit, const Exp_Dot* member, co
     func_i->m_val = (m_uint)(func->code ?: (VM_Code)func);
     return GW_OK;
   }
-  if(func->def->tmpl)
+  if(func->def->base->tmpl)
     emit_add_instr(emit, DotTmplVal);
   else {
     const Instr instr = emit_add_instr(emit, GET_FLAG(func, member) ? DotFunc : DotStaticFunc);
@@ -1662,13 +1666,13 @@ ANN static m_bool emit_func_def(const Emitter emit, const Func_Def func_def) {
   const Func former = emit->env->func;
   if(func->code)
     return GW_OK;
-  if(tmpl_base(func_def->tmpl)) {
+  if(tmpl_base(func_def->base->tmpl)) {
     UNSET_FLAG(func_def, template);
     return GW_OK;
   }
   if(SAFE_FLAG(emit->env->class_def, builtin) && GET_FLAG(emit->env->class_def, template))
     return GW_OK;
-  if(!emit->env->class_def && !GET_FLAG(func_def, global) && !func_def->tmpl && !emit->env->scope->depth)
+  if(!emit->env->class_def && !GET_FLAG(func_def, global) && !func_def->base->tmpl && !emit->env->scope->depth)
     func->value_ref->offset = emit_local(emit, SZ_INT, 0);
   emit_func_def_init(emit, func);
   if(GET_FLAG(func, member))
@@ -1690,7 +1694,7 @@ ANN static m_bool emit_func_def(const Emitter emit, const Func_Def func_def) {
   emit_pop_code(emit);
   if(GET_FLAG(func_def, op))
     SET_FLAG(func->code, op);
-  if(!emit->env->class_def && !GET_FLAG(func_def, global) && !func_def->tmpl)
+  if(!emit->env->class_def && !GET_FLAG(func_def, global) && !func_def->base->tmpl)
     emit_func_def_global(emit, func->value_ref);
   if(emit->memoize && GET_FLAG(func, pure))
     func->code->memoize = memoize_ini(emit, func,
@@ -1712,20 +1716,21 @@ ANN Code* emit_class_code(const Emitter emit, const m_str name) {
 ANN inline void emit_class_finish(const Emitter emit, const Nspc nspc) {
   emit_add_instr(emit, FuncReturn);
   nspc->pre_ctor = emit_code(emit);
+  SET_FLAG(nspc->pre_ctor, ctor);
+}
+
+ANN static m_bool emit_parent(const Emitter emit, const Class_Def cdef) {
+  const Type parent = cdef->base.type->e->parent;
+  return scanx_parent(parent, emit_parent_inner, emit);
 }
 
 ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
   const Type type = cdef->base.type;
   const Nspc nspc = type->nspc;
-  if(tmpl_base(cdef->tmpl))
+  if(tmpl_base(cdef->base.tmpl))
     return GW_OK;
-  if(cdef->base.ext && ((!GET_FLAG(type->e->parent, emit) &&
-      GET_FLAG(cdef->base.ext, typedef)) || cdef->base.ext->types)) {
-    const Type base = cdef->base.ext->array ?
-             array_base(type->e->parent) : type->e->parent;
-    if(!base->nspc->pre_ctor)
-      CHECK_BB(emit_class_def(emit, base->e->def))
-  }
+  if(cdef->base.ext && cdef->base.ext->types)
+    CHECK_BB(scanx_ext(emit->env, cdef, emit_parent, emit))
   nspc_allocdata(emit->gwion->mp, nspc);
   emit_class_code(emit, type->name);
   if(cdef->base.ext && cdef->base.ext->array)
@@ -1733,7 +1738,6 @@ ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
   if(cdef->body)
     CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit))
   emit_class_finish(emit, nspc);
-  SET_FLAG(cdef->base.type->nspc->pre_ctor, ctor);
   emit_pop_code(emit);
   SET_FLAG(type, emit);
   return GW_OK;
index 7b2dc7eeb837bf5e453e520f6d0c11a32a0c159b..f8aea4e49b331bb54e72c1097f0925fc724eb587 100644 (file)
@@ -221,7 +221,7 @@ ANN2(1,2) m_int gwi_class_ini(const Gwi gwi, const Type type, const f_xtor pre_c
   if(gwi->templater.n) {
     const ID_List types = templater_def(gwi->gwion->st, gwi);
     type->e->def = new_class_def(gwi->gwion->mp, 0, insert_symbol(gwi->gwion->st, type->name), NULL, NULL, loc_cpy(gwi->gwion->mp, gwi->loc));
-    type->e->def->tmpl = new_tmpl(gwi->gwion->mp, types, -1);
+    type->e->def->base.tmpl = new_tmpl(gwi->gwion->mp, types, -1);
     type->e->def->base.type = type;
     SET_FLAG(type, template);
   } else
@@ -452,7 +452,7 @@ ANN m_int gwi_func_end(const Gwi gwi, const ae_flag flag) {
   if(gwi->templater.n) {
     def = new_func_def(gwi->gwion->mp, new_func_base(gwi->gwion->mp, NULL, NULL, NULL), NULL, 0, loc_cpy(gwi->gwion->mp, gwi->loc));
     const ID_List list = templater_def(gwi->gwion->st, gwi);
-    def->tmpl = new_tmpl(gwi->gwion->mp, list, -1);
+    def->base->tmpl = new_tmpl(gwi->gwion->mp, list, -1);
     SET_FLAG(def, template);
   }
   if(gwi->gwion->env->class_def && GET_FLAG(gwi->gwion->env->class_def, template)) {
index 4929dc44b498998f2e7121d12ec45fbf3c5589a9..8529b8cdfe783a77f08b7dda67b231bf657aedd2 100644 (file)
@@ -66,7 +66,7 @@ ANN static Func_Def from_base(const Env env, const struct dottmpl_ *dt, const Ty
   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->tmpl = new_tmpl(env->gwion->mp, base->tmpl->list, dt->overload);
+  def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, dt->overload);
   SET_FLAG(def, template);
   return def;
 }
index 6dbecbd5ed6acb99b6c49dfec2bf1c706d5b649b..f6c07bd2d18ef60f43b2e93ac9533a81102cb35d 100644 (file)
@@ -104,9 +104,8 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
   if(!decl->type) // TODO: remove when scan passes are complete
       ERR_O(td_pos(decl->td), "can't infer type.");
   if(GET_FLAG(decl->type , template)) {
-    const Type t = typedef_base(decl->type);
-    if(!GET_FLAG(t, check))
-      CHECK_BO(traverse_class_def(env, t->e->def))
+    if(!GET_FLAG(decl->type, check))
+      CHECK_BO(traverse_class_def(env, decl->type->e->def))
   }
   const m_bool global = GET_FLAG(decl->td, global);
   const m_uint scope = !global ? env->scope->depth : env_push_global(env);
@@ -258,7 +257,7 @@ ANN static Type prim_vec(const Env env, const Exp_Primary* primary) {
   struct VecInfo info = { .n=vec->dim };
   vec_info(t, &info);
   if(vec->dim > info.n)
-    ERR_O(vec->exp->pos, "extraneous component of %s value...", info.s)
+    ERR_O(vec->exp->pos, "extraneous component of %s value...", info.t->name)
   CHECK_BO(vec_value(env, vec->exp, info.s))
   return info.t;
 }
@@ -423,11 +422,11 @@ if(types->td->types)exit(12);
         return env->func;
       }
       base = def = value->d.func_ref->def;
-      if(!def->tmpl) {
+      if(!def->base->tmpl) {
         if(!(value = template_get_ready(env, v, "template", i)))
           continue;
         base = value->d.func_ref->def;
-        def->tmpl = new_tmpl(env->gwion->mp, base->tmpl->list, (m_int)i);
+        def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i);
       }
     } else {
       if(!(value = template_get_ready(env, v, "template", i)))
@@ -435,10 +434,10 @@ if(types->td->types)exit(12);
       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),
                 base->base->args), base->d.code, base->flag, loc_cpy(env->gwion->mp, base->pos));
-      def->tmpl = new_tmpl(env->gwion->mp, base->tmpl->list, (m_int)i);
+      def->base->tmpl = new_tmpl(env->gwion->mp, base->base->tmpl->list, (m_int)i);
       SET_FLAG(def, template);
     }
-    def->tmpl->call = types;
+    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) {
@@ -518,7 +517,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->tmpl->list;
+    tmpl->list = v->d.func_ref->def->base->tmpl->list;
     ((Exp_Call*)func)->tmpl = tmpl;
     return ((Exp_Call*)func)->m_func = f;
   }
@@ -535,9 +534,9 @@ ANN static Type check_exp_call_template(const Env env, const Exp_Call *exp) {
   m_uint args_number = 0;
   const Value value = nspc_lookup_value1(call->type->e->owner, insert_symbol(call->type->name));
   CHECK_OO(value)
-  const m_uint type_number = get_type_number(value->d.func_ref->def->tmpl->list);
+  const m_uint type_number = get_type_number(value->d.func_ref->def->base->tmpl->list);
   Type_List tl[type_number];
-  ID_List list = value->d.func_ref->def->tmpl->list;
+  ID_List list = value->d.func_ref->def->base->tmpl->list;
   while(list) {
     Arg_List arg = value->d.func_ref->def->base->args;
     Exp template_arg = args;
@@ -650,7 +649,7 @@ ANN static Type check_exp_call(const Env env, Exp_Call* exp) {
       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-function value.")
-    if(!v->d.func_ref->def->tmpl)
+    if(!v->d.func_ref->def->base->tmpl)
       ERR_O(exp_self(exp)->pos, "template call of non-template function.")
     const Func ret = find_template_match(env, v, exp);
     CHECK_OO((exp->m_func = ret))
@@ -1007,7 +1006,7 @@ ANN static m_bool check_signature_match(const Env env, const Func_Def f, const F
           c_name, f_name, p_name, c_name,
           GET_FLAG(f, static) ? c_name : p_name, f_name)
   }
-  return !f->tmpl ? isa(f->base->ret_type, parent->def->base->ret_type) : GW_OK;
+  return !f->base->tmpl ? isa(f->base->ret_type, parent->def->base->ret_type) : GW_OK;
 }
 
 ANN static m_bool parent_match_actual(const Env env, const restrict Func_Def f,
@@ -1016,7 +1015,7 @@ ANN static m_bool parent_match_actual(const Env env, const restrict Func_Def f,
   do {
     if(compat_func(f, parent_func->def) > 0) {
       CHECK_BB(check_signature_match(env, f, parent_func))
-      if(!f->tmpl) {
+      if(!f->base->tmpl) {
         f->base->func->vt_index = parent_func->vt_index;
         vector_set(&env->curr->info->vtable, f->base->func->vt_index, (vtype)f->base->func);
       }
@@ -1088,7 +1087,7 @@ ANN static m_bool check_func_def_override(const Env env, const Func_Def f) {
             "\tfrom super class '%s'...",
             s_name(f->base->xid), override->owner_class->name)
   }
-  if(func->value_ref->offset && (!f->tmpl || !f->tmpl->base))
+  if(func->value_ref->offset && (!f->base->tmpl || !f->base->tmpl->base))
     CHECK_BB(check_func_overload(env, f))
   return GW_OK;
 }
@@ -1113,7 +1112,7 @@ ANN static void operator_func(const Func f) {
 ANN m_bool check_func_def(const Env env, const Func_Def f) {
   const Func func = get_func(env, f);
   m_bool ret = GW_OK;
-  if(tmpl_base(f->tmpl))
+  if(tmpl_base(f->base->tmpl))
     return env->class_def ? check_parent_match(env, f) : 1;
   if(f->base->td && !f->base->td->xid) {
     f->base->ret_type = check_td(env, f->base->td);
@@ -1156,18 +1155,9 @@ DECL_SECTION_FUNC(check)
 ANN static m_bool check_class_parent(const Env env, const Class_Def cdef) {
   const Type parent = cdef->base.type->e->parent;
   const Type_Decl *td = cdef->base.ext;
-  if(td->array) {
+  if(td->array)
     CHECK_BB(check_exp_array_subscripts(env, td->array->exp))
-    if(!GET_FLAG(cdef->base.type, check) && cdef->tmpl)
-      REM_REF(parent->nspc, env->gwion);
-  }
-  if(td->types) {
-    const Type t = parent->array_depth ? array_base(parent) : parent;
-    if(!GET_FLAG(t, checked))
-      CHECK_BB(traverse_class_def(env, t->e->def))
-  }
-  if(!GET_FLAG(parent, checked))
-      CHECK_BB(check_class_def(env, parent->e->def))
+  CHECK_BB(scanx_parent(parent, traverse_class_def, env))
   if(GET_FLAG(parent, typedef))
     SET_FLAG(cdef->base.type, typedef);
   return GW_OK;
@@ -1181,15 +1171,15 @@ ANN static inline void inherit(const Type t) {
 }
 
 ANN m_bool check_class_def(const Env env, const Class_Def cdef) {
-  if(tmpl_base(cdef->tmpl))
+  if(tmpl_base(cdef->base.tmpl))
     return GW_OK;
   const Type type = cdef->base.type;
-   if(type->e->parent == t_undefined) {
+  if(type->e->parent == t_undefined) {
     type->e->parent = check_td(env, cdef->base.ext);
     return traverse_class_def(env, cdef);
   }
   if(cdef->base.ext)
-    CHECK_BB(check_class_parent(env, cdef))
+    CHECK_BB(env_ext(env, cdef, check_class_parent))
   else if(!type->e->parent)
     type->e->parent = t_object;
   inherit(type);
index 62597aaaf2aee350095834fddebca4f60011dc07..d34f381dd7c856733b88d7301677af161e5de6d2 100644 (file)
@@ -11,7 +11,7 @@
 
 ANN static void free_func(Func a, Gwion gwion) {
   if(GET_FLAG(a, template)) {
-    free_tmpl(gwion->mp, a->def->tmpl);
+    free_tmpl(gwion->mp, a->def->base->tmpl);
     free_func_base(gwion->mp, a->def->base);
     free_loc(gwion->mp, a->def->pos);
     mp_free(gwion->mp, Func_Def, a->def);
index 9c8ebbdfe3cf886dfbd66262ac0a98f90b6fc136..10ac806946f9c55351a3bfe70fe20d0e53939dd3 100644 (file)
@@ -45,7 +45,7 @@ ANN m_bool scan0_stmt_fptr(const Env env, const Stmt_Fptr stmt) {
 
 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))
-  const Type base = known_type(env, stmt->ext);
+  const Type base = stmt->tmpl ? find_type(env, stmt->ext->xid) : known_type(env, stmt->ext);
   CHECK_OB(base)
   CHECK_BB(scan0_defined(env, stmt->xid, td_pos(stmt->ext)))
   if(!stmt->ext->types && (!stmt->ext->array || !stmt->ext->array->exp)) {
@@ -65,6 +65,7 @@ ANN m_bool scan0_stmt_type(const Env env, const Stmt_Type stmt) {
       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;
   }
   SET_FLAG(stmt->type, typedef);
   return GW_OK;
@@ -200,7 +201,7 @@ ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
   t->flag = cdef->flag;
   if(!strstr(t->name, "<"))
     nspc_add_type(env->curr, cdef->base.xid, t);
-  if(cdef->tmpl) {
+  if(cdef->base.tmpl) {
     SET_FLAG(t, template);
     SET_FLAG(cdef, template);
   }
@@ -227,10 +228,10 @@ ANN m_bool scan0_class_def(const Env env, const Class_Def cdef) {
   CHECK_BB(scan0_class_def_pre(env, cdef))
   CHECK_OB((cdef->base.type = scan0_class_def_init(env, cdef)))
   if(cdef->body) {
-int call = cdef->tmpl && !cdef->tmpl->call;
-if(call)cdef->tmpl->call = (Type_List)1;
+int call = cdef->base.tmpl && !cdef->base.tmpl->call;
+if(call)cdef->base.tmpl->call = (Type_List)1;
     CHECK_BB(env_body(env, cdef, scan0_section))
-if(call)cdef->tmpl->call = NULL;
+if(call)cdef->base.tmpl->call = NULL;
 }
   (void)mk_class(env, cdef->base.type);
   if(GET_FLAG(cdef, global))
index a5fe7efa1df4f88e63d4172efa92779fb466d92b..68b83bee32b65b8353ff4863b1af05646a2ee52b 100644 (file)
@@ -287,7 +287,7 @@ ANN static m_bool scan1_stmt_list(const Env env, Stmt_List l) {
 ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
   if(fdef->base->td)
     CHECK_BB(env_storage(env, fdef->flag, td_pos(fdef->base->td)))
-  if(tmpl_base(fdef->tmpl))
+  if(tmpl_base(fdef->base->tmpl))
     return GW_OK;
   struct Func_ fake = { .name=s_name(fdef->base->xid) }, *const former = env->func;
   env->func = &fake;
@@ -309,27 +309,21 @@ ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
 
 DECL_SECTION_FUNC(scan1)
 
-ANN static m_bool scan1_class_parent(const Env env, const Class_Def cdef) {
+ANN static m_bool scan1_parent(const Env env, const Class_Def cdef) {
   const loc_t pos = td_pos(cdef->base.ext);
   if(cdef->base.ext->array)
     CHECK_BB(scan1_exp(env, cdef->base.ext->array->exp))
   const Type parent = cdef->base.type->e->parent = known_type(env, cdef->base.ext);
   CHECK_OB(parent)
-  if(parent == t_undefined)
-    return GW_OK;
   Type t = parent;
   while(t) {
     if(cdef->base.type == t)
       ERR_B(pos, "recursive (%s <= %s) class declaration.", cdef->base.type->name, t->name);
     t = t->e->parent;
   }
-  if(parent == cdef->base.type)
-    ERR_B(pos, "class '%s' cannot extend itself", cdef->base.type->name);
-  if(isa(cdef->base.type->e->parent, t_object) < 0)
-    ERR_B(pos, "cannot extend primitive type '%s'",
-            cdef->base.type->e->parent->name)
-  if(!GET_FLAG(parent, scan1) && parent->e->def)
-    CHECK_BB(scan1_class_def(env, parent->e->def))
+  if(isa(parent, t_object) < 0)
+    ERR_B(pos, "cannot extend primitive type '%s'", parent->name)
+  CHECK_BB(scanx_parent(parent, scan1_class_def, env))
   if(type_ref(parent))
     ERR_B(pos, "can't use ref type in class extend")
   return GW_OK;
@@ -338,10 +332,10 @@ ANN static m_bool scan1_class_parent(const Env env, const Class_Def cdef) {
 ANN m_bool scan1_class_def(const Env env, const Class_Def cdef) {
   if(!cdef->base.type)
     CHECK_BB(scan0_class_def(env, cdef))
-  if(tmpl_base(cdef->tmpl))
+  if(tmpl_base(cdef->base.tmpl))
     return GW_OK;
   if(cdef->base.ext)
-    CHECK_BB(scan1_class_parent(env, cdef))
+    CHECK_BB(env_ext(env, cdef, scan1_parent))
   if(cdef->body)
     CHECK_BB(env_body(env, cdef, scan1_section))
   SET_FLAG(cdef->base.type, scan1);
index c18600890557ebdd29d31be9bd596fac0cc80c51..254967f1bc8a8407629c6a8d4d8cf4f71b84ad33 100644 (file)
@@ -298,7 +298,7 @@ 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->tmpl);
+  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)
     ERR_B(f->pos, "function name '%s' is already used by another value", overload->name)
@@ -438,7 +438,7 @@ ANN static void scan2_func_def_flag(const Env env, const Func_Def f) {
 ANN static m_str func_tmpl_name(const Env env, const Func_Def f) {
   const m_str name = s_name(f->base->xid);
   struct Vector_ v;
-  ID_List id = f->tmpl->list;
+  ID_List id = f->base->tmpl->list;
   m_uint tlen = 0;
   vector_init(&v);
   do {
@@ -461,7 +461,7 @@ ANN static m_str func_tmpl_name(const Env env, const Func_Def f) {
   }
   tmpl_name[tlen+1] = '\0';
   vector_release(&v);
-  const Symbol sym = func_symbol(env, env->curr->name, name, tmpl_name, (m_uint)f->tmpl->base);
+  const Symbol sym = func_symbol(env, env->curr->name, name, tmpl_name, (m_uint)f->base->tmpl->base);
   return s_name(sym);
 }
 
@@ -500,7 +500,7 @@ ANN static m_str template_helper(const Env env, const Func_Def f) {
 }
 
 ANN2(1,2) static m_str func_name(const Env env, const Func_Def f, const Value v) {
-  if(!f->tmpl) {
+  if(!f->base->tmpl) {
     const Symbol sym  = func_symbol(env, env->curr->name, s_name(f->base->xid), NULL, v ? ++v->offset : 0);
     return s_name(sym);
   }
@@ -516,7 +516,7 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def f) {
   f->stack_depth = 0;
   if(overload)
     CHECK_BB(scan2_func_def_overload(env, f, overload))
-  if(tmpl_base(f->tmpl))
+  if(tmpl_base(f->base->tmpl))
     return scan2_func_def_template(env, f, overload);
   const m_str name = func_name(env, f, overload);
   if((m_int)name <= GW_OK)
@@ -547,20 +547,18 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def f) {
 DECL_SECTION_FUNC(scan2)
 
 ANN static m_bool scan2_class_parent(const Env env, const Class_Def cdef) {
-  const Type t = cdef->base.type->e->parent->array_depth ?
-    array_base(cdef->base.type->e->parent) : cdef->base.type->e->parent;
-  if(!GET_FLAG(t, scan2) && GET_FLAG(cdef->base.ext, typedef))
-    CHECK_BB(scan2_class_def(env, t->e->def))
+  const Type parent = cdef->base.type->e->parent;
+  CHECK_BB(scanx_parent(parent, scan2_class_def, env))
   if(cdef->base.ext->array)
     CHECK_BB(scan2_exp(env, cdef->base.ext->array->exp))
   return GW_OK;
 }
 
 ANN m_bool scan2_class_def(const Env env, const Class_Def cdef) {
-  if(tmpl_base(cdef->tmpl))
+  if(tmpl_base(cdef->base.tmpl))
     return GW_OK;
   if(cdef->base.ext)
-    CHECK_BB(scan2_class_parent(env, cdef))
+    CHECK_BB(env_ext(env, cdef, scan2_class_parent))
   if(cdef->body)
     CHECK_BB(env_body(env, cdef, scan2_section))
   SET_FLAG(cdef->base.type, scan2);
index be6917e4c961131e9cb71fc781d93d86e016a2cc..e722b0869a7ca80b2b4ca9b4894f7f768133ffc7 100644 (file)
@@ -20,20 +20,18 @@ ANN static inline int actual(const Tmpl *tmpl) {
 }
 
 ANN static inline m_bool tmpl_push(const Env env, const Tmpl* tmpl) {
-  if(actual(tmpl))
-    return template_push_types(env, tmpl);
-  return GW_ERROR;
+  return actual(tmpl) ? template_push_types(env, tmpl) : GW_ERROR;
 }
 
 ANN static inline m_int _push(const Env env, const Class_Def c) {
   const m_uint scope = env_push_type(env, c->base.type);
-  if(c->tmpl && !tmpl_push(env, c->tmpl))
+  if(c->base.tmpl && !tmpl_push(env, c->base.tmpl))
     return GW_ERROR;
   return scope;
 }
 
 ANN static inline void _pop(const Env e, const Class_Def c, const m_uint s) {
-  if(c->tmpl && actual(c->tmpl))
+  if(c->base.tmpl && actual(c->base.tmpl))
     nspc_pop_type(e->gwion->mp, e->curr);
   env_pop(e, s);
 }
@@ -46,3 +44,50 @@ scanx_body(const Env e, const Class_Def c, const _exp_func f, void* d) {
   _pop(e, c, scope);
   return ret;
 }
+
+#undef scanx_ext
+ANN m_bool
+scanx_ext(const Env e, const Class_Def c, const _exp_func f, void* d) {
+  const m_int scope = _push(e, c);
+  CHECK_BB(scope)
+  const m_bool ret =  f(d, c);
+  _pop(e, c, scope);
+  return ret;
+}
+#undef scanx_parent
+__attribute__((returns_nonnull))
+static inline Type get_type(const Type t) {
+  return !t->array_depth ? t : array_base(t);
+}
+
+__attribute__((returns_nonnull))
+static inline Class_Def get_type_def(const Type t) {
+  return get_type(t)->e->def;
+}
+
+ANN m_bool
+scanx_parent(const Type t, const _exp_func f, void* d) {
+  const Class_Def def = get_type_def(t);
+  return def ? f(d, def) : GW_OK;
+}
+/*
+struct Parent_ {
+  void* ptr;
+  const Type t;
+  m_bool (*f)(void*, void*);
+  const ae_flag flag;
+};
+ANN m_bool scanx_parent_actual(void* ptr, const Type t, m_bool (*f)(void*, void*), const ae_flag flag) {
+  if(t->e->def && (t->flag & flag) != flag)
+    return f(ptr, t->e->def);
+  return GW_OK;
+}
+
+ANN m_bool scanx_parent(void* ptr, const Type t, m_bool (*f)(void*, void*), const ae_flag flag) {
+  if(t->array_depth)
+     CHECK_BB(f(ptr, array_base(t)))
+  else
+     CHECK_BB(f(ptr, t))
+  return GW_OK;
+}
+*/
index 60749128d7194d83515ce68fc3986b0463389101..f2511a58604d148fcf166b95a6058fc41058b35b 100644 (file)
@@ -19,7 +19,7 @@ ANN static inline Type owner_type(const Env env, const Type t) {
 ANEW ANN static Vector get_types(const Env env, Type t) {
   const Vector v = new_vector(env->gwion->mp);
   do if(GET_FLAG(t, template))
-    vector_add(v, (vtype)t->e->def->tmpl->list);
+    vector_add(v, (vtype)t->e->def->base.tmpl->list);
   while((t = owner_type(env, t)));
   return v;
 }
@@ -35,12 +35,12 @@ ANEW ANN static ID_List id_list_copy(MemPool p, ID_List src) {
 ANN static ID_List get_total_type_list(const Env env, const Type t) {
   const Type parent = owner_type(env, t);
   if(!parent)
-    return t->e->def->tmpl ? t->e->def->tmpl->list : NULL;
+    return t->e->def->base.tmpl ? t->e->def->base.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->tmpl ? t->e->def->tmpl->list : NULL;
+    return t->e->def->base.tmpl ? t->e->def->base.tmpl->list : NULL;
   }
   const ID_List types = id_list_copy(env->gwion->mp, base);
   ID_List list, tmp = types;
@@ -48,7 +48,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->tmpl->list;
+  tmp->next = t->e->def->base.tmpl->list;
   free_vector(env->gwion->mp, v);
   return types;
 }
@@ -69,7 +69,7 @@ ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) {
 }
 
 ANN static size_t template_size(const Env env, struct tmpl_info* info) {
-  ID_List base = info->cdef->tmpl->list;
+  ID_List base = info->cdef->base.tmpl->list;
   size_t size = tmpl_set(info, info->cdef->base.type);
   do size += tmpl_set(info, type_decl_resolve(env, info->call->td));
   while((info->call = info->call->next) && (base = base->next) && ++size);
@@ -150,14 +150,14 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) {
     if(!type->types)
       ERR_O(t->e->def->pos,
         "you must provide template types for type '%s'", t->name)
-    if(template_match(t->e->def->tmpl->list, type->types) < 0)
+    if(template_match(t->e->def->base.tmpl->list, type->types) < 0)
       ERR_O(type->xid->pos, "invalid template types number")
     const Class_Def a = template_class(env, t->e->def, type->types);
     SET_FLAG(a, ref);
     if(a->base.type)
       return a->base.type;
-    a->tmpl = new_tmpl(env->gwion->mp, get_total_type_list(env, t), 0);
-    a->tmpl->call = type->types;
+    a->base.tmpl = new_tmpl(env->gwion->mp, get_total_type_list(env, t), 0);
+    a->base.tmpl->call = type->types;
 
     CHECK_BO(scan0_class_def(env, a))
     SET_FLAG(a->base.type, template | ae_flag_ref);
index 9dbbb03f5c1ae28de57cee859290decddb4183f3..8b32476febd7b66345b175dbee5a1bd14f2de26d 100644 (file)
@@ -9,6 +9,6 @@
 #include "gwion.h"
 
 ANN m_bool traverse_func_template(const Env env, const Func_Def def) {
-  CHECK_BB(template_push_types(env, def->tmpl))
+  CHECK_BB(template_push_types(env, def->base->tmpl))
   return traverse_func_def(env, def);
 }
diff --git a/util b/util
index 059393b7d69ed555bfef29ba99500d508a378637..6e10d0bd6a9e6731e35cc01d44562e0271755676 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 059393b7d69ed555bfef29ba99500d508a378637
+Subproject commit 6e10d0bd6a9e6731e35cc01d44562e0271755676