]> Nishi Git Mirror - gwion.git/commitdiff
:art: Improve class templating
authorfennecdjay <astor.jeremie@wanadoo.fr>
Fri, 17 May 2019 10:12:31 +0000 (12:12 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Fri, 17 May 2019 10:12:31 +0000 (12:12 +0200)
include/traverse.h
src/emit/emit.c
src/oo/env_utils.c
src/parse/check.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/template.c
src/parse/traverse_template.c
tests/tree/class_template.gw

index 518679eaf7b30ba294be23836df4a52a17c1b738..8faf1020ed8938ec94290862c9fb1c37c054f7dc 100644 (file)
@@ -2,7 +2,6 @@
 #define __TRAVERSE
 ANN m_bool traverse_ast(const Env, const Ast);
 ANN m_bool traverse_class_def(const Env, const Class_Def);
-ANN m_bool traverse_template(const Env, const Class_Def);
 ANN m_bool traverse_func_def(const Env, const Func_Def);
 ANN m_bool traverse_stmt_union(const Env, const Stmt_Union);
 ANN m_bool traverse_stmt_enum(const Env, const Stmt_Enum);
index 550408cbcd60892ae802160140b20b3c1bd5e1c3..527693c9b49a847724cc5bfea8da9c7e3bc702f8 100644 (file)
@@ -613,6 +613,7 @@ ANN static m_bool emit_class_def(const Emitter, const Class_Def);
 
 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;
 }
 
@@ -632,7 +633,7 @@ ANN static m_bool emit_exp_decl(const Emitter emit, const Exp_Decl* decl) {
       CHECK_BB(emit_exp_decl_static(emit, list->self, r, var))
     else if(!global)
       CHECK_BB(emit_exp_decl_non_static(emit, list->self, r, var))
-else
+    else
       CHECK_BB(emit_exp_decl_global(emit, list->self, r, var))
   } while((list = list->next));
   if(global)
@@ -788,7 +789,7 @@ if(vector_size(&emit->code->instr)) {
 
 ANN static m_bool emit_template_code(const Emitter emit, const Func f) {
   if(GET_FLAG(f, ref))
-    CHECK_BB(traverse_template(emit->env, f->value_ref->owner_class->e->def))
+    CHECK_BB(traverse_class_def(emit->env, f->value_ref->owner_class->e->def))
   const Value v = f->value_ref;
   size_t scope = emit_push(emit, v->owner_class, v->owner);
   CHECK_BB(emit_func_def(emit, f->def))
@@ -1746,14 +1747,14 @@ ANN static inline void emit_class_pop(const Emitter emit) {
   emit_pop_code(emit);
 }
 
-ANN static m_bool emit_class_def(const Emitter emit, const Class_Def class_def) {
-  const Type type = class_def->base.type;
+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_class_base(class_def->tmpl))
+  if(tmpl_class_base(cdef->tmpl))
     return GW_OK;
-  if(class_def->base.ext && ((/*!GET_FLAG(type->e->parent, emit) &&*/
-      GET_FLAG(class_def->base.ext, typedef)) || class_def->base.ext->types)) {
-    const Type base = class_def->base.ext->array ?
+  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))
@@ -1762,15 +1763,21 @@ ANN static m_bool emit_class_def(const Emitter emit, const Class_Def class_def)
     nspc->info->class_data = (m_bit*)xcalloc(1, nspc->info->class_data_size);
   emit_class_push(emit, type);
   emit_class_code(emit, type->name);
-  if(class_def->base.ext && class_def->base.ext->array)
-    CHECK_BB(emit_array_extend(emit, type->e->parent, class_def->base.ext->array->exp))
-  if(class_def->body) {
-    Class_Body body = class_def->body;
+  if(cdef->base.ext && cdef->base.ext->array)
+    CHECK_BB(emit_array_extend(emit, type->e->parent, cdef->base.ext->array->exp))
+  if(cdef->body) {
+    const m_uint scope = env_push_type(emit->env, cdef->base.type);
+    if(cdef->tmpl)
+      template_push_types(emit->env, cdef->tmpl->list.list, cdef->tmpl->base);
+    Class_Body body = cdef->body;
     do CHECK_BB(emit_section(emit, body->section))
     while((body = body->next));
+    if(cdef->tmpl)
+      nspc_pop_type(emit->env->gwion->mp, emit->env->curr);
+    env_pop(emit->env, scope);
   }
   emit_class_finish(emit, nspc);
-  SET_FLAG(class_def->base.type->nspc->pre_ctor, ctor);
+  SET_FLAG(cdef->base.type->nspc->pre_ctor, ctor);
   emit_class_pop(emit);
   SET_FLAG(type, emit);
   return GW_OK;
index 66b5911e2f8ecc521027527a7a9e76ab83b61e5a..c7453bad94cf2529be02a44358051e8118aa2983 100644 (file)
@@ -77,7 +77,7 @@ ANN Type find_type(const Env env, ID_List path) {
 
 ANN m_bool already_defined(const Env env, const Symbol s, const loc_t pos) {
   const Value v = nspc_lookup_value0(env->curr, s);
-  if(!v)
+  if(!v || isa(v->type, t_class) > 0)
     return GW_OK;
   env_err(env, pos,
       "'%s' already declared as variable of type '%s'.", s_name(s), v->type->name);
index 9b88515061064864054ebd9f792e940bd7e476e9..a0f886d390546de6fd374124d861e653daf3d80a 100644 (file)
@@ -106,7 +106,7 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) {
   if(GET_FLAG(decl->type , template)) {
     const Type t = typedef_base(decl->type);
     if(!GET_FLAG(t, check))
-      CHECK_BO(traverse_template(env, t->e->def))
+      CHECK_BO(traverse_class_def(env, t->e->def))
   }
   const m_bool global = GET_FLAG(decl->td, global);
   const m_uint scope = !global ? env->scope->depth : env_push_global(env);
@@ -599,7 +599,7 @@ ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
     return check_lambda_call(env, exp);
   if(GET_FLAG(exp->func->type->e->d.func, ref)) {
     const Value value = exp->func->type->e->d.func->value_ref;
-    CHECK_BO(traverse_template(env, value->owner_class->e->def))
+    CHECK_BO(traverse_class_def(env, value->owner_class->e->def))
   }
   if(exp->args)
     CHECK_OO(check_exp(env, exp->args))
@@ -1163,7 +1163,7 @@ ANN static m_bool check_class_parent(const Env env, const Class_Def cdef) {
   if(td->types) {
     const Type t = parent->array_depth ? array_base(parent) : parent;
     if(!GET_FLAG(t, checked))
-      CHECK_BB(traverse_template(env, t->e->def))
+      CHECK_BB(traverse_class_def(env, t->e->def))
   }
   if(!GET_FLAG(parent, checked))
       CHECK_BB(check_class_def(env, parent->e->def))
@@ -1175,8 +1175,12 @@ ANN static m_bool check_class_parent(const Env env, const Class_Def cdef) {
 ANN static m_bool check_class_body(const Env env, const Class_Def cdef) {
   const m_uint scope = env_push_type(env, cdef->base.type);
   Class_Body body = cdef->body;
+  if(cdef->tmpl)
+    template_push_types(env, cdef->tmpl->list.list, cdef->tmpl->base);
   do CHECK_BB(check_section(env, body->section))
   while((body = body->next));
+  if(cdef->tmpl)
+    nspc_pop_type(env->gwion->mp, env->curr);
   env_pop(env, scope);
   return GW_OK;
 }
index 91aeaa58afd1e8824aaded4d29d171079aaf64b0..0061bf37f0548ac25692f8e19eeba2b85091b9ff 100644 (file)
@@ -10,6 +10,7 @@
 #include "vm.h"
 #include "parse.h"
 #include "traverse.h"
+#include "template.h"
 
 ANN static Value mk_class(const Env env, const Type base) {
   const Type t = type_copy(env->gwion->mp, t_class);
@@ -228,8 +229,12 @@ ANN m_bool scan0_class_def(const Env env, const Class_Def cdef) {
   if(cdef->body) {
     Class_Body body = cdef->body;
     const m_uint scope = env_push_type(env, cdef->base.type);
+    if(cdef->tmpl)
+      template_push_types(env, cdef->tmpl->list.list, cdef->tmpl->base);
     do CHECK_BB(scan0_section(env, body->section))
     while((body = body->next));
+    if(cdef->tmpl)
+      nspc_pop_type(env->gwion->mp, env->curr);
     env_pop(env, scope);
   }
   (void)mk_class(env, cdef->base.type);
index 09fbf4a3325d2861f1740e8c6e5e0516a7b42e08..63b7f30fdab72ad06c1d6f09d4ef43d0d01a5612 100644 (file)
@@ -338,8 +338,12 @@ ANN static m_bool scan1_class_parent(const Env env, const Class_Def cdef) {
 ANN static m_bool scan1_class_body(const Env env, const Class_Def cdef) {
   const m_uint scope = env_push_type(env, cdef->base.type);
   Class_Body body = cdef->body;
+  if(cdef->tmpl)
+    template_push_types(env, cdef->tmpl->list.list, cdef->tmpl->base);
   do CHECK_BB(scan1_section(env, body->section))
   while((body = body->next));
+  if(cdef->tmpl)
+    nspc_pop_type(env->gwion->mp, env->curr);
   env_pop(env, scope);
   return GW_OK;
 }
index 19d75c07e39bf336a5a88f4f2f172be716c3965a..6d9230e0b0142714620cf5ceeeed1106c0eaf040 100644 (file)
@@ -20,10 +20,8 @@ extern ANN m_bool scan1_class_def(const Env, const Class_Def);
 ANN m_bool scan2_class_def(const Env, const Class_Def);
 
 ANN static m_bool scan2_exp_decl_template(const Env env, const Exp_Decl* decl) {
-  CHECK_BB(template_push_types(env, decl->base->tmpl->list.list, decl->td->types));
   CHECK_BB(scan1_class_def(env, decl->type->e->def))
   CHECK_BB(scan2_class_def(env, decl->type->e->def))
-  nspc_pop_type(env->gwion->mp, env->curr);
   return GW_OK;
 }
 
@@ -553,8 +551,12 @@ ANN static m_bool scan2_class_parent(const Env env, const Class_Def cdef) {
 ANN static m_bool scan2_class_body(const Env env, const Class_Def cdef) {
   const m_uint scope = env_push_type(env, cdef->base.type);
   Class_Body body = cdef->body;
+  if(cdef->tmpl)
+    template_push_types(env, cdef->tmpl->list.list, cdef->tmpl->base);
   do CHECK_BB(scan2_section(env, body->section))
   while((body = body->next));
+  if(cdef->tmpl)
+    nspc_pop_type(env->gwion->mp, env->curr);
   env_pop(env, scope);
   return GW_OK;
 }
index d6d9ed36c6f03a783166d0ff0799d9bd53a2c19b..5c2206d01b4eb0b2624a6862ec9ae0607890d2a0 100644 (file)
@@ -151,25 +151,24 @@ ANN Type scan_type(const Env env, const Type t, const Type_Decl* type) {
         "you must provide template types for type '%s'", t->name)
     if(template_match(t->e->def->tmpl->list.list, type->types) < 0)
       ERR_O(type->xid->pos, "invalid template types number")
-    CHECK_BO(template_push_types(env, t->e->def->tmpl->list.list, type->types))
     const Class_Def a = template_class(env, t->e->def, type->types);
     SET_FLAG(a, ref);
     if(a->base.type)
-      POP_RET(a->base.type);
+      return a->base.type;
+    a->tmpl = new_tmpl_class(env->gwion->mp, get_total_type_list(env, t), 0);
+    a->tmpl->base = type->types;
+
     CHECK_BO(scan0_class_def(env, a))
     SET_FLAG(a->base.type, template | ae_flag_ref);
     a->base.type->e->owner = t->e->owner;
     if(GET_FLAG(t, builtin))
       SET_FLAG(a->base.type, builtin);
     CHECK_BO(scan1_class_def(env, a))
-    nspc_pop_type(env->gwion->mp, env->curr);
     if(t->nspc->dtor) {
       a->base.type->nspc->dtor = t->nspc->dtor;
       SET_FLAG(a->base.type, dtor);
       ADD_REF(t->nspc->dtor)
     }
-    a->tmpl = new_tmpl_class(env->gwion->mp, get_total_type_list(env, t), 0);
-    a->tmpl->base = type->types;
     nspc_add_type(t->e->owner, insert_symbol(a->base.type->name), a->base.type);
     return a->base.type;
   } else if(type->types)
index 85447e0d8414dd1ead3e68a7a32a9c5480fbe4a6..94bb009f437dec799eed39a56995da60fa323c1c 100644 (file)
@@ -8,12 +8,6 @@
 #include "vm.h"
 #include "gwion.h"
 
-ANN m_bool traverse_template(const Env env, const Class_Def def) {
-  CHECK_BB(template_push_types(env, def->tmpl->list.list, def->tmpl->base))
-  CHECK_BB(traverse_class_def(env, def))
-  POP_RET(1);
-}
-
 ANN m_bool traverse_func_template(const Env env, const Func_Def def, const Type_List types) {
   CHECK_BB(template_push_types(env, def->tmpl->list, types))
   return traverse_func_def(env, def);
index 9501a3159457e6839757f615cf7e3bc341cb1780..fc23b0294ee3c48e051d783a8c6233d800e52473 100644 (file)
@@ -1,5 +1,4 @@
-template<~A, B~>
-class C {
+class<~A,B~> C {
   A a;
   B b; 
   fun A test() {