]> Nishi Git Mirror - gwion.git/commitdiff
:art: Update
authorJérémie Astor <fennecdjay@gmail.com>
Sat, 29 May 2021 11:05:09 +0000 (13:05 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Sat, 29 May 2021 11:05:09 +0000 (13:05 +0200)
27 files changed:
examples/template_dyn.gw
include/env/nspc.h
include/env/trait.h [new file with mode: 0644]
include/env/type.h
include/gwi.h
include/gwion_env.h
include/import/checker.h
include/tmpl_info.h
plug
src/clean.c
src/emit/emit.c
src/env/nspc.c
src/env/trait.c [new file with mode: 0644]
src/env/type.c
src/import/import_cdef.c
src/import/import_checker.c
src/lib/array.c
src/lib/lib_func.c
src/lib/object.c
src/lib/tmpl_info.c
src/lib/union.c
src/parse/check.c
src/parse/func_resolve_tmpl.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/template.c

index 32e81dfe20be309de4ad2a3b54bda82155a6c49e..e355caf421a402d621cea2a9a6d309572e76738b 100644 (file)
@@ -4,15 +4,15 @@ fun void test(C cc, int i) { <<< 1 >>>; <<< cc.test(i, i) >>>; }
 
 
 class C {
-  fun int test:[A](A a) { <<< " A ", a >>>; }
-  fun int test:[A](A a, int i) { <<< " ", a  >>>; }
-  fun int test:[A](A a, int i, int j) { <<< a >>>; }
+  fun void test:[A](A a) { <<< " A ", a >>>; }
+  fun void test:[A](A a, int i) { <<< " ", a  >>>; }
+  fun void test:[A](A a, int i, int j) { <<< a >>>; }
 }
 class D extends C {
-  fun int test:[A](A a, int i) { <<< this, " extent ", a, __func__ >>>; }
+  fun void test:[A](A a, int i) { <<< this, " extent ", a, __func__ >>>; }
 }
 class E extends D {
-  fun int test:[A](A a, int i) { <<< this, " Extent ", a, __func__ >>>; }
+  fun void test:[A](A a, int i) { <<< this, " Extent ", a, __func__ >>>; }
 }
 
 
index f8dda3c8712958c4dec52c92a079f8267cde3848..3790790cce36164b498e4f21dcbcc6e345dca0e7 100644 (file)
@@ -1,23 +1,24 @@
 #ifndef __NSPC
 #define __NSPC
 struct NspcInfo_ {
-  m_bit* class_data;
-  struct Vector_    vtable;
-  struct Map_          op_map;
-  Scope  value;
-  Scope  type;
-  Scope  func;
-  size_t offset;
-  size_t class_data_size;
+  m_bit*      class_data;
+  struct Map_ op_map;
+  Scope       value;
+  Scope       type;
+  Scope       func;
+  Scope       trait;
+  size_t      offset;
+  size_t      class_data_size;
 };
 
 struct Nspc_ {
   struct NspcInfo_* info;
-  Nspc parent;
-  m_str     name;
-  struct VM_Code_*   pre_ctor;
-  struct VM_Code_*   dtor;
-  uint16_t ref;
+  Nspc              parent;
+  m_str             name;
+  struct Vector_    vtable;
+  struct VM_Code_*  pre_ctor;
+  struct VM_Code_*  dtor;
+  uint16_t          ref;
 };
 
 REF_FUNC(Nspc, nspc)
@@ -63,6 +64,7 @@ describe_lookups(A, b)
 describe_nspc_func(Value, value)
 describe_nspc_func(Type, type)
 describe_nspc_func(Func, func)
+describe_nspc_func(Trait, trait)
 /* howere there is no need for lookup_func0, push_func, pop_func */
 ANN void did_you_mean_nspc(const Nspc, const char*);
 ANN void did_you_mean_type(const Type, const char*);
diff --git a/include/env/trait.h b/include/env/trait.h
new file mode 100644 (file)
index 0000000..6a83b10
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __TRAIT
+#define __TRAIT
+
+typedef struct Trait_ {
+  struct Vector_ requested_values;
+  struct Vector_ requested_funcs;
+  m_str filename;
+  loc_t loc;
+} *Trait;
+
+ANN Trait new_trait(MemPool, const loc_t);
+ANN void free_trait(MemPool, Trait);
+#endif
index c0777f449b15e174f94da64b6887a79d3ac8d64e..0b021da4cbf2f16e102879cde7c0523f864d617c 100644 (file)
@@ -12,6 +12,7 @@ struct TypeInfo_ {
   Type      base_type;
   struct TupleForm_* tuple;
   struct VM_Code_ *gack;
+  ID_List traits;
 };
 
 enum tflag {
index 5330e9394840d7c5c68717f59fb0ffa1b05588df..2ded2e39b02662fda16e66a6d8db8e3296393bcc 100644 (file)
@@ -19,7 +19,7 @@ struct Gwi_ {
 
 #include "import/internals.h"
 static inline Tmpl* gwi_tmpl(const Gwi gwi) {
-  return new_tmpl_base(gwi->gwion->mp, gwi->ck->tmpl);
+  return new_tmpl_base(gwi->gwion->mp, gwi->ck->sl);
 }
 
 ANN void gwi_effects(const Gwi gwi, const m_str name);
index a97ae2e667d09c0177bcd30f9c4e28979758346e..7048955821678233453789cb5d49970f78bae8d5 100644 (file)
@@ -2,6 +2,7 @@
 #define __GWION_ENV
 
 #include "env/oo.h"
+#include "env/trait.h"
 #include "env/nspc.h"
 #include "env/env.h"
 
index 29024ebd890bd00217595ca4daddfbca69601e23..5f80b16ec7f0c679a2276c7ff96a91b81e9bfda2 100644 (file)
@@ -15,6 +15,7 @@ typedef struct ImportCK { // name_checker ?
   Symbol sym;
   union {
     ID_List tmpl;
+    Specialized_List sl;
     Exp exp;
   };
   union {
index 30acc1bf58e0f99517a91500d8cdd3410328b34f..9f46f95dce673cfbe1535c9fed70e75fde527790 100644 (file)
@@ -2,7 +2,7 @@
 #define _TMPL_INFO
 struct tmpl_info {
   Symbol           name;
-  ID_List          list;
+  Specialized_List list;
   const Type_Decl* td;
   Type             ret;
   Type             base;
diff --git a/plug b/plug
index fb296d97fea12ee3e44a1120c47033dfe5325a62..bbba0ebd0da010c4fdaaa53aee5da38e7513c3ff 160000 (submodule)
--- a/plug
+++ b/plug
@@ -1 +1 @@
-Subproject commit fb296d97fea12ee3e44a1120c47033dfe5325a62
+Subproject commit bbba0ebd0da010c4fdaaa53aee5da38e7513c3ff
index da790e5c43271c4293007a574cc389f655cfb186..fb9b07646a5d392742e9e9ae40212ae1d6a7faab 100644 (file)
@@ -16,6 +16,13 @@ ANN static void clean_id_list(Clean *a, ID_List b) {
     clean_id_list(a, b->next);
 }
 
+ANN static void clean_specialized_list(Clean *a, Specialized_List b) {
+  if(b->traits)
+    clean_id_list(a, b->traits);
+  if(b->next)
+    clean_specialized_list(a, b->next);
+}
+
 ANN static void clean_type_list(Clean *a, Type_List b) {
   clean_type_decl(a, b->td);
   if(b->next)
@@ -24,7 +31,7 @@ ANN static void clean_type_list(Clean *a, Type_List b) {
 
 ANN static void clean_tmpl(Clean *a, Tmpl *b) {
   if(b->base < 0 && b->list)
-    clean_id_list(a, b->list);
+    clean_specialized_list(a, b->list);
   if(b->call)
     clean_type_list(a, b->call);
 }
@@ -322,6 +329,8 @@ ANN static void clean_extend_def(Clean *a, Extend_Def b) {
 
 ANN static void clean_class_def(Clean *a, Class_Def b) {
   clean_type_def(a, &b->base);
+  if(b->traits)
+    clean_id_list(a, b->traits);
   if(b->body)
     clean_ast(a, b->body);
 }
@@ -367,6 +376,14 @@ ANN static void clean_type_def(Clean *a, Type_Def b) {
   if(b->tmpl)
     clean_tmpl(a, b->tmpl);
 }
+
+ANN static void clean_trait_def(Clean *a, Trait_Def b) {
+  if(b->traits)
+    clean_id_list(a, b->traits);
+  if(b->body)
+    clean_ast(a, b->body);
+}
+
 DECL_SECTION_FUNC(clean, void, Clean*)
 
 ANN static inline void clean_section(Clean *a, Section *b) {
index f62afc692db703f28036361d6085fd621f8ad28a..d836595ab1f48f73d85b28348c4c4798fcee0e91 100644 (file)
@@ -1064,11 +1064,13 @@ ANN static inline m_bool emit_inline(const Emitter emit, const Func f, const Exp
 }
 
 ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call* exp_call) {
+/*
 #ifndef GWION_NOINLINE
   const Func f = is_inlinable(emit, exp_call);
   if(f)
     return emit_inline(emit, f, exp_call);
 #endif
+*/
   CHECK_BB(prepare_call(emit, exp_call));
   const Type t = actual_type(emit->gwion, exp_call->func->type);
   if(isa(t, emit->gwion->type[et_function]) > 0)
@@ -2511,6 +2513,7 @@ ANN m_bool emit_func_def(const Emitter emit, const Func_Def f) {
 
 ANN static m_bool emit_extend_def(const Emitter emit, const Extend_Def xdef);
 #define emit_fptr_def dummy_func
+#define emit_trait_def dummy_func
 HANDLE_SECTION_FUNC(emit, m_bool, Emitter)
 
 ANN static inline m_bool emit_ast_inner(const Emitter emit, Ast ast) {
index 247cc17f1ed16cbbedcc3e7b4fdf8738dfba57ba..1fad63ab4cb57853576087de12c4665ef24c2d42 100644 (file)
@@ -10,6 +10,7 @@ ANN void nspc_commit(const Nspc nspc) {
   scope_commit(nspc->info->value);
   scope_commit(nspc->info->func);
   scope_commit(nspc->info->type);
+  scope_commit(nspc->info->trait);
 }
 
 ANN static inline void nspc_release_object(const Nspc a, Value value, Gwion gwion) {
@@ -60,17 +61,25 @@ ANN static void nspc_free_##b(Nspc n, Gwion gwion) {\
 
 describe_nspc_free(Func, func)
 describe_nspc_free(Type, type)
+ANN static void nspc_free_trait(Nspc n, Gwion gwion) {
+  struct scope_iter iter = { n->info->trait, 0, 0 };
+  Trait a;
+  while(scope_iter(&iter, &a) > 0)
+    free_trait(gwion->mp, a);
+  free_scope(gwion->mp, n->info->trait);
+}
 
 ANN void free_nspc(const Nspc a, const Gwion gwion) {
   free_nspc_value(a, gwion);
   nspc_free_func(a, gwion);
+  nspc_free_trait(a, gwion);
   if(a->info->op_map.ptr)
     free_op_map(&a->info->op_map, gwion);
   nspc_free_type(a, gwion);
   if(a->info->class_data && a->info->class_data_size)
     mp_free2(gwion->mp, a->info->class_data_size, a->info->class_data);
-  if(a->info->vtable.ptr)
-    vector_release(&a->info->vtable);
+  if(a->vtable.ptr)
+    vector_release(&a->vtable);
   mp_free(gwion->mp, NspcInfo, a->info);
   if(a->pre_ctor)
     vmcode_remref(a->pre_ctor, gwion);
@@ -84,8 +93,9 @@ ANN Nspc new_nspc(MemPool p, const m_str name) {
   a->name = name;
   a->info = mp_calloc(p, NspcInfo);
   a->info->value = new_scope(p);
-  a->info->type = new_scope(p);
-  a->info->func = new_scope(p);
+  a->info->type  = new_scope(p);
+  a->info->func  = new_scope(p);
+  a->info->trait = new_scope(p);
   a->ref = 1;
   return a;
 }
diff --git a/src/env/trait.c b/src/env/trait.c
new file mode 100644 (file)
index 0000000..c6b53fb
--- /dev/null
@@ -0,0 +1,17 @@
+#include <gwion_util.h>
+#include <gwion_ast.h>
+#include <gwion_env.h>
+
+ANN Trait new_trait(MemPool mp, const loc_t loc) {
+  const Trait a = mp_calloc(mp, Trait);
+  a->loc = loc;
+  return a;
+}
+
+ANN void free_trait(MemPool mp, Trait a) {
+  if(a->requested_values.ptr)
+    vector_release(&a->requested_values);
+  if(a->requested_funcs.ptr)
+    vector_release(&a->requested_funcs);
+  mp_free(mp, Trait, a);
+}
index 21caa22854d092a01933a8100f4b80d74a4148f7..547f2fef942344a9b22e9db9e809ec8f03b26f0f 100644 (file)
@@ -157,6 +157,6 @@ ANN void inherit(const Type t) {
   if(!nspc || !parent)
     return;
   nspc->info->offset = parent->info->offset;
-  if(parent->info->vtable.ptr)
-    vector_copy2(&parent->info->vtable, &nspc->info->vtable);
+  if(parent->vtable.ptr)
+    vector_copy2(&parent->vtable, &nspc->vtable);
 }
index d6fed1549b6b1fadef5dddafbade4084d88ebdb4..f8f202fdbff7c301696cfc0eb541b8d3cdfc47f7 100644 (file)
@@ -38,7 +38,7 @@ ANN2(1) void add_template(const Env env, const Type t) {
   Tmpl* tmpl = t->info->cdef->base.tmpl;
   if(tmpl) {
     nspc_push_type(env->gwion->mp, env->curr);//
-    ID_List il = tmpl->list;
+    Specialized_List il = tmpl->list;
     do nspc_add_type(env->curr, il->xid, env->gwion->type[et_auto]);
     while((il = il->next));
   }
@@ -75,7 +75,7 @@ ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str name, const m_str parent
   struct ImportCK ck = { .name=name };
   CHECK_BO(check_typename_def(gwi, &ck));
   DECL_OO(Type_Decl *,td, = gwi_str2td(gwi, parent ?: "Object"));
-  Tmpl* tmpl = ck.tmpl ? new_tmpl_base(gwi->gwion->mp, ck.tmpl) : NULL;
+  Tmpl* tmpl = ck.sl ? new_tmpl_base(gwi->gwion->mp, ck.sl) : NULL;
   if(tmpl)
     CHECK_BO(template_push_types(gwi->gwion->env, tmpl));
   const Type base = find_type(gwi->gwion->env, td);
@@ -95,7 +95,7 @@ ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str name, const m_str parent
   t->info->parent = p;
   if(td->array)
     set_tflag(t, tflag_typedef);
-  if(ck.tmpl)
+  if(ck.sl)
     set_tflag(t, tflag_tmpl | tflag_ntmpl);
   else
     gwi_type_flag(t);
@@ -107,12 +107,12 @@ ANN Type gwi_struct_ini(const Gwi gwi, const m_str name) {
   CHECK_BO(check_typename_def(gwi, &ck));
   const Type t = new_type(gwi->gwion->mp, s_name(ck.sym), gwi->gwion->type[et_compound]);
   set_tflag(t, tflag_struct);
-  if(!ck.tmpl)
+  if(!ck.sl)
     gwi_type_flag(t);
   else {
     t->info->cdef = new_class_def(gwi->gwion->mp, 0, ck.sym, NULL, NULL, gwi->loc);
     t->info->cdef->base.type = t;
-    t->info->cdef->base.tmpl = new_tmpl_base(gwi->gwion->mp, ck.tmpl);
+    t->info->cdef->base.tmpl = new_tmpl_base(gwi->gwion->mp, ck.sl);
     t->info->tuple = new_tupleform(gwi->gwion->mp, NULL);
     t->info->parent = NULL;
     t->info->cdef->cflag |= cflag_struct;
index 46ebe15481164c7aaca8e0678b1dceb65956afab..85628e6665a1ea9053aa2b37c09dd68f4a1b3f01 100644 (file)
@@ -93,32 +93,34 @@ ANN Var_Decl_List str2varlist(const Gwion gwion, const m_str path, const loc_t p
   return new_var_decl_list(gwion->mp, var, NULL);
 }
 
-ANN static ID_List _tmpl_list(const Gwion gwion, struct td_checker *tdc) {
+#define SPEC_ERROR (Specialized_List)GW_ERROR
+ANN static Specialized_List _tmpl_list(const Gwion gwion, struct td_checker *tdc) {
   DECL_OO(const Symbol, sym, = __str2sym(gwion, tdc));
-  ID_List next = NULL;
+  Specialized_List next = NULL;
   if(*tdc->str == ',') {
     ++tdc->str;
-    if(!(next = _tmpl_list(gwion, tdc)) || next == (ID_List)GW_ERROR)
-      return (ID_List)GW_ERROR;
+    if(!(next = _tmpl_list(gwion, tdc)) || next == SPEC_ERROR)
+      return SPEC_ERROR;
   }
-  const ID_List list = new_id_list(gwion->mp, sym);
+  // TODO: handle traits?
+  const Specialized_List list = new_specialized_list(gwion->mp, sym, NULL, tdc->pos);
   list->next = next;
   return list;
 }
 
-ANN static ID_List __tmpl_list(const Gwion gwion, struct td_checker *tdc) {
+ANN static Specialized_List __tmpl_list(const Gwion gwion, struct td_checker *tdc) {
   if(tdc->str[0] != ':')
     return NULL;
   if(tdc->str[1] != '[')
-    return (ID_List)GW_ERROR;
+    return SPEC_ERROR;
   tdc->str += 2;
-  const ID_List list =  _tmpl_list(gwion, tdc);
-  if(list == (ID_List)GW_ERROR)
-    return (ID_List)GW_ERROR;
+  const Specialized_List list =  _tmpl_list(gwion, tdc);
+  if(list == SPEC_ERROR)
+    return SPEC_ERROR;
   if(tdc->str[0] != ']') { // unfinished template
     if(list)
-      free_id_list(gwion->mp, list);
-    return (ID_List)GW_ERROR;
+      free_specialized_list(gwion->mp, list);
+    return SPEC_ERROR;
   }
   ++tdc->str;
   return list;
@@ -128,10 +130,10 @@ ANN m_bool check_typename_def(const Gwi gwi, ImportCK *ck) {
   struct td_checker tdc = { .str= ck->name, .pos=gwi->loc };
   if(!(ck->sym = _str2sym(gwi->gwion, &tdc, tdc.str)))
     return GW_ERROR;
-  ID_List il = __tmpl_list(gwi->gwion, &tdc);
-  if(il == (ID_List)GW_ERROR)
+  Specialized_List sl = __tmpl_list(gwi->gwion, &tdc);
+  if(sl == SPEC_ERROR)
     return GW_ERROR;
-  ck->tmpl = il;
+  ck->sl = sl;
   ck->name = s_name(ck->sym);
   return GW_OK;
 
index ba9a5e61b2729424486bca5fc8eef88033c47ce9..8a6697def8c1cd9c269a0489f1cb2c09c52fce22 100644 (file)
@@ -671,20 +671,20 @@ static OP_CHECK(opck_array_scan) {
   set_tflag(t, tflag_cdef | tflag_tmpl);
   void* rem = isa(base, env->gwion->type[et_compound]) > 0 ?
     !tflag(base, tflag_struct) ? vm_vector_rem_obj : vm_vector_rem_struct : vm_vector_rem;
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 0), rem);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 0), rem);
   void* insert = isa(base, env->gwion->type[et_compound]) > 0 ?
     !tflag(base, tflag_struct) ? vm_vector_insert_obj : vm_vector_insert_struct : vm_vector_insert;
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 1), insert);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 2), vm_vector_size);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 3), vm_vector_depth);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 4), vm_vector_cap);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 5), vm_vector_random);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 6), vm_vector_map);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 7), vm_vector_compactmap);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 8), vm_vector_filter);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 9), vm_vector_count);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 10), vm_vector_foldl);
-  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->info->vtable, 11), vm_vector_foldr);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 1), insert);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 2), vm_vector_size);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 3), vm_vector_depth);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 4), vm_vector_cap);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 5), vm_vector_random);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 6), vm_vector_map);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 7), vm_vector_compactmap);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 8), vm_vector_filter);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 9), vm_vector_count);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 10), vm_vector_foldl);
+  builtin_func(env->gwion->mp, (Func)vector_at(&t->nspc->vtable, 11), vm_vector_foldr);
   if(isa(base, env->gwion->type[et_compound]) > 0) {
     t->nspc->dtor = new_vmcode(env->gwion->mp, NULL, SZ_INT, 1, "array component dtor");
     set_tflag(t, tflag_dtor);
index 08f622d482f3cec53e4e0dc4206a647cc9bf12d8..992cb3708209e10d9779f820b201a8adcf7f2e68 100644 (file)
@@ -56,7 +56,7 @@ ANN static void _fptr_tmpl_push(const Env env, const Func f) {
   Type_List tl = tmpl->call;
   if(!tl)
     return;
-  ID_List il = tmpl->list;
+  Specialized_List il = tmpl->list;
   while(il) {
     const Type t = known_type(env, tl->td);
     nspc_add_type(env->curr, il->xid, t);
index 4afab57b6dae179ca57ec3caef73d16eaa3b1438..74549429ad00048855b4e85ea0213484ba9fc171 100644 (file)
@@ -25,7 +25,7 @@ M_Object new_object(MemPool p, const VM_Shred shred, const Type t) {
   a->ref = 1;
   a->type_ref = t;
   if(t->nspc) {
-    a->vtable.ptr = t->nspc->info->vtable.ptr;
+    a->vtable.ptr = t->nspc->vtable.ptr;
     if(t->nspc->info->offset)
       a->data = (m_bit*)_mp_calloc(p, t->nspc->info->offset);
   }
index 9a805fe4319bf7abe8a9663253a5f208db7b9504..8414edccc2570fa27c320d07668465c860517e0c 100644 (file)
@@ -66,7 +66,7 @@ ANEW ANN static Symbol template_id(const Env env, struct tmpl_info *const info)
   return sym;
 }
 
-ANN static m_bool template_match(ID_List base, Type_List call) {
+ANN static m_bool template_match(Specialized_List base, Type_List call) {
   while((call = call->next) && (base = base->next));
   return !call ? GW_OK : GW_ERROR;
 }
index 2ea352d5c6bb5293395d9bbf82d988d43cbb8faf..611a2b305c551c3cf6a0096a10f45095d4675fe9 100644 (file)
@@ -39,7 +39,7 @@ static OP_EMIT(opem_union_dot) {
   CHECK_BB(emit_exp(emit, member->base));
   if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0) {
     const Instr instr = emit_add_instr(emit, RegPushImm);
-    const Func f = (Func)vector_front(&member->base->type->info->parent->nspc->info->vtable);
+    const Func f = (Func)vector_front(&member->base->type->info->parent->nspc->vtable);
     instr->m_val = (m_uint)f->code;
     return GW_OK;
   }
@@ -179,7 +179,7 @@ ANN GWION_IMPORT(union) {
   GWI_BB(gwi_oper_emi(gwi, opem_union_ctor))
   GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
 
-  const Func f = (Func)vector_front(&t_union->nspc->info->vtable);
+  const Func f = (Func)vector_front(&t_union->nspc->vtable);
   const struct Op_Func opfunc = { .ck=opck_union_is };
   const struct Op_Import opi = { .rhs=f->value_ref->type,
        .func=&opfunc, .data=(uintptr_t)f, .pos=gwi->loc, .op=insert_symbol(gwi->gwion->st, "@func_check") };
index eb1e692e6491e7e14f5c890eb5643e3ebe3afee5..c9c88ef81654c2f592fbde387ad184c2ac8a5fb7 100644 (file)
@@ -609,7 +609,7 @@ ANN2(1) static void function_alternative(const Env env, const Type f, const Exp
     gw_err(_("and not:\n  {G}void{0}\n"));
 }
 
-ANN static m_uint get_type_number(ID_List list) {
+ANN static m_uint get_type_number(Specialized_List list) {
   m_uint type_number = 0;
   do ++type_number;
   while((list = list->next));
@@ -662,7 +662,7 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp, const Tmp
   const m_uint type_number = get_type_number(tm->list);
   Type_List tl[type_number];
   tl[0] = NULL;
-  ID_List list = tm->list;
+  Specialized_List list = tm->list;
   while(list) {
     Arg_List arg = fdef->base->args;
     Exp template_arg = exp->args;
@@ -1371,7 +1371,7 @@ ANN static m_bool parent_match_actual(const Env env, const restrict Func_Def fde
       CHECK_BB(check_signature_match(env, fdef, parent_func));
       if(!fdef->base->tmpl) {
         fdef->base->func->vt_index = parent_func->vt_index;
-        vector_set(&env->curr->info->vtable, fdef->base->func->vt_index, (vtype)fdef->base->func);
+        vector_set(&env->curr->vtable, fdef->base->func->vt_index, (vtype)fdef->base->func);
       }
       return GW_OK;
     }
@@ -1382,8 +1382,8 @@ ANN static m_bool parent_match_actual(const Env env, const restrict Func_Def fde
 ANN static m_bool check_parent_match(const Env env, const Func_Def fdef) {
   const Func func = fdef->base->func;
   const Type parent = env->class_def->info->parent;
-  if(!env->curr->info->vtable.ptr)
-    vector_init(&env->curr->info->vtable);
+  if(!env->curr->vtable.ptr)
+    vector_init(&env->curr->vtable);
   if(parent) {
     const Value v = find_value(parent, fdef->base->xid);
     if(v && isa(v->type, env->gwion->type[et_function]) > 0) {
@@ -1392,8 +1392,8 @@ ANN static m_bool check_parent_match(const Env env, const Func_Def fdef) {
         return match;
     }
   }
-  func->vt_index = vector_size(&env->curr->info->vtable);
-  vector_add(&env->curr->info->vtable, (vtype)func);
+  func->vt_index = vector_size(&env->curr->vtable);
+  vector_add(&env->curr->vtable, (vtype)func);
   return GW_OK;
 }
 
@@ -1529,6 +1529,39 @@ ANN static m_bool check_extend_def(const Env env, const Extend_Def xdef) {
   return ret;
 }
 
+ANN static m_bool _check_trait_def(const Env env, const Trait_Def pdef) {
+  const Trait trait = nspc_lookup_trait1(env->curr, pdef->xid);
+  Ast ast = pdef->body;
+  while(ast) {
+    Section * section = ast->section;
+    if(section->section_type == ae_section_stmt) {
+      Stmt_List list = section->d.stmt_list;
+      while(list) {
+        const Stmt stmt = list->stmt;
+        if(stmt->stmt_type == ae_stmt_exp) {
+          CHECK_BB(traverse_exp(env, stmt->d.stmt_exp.val));
+          Var_Decl_List list = stmt->d.stmt_exp.val->d.exp_decl.list;
+          while(list) {
+            const Value value = list->self->value;
+            valuefrom(env, value->from, list->self->pos); // we do not need owner
+            if(!trait->requested_values.ptr)
+              vector_init(&trait->requested_values);
+            vector_add(&trait->requested_values, (m_uint)value);
+            list = list->next;
+          }
+        }
+        list = list->next;
+      }
+    }
+    ast = ast->next;
+  }
+  return GW_OK;
+}
+
+ANN static m_bool check_trait_def(const Env env, const Trait_Def pdef) {
+  RET_NSPC(_check_trait_def(env, pdef));
+}
+
 #define check_fptr_def dummy_func
 HANDLE_SECTION_FUNC(check, m_bool, Env)
 
@@ -1556,11 +1589,11 @@ ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
 }
 
 ANN m_bool check_abstract(const Env env, const Class_Def cdef) {
-  if(!cdef->base.type->nspc->info->vtable.ptr)
+  if(!cdef->base.type->nspc->vtable.ptr)
     return GW_OK;
   bool err = false;
-  for(m_uint i = 0; i < vector_size(&cdef->base.type->nspc->info->vtable); ++i) {
-    Func f = (Func)vector_at(&cdef->base.type->nspc->info->vtable, i);
+  for(m_uint i = 0; i < vector_size(&cdef->base.type->nspc->vtable); ++i) {
+    Func f = (Func)vector_at(&cdef->base.type->nspc->vtable, i);
     if(f && GET_FLAG(f->def->base, abstract)) {
       if(!err) {
         err = true;
@@ -1634,6 +1667,120 @@ if(isa(dlist->self->value->type, env->gwion->type[et_compound]) > 0)
   return false;
 }
 
+ANN static bool request_var(const Env env, const Type t, const Value request) {
+  const Value value = nspc_lookup_value0(t->nspc, insert_symbol(request->name));
+  if(!value) {
+    gwerr_basic("missing requested variable", NULL, NULL,
+        request->from->filename, request->from->loc, 0);
+    return false;
+  }
+  bool error = true;
+  if(isa(value->type, request->type) < 0) {
+    gwerr_basic("invalid variable type", NULL, NULL,
+        value->from->filename, value->from->loc, 0);
+    // can we point to the type decl?
+    error = false;
+  }
+  if(GET_FLAG(value, const) && !GET_FLAG(request, const)) {
+    gwerr_basic("variable differs in {/}constness{0}", NULL, NULL,
+        value->from->filename, value->from->loc, 0);
+    // can we point to the flag?
+    error = false;
+  }
+  if(error)
+    return true;
+  gwerr_secondary("from requested variable", request->from->filename, request->from->loc);
+  return error;
+}
+
+ANN static bool check_trait_variables(const Env env, const Type t, const Trait trait) {
+  bool error = false;
+  for(m_uint i = 0; i < vector_size(&trait->requested_values); i++) {
+    const Value request = (Value)vector_at(&trait->requested_values, i);
+    if(!request_var(env, t, request))
+      error = true;
+  }
+  return error;
+}
+
+ANN static bool request_fun(const Env env, const Type t, const Func_Def request) {
+  const Value v = nspc_lookup_value0(t->nspc, request->base->xid);
+if(v) {
+  if(isa(v->type, env->gwion->type[et_function]) < 0 || is_fptr(env->gwion, v->type)) {
+    gwerr_basic("is not a function", NULL, NULL,
+      v->from->filename, v->from->loc, 0);
+    return false;
+  }
+  Func f = v->d.func_ref;
+  do {
+    if(compat_func(f->def, request) > 0) {
+      if(!GET_FLAG(f->def->base, abstract))
+        return true;
+    }
+  } while ((f = f->next));
+}
+  if(!GET_FLAG(request->base, abstract)){
+    const m_uint scope = env_push_type(env, t);
+    const Func_Def cpy = cpy_func_def(env->gwion->mp, request);
+    const m_bool ret = traverse_func_def(env, cpy);
+    env_pop(env, scope);
+    if(ret > 0){
+      Section *section = new_section_func_def(env->gwion->mp, cpy);
+      const Ast ast = new_ast(env->gwion->mp, section, NULL);
+      Ast last = t->info->cdef->body;
+      while(last->next)
+        last = last->next;
+      last->next = ast;
+      return true;
+    } else
+    free_func_def(env->gwion->mp, cpy);
+  }
+  if(!v) {
+    gwerr_basic("missing requested function", NULL, NULL,
+      env->name, request->base->pos, 0);
+    return false;
+  }
+  return true;
+}
+
+ANN static bool check_trait_functions(const Env env, const Type t, const Trait trait) {
+  bool error = false;
+  for(m_uint i = 0; i < vector_size(&trait->requested_funcs); i++) {
+    const Func_Def request = (Func_Def)vector_at(&trait->requested_funcs, i);
+    if(!request_fun(env, t, request))
+      error = true;
+  }
+  return error;
+}
+
+ANN2(1,2,3) static inline bool trait_nodup(Type t, const Symbol trait, ID_List list) {
+  bool nodup = true;
+  do {
+    while(list) {
+      if(trait == list->xid)
+//        return false;
+        nodup = false;
+      list = list->next;
+    }
+  } while ((t = t->info->parent));
+  return nodup;
+}
+
+ANN static bool check_trait_requests(const Env env, const Type t, const ID_List list) {
+  const Trait trait = nspc_lookup_trait1(env->curr, list->xid);
+  if(!trait_nodup(t, list->xid, list->next)) {
+    gwerr_secondary("duplicated trait", trait->filename, trait->loc);
+    return false;
+  }
+  const bool value_error = check_trait_variables(env, t, trait);
+  const bool funcs_error = check_trait_functions(env, t, trait);
+  if(!value_error && !funcs_error)
+    return true;
+  const Value request = (Value)vector_front(&trait->requested_values);
+  gwerr_secondary("from trait", request->from->filename, trait->loc);
+  return false;
+}
+
 ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
   const Type t = cdef->base.type;
   if(cdef->base.ext)
@@ -1647,6 +1794,21 @@ ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
   }
   if(!GET_FLAG(cdef, abstract))
     CHECK_BB(check_abstract(env, cdef));
+  if(cdef->traits) {
+    ID_List list = cdef->traits;
+    bool value_error = false;
+    do if(!check_trait_requests(env, t, list))
+      value_error = true;
+    while((list = list->next));
+
+    if(value_error) {
+      env->class_def = t;
+      env_error_footer(env);
+      env->context->error = true;
+      return GW_ERROR;
+    }
+  }
+
   Value value;
   struct scope_iter iter = { t->nspc->info->value, 0, 0 };
   while(scope_iter(&iter, &value) > 0) {
@@ -1657,11 +1819,10 @@ ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
   struct scope_iter inner = { value->type->nspc->info->value, 0, 0 };
   while(scope_iter(&inner, &v) > 0) {
       if(isa(v->type, t) > 0 || isa(t, v->type) > 0) {
-//exit(3);
         env_err(env, v->from->loc, _("recursive type"));
-env->context->error = false;
+        env->context->error = false;
         env_err(env, value->from->loc, _("recursive type"));
-env->context->error = true;
+       env->context->error = true;
 return GW_ERROR;
 }
 }
index 4059908f10fa8972d5d0c95ddd88fda77f83cf51..52b74fa0726e6b6ca6024415f8b849c379e0846d 100644 (file)
@@ -140,13 +140,45 @@ ANN static Func find_tmpl(const Env env, const Value v, Exp_Call *const exp, con
   return m_func;
 }
 
-ANN static Func _find_template_match(const Env env, const Value v, Exp_Call *const exp) {
+ANN static Func __find_template_match(const Env env, const Value v, Exp_Call *const exp) {
   DECL_OO(const m_str, tmpl_name, = tl2str(env->gwion, exp->tmpl->call, exp->func->pos));
   const Func f = find_tmpl(env, v, exp, tmpl_name);
   free_mstr(env->gwion->mp, tmpl_name);
   return f;
 }
 
+ANN static inline bool has_trait(const Type t, const Symbol trait) {
+  ID_List list = t->info->traits;
+  while(list) {
+    if(list->xid == trait)
+      return true;
+    list = list->next;
+  }
+  return false;
+}
+
+ANN static inline bool has_traits(const Type t, ID_List traits) {
+  while(traits) {
+    if(!has_trait(t, traits->xid))
+      return false;
+    traits = traits->next;
+  }
+  return true;
+}
+
+ANN static Func _find_template_match(const Env env, const Value v, Exp_Call *const exp) {
+  DECL_OO(const Func, f, = __find_template_match(env, v, exp));
+  Type_List tl = exp->tmpl->call;
+  Specialized_List sl = f->def->base->tmpl->list;
+  while(tl) {
+    DECL_OO(const Type, t, = known_type(env, tl->td));
+    if(!has_traits(t, sl->traits))
+      return NULL;
+    tl = tl->next;
+  }
+  return f;
+}
+
 ANN static inline m_bool check_call(const Env env, const Exp_Call* exp) {
   const ae_exp_t et = exp->func->exp_type;
   if(et != ae_exp_primary && et != ae_exp_dot && et != ae_exp_cast)
index 6da1147803fdc8186ddd1fa3d5634ea888b00149..b2ff420dc46c4360dbf48bccaae590589eb25dcf 100644 (file)
@@ -334,11 +334,21 @@ ANN static Type cdef_parent(const Env env, const Class_Def cdef) {
   return t ?: (Type)GW_ERROR;
 }
 
+ANN static m_bool cdef_traits(const Env env, ID_List traits, const loc_t pos) {
+  do {
+    if(!nspc_lookup_trait1(env->curr, traits->xid))
+      ERR_B(pos, _("can't find trait"));
+  } while((traits = traits->next));
+  return GW_OK;
+}
+
 ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
   CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos));
   const Type parent = cdef_parent(env, cdef);
   if(parent == (Type)GW_ERROR)
     return NULL;
+  if(cdef->traits)
+    CHECK_BO(cdef_traits(env, cdef->traits, cdef->pos));
   const Type t = scan0_type(env, s_name(cdef->base.xid), parent);
   if(cflag(cdef, cflag_struct)) {
     t->size = 0;
@@ -437,10 +447,43 @@ ANN static m_bool scan0_extend_def(const Env env, const Extend_Def xdef) {
   return GW_OK;
 }
 
+ANN static m_bool _scan0_trait_def(const Env env, const Trait_Def pdef) {
+  const Trait trait = new_trait(env->gwion->mp, pdef->pos);
+  trait->loc = pdef->pos;
+  trait->filename = env->name;
+  nspc_add_trait(env->curr, pdef->xid, trait);
+  Ast ast = pdef->body;
+  while(ast) {
+    Section * section = ast->section;
+    if(section->section_type == ae_section_func) {
+      const Func_Def fdef = section->d.func_def;
+      if(!trait->requested_funcs.ptr)
+        vector_init(&trait->requested_funcs);
+      vector_add(&trait->requested_funcs, (m_uint)fdef);
+    }
+    ast = ast->next;
+  }
+  return GW_OK;
+}
+
+ANN static m_bool scan0_trait_def(const Env env, const Trait_Def pdef) {
+  const Symbol s = pdef->xid;
+  const Trait exists = nspc_lookup_trait1(env->curr, s);
+  if(exists) {
+    gwerr_basic("trait already defined", NULL, NULL, env->name, pdef->pos, 0);
+    gwerr_secondary("defined here", env->name, exists->loc);
+    env->context->error = true;
+    return already_defined(env, s, pdef->pos);
+  }
+  _scan0_trait_def(env, pdef);
+  return GW_OK;
+}
+
 HANDLE_SECTION_FUNC(scan0, m_bool, Env)
 
 ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
   CHECK_OB((cdef->base.type = scan0_class_def_init(env, cdef)));
+  cdef->base.type->info->traits = cdef->traits;
   set_tflag(cdef->base.type, tflag_scan0);
   (void)mk_class(env, cdef->base.type, cdef->pos);
   add_type(env, cdef->base.type->info->value->from->owner, cdef->base.type);
index 34d05424a0d5ed6e8fdf7dd981b5e4d815d68840..6fff9351937c3a49e065629e04efc24100fd50f5 100644 (file)
@@ -109,9 +109,9 @@ ANN static m_bool scan1_decl(const Env env, const Exp_Decl* decl) {
             env->class_def->size += t->size;
           }
         }
-      } else
-        set_vflag(v, vflag_fglobal);// file global
-    }
+      }
+      set_vflag(v, vflag_fglobal);// file global
+    } else
     if(GET_FLAG(decl->td, global))
       SET_FLAG(v, global);
   } while((list = list->next));
@@ -410,7 +410,7 @@ ANN static Type scan1_noret(const Env env, const Func_Base *base) {
 }
 
 ANN static m_bool _scan1_fdef_base_tmpl(const Env env, Func_Base *base) {
-  ID_List id = base->tmpl->list;
+  Specialized_List id = base->tmpl->list;
   do nspc_add_type(env->curr, id->xid, env->gwion->type[et_auto]);
   while((id = id->next));
   CHECK_OB((base->ret_type = scan1_noret(env, base)));
@@ -641,6 +641,7 @@ ANN static m_bool scan1_extend_def(const Env env, const Extend_Def xdef) {
   return ret;
 }
 
+#define scan1_trait_def dummy_func
 HANDLE_SECTION_FUNC(scan1, m_bool, Env)
 
 ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) {
index 1998c93dcaf6c46e7fb6aa9474004cfeffba8e31..f8e70f41636c2191f2ed1c2fa821711f632ea0a5 100644 (file)
@@ -415,7 +415,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->base->tmpl->list;
+  Specialized_List id = f->base->tmpl->list;
   m_uint tlen = 0;
   vector_init(&v);
   do {
@@ -547,6 +547,8 @@ ANN static m_bool scan2_extend_def(const Env env, const Extend_Def xdef) {
 }
 
 #define scan2_enum_def dummy_func
+#define scan2_trait_def dummy_func
+
 HANDLE_SECTION_FUNC(scan2, m_bool, Env)
 
 ANN static m_bool scan2_parent(const Env env, const Class_Def cdef) {
index 40144b5e4bf356e921cca7b8c83f718b0ff31b99..af92ddeee696436dd9a8fa195496eb824ff8b047 100644 (file)
@@ -13,7 +13,7 @@
 #include "import.h"
 
 ANN static m_bool push_types(const Env env, const Tmpl *tmpl) {
-  ID_List list = tmpl->list;
+  Specialized_List list = tmpl->list;
   Type_List call = tmpl->call;
   do {
     if(!call)