]> Nishi Git Mirror - gwion.git/commitdiff
:art: Add new Closures, new extends, variadic generics, colored help
authorfennecdjay <fennecdjay@gmail.com>
Sun, 26 Jun 2022 18:49:32 +0000 (20:49 +0200)
committerfennecdjay <fennecdjay@gmail.com>
Sun, 26 Jun 2022 18:49:32 +0000 (20:49 +0200)
134 files changed:
Makefile
ast
examples/array_lit.gw
examples/op2.gw
examples/template_vararg.gw [deleted file]
examples/vararg.gw [deleted file]
fmt
highlighters/gwion.kak
include/clean.h
include/emit.h
include/env/context.h
include/env/func.h
include/env/trait.h
include/env/type.h
include/env/value.h
include/gwi.h
include/gwion_all.h
include/gwion_env.h
include/import/checker.h
include/instr.h
include/lang_private.h
include/operator.h
include/spread.h [new file with mode: 0644]
include/traverse.h
include/vararg.h [deleted file]
libcmdapp
plug
src/clean.c
src/emit/emit.c
src/emit/emitter.c
src/env/context.c
src/env/env.c
src/env/env_utils.c
src/env/trait.c
src/env/type.c
src/env/value.c
src/gwion.c
src/import/import_cdef.c
src/import/import_checker.c
src/import/import_enum.c
src/import/import_fdef.c
src/import/import_internals.c
src/import/import_item.c
src/import/import_udef.c
src/lib/array.c
src/lib/closure.c [moved from src/lib/lib_func.c with 59% similarity]
src/lib/ctrl.c
src/lib/deep_equal.c
src/lib/dict.c
src/lib/engine.c
src/lib/instr.c
src/lib/modules.c
src/lib/object.c
src/lib/object_op.c
src/lib/sift.c
src/lib/union.c
src/lib/vararg.c [deleted file]
src/lib/xork.c [new file with mode: 0644]
src/parse/check.c
src/parse/check_traits.c
src/parse/default_arg.c
src/parse/func_resolve_tmpl.c
src/parse/operator.c
src/parse/partial.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/scanx.c
src/parse/spread.c [new file with mode: 0644]
src/parse/template.c
src/parse/traverse.c
src/parse/type_decl.c
src/vm/vm.c
tests/error/array_assign_exp.gw
tests/error/array_depth_match.gw
tests/error/array_err2.gw
tests/error/array_err3.gw
tests/error/array_failure.gw
tests/error/array_multi_oob.gw
tests/error/array_no_member.gw
tests/error/array_oob.gw
tests/error/array_oob_multi.gw
tests/error/array_type_match.gw
tests/error/fptr_other_class.gw [deleted file]
tests/error/func_arg_array_empty.gw
tests/error/func_no_match.gw
tests/error/invalid_array_acces.gw
tests/error/invalid_array_shift.gw
tests/error/multi_decl.gw [deleted file]
tests/error/negative_array.gw
tests/error/negative_array2.gw
tests/error/op_test.gw
tests/error/ptr_arg_array.gw
tests/error/ptr_assign_global.gw [deleted file]
tests/error/ptr_assign_member.gw [deleted file]
tests/error/ptr_assign_other.gw [deleted file]
tests/error/typedef_func_tmpl_types2.gw
tests/error/vararg_invalid_acces.gw [deleted file]
tests/error/vararg_outside.gw [deleted file]
tests/error/vararg_outside_varloop.gw [deleted file]
tests/error/varloop_not_vararg.gw [deleted file]
tests/extend/extend.gw [deleted file]
tests/extend/extend_abstract.gw [deleted file]
tests/extend/extend_final.gw [deleted file]
tests/extend/extend_not_compound.gw [deleted file]
tests/extend/extend_tmpl.gw [deleted file]
tests/fptr/class_ptr01.gw [deleted file]
tests/fptr/class_ptr31.gw [deleted file]
tests/lambdas/lambda.gw
tests/lambdas/lambda2.gw
tests/new/typedef_func_class_variadic.gw [deleted file]
tests/new/vararg_cpy.gw [deleted file]
tests/plug/op_already_imported.c [deleted file]
tests/plug/op_already_imported.gw [deleted file]
tests/plug/variadic.c [deleted file]
tests/plug/variadic.gw [deleted file]
tests/sh/import.sh
tests/spread/spread.gw [new file with mode: 0644]
tests/spread/spread_error.gw [new file with mode: 0644]
tests/spread/spread_func.gw [new file with mode: 0644]
tests/spread/spread_outside.gw [new file with mode: 0644]
tests/spread/spread_outside_class.gw [new file with mode: 0644]
tests/spread/spread_outside_func.gw [new file with mode: 0644]
tests/tree/array_empty.gw
tests/tree/class_dot.gw
tests/tree/class_multi_decl.gw [deleted file]
tests/tree/cpy_ast.gw
tests/tree/empty_vararg.gw [deleted file]
tests/tree/fptr_other_class.gw [deleted file]
tests/tree/multi_decl.gw [deleted file]
tests/tree/vararg_empty.gw [deleted file]
tests/tree/variadic_offset.gw [deleted file]
tests/tree/varobject_assign.gw [deleted file]
util

index 8d979e21cc14c9fadb122492eb1bab32c7fa9b16..04568835b524833bca858ae4bdeeb1377555635f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,7 @@ test_dir += examples
 src := $(wildcard src/*.c)
 src += $(wildcard src/*/*.c)
 
-CFLAGS += -Iutil/include -Iast/include -Ilibcmdapp/src -D_GNU_SOURCE
+CFLAGS += -Iutil/include -Iutil/libtermcolor/include -Iast/include -Ilibcmdapp/src -D_GNU_SOURCE
 CFLAGS += -Iast/libprettyerr/src -Ifmt/include
 
 # add commit hash to version for now
@@ -101,7 +101,7 @@ ast/libgwion_ast.a: util/libgwion_util.a
        @+ ${MAKE} -s -C ast
 
 libcmdapp/libcmdapp.a:
-       @+${MAKE} -s -C libcmdapp static
+       @+CFLAGS=-I$(shell pwd)/util/libtermcolor/include ${MAKE} -s -C libcmdapp static
 
 fmt/libgwion-fmt.a:
        @+${MAKE} -s -C fmt libgwion-fmt.a
diff --git a/ast b/ast
index dc4e477f0be36712aebefe9ed3c0f06fcffd80d1..b4c4887fbcc669621e9138e924342981282ca1f7 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit dc4e477f0be36712aebefe9ed3c0f06fcffd80d1
+Subproject commit b4c4887fbcc669621e9138e924342981282ca1f7
index 11cafee691f21274dbedc69eccbdd5284767e75d..d41180a7e96e63e2468de487f3637310882f93b7 100644 (file)
@@ -1,13 +1,13 @@
 [1,2,3,4];
 [ [1,2,3,4], [1,2,3,4] ];
 <<< [1,2,3,4] >>>;
-var int i[];
-var int j[3];
-var Object o[2];
-var Object p[2][3];
-var Object r[2][3][4];
-var Object s[2][3][4][5];
-var Object t[2][12][3][4][5];
+var int[] i;
+var int[3] j;
+var Object[2] o;
+var Object[2][3] p;
+var Object[2][3][4] r;
+var Object[2][3][4][5] s;
+var Object[2][12][3][4][5] t;
 [1,2,3,4] => i;
 var int k[1][1];
 
index 237f96ef9cefc7faa11be0dc26e8a216a8f53869..a12f6f3ea9a85f509d36d7b3a21cc2aeee53898f 100644 (file)
@@ -10,7 +10,8 @@ operator float  => (float   f, C d){ <<< "float   => C: ", f     => d.f >>>; ret
 operator float =>  (C d, int     c){ <<< "int   => C: ", c => d.f >>>; return 2.0;}
 operator float =>  (C d,  float   f){ <<< "C   => float: ", f     => d.f >>>; return 2.0;}
 
-var C c, d;
+var C c;
+var C d;
 
 12.3 => c.f;
 <<<  c                     => d  >>>;
diff --git a/examples/template_vararg.gw b/examples/template_vararg.gw
deleted file mode 100644 (file)
index a8d5ceb..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-fun void test:[A](...) {
-  varloop vararg {
-    <<< vararg $ int >>>;
-  }
-}
-test:[int](1, 2);
-test:[float](1, 2, 3);
diff --git a/examples/vararg.gw b/examples/vararg.gw
deleted file mode 100644 (file)
index 6b8603f..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-fun void test(...) {
-  var int i;
-  varloop vararg {
-       if(i == 0)
-               <<< vararg $ int >>>;
-       else if(i == 1)
-               <<< vararg $ float >>>;
-       else if(i == 2)
-               <<< vararg $ Object >>>;
-         i++;
-  }
-}
-test(1);
-test(1, 2.3, new Object);
diff --git a/fmt b/fmt
index 53b717147dd54f34915dc27ff15660084b7963bf..e206236cb8890dfca9492a7c21ff35f8561a8611 160000 (submodule)
--- a/fmt
+++ b/fmt
@@ -1 +1 @@
-Subproject commit 53b717147dd54f34915dc27ff15660084b7963bf
+Subproject commit e206236cb8890dfca9492a7c21ff35f8561a8611
index ce0c2b1b8708d2982d6cb32bc27c4192c27a33ad..d2d5ff56e3f8ee833e17e798ad78c25d7f17bd1f 100644 (file)
@@ -19,12 +19,12 @@ provide-module -override gwion %{
                        default late if else
                        break continue return while do
                        until repeat for foreach match
-                       where when case varloop
+                       where when case
                        defer try perform handle retry
                        fun function typedef distinct funptr
                        new spork fork locale'
 
-               attributes='const var static private public protect variadic template samp ms second minute delay'
+               attributes='const var static private public protect template samp ms second minute delay'
                types='auto int float bool dur time void Object Shred Event'
                values='true false none this now me adc dac maybe'
                builtins='__file__ __line__ __func__'
index c5647836ece6a375e1032b5719a4f81a82c73cae..0c584f63ace2e29be34a978f14a7d0910a3a86bb 100644 (file)
@@ -16,8 +16,7 @@ ANN static void clean_tmpl(Clean *a, Tmpl *b);
 ANN static void clean_range(Clean *a, Range *b);
 ANN static void clean_type_decl(Clean *a, Type_Decl *b);
 ANN static void clean_prim(Clean *a, Exp_Primary *b);
-ANN static void clean_var_decl(Clean *a, Var_Decl b);
-ANN static void clean_var_decl_list(Clean *a, Var_Decl_List b);
+ANN static void clean_var_decl(Clean *a, Var_Decl *b);
 ANN static void clean_exp_decl(Clean *a, Exp_Decl *b);
 ANN static void clean_exp_binary(Clean *a, Exp_Binary *b);
 ANN static void clean_exp_unary(Clean *a, Exp_Unary *b);
@@ -36,7 +35,6 @@ ANN static void clean_stmt_each(Clean *a, Stmt_Each b);
 ANN static void clean_stmt_loop(Clean *a, Stmt_Loop b);
 ANN static void clean_stmt_if(Clean *a, Stmt_If b);
 ANN static void clean_stmt_code(Clean *a, Stmt_Code b);
-ANN static void clean_stmt_varloop(Clean *a, Stmt_VarLoop b);
 ANN static void clean_stmt_return(Clean *a, Stmt_Exp b);
 ANN static void clean_case_list(Clean *a, Stmt_List b);
 ANN static void clean_stmt_match(Clean *a, Stmt_Match b);
index a5928716511035aea4a8d22d0e7e19c71d01a8c0..239ca6de39e3b065f0f97585fa7bda588d0ba523 100644 (file)
@@ -40,12 +40,16 @@ struct EmitterInfo_ {
   char *         escape;
   VM_Code (*emit_code)(const Emitter);
   VM_Code  code;
-  uint16_t unroll;
-  uint16_t line;
   bool     debug;
   bool     dump;
 };
 
+typedef struct EmitterStatus {
+  uint16_t             this_offset;   // reset
+  uint16_t unroll;
+  uint16_t line;
+} EmitterStatus;
+
 struct Emitter_ {
   Env                  env;
   Code *               code;
@@ -53,8 +57,7 @@ struct Emitter_ {
   struct EmitterInfo_ *info;
   struct Vector_       stack;
   Func                 locale;
-  uint16_t             this_offset;   // reset
-  uint16_t             vararg_offset; // reset
+  EmitterStatus status;
 };
 
 ANEW ANN Emitter new_emitter(MemPool);
@@ -109,7 +112,7 @@ ANN Instr emit_dotmember(Emitter, const m_uint, const bool);
 ANN Instr emit_structmember(Emitter, const m_uint, const bool);
 ANN Instr emit_unionmember(Emitter, const m_uint, const bool);
 
-void emit_fast_except(const Emitter emit, const struct ValueFrom_ *vf, const loc_t loc);
+void emit_fast_except(const Emitter emit, const ValueFrom *vf, const loc_t loc);
 ANN static inline m_uint emit_code_size(const Emitter emit) {
   return vector_size(&emit->code->instr);
 }
index af191283bdc685a894064476b57038354c3cc1d6..0b5e3ea8170e929e756e06997d4905436c126362 100644 (file)
@@ -5,6 +5,7 @@ struct Context_ {
   Nspc     nspc;
   m_str    name;
   Ast      tree;
+  Ast      extend;
   uint16_t ref;
   uint16_t weight;
   bool     error;
@@ -16,7 +17,7 @@ ANN2(1, 3) ANEW Context new_context(MemPool p, const Ast, const m_str);
 ANN void load_context(const Context, const Env);
 ANN void unload_context(const Context, const Env);
 
-ANN static inline void env_set_error(const Env env) {
-  if(env->context) env->context->error = true;
+ANN static inline void env_set_error(const Env env, const bool state) {
+  if(env->context) env->context->error = state;
 }
 #endif
index db728f35f65c5f857c55b66b2b332ff25a16b2a2..3316d7897859556bc6178f2e78cab560c1113652 100644 (file)
@@ -8,6 +8,7 @@ enum fflag {
   fflag_tmpl   = 1 << 3,
   fflag_valid  = 1 << 4,
   fflag_emit   = 1 << 5,
+  fflag_fptr   = 1 << 6,
 } __attribute__((packed));
 
 struct Func_ {
@@ -20,7 +21,7 @@ struct Func_ {
   uint16_t         weight;  // used to mark gack use in scan1
   uint16_t         memoize; // used to mark return in scan1
   uint16_t         ref;
-  uint16_t         vt_index;
+//  uint16_t         vt_index;
   ae_flag          flag;
   enum fflag       fflag;
 };
index 7a1fea48e3cc49857d9af7aa6f9a132b57c21703..e9c8307b28409a76f3ebb2365317a754e70f3598 100644 (file)
@@ -2,11 +2,11 @@
 #define __TRAIT
 
 typedef struct Trait_ {
-  struct Vector_ requested_values;
-  struct Vector_ requested_funcs;
-  m_str          name;
-  m_str          filename;
-  loc_t          loc;
+  MP_Vector *var;
+  MP_Vector *fun;
+  m_str      name;
+  m_str      filename;
+  loc_t      loc;
 } * Trait;
 
 ANN Trait new_trait(MemPool, const loc_t);
index 33d05a0e5c904d5f18c53e4453b93fefaee86424..821fa1838fc0546b1ce6af2f622220641cb31799 100644 (file)
@@ -66,7 +66,6 @@ ANN m_bool    isa(const Type, const Type) __attribute__((pure));
 ANN m_bool    isres(const Env, const Symbol, const loc_t pos);
 ANN Type      array_type(const Env, const Type, const m_uint);
 ANN Type      find_common_anc(const Type, const Type) __attribute__((pure));
-ANN Type      typedef_base(Type) __attribute__((pure));
 ANN Type      array_base(Type) __attribute__((pure));
 ANN Symbol array_sym(const Env env, const Type src,
                                  const m_uint depth);
@@ -79,7 +78,6 @@ ANN static inline m_uint env_push_type(const Env env, const Type type) {
   return env_push(env, type, type->nspc);
 }
 ANN bool is_func(const struct Gwion_ *, const Type t);
-ANN bool is_fptr(const struct Gwion_ *, const Type t);
 ANN bool is_class(const struct Gwion_ *, const Type t);
 ANN __attribute__((returns_nonnull)) static inline Type _class_base(Type t) {
   return t->info->base_type;
@@ -89,9 +87,18 @@ ANN void   inherit(const Type);
 ANN bool type_global(const Env env, Type t);
 ANN bool from_global_nspc(const Env env, const Nspc nspc);
 
+ANN static inline Type typedef_base(Type t) {
+  while (tflag(t, tflag_typedef)) t = t->info->parent;
+  return t;
+}
+
+ANN static inline Func_Def closure_def(Type t) {
+  t = typedef_base(t);
+  return mp_vector_at(t->info->cdef->body, Section, 0)->d.func_def;
+}
+
 __attribute__((returns_nonnull)) ANN static inline Type get_gack(Type t) {
-  do
-    if (t->info->gack) return t;
+  do if (t->info->gack) return t;
   while ((t = t->info->parent));
   return t; // unreachable
 }
@@ -135,9 +142,7 @@ typedef enum {
   et_array,
   et_gack,
   et_function,
-  et_fptr,
-  et_vararg,
-  et_lambda,
+  et_closure,
   et_op,
   et_class,
   et_union,
index 67d269425d6662fd96bd33ff0f67d67a638e7f47..44d93db2c3b44d512fa36f9e3a04eff5f8457107 100644 (file)
@@ -1,13 +1,13 @@
 #ifndef __VALUE
 #define __VALUE
-struct ValueFrom_ {
+typedef struct ValueFrom_ {
   Nspc             owner;
   Type             owner_class;
   struct Context_ *ctx;
   size_t           offset;
   m_str            filename;
   loc_t            loc;
-};
+} ValueFrom;
 
 enum vflag {
   vflag_none     = 1 << 0,
@@ -35,7 +35,7 @@ union value_data {
 struct Value_ {
   Type               type;
   m_str              name;
-  struct ValueFrom_ *from;
+  ValueFrom *from;
   union value_data   d;
   uint16_t           ref;
   ae_flag            flag;
@@ -46,7 +46,7 @@ REF_FUNC(Value, value)
 FLAG_FUNC(Value, v)
 
 ANEW ANN Value new_value(const Env, const Type type, const m_str name, const loc_t loc);
-ANN void       valuefrom(const Env, struct ValueFrom_ *);
+ANN void       valuefrom(const Env, ValueFrom *);
 
 ANN static inline void defined_here(const Value v) {
   if (v->from->filename) // TODO: check why is that from check
index 91868de635ededec50a9a838702635f6e4728f7e..35383c818ce61af736d712dc1b2e205dee2fbb1a 100644 (file)
@@ -33,7 +33,7 @@ struct Gwi_ {
 
 #include "import/internals.h"
 static inline Tmpl *gwi_tmpl(const Gwi gwi) {
-  return new_tmpl_base(gwi->gwion->mp, gwi->ck->sl);
+  return new_tmpl(gwi->gwion->mp, gwi->ck->sl);
 }
 
 ANN void   gwi_effects(const Gwi gwi, const m_str name);
index f11b0be86ba6551d9015d78f8da6d53ab96ca6a7..88a7f15bc038494e39bf14520e65ce4c6bc02caf 100644 (file)
@@ -30,6 +30,5 @@
 #include "template.h"
 #include "traverse.h"
 #include "ugen.h"
-#include "vararg.h"
 #include "vm.h"
 #endif
index 7048955821678233453789cb5d49970f78bae8d5..00fc4804a7922bb8039f804e181acecfaee9f357 100644 (file)
 #include "env/tuple.h"
 #include "env/envset.h"
 
+ANN2(1,4) static inline void gwerr_basic_from(const m_str msg, const m_str explain,
+                                              const m_str fix, const ValueFrom *from,
+                                              const uint code) {
+  gwerr_basic(msg, explain, fix, from->filename, from->loc, code);
+}
+ANN static inline void gwerr_secondary_from(const m_str msg, const ValueFrom *from) {
+  gwerr_secondary(msg, from->filename, from->loc);
+}
 #endif
index 480447498b72175f1a236d2b44d232733cd8e643..fbe4b50f80e3f68329fe5217441494fee4c9ab88 100644 (file)
@@ -25,7 +25,6 @@ typedef struct ImportCK { // name_checker ?
     Type_Decl *td;   // typedef
     ID_List    curr; // enum
   };
-  bool               variadic;
   enum importck_type type;
   ae_flag            flag; // ????
 } ImportCK;
@@ -45,7 +44,7 @@ ANN m_bool check_typename_def(const Gwi gwi, struct ImportCK *ck);
 
 ANN Symbol        str2sym(const Gwion, const m_str, const loc_t);
 ANN ID_List       str2symlist(const Gwion, const m_str, const loc_t);
-ANN m_bool str2var(const Gwion, Var_Decl, const m_str, const loc_t);
+ANN m_bool str2var(const Gwion, Var_Decl*, const m_str, const loc_t);
 ANN Type_Decl *str2td(const Gwion, const m_str, const loc_t);
 ANN Type       str2type(const Gwion, const m_str, const loc_t);
 
index 2b9b53924b7f3d51f3601c79c4cd52c594bc5c29..2b42da0c28ad453d361971257ee62f049a99ce7d 100644 (file)
@@ -38,10 +38,6 @@ struct Instr_ {
 ANN void free_instr(const Gwion, const Instr);
 INSTR(EOC);
 INSTR(DTOR_EOC);
-INSTR(DtorReturn);
-
-INSTR(ComplexReal);
-INSTR(ComplexImag);
 
 struct FastExceptInfo {
   m_str file;
@@ -51,8 +47,6 @@ struct FastExceptInfo {
 };
 
 INSTR(fast_except);
-/* function */
-INSTR(DtorReturn);
 
 /* array */
 INSTR(ArrayBottom);
@@ -61,30 +55,18 @@ INSTR(ArrayInit);
 INSTR(ArrayAlloc);
 INSTR(ArrayStruct);
 
-/* vararg */
-INSTR(VarargIni);
-
 INSTR(DotTmpl);
 INSTR(GTmpl);
 
 struct dottmpl_ {
-  size_t    len;
   m_str     name;
   Func_Def  base, def;
-  Type      owner_class;
-  Nspc      owner;
   Type_List tl;
-  void *    xfun; // (type is f_xfun)
 };
-ANN void   free_dottmpl(struct dottmpl_ *);
-ANN m_bool traverse_dot_tmpl(const Emitter emit, const struct dottmpl_ *dt);
+ANN m_bool traverse_dot_tmpl(const Emitter emit, const Func_Def fdef, const Value v);
 
 INSTR(SetFunc);
 INSTR(SetCtor);
-// optimizations
-#ifdef OPTIMIZE
-INSTR(PutArgsInMem);
-#endif
 #include "opcode.h"
 
 INSTR(dict_ctor_alt);
index 61ea2602955259d6c50224c05e5fb4a260c650c7..4e8441d71267853197e748866e734274a6eb89e9 100644 (file)
@@ -3,14 +3,14 @@
 ANN m_bool import_class(const Gwi gwi);
 ANN m_bool import_prim(const Gwi gwi);
 ANN m_bool import_object(const Gwi gwi);
-ANN m_bool import_vararg(const Gwi gwi);
+ANN m_bool import_func(const Gwi gwi);
 ANN m_bool import_string(const Gwi gwi);
 ANN m_bool import_shred(const Gwi gwi);
 ANN m_bool import_event(const Gwi gwi);
 ANN m_bool import_ugen(const Gwi gwi);
 ANN m_bool import_array(const Gwi gwi);
 ANN m_bool import_ptr(const Gwi gwi);
-ANN m_bool import_func(const Gwi gwi);
+ANN m_bool import_xork(const Gwi gwi);
 ANN m_bool import_modules(const Gwi gwi);
 ANN m_bool import_object_op(const Gwi gwi);
 ANN m_bool import_values(const Gwi gwi);
index 5f3b012df9c466585760491c45af66d3eb51c3d7..4c38c0d6b1576b4945a88a21cc68a072f11edbf8 100644 (file)
@@ -92,10 +92,8 @@ ANN static inline void operator_resume(struct Op_Import *opi) {
 }
 
 ANN static inline void set_decl_ref(const Exp e) {
-  if (e->exp_type == ae_exp_decl) {
-    Var_Decl vd = mp_vector_at(e->d.exp_decl.list, struct Var_Decl_, 0);
-    SET_FLAG(vd->value, late);
-  }
+  if (e->exp_type == ae_exp_decl)
+    SET_FLAG(e->d.exp_decl.vd.value, late);
 }
 
 ANN void func_operator(const Func_Def fdef, struct Op_Import *opi);
diff --git a/include/spread.h b/include/spread.h
new file mode 100644 (file)
index 0000000..cf1d45c
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __SPREAD
+#define __SPREAD
+
+ANN static inline bool is_spread_tmpl(const Tmpl *tmpl) {
+  const Specialized *spec = mp_vector_at(tmpl->list, Specialized, tmpl->list->len - 1);
+  return !strcmp(s_name(spec->xid), "...");
+}
+
+ANN m_bool spread_ast(const Env env, const Spread_Def spread, const Tmpl *tmpl);
+ANN Stmt_List spread_func(const Env env, const Stmt_List body);
+
+#endif
index 18447fc7dda5c23bd4631e890ec6815350e6c7ea..176dc24cf011c83cbba747565cda5da1f9bd22fb 100644 (file)
@@ -18,6 +18,7 @@ ANN m_bool scan1_exp(const Env, const Exp);
 ANN m_bool scan2_exp(const Env, const Exp);
 ANN Type   check_exp(const Env, const Exp);
 
+ANN m_bool scan0_func_def(const Env, const Func_Def);
 ANN m_bool scan1_func_def(const Env, const Func_Def);
 ANN m_bool scan2_func_def(const Env, const Func_Def);
 ANN m_bool check_func_def(const Env, const Func_Def);
@@ -25,7 +26,7 @@ ANN m_bool check_func_def(const Env, const Func_Def);
 ANN m_bool scan0_fptr_def(const Env, const Fptr_Def);
 ANN m_bool scan1_fptr_def(const Env, const Fptr_Def);
 ANN m_bool scan2_fptr_def(const Env, const Fptr_Def);
-// ANN m_bool check_fptr_def(const Env, const Fptr);
+ANN m_bool check_fptr_def(const Env, const Fptr_Def);
 
 ANN m_bool scan0_union_def(const Env, const Union_Def);
 ANN m_bool scan1_union_def(const Env, const Union_Def);
diff --git a/include/vararg.h b/include/vararg.h
deleted file mode 100644 (file)
index bf3aac3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __VARARG
-#define __VARARG
-struct Vararg_ {
-  struct Vector_      t; // types
-  m_bit *             d; // d(ata)
-  m_uint /*o, i, s,*/ l; // o(ffset), i(ndex), s(ize), l(en)
-  m_uint              pc;
-};
-ANN void emit_vararg_end(const Emitter emit, const m_uint pc);
-void     free_vararg(MemPool p, struct Vararg_ *arg);
-#endif
index ac63edc2b3d3d0ad262486903cde45a4ed5d9a84..115e5da46cb49dc285b9ca2daae358954c0e2853 160000 (submodule)
--- a/libcmdapp
+++ b/libcmdapp
@@ -1 +1 @@
-Subproject commit ac63edc2b3d3d0ad262486903cde45a4ed5d9a84
+Subproject commit 115e5da46cb49dc285b9ca2daae358954c0e2853
diff --git a/plug b/plug
index 2377a71db5f6a711ee2eedbd074f013863694ec8..ec74718b911d962d274f142fc81c664ac2accf71 160000 (submodule)
--- a/plug
+++ b/plug
@@ -1 +1 @@
-Subproject commit 2377a71db5f6a711ee2eedbd074f013863694ec8
+Subproject commit ec74718b911d962d274f142fc81c664ac2accf71
index 7475da7543e6857d132e5749c91d8de2eb8be785..66c94aa0105847db86dafbc7d4255d553ab9f39a 100644 (file)
@@ -10,8 +10,8 @@ ANN static void clean_array_sub(Clean *a, Array_Sub b) {
   if (b->exp) clean_exp(a, b->exp);
 }
 
-#define clean_id_list(a, b) {}
-#define clean_specialized_list(a, b) {}
+#define clean_id_list(a, b) do {} while(0)
+#define clean_specialized_list(a, b) do {} while(0)
 
 ANN static void clean_type_list(Clean *a, Type_List b) {
   for(uint32_t i = 0; i < b->len; i++) {
@@ -21,8 +21,8 @@ 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_specialized_list(a, b->list);
-  if (b->call) clean_type_list(a, b->call);
+  if (!b->call) clean_specialized_list(a, b->list);
+  else clean_type_list(a, b->call);
 }
 
 ANN static void clean_range(Clean *a, Range *b) {
@@ -46,21 +46,13 @@ ANN static void clean_prim(Clean *a, Exp_Primary *b) {
     clean_range(a, b->d.range);
 }
 
-ANN static void clean_var_decl(Clean *a, Var_Decl b) {
-  if (b->array) clean_array_sub(a, b->array);
+ANN static void clean_var_decl(Clean *a, Var_Decl *b) {
   if (a->scope && b->value && !tflag(b->value->type, tflag_error)) value_remref(b->value, a->gwion);
 }
 
-ANN static void clean_var_decl_list(Clean *a, Var_Decl_List b) {
-  for(uint32_t i = 0; i < b->len; i++) {
-    Var_Decl vd = mp_vector_at(b, struct Var_Decl_, i);
-    clean_var_decl(a, vd);
-  }
-}
-
 ANN static void clean_exp_decl(Clean *a, Exp_Decl *b) {
   if (b->td) clean_type_decl(a, b->td);
-  clean_var_decl_list(a, b->list);
+  clean_var_decl(a, &b->vd);
 }
 
 ANN static void clean_exp_binary(Clean *a, Exp_Binary *b) {
@@ -196,13 +188,6 @@ ANN static void clean_stmt_code(Clean *a, Stmt_Code b) {
   --a->scope;
 }
 
-ANN static void clean_stmt_varloop(Clean *a, Stmt_VarLoop b) {
-  ++a->scope;
-  clean_exp(a, b->exp);
-  clean_stmt(a, b->body);
-  --a->scope;
-}
-
 ANN static void clean_stmt_return(Clean *a, Stmt_Exp b) {
   if (b->val) clean_exp(a, b->val);
 }
@@ -256,6 +241,7 @@ ANN static void clean_dummy(Clean *a NUSED, void *b NUSED) {}
 #define clean_stmt_break    clean_dummy
 #define clean_stmt_continue clean_dummy
 #define clean_stmt_retry    clean_dummy
+#define clean_stmt_spread   clean_dummy
 
 DECL_STMT_FUNC(clean, void, Clean *)
 ANN static void clean_stmt(Clean *a, Stmt b) {
@@ -303,7 +289,6 @@ ANN void func_def_cleaner(const Gwion gwion, Func_Def b) {
 
 ANN static void clean_extend_def(Clean *a, Extend_Def b) {
   clean_type_decl(a, b->td);
-  clean_ast(a, b->body);
 }
 
 ANN static void clean_class_def(Clean *a, Class_Def b) {
@@ -338,7 +323,7 @@ ANN static void clean_union_def(Clean *a, Union_Def b) {
 
 ANN static void clean_fptr_def(Clean *a, Fptr_Def b) {
   clean_func_base(a, b->base);
-  if (b->type) type_remref(b->type, a->gwion);
+//  if (b->type) type_remref(b->type, a->gwion);
 }
 
 ANN static void clean_type_def(Clean *a, Type_Def b) {
@@ -355,7 +340,7 @@ ANN static void clean_trait_def(Clean *a, Trait_Def b) {
   if (b->body) clean_ast(a, b->body);
 }
 
-DECL_SECTION_FUNC(clean, void, Clean *)
+DECL_SECTION_FUNC(clean, void, Clean *);
 
 ANN static inline void clean_section(Clean *a, Section *b) {
   clean_section_func[b->section_type](a, *(void **)&b->d);
index e77094ff0f4f0040b8e9d3e65e4ee2af342bc569..5139e9c8d919691e6f6b8b374b481e67e2e5af50 100644 (file)
@@ -16,7 +16,6 @@
 #include "import.h"
 #include "match.h"
 #include "specialid.h"
-#include "vararg.h"
 #include "looper.h"
 #include "shreduler_private.h"
 
@@ -77,7 +76,7 @@ ANN static void release_maybe_stack(const MemPool mp, MP_Vector * ms) {
     struct M_Vector_ v = { .ptr = mv->ptr };
     m_vector_release(&v);
   }
-  free_mp_vector(mp, sizeof(MaybeVal), ms);
+  free_mp_vector(mp, MaybeVal, ms);
 }
 
 ANN static void free_frame(MemPool p, Frame *a) {
@@ -483,7 +482,7 @@ m_bool emit_instantiate_object(const Emitter emit, const Type type,
                                       is_ref));
     return GW_OK;
   } else if (!is_ref) {
-    if(!tflag(type, tflag_typedef)) {
+    if(!tflag(type, tflag_typedef) || isa(type, emit->gwion->type[et_closure]) > 0) {
       const Instr instr = emit_add_instr(emit, ObjectInstantiate);
       instr->m_val2     = (m_uint)type;
     } // maybe we should instantiate the first actual type
@@ -494,21 +493,8 @@ m_bool emit_instantiate_object(const Emitter emit, const Type type,
 
 ANN2(1, 2)
 m_bool emit_instantiate_decl(const Emitter emit, const Type type,
-                             const Type_Decl *td, const Array_Sub array,
-                             const m_bool is_ref) {
-  Exp base = td->array ? td->array->exp : NULL, exp = base,
-      next = array ? array->exp : NULL;
-  const m_uint depth =
-      (td->array ? td->array->depth : 0) + (array ? array->depth : 0);
-  if (exp) {
-    while (exp->next) exp = exp->next;
-    exp->next = next;
-  } else
-    base = next;
-  struct Array_Sub_ a   = {.exp = base, .depth = depth};
-  const m_bool      ret = emit_instantiate_object(emit, type, &a, is_ref);
-  if (td->array && td->array->exp) exp->next = NULL;
-  return ret;
+                             const Type_Decl *td, const m_bool is_ref) {
+  return emit_instantiate_object(emit, type, td->array, is_ref);
 }
 
 ANN static m_bool emit_symbol_builtin(const Emitter emit, const Symbol *data) {
@@ -541,14 +527,15 @@ ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) {
   }
   if (vflag(v, vflag_builtin) || vflag(v, vflag_direct))
     return emit_symbol_builtin(emit, data);
-  if(is_func(emit->gwion, v->type) && !is_fptr(emit->gwion, v->type)) { // is_func
-    const Func f = v->type->info->func;
+  const Type t = prim_exp(data)->type;
+  if(is_func(emit->gwion, v->type)) {
+    const Func f = t->info->func;
     if(f->code)
       regpushi(emit, (m_uint)f->code);
-    else {
+    else if(!f->def->base->tmpl) {
       const Instr instr = emit_add_instr(emit, SetFunc);
       instr->m_val = (m_uint)f;
-    }
+    } else regpushi(emit, (m_uint)f);
     return GW_OK;
   }
   if (tflag(v->type, tflag_ref) && !safe_tflag(prim_exp(data)->cast_to, tflag_ref)) {
@@ -571,8 +558,7 @@ ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) {
            : emit_regpushbase(emit, size, exp_getvar(prim_exp(data)));
   instr->m_val = v->from->offset;
   if (GET_FLAG(v, late) && !exp_getvar(prim_exp(data)) &&
-      (isa(v->type, emit->gwion->type[et_object]) > 0 ||
-       is_fptr(emit->gwion, v->type)))
+      isa(v->type, emit->gwion->type[et_object]) > 0)
     emit_fast_except(emit, v->from, prim_pos(data));
   return GW_OK;
 }
@@ -835,17 +821,6 @@ ANN static m_bool emit_prim_str(const Emitter emit, const struct AstString *str)
 
 #define emit_prim_nil (void *)dummy_func
 
-ANN static void interp_multi(const Emitter emit, const Exp e) {
-  const bool    emit_var = exp_getvar(e);
-  m_uint        offset   = 0;
-  Var_Decl_List list     = e->d.exp_decl.list;
-  for(uint32_t i = 1; i < list->len; i++) {
-    Var_Decl vd = mp_vector_at(list, struct Var_Decl_, i);
-    offset += !emit_var ? vd->value->type->size : SZ_INT;
-  }
-  if (offset) regpop(emit, offset);
-}
-
 ANN static inline void interp_size(const Emitter emit, const Exp e) {
   const Type t = !tflag(e->type, tflag_ref) || safe_tflag(e->cast_to, tflag_ref) ?
     e->type : (Type)vector_front(&e->type->info->tuple->contains);
@@ -863,8 +838,6 @@ ANN /*static*/ m_bool emit_interp(const Emitter emit, const Exp exp) {
       e->next = next;
       return GW_ERROR;
     }
-    if (e->exp_type == ae_exp_decl) // why only objects?
-      interp_multi(emit, e);
     if(tflag(e->type, tflag_ref) && !safe_tflag(e->cast_to, tflag_ref)) {
       const Type t = (Type)vector_front(&e->type->info->tuple->contains);
       regseti(emit, (m_uint)t);
@@ -902,7 +875,7 @@ ANN static m_bool emit_prim_interp(const Emitter emit, const Exp *exp) {
 }
 
 ANN static m_bool emit_ensure_func(const Emitter emit, const Func f) {
-  const struct ValueFrom_ *from = f->value_ref->from;
+  const ValueFrom *from = f->value_ref->from;
   if(from->owner_class)
     CHECK_BB(ensure_emit(emit, from->owner_class));
   if(f->code) return GW_OK;
@@ -954,10 +927,9 @@ ANN static m_bool emit_dot_static_data(const Emitter emit, const Value v,
 }
 
 ANN static m_bool _decl_static(const Emitter emit, const Exp_Decl *decl,
-                              const Var_Decl var_decl, const uint is_ref) {
+                              const Var_Decl *var_decl, const uint is_ref) {
   const Value v    = var_decl->value;
-  CHECK_BB(
-      emit_instantiate_decl(emit, v->type, decl->td, var_decl->array, is_ref));
+  CHECK_BB(emit_instantiate_decl(emit, v->type, decl->td, is_ref));
   CHECK_BB(emit_dot_static_data(emit, v, 1));
   emit_add_instr(emit, Assign);
 //  if(get_depth(var_decl->value->type) && !is_ref)
@@ -967,7 +939,7 @@ ANN static m_bool _decl_static(const Emitter emit, const Exp_Decl *decl,
 }
 
 ANN static m_bool decl_static(const Emitter emit, const Exp_Decl *decl,
-                              const Var_Decl var_decl, const uint is_ref) {
+                              const Var_Decl *var_decl, const uint is_ref) {
   Code *const code = emit->code;
   emit->code       = (Code *)vector_back(&emit->stack);
   const m_bool ret = _decl_static(emit, decl, var_decl, is_ref);
@@ -993,7 +965,7 @@ ANN static void emit_struct_decl_finish(const Emitter emit, const Type t,
 }
 
 ANN static m_bool emit_exp_decl_static(const Emitter emit, const Exp_Decl *decl,
-                                       const Var_Decl var_decl,
+                                       const Var_Decl *var_decl,
                                        const bool     is_ref,
                                        const bool     emit_addr) {
   const Value v = var_decl->value;
@@ -1043,18 +1015,16 @@ ANN static m_uint decl_non_static_offset(const Emitter emit, const Exp_Decl *dec
 
 ANN static m_bool emit_exp_decl_non_static(const Emitter   emit,
                                            const Exp_Decl *decl,
-                                           const Var_Decl var_decl,
+                                           const Var_Decl *var_decl,
                                            const uint      is_ref,
                                            const uint      emit_var) {
   const Value     v        = var_decl->value;
   const Type      type     = v->type;
-  const Array_Sub array    = var_decl->array;
-  const bool      is_array = array && array->exp;
   const bool      is_obj   = isa(type, emit->gwion->type[et_object]) > 0;
-  const bool emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : true;
-  if (is_obj && (is_array || !is_ref) && !exp_self(decl)->ref)
+  const bool emit_addr = (!is_obj || is_ref) ? emit_var : true;
+  if (is_obj && !is_ref && !exp_self(decl)->ref)
 //  if (is_obj && ((is_array && !exp_self(decl)->ref) || !is_ref))
-    CHECK_BB(emit_instantiate_decl(emit, type, decl->td, array, is_ref));
+    CHECK_BB(emit_instantiate_decl(emit, type, decl->td, is_ref));
   f_instr *exec = (f_instr *)allocmember;
   if (!emit->env->scope->depth) emit_debug(emit, v);
   if (!vflag(v, vflag_member)) {
@@ -1072,7 +1042,7 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter   emit,
                       exec)
           : emit_struct_decl(emit, v, !struct_ctor(v) ? emit_addr : 1);
   instr->m_val = v->from->offset;
-  if (is_obj && (is_array || !is_ref) && !exp_self(decl)->ref) {
+  if (is_obj && !is_ref && !exp_self(decl)->ref) {
     if (!emit_var)
       emit_add_instr(emit, Assign);
     else {
@@ -1080,24 +1050,22 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter   emit,
       const Instr instr = emit_add_instr(emit, Reg2Reg);
       instr->m_val      = -SZ_INT;
     }
-//    if(safe_tflag(emit->env->class_def, tflag_struct) && GET_FLAG(emit->env->class_def, global))
-//      emit_object_addref(emit, 0, emit_addr);
+    if(safe_tflag(emit->env->class_def, tflag_struct) && GET_FLAG(emit->env->class_def, global))
+      emit_object_addref(emit, 0, emit_addr);
   } else if (struct_ctor(v))
     emit_struct_decl_finish(emit, v->type, emit_addr);
   return GW_OK;
 }
 
 ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl,
-                                       const Var_Decl var_decl,
+                                       const Var_Decl *var_decl,
                                        const uint is_ref, const bool emit_var) {
   const Value     v        = var_decl->value;
   const Type      type     = v->type;
-  const Array_Sub array    = var_decl->array;
-  const bool      is_array = array && array->exp;
   const bool      is_obj   = isa(type, emit->gwion->type[et_object]) > 0;
-  const bool emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : true;
-  if (is_obj && (is_array || !is_ref))
-    CHECK_BB(emit_instantiate_decl(emit, type, decl->td, array, is_ref));
+  const bool emit_addr = (!is_obj || is_ref) ? emit_var : true;
+  if (is_obj && !is_ref)
+    CHECK_BB(emit_instantiate_decl(emit, type, decl->td, is_ref));
   const Instr instr =
       emit_dotstatic(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1);
   if (type->size > SZ_INT) //{
@@ -1105,7 +1073,7 @@ ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl,
   instr->m_val = (m_uint)&v->d.ptr;
   set_vflag(v, vflag_direct); // mpalloc
   instr->m_val2 = v->type->size;
-  if (is_obj && (is_array || !is_ref)) {
+  if (is_obj && !is_ref) {
     const Instr assign = emit_add_instr(emit, Assign);
     assign->m_val      = emit_var;
     (void)emit_object_addref(emit, -SZ_INT, emit_var);
@@ -1116,62 +1084,50 @@ ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl,
   return GW_OK;
 }
 
-ANN static void set_late(const Gwion gwion, const Exp_Decl *decl,
-                         const Var_Decl var) {
+ANN static void set_late(const Exp_Decl *decl, const Var_Decl *var) {
   const Value v         = var->value;
-  const uint  array_ref = (decl->td->array && !decl->td->array->exp) ||
-                         (var->array && !var->array->exp);
   if (!exp_getvar(exp_self(decl)) &&
-      (GET_FLAG(array_base_simple(v->type), abstract) || GET_FLAG(decl->td, late) ||
-       is_fptr(gwion, v->type) || array_ref)) {
+      (GET_FLAG(array_base_simple(v->type), abstract) || GET_FLAG(decl->td, late)))
     SET_FLAG(v, late);
-  } else
-    UNSET_FLAG(v, late);
+  else UNSET_FLAG(v, late);
 }
 
-static inline bool _late_array(const Array_Sub array) {
-  return !array || !array->exp;
+static inline bool late_array(const Type_Decl* td) {
+  return !td->array || !td->array->exp;
 }
 
-ANN static inline bool late_array(const Type_Decl *td, const Var_Decl var) {
-  return _late_array(td->array) || _late_array(var->array);
-}
-
-ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl *decl) {
+ANN static m_bool emit_decl(const Emitter emit, Exp_Decl *const decl) {
   const m_bool  global = GET_FLAG(decl->td, global);
   const uint    var    = exp_getvar(exp_self(decl));
   const uint    ref    = GET_FLAG(decl->td, late) || type_ref(decl->type);
-  Var_Decl_List list   = decl->list;
-  for(uint32_t i = 0; i < list->len; i++) {
-    Var_Decl vd = mp_vector_at(list, struct Var_Decl_, i);
-    const Value v = vd->value;
-    const uint  r = ref || GET_FLAG(v, late);
-    if (GET_FLAG(decl->td, static))
-      CHECK_BB(emit_exp_decl_static(emit, decl, vd, r, var));
-    else if (!global)
-      CHECK_BB(emit_exp_decl_non_static(emit, decl, vd, r, var));
-    else
-      CHECK_BB(emit_exp_decl_global(emit, decl, vd, r, var));
-    if (tflag(v->type, tflag_contract) &&
-        !exp_getvar(exp_self(decl))) {
-      const Type       t   = v->type;
-      struct Op_Import opi = {.lhs = t->info->base_type,
-                              .op  = insert_symbol("@implicit"),
-                              .rhs = t};
-      CHECK_BB(op_emit(emit, &opi));
-    }
-    set_late(emit->gwion, decl, vd);
-    if (!exp_self(decl)->emit_var && GET_FLAG(array_base_simple(v->type), abstract) && !GET_FLAG(decl->td, late) &&
-        GET_FLAG(v, late) && late_array(decl->td, vd)
-        && GET_FLAG(v->type, abstract)) {
-      env_warn(emit->env, decl->td->pos, _("Type '%s' is abstract, use {+G}late{0} instead of {G+}%s{0}"),
-               v->type->name, !GET_FLAG(decl->td, const) ? "var" : "const");
-    }
+  Var_Decl *vd = &decl->vd;
+  const Value v = vd->value;
+  const uint  r = ref || GET_FLAG(v, late);
+  if (GET_FLAG(decl->td, static))
+    CHECK_BB(emit_exp_decl_static(emit, decl, vd, r, var));
+  else if (!global)
+    CHECK_BB(emit_exp_decl_non_static(emit, decl, vd, r, var));
+  else
+    CHECK_BB(emit_exp_decl_global(emit, decl, vd, r, var));
+  if (tflag(v->type, tflag_contract) &&
+      !exp_getvar(exp_self(decl))) {
+    const Type       t   = v->type;
+    struct Op_Import opi = {.lhs = t->info->base_type,
+                            .op  = insert_symbol("@implicit"),
+                            .rhs = t};
+    CHECK_BB(op_emit(emit, &opi));
+  }
+  set_late(decl, vd);
+  if (!exp_self(decl)->emit_var && GET_FLAG(array_base_simple(v->type), abstract) && !GET_FLAG(decl->td, late) &&
+      GET_FLAG(v, late) && late_array(decl->td)
+      && GET_FLAG(v->type, abstract)) {
+    env_warn(emit->env, decl->td->pos, _("Type '%s' is abstract, use {+G}late{0} instead of {G+}%s{0}"),
+             v->type->name, !GET_FLAG(decl->td, const) ? "var" : "const");
   }
   return GW_OK;
 }
 
-ANN /*static */ m_bool emit_exp_decl(const Emitter emit, const Exp_Decl *decl) {
+ANN /*static */ m_bool emit_exp_decl(const Emitter emit, Exp_Decl *const decl) {
   const Type t = decl->type;
   CHECK_BB(ensure_emit(emit, t));
   const m_bool global = GET_FLAG(decl->td, global);
@@ -1190,38 +1146,8 @@ Exp nth_exp(Exp e, uint32_t n) {
   return e;
 }
 
-ANN static m_uint vararg_size(const Gwion gwion, const Exp_Call *exp_call,
-                              const Vector kinds) {
-  const Type t    = actual_type(gwion, exp_call->func->type);
-  Arg_List   l    = t->info->func->def->base->args;
-  Exp        e    = l ? nth_exp(exp_call->args, l->len) : exp_call->args;
-//  Exp        e    = l ? take_exp(exp_call->args, l->len - 1) : exp_call->args;
-  m_uint     size = 0;
-  while (e) {
-    size += e->type->size;
-    vector_add(kinds, (vtype)e->type); // ->size
-    e = e->next;
-  }
-  return size;
-}
-
-ANN static void emit_func_arg_vararg(const Emitter   emit,
-                                     const Exp_Call *exp_call) {
-  const Instr  instr = emit_add_instr(emit, VarargIni);
-  struct Vector_ kinds;
-  vector_init(&kinds);
-  if ((instr->m_val = vararg_size(emit->gwion, exp_call, &kinds)))
-    instr->m_val2 = (m_uint)kinds.ptr;
-  else
-    vector_release(&kinds);
-}
-
 ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call *exp_call) {
   if (exp_call->args) CHECK_BB(emit_exp(emit, exp_call->args));
-  const Type t = actual_type(emit->gwion, exp_call->func->type);
-  if (is_func(emit->gwion, t) &&
-      fbflag(t->info->func->def->base, fbflag_variadic)) // is_callable
-    emit_func_arg_vararg(emit, exp_call);
   return GW_OK;
 }
 
@@ -1266,7 +1192,7 @@ ANN static inline bool member_inlinable(const Emitter emit, const Func f, const
 ANN static inline Func is_inlinable(const Emitter   emit,
                                     const Exp_Call *exp_call) {
   const Type ftype = exp_call->func->type;
-  if (!is_func(emit->gwion, ftype) || is_fptr(emit->gwion, ftype) || // is_fptr
+  if (!is_func(emit->gwion, ftype) ||
       !ftype->info->func->code || ftype->info->func->code->builtin)
     return false;
   const Func f = ftype->info->func;
@@ -1278,7 +1204,7 @@ ANN static inline void inline_args_ini(const Emitter emit, const Func f,
                                        const Vector v) {
   const bool member =  f->value_ref->from->owner_class && vflag(f->value_ref, vflag_member);
   if(member)
-    emit->this_offset = emit_local(emit, emit->gwion->type[et_int]);
+    emit->status.this_offset = emit_local(emit, emit->gwion->type[et_int]);
   const m_uint start_offset = emit_code_offset(emit) - (member ? SZ_INT : 0);
   Arg_List args          = f->def->base->args;
   for(uint32_t i = 0; i < args->len; i++) {
@@ -1288,8 +1214,6 @@ ANN static inline void inline_args_ini(const Emitter emit, const Func f,
     value->from->offset = emit_local(emit, value->type);
     nspc_add_value(emit->env->curr, arg->var_decl.xid, value);
   }
-  if (fbflag(f->def->base, fbflag_variadic))
-    emit->vararg_offset = emit_local(emit, emit->gwion->type[et_int]) + SZ_INT;
   regpop(emit, f->code->stack_depth);
   const Instr cpy = emit_add_instr(emit, Reg2Mem4);
   cpy->m_val2     = f->code->stack_depth;
@@ -1338,13 +1262,11 @@ ANN static inline m_bool _emit_inline(const Emitter emit, const Func f,
 
 ANN static inline m_bool emit_inline(const Emitter emit, const Func f,
                                      const Exp_Call *exp_call) {
-  const uint16_t this_offset   = emit->this_offset;
-  const uint16_t vararg_offset = emit->vararg_offset;
+  const EmitterStatus status = emit->status;
   nspc_push_value(emit->gwion->mp, emit->env->curr);
   const m_bool ret = _emit_inline(emit, f, exp_call);
   nspc_pop_value(emit->gwion->mp, emit->env->curr);
-  emit->this_offset   = this_offset;
-  emit->vararg_offset = vararg_offset;
+  emitter->status = status;
   return ret;
 }
 #endif
@@ -1366,7 +1288,7 @@ ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *exp_call) {
   // skip when recursing
   const Type t = actual_type(emit->gwion, exp_call->func->type);
   const Func f = t->info->func;
-  if (is_fptr(emit->gwion, t) || strstr(emit->code->name, "ork~") ||
+  if (strstr(emit->code->name, "ork~") ||
       (f != emit->env->func || (f && f->value_ref->from->owner_class)))
     CHECK_BB(prepare_call(emit, exp_call));
   else
@@ -1405,16 +1327,6 @@ ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call *exp_call) {
   return GW_OK;
 }
 
-ANN static m_uint get_decl_size(Var_Decl_List list, bool emit_addr) {
-  m_uint size = 0;
-  for(uint32_t i = 0; i < list->len; i++) {
-    Var_Decl vd = mp_vector_at(list, struct Var_Decl_, i);
-    // if(GET_FLAG(vd->value, used))
-    size += !emit_addr ? vd->value->type->size : SZ_INT;
-  }
-  return size;
-}
-
 ANN static m_uint get_type_size(const Exp e) {
   if(tflag(e->type, tflag_ref)&& !safe_tflag(e->cast_to, tflag_ref)) {
     const Type base =(Type)vector_front(&e->type->info->tuple->contains);
@@ -1426,13 +1338,8 @@ ANN static m_uint get_type_size(const Exp e) {
 ANN static m_uint pop_exp_size(Exp e) {
   const bool emit_addr = exp_getvar(e);
   m_uint     size      = 0;
-  do {
-    size += (e->exp_type == ae_exp_decl
-                 ? get_decl_size(e->d.exp_decl.list, emit_addr)
-             : !emit_addr ? get_type_size(e)
-//             : !emit_addr ? e->type->size
-                          : SZ_INT);
-  } while ((e = e->next));
+  do size += !emit_addr ? get_type_size(e) : SZ_INT;
+  while ((e = e->next));
   return size;
 }
 
@@ -1443,13 +1350,6 @@ ANN static inline void pop_exp(const Emitter emit, Exp e) {
 
 ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e) {
   CHECK_BB(emit_exp(emit, e));
-  if (e->exp_type == ae_exp_decl) {
-    Var_Decl_List list = e->d.exp_decl.list;
-    for(uint32_t i = 1; i < list->len; i++) {
-      Var_Decl vd = mp_vector_at(list, struct Var_Decl_, i);
-      regpop(emit, !exp_getvar(e) ? vd->value->type->size : SZ_INT);
-    }
-  }
   if (e->next) pop_exp(emit, e->next);
   return GW_OK;
 }
@@ -1494,7 +1394,7 @@ ANN static inline m_bool traverse_emit_func_def(const Emitter  emit,
   return emit_func_def(emit, fdef);
 }
 
-ANN m_bool traverse_dot_tmpl(const Emitter emit, const struct dottmpl_ *dt) {
+ANN m_bool traverse_dot_tmpl(const Emitter emit, const Func_Def fdef, const Value v) {
   const m_uint  scope = emit->env->scope->depth;
   const bool    shadowing = emit->env->scope->shadowing;
   emit->env->scope->shadowing = true;
@@ -1503,16 +1403,28 @@ ANN m_bool traverse_dot_tmpl(const Emitter emit, const struct dottmpl_ *dt) {
                       .func  = (_exp_func)emit_cdef,
                       .scope = scope,
                       .flag  = tflag_emit};
-  CHECK_BB(envset_push(&es, dt->owner_class, dt->owner));
-  (void)emit_push(emit, dt->owner_class, dt->owner);
-  const m_bool ret = traverse_emit_func_def(emit, dt->def);
-  if (es.run) envset_pop(&es, dt->owner_class);
+  CHECK_BB(envset_push(&es, v->from->owner_class, v->from->owner));
+  (void)emit_push(emit, v->from->owner_class, v->from->owner);
+  const m_bool ret = traverse_emit_func_def(emit, fdef);
+  if (es.run) envset_pop(&es, v->from->owner_class);
   emit_pop(emit, scope);
   emit->env->scope->shadowing = shadowing;
-  if(ret > 0) set_fflag(dt->def->base->func, fflag_tmpl);
+  if(ret > 0) set_fflag(fdef->base->func, fflag_tmpl);
   return ret;
 }
 
+static INSTR(fptr_call) {
+  const M_Object o = *(M_Object*)REG(-SZ_INT);
+  *(VM_Code*)REG(-SZ_INT) = *(VM_Code*)(o->data + instr->m_val);
+  const m_bit *caps = *(m_bit**)(o->data + SZ_INT);
+  if(caps) {
+    const Func_Def fdef = *(Func_Def*) caps;
+    const Capture *cap = mp_vector_at(fdef->captures, Capture, fdef->captures->len - 1);
+    const uint32_t sz = cap->offset + cap->temp->type->size - fdef->stack_depth;
+    memcpy(REG(SZ_INT), caps + SZ_INT, sz);
+  }
+}
+
 static inline m_bool push_func_code(const Emitter emit, const Func f) {
   if (!vector_size(&emit->code->instr)) {
     if(fflag(f, fflag_tmpl)) {
@@ -1526,19 +1438,9 @@ static inline m_bool push_func_code(const Emitter emit, const Func f) {
   }
   const Instr instr = (Instr)vector_back(&emit->code->instr);
   if (instr->opcode == eDotTmplVal) {
-    size_t len = strlen(f->name);
-    assert(f->value_ref->from->owner_class);
-    size_t sz = len - strlen(f->value_ref->from->owner_class->name);
-    char   c[sz + 1];
-    memcpy(c, f->name, sz);
-    c[sz]               = '\0';
-    struct dottmpl_ *dt = mp_calloc(emit->gwion->mp, dottmpl);
-    dt->name            = s_name(insert_symbol(c));
-    dt->tl         = cpy_type_list(emit->gwion->mp, f->def->base->tmpl->call);
-    dt->base       = f->def;
     instr->opcode  = eOP_MAX;
-    instr->m_val   = (m_uint)dt;
-    instr->m_val2  = strlen(c);
+    instr->m_val   = (m_uint)f->def;
+    instr->m_val2  = (m_uint)tl2str(emit->gwion, f->def->base->tmpl->call, f->def->base->pos);
     instr->execute = DotTmpl;
     return GW_OK;
   }
@@ -1564,33 +1466,15 @@ ANN static m_bool emit_template_code(const Emitter emit, const Func f) {
 }
 
 ANN static void tmpl_prelude(const Emitter emit, const Func f) {
-  struct dottmpl_ *dt  = (struct dottmpl_ *)mp_calloc(emit->gwion->mp, dottmpl);
-  size_t           len = strlen(f->name);
-  size_t           slen = strlen(f->value_ref->from->owner->name);
-  assert(len > slen);
-  size_t sz = len - slen;
-  char   c[sz + 1];
-  memcpy(c, f->name, sz);
-  c[sz]             = '\0';
-  dt->tl            = cpy_type_list(emit->gwion->mp, f->def->base->tmpl->call);
-  dt->name          = s_name(insert_symbol(c));
-  dt->base          = f->def;
-  dt->owner         = f->value_ref->from->owner;
-  dt->owner_class   = f->value_ref->from->owner_class;
   const Instr gtmpl = emit_add_instr(emit, GTmpl);
-  gtmpl->m_val      = (m_uint)dt;
-  gtmpl->m_val2     = strlen(c);
+  gtmpl->m_val      = (m_uint)f->def;
+  gtmpl->m_val2     = (m_uint)tl2str(emit->gwion, f->def->base->tmpl->call, f->def->base->pos);
 }
 
 ANN static Instr get_prelude(const Emitter emit, const Func f,
                              const bool is_static) {
-  const Type t  = actual_type(emit->gwion, f->value_ref->type);
-  const bool fp = is_fptr(emit->gwion, t);
-  if (is_fptr(emit->gwion, t)) {
-    if (f->def->base->tmpl) tmpl_prelude(emit, f);
-  }
-  if (fp || f != emit->env->func || (!is_static && strcmp(s_name(f->def->base->xid), "new"))||
-      strstr(emit->code->name, "ork~")) {
+  if (f != emit->env->func || (!is_static && strcmp(s_name(f->def->base->xid), "new")) /* ||
+//      strstr(emit->code->name, "ork~")*/) {
     const Instr instr = emit_add_instr(emit, SetCode);
     instr->udata.one  = 1;
     return instr;
@@ -1695,7 +1579,7 @@ ANN static Instr emit_call(const Emitter emit, const Func f,
     ++prelude->m_val2;
   }
   if (f->def->stack_depth - member) {
-    //  if(is_fptr(emit->gwion, t) || f != emit->env->func ||
+    //  f != emit->env->func ||
     //  f->value_ref->from->owner_class || strstr(emit->code->name, "ork~"))
     {
       emit_args(emit, f);
@@ -1705,91 +1589,37 @@ ANN static Instr emit_call(const Emitter emit, const Func f,
   return emit_add_instr(emit, Overflow);
 }
 
-ANN m_bool emit_exp_call1(const Emitter emit, const Func f,
-                          const bool is_static) {
-  const m_uint this_offset   = emit->this_offset;
-  const m_uint vararg_offset = emit->vararg_offset;
-  emit->this_offset          = 0;
-  const int tmpl             = fflag(f, fflag_tmpl);
-  if (!f->code ||
-      (fflag(f, fflag_ftmpl) && !vflag(f->value_ref, vflag_builtin))) {
-    if (tmpl && !is_fptr(emit->gwion, f->value_ref->type)) {
-      if (emit->env->func != f)
-        CHECK_BB(emit_template_code(emit, f));
-    } else if (emit->env->func != f && !f->value_ref->from->owner_class &&
-               !f->code && !is_fptr(emit->gwion, f->value_ref->type)) {
-      if (fbflag(f->def->base, fbflag_op)) {
-        if(f->def->base->tmpl)
-          CHECK_BB(emit_ensure_func(emit, f));
-        const Instr back = (Instr)vector_back(&emit->code->instr);
-        assert(back->execute == SetFunc);
-        if(f->code) {
-          back->opcode = eRegPushImm;
-          back->m_val = (m_uint)f->code;
-        } else
-          back->m_val      = (m_uint)f;
-      } else // calling a local func not emitted yet
-        vector_pop(&emit->code->instr);
-    }
-  } else if ((f->value_ref->from->owner_class &&
-              tflag(f->value_ref->from->owner_class, tflag_struct)) ||
-             !f->value_ref->from->owner_class ||
-             (tmpl && !is_fptr(emit->gwion, f->value_ref->type)))
-    push_func_code(emit, f);
-  else if (vector_size(&emit->code->instr)) {
-    const Instr back = (Instr)vector_back(&emit->code->instr);
-    if (back->opcode == eDotFunc) back->m_val = f->vt_index;
-  }
-  if (vector_size(&emit->code->instr) && vflag(f->value_ref, vflag_member) &&
-      is_fptr(emit->gwion, f->value_ref->type)) {
-    const Instr back      = (Instr)vector_back(&emit->code->instr);
-    const bool  is_except = back->opcode == eGWOP_EXCEPT || (back->opcode == eOP_MAX && back->execute == fast_except);
-    const Instr base =
-        !is_except ? back
-                   : (Instr)vector_at(&emit->code->instr,
-                                      vector_size(&emit->code->instr) - 2);
-    if (is_except) vector_pop(&emit->code->instr);
-    const m_bit  exec = base->opcode;
-    const m_uint val  = base->m_val;
-    const m_uint val2 = base->m_val2;
-    base->opcode      = eReg2Reg;
-//    base->m_val       = 0;//-SZ_INT;
-    base->m_val2      = -SZ_INT;
-    regpush(emit, SZ_INT);
-    const Instr instr = emit_add_instr(emit, (f_instr)(m_uint)exec);
-    instr->m_val      = val;
-    instr->m_val2     = val2;
-    if (is_except) {
-      vector_add(&emit->code->instr, (m_uint)back);
-      back->m_val = -SZ_INT;
-    }
-  } else if (f != emit->env->func && !f->code &&
-             !is_fptr(emit->gwion, f->value_ref->type)) {
-    // not yet emitted static func
-    if (f->value_ref->from->owner_class) {
-      assert(GET_FLAG(f->value_ref, static));
-      const Instr instr = vector_size(&emit->code->instr)
-                              ? (Instr)vector_back(&emit->code->instr)
-                              : emit_add_instr(emit, SetFunc);
-      instr->opcode     = eOP_MAX;
-      instr->execute    = SetFunc;
-      instr->m_val      = (m_uint)f;
-    } else {
-//      const Instr back = (Instr)vector_back(&emit->code->instr);
-//      if(back->execute != SetFunc || back->m_val != f) {
-        const Instr instr = emit_add_instr(emit, SetFunc);
-        instr->m_val      = (m_uint)f;
-//      }
-    }
+ANN static void emit_fptr_call(const Emitter emit, const Func f) {
+  const Instr call = emit_add_instr(emit, fptr_call);
+  if(f->def->base->tmpl) {
+    // maybe merge those
+    call->m_val = SZ_INT*2;
+    tmpl_prelude(emit, f);
   }
+}
+
+ANN static void call_finish(const Emitter emit, const Func f,
+                          const bool is_static) {
   const m_uint offset = emit_code_offset(emit);
   if (f != emit->env->func || !is_static)
-    regseti(emit, offset /*+ f->def->stack_depth + sizeof(frame_t)*/);
+    regseti(emit, offset);
   const Instr instr   = emit_call(emit, f, is_static);
   instr->m_val        = f->def->base->ret_type->size;
   instr->m_val2       = offset;
-  emit->this_offset   = this_offset;
-  emit->vararg_offset = vararg_offset;
+}
+
+ANN m_bool emit_exp_call1(const Emitter emit, const Func f,
+                          const bool is_static) {
+  const EmitterStatus status = emit->status;
+  emit->status =  (EmitterStatus){};
+  const int tmpl             = fflag(f, fflag_tmpl);
+  if(unlikely(fflag(f, fflag_fptr))) emit_fptr_call(emit, f);
+  else if (unlikely(!f->code && emit->env->func != f)) {
+    if (tmpl) CHECK_BB(emit_template_code(emit, f));
+    else CHECK_BB(emit_ensure_func(emit, f));
+  } else push_func_code(emit, f);
+  call_finish(emit, f, is_static);
+  emit->status = status;
   return GW_OK;
 }
 
@@ -1800,8 +1630,7 @@ ANN static void emit_exp_spork_finish(const Emitter emit, const m_uint depth) {
   spork->m_val2     = -SZ_INT;
 }
 
-ANN static inline void
-stack_alloc(const Emitter emit) { // maybe vararg could use t_vararg instead
+ANN static inline void stack_alloc(const Emitter emit) {
   emit_local(emit,
              emit->gwion->type[et_int]); // hiding the fact it is an object
   emit->code->stack_depth += SZ_INT;
@@ -1891,23 +1720,7 @@ ANN void spork_code(const Emitter emit, const struct Sporker *sp) {
 ANN void spork_func(const Emitter emit, const struct Sporker *sp) {
   const Func f =
       actual_type(emit->gwion, sp->exp->d.exp_call.func->type)->info->func;
-  if (vflag(f->value_ref, vflag_member) &&
-      is_fptr(emit->gwion, f->value_ref->type)) {
-    regpush(emit, SZ_INT * 2);
-    // (re-)emit owner
-    if (sp->exp->d.exp_call.func->exp_type == ae_exp_dot)
-      emit_exp(emit, sp->exp->d.exp_call.func->d.exp_dot.base);
-    else {
-      assert(sp->exp->d.exp_call.func->exp_type == ae_exp_primary);
-      emit_add_instr(emit, RegPushMem);
-    }
-    regpop(emit, SZ_INT * 3);
-    const m_uint depth = f->def->stack_depth;
-    regpop(emit, depth - SZ_INT);
-    const Instr spork = emit_add_instr(emit, SporkMemberFptr);
-    spork->m_val      = depth;
-  } else
-    emit_exp_spork_finish(emit, f->def->stack_depth);
+  emit_exp_spork_finish(emit, f->def->stack_depth);
   (void)emit_add_instr(emit, SporkEnd);
 }
 
@@ -2033,7 +1846,7 @@ static void emit_maybe_stack(const Emitter emit, const Instr instr, const MaybeV
   instr->m_val = -SZ_INT;
   instr->m_val2 = mv->reg;
   if(!emit->code->frame->maybe_stack)
-    emit->code->frame->maybe_stack = new_mp_vector(emit->gwion->mp, sizeof(MaybeVal), 0);
+    emit->code->frame->maybe_stack = new_mp_vector(emit->gwion->mp, MaybeVal, 0);
   mp_vector_add(emit->gwion->mp, &emit->code->frame->maybe_stack, MaybeVal, *mv);
 }
 
@@ -2132,9 +1945,9 @@ DECL_EXP_FUNC(emit, m_bool, Emitter)
 ANN2(1) /*static */ m_bool emit_exp(const Emitter emit, /* const */ Exp e) {
   Exp exp = e;
   do {
-    if (emit->info->debug && emit->info->line < e->pos.first.line) {
+    if (emit->info->debug && emit->status.line < e->pos.first.line) {
       const Instr instr = emit_add_instr(emit, DebugLine);
-      instr->m_val = emit->info->line = e->pos.first.line;
+      instr->m_val = emit->status.line = e->pos.first.line;
     }
     CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d));
     if (exp->cast_to) CHECK_BB(emit_implicit_cast(emit, exp, exp->cast_to));
@@ -2142,8 +1955,8 @@ ANN2(1) /*static */ m_bool emit_exp(const Emitter emit, /* const */ Exp e) {
         (e->cast_to ? isa(e->cast_to, emit->gwion->type[et_object]) > 0 : 1) &&
         e->exp_type == ae_exp_decl && GET_FLAG(e->d.exp_decl.td, late) &&
         exp_getuse(e) && !exp_getvar(e) &&
-        GET_FLAG(mp_vector_at(e->d.exp_decl.list, struct Var_Decl_, 0)->value, late))
-    emit_fast_except(emit, mp_vector_at(e->d.exp_decl.list, struct Var_Decl_, 0)->value->from, e->pos);
+        GET_FLAG(e->d.exp_decl.vd.value, late))
+    emit_fast_except(emit, e->d.exp_decl.vd.value->from, e->pos);
   } while ((exp = exp->next));
   return GW_OK;
 }
@@ -2314,39 +2127,6 @@ ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
   return ret;
 }
 
-ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt,
-                                 const m_uint status) {
-  regpushi(emit, status);
-  CHECK_BB(emit_exp(emit, stmt->exp));
-  const Instr member = emit_add_instr(emit, DotMember4);
-  member->m_val      = SZ_INT;
-  emit_add_instr(emit, int_r_assign);
-  regpop(emit, SZ_INT);
-  return GW_OK;
-}
-
-ANN static m_bool emit_stmt_varloop(const Emitter      emit,
-                                    const Stmt_VarLoop stmt) {
-  CHECK_BB(variadic_state(emit, stmt, 1));
-  CHECK_BB(emit_exp(emit, stmt->exp));
-  const Instr s       = emit_add_instr(emit, DotMember);
-  s->m_val            = SZ_INT * 5;
-  const Instr nonnull = emit_add_instr(emit, Goto);
-  regpop(emit, SZ_INT);
-  const Instr check  = emit_add_instr(emit, Goto);
-  const Instr member = emit_add_instr(emit, DotMember4);
-  member->m_val      = SZ_INT * 2;
-  nonnull->m_val     = emit_code_size(emit);
-  const Instr  instr = emit_add_instr(emit, BranchEqInt);
-  const m_uint pc    = emit_code_size(emit);
-  emit_stmt(emit, stmt->body, 1);
-  CHECK_BB(emit_exp(emit, stmt->exp));
-  emit_vararg_end(emit, pc);
-  CHECK_BB(variadic_state(emit, stmt, 0));
-  check->m_val = instr->m_val = emit_code_size(emit);
-  return GW_OK;
-}
-
 ANN static m_bool _emit_stmt_for(const Emitter emit, const Stmt_For stmt,
                                  m_uint *action_index) {
   CHECK_BB(emit_stmt(emit, stmt->c1, 1));
@@ -2441,7 +2221,7 @@ ANN static inline m_bool looper_run(const Emitter        emit,
 
 ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt,
                                   m_uint *end_pc) {
-  const uint n = emit->info->unroll;
+  const uint n = emit->status.unroll;
   const m_uint arr_offset = emit_local(emit, emit->gwion->type[et_int]); // array?
   const m_uint key_offset = /*!stmt->idx
      ? */emit_local(emit, emit->gwion->type[et_int])
@@ -2489,7 +2269,7 @@ nspc_add_value(emit->env->curr, stmt->idx->sym, stmt->idx->v);
 }
 
 ANN static m_bool emit_stmt_each(const Emitter emit, const Stmt_Each stmt) {
-  const uint n = emit->info->unroll;
+  const uint n = emit->status.unroll;
   nspc_push_value(emit->gwion->mp, emit->env->curr);
 
   CHECK_BB(emit_exp(emit, stmt->exp)); // add ref?
@@ -2505,7 +2285,7 @@ ANN static m_bool emit_stmt_each(const Emitter emit, const Stmt_Each stmt) {
   const m_bool ret    = _emit_stmt_each(emit, stmt, &end_pc);
   emit_pop_stack(emit, end_pc);
 nspc_pop_value(emit->gwion->mp, emit->env->curr);
-  emit->info->unroll = 0;
+  emit->status.unroll = 0;
   return ret;
 }
 
@@ -2524,10 +2304,10 @@ ANN static Instr stmt_loop_roll_idx(const Emitter        emit,
 
 ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt,
                                   m_uint *index) {
-  const uint n = emit->info->unroll;
+  const uint n = emit->status.unroll;
   if (n) {
     unroll_init(emit, n);
-    emit->info->unroll = 0;
+    emit->status.unroll = 0;
   }
   const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
   if (stmt->idx) {
@@ -2566,13 +2346,11 @@ ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
 ANN static m_bool emit_type_def(const Emitter emit, const Type_Def tdef) {
   if (tdef->when_def) CHECK_BB(emit_func_def(emit, tdef->when_def));
 
-  if (!is_fptr(emit->gwion, tdef->type) && !tflag(tdef->type, tflag_cdef)) {
+  if (tflag(tdef->type, tflag_cdef)) {
     if(!tflag(tdef->type->info->parent, tflag_emit))
                     return emit_class_def(emit, tdef->type->info->parent->info->cdef);
   }
-  return (!is_fptr(emit->gwion, tdef->type) && tdef->type->info->cdef)
-             ? emit_class_def(emit, tdef->type->info->cdef)
-             : GW_OK;
+  return tdef->type->info->cdef ? emit_class_def(emit, tdef->type->info->cdef) : GW_OK;
 }
 
 ANN static m_bool emit_enum_def(const Emitter emit NUSED, const Enum_Def edef) {
@@ -2825,7 +2603,7 @@ ANN static m_bool emit_stmt_pp(const Emitter          emit,
     emit->locale = stmt->exp->d.exp_lambda.def->base->func;
   else if (stmt->pp_type == ae_pp_pragma) {
     if (!strncmp(stmt->data, "unroll", strlen("unroll")))
-      emit->info->unroll = strtol(stmt->data + 6, NULL, 10);
+      emit->status.unroll = strtol(stmt->data + 6, NULL, 10);
   }
   return GW_OK;
 }
@@ -2845,7 +2623,9 @@ ANN static m_bool emit_stmt_retry(const Emitter                  emit,
 
 #define emit_stmt_while emit_stmt_flow
 #define emit_stmt_until emit_stmt_flow
-DECL_STMT_FUNC(emit, m_bool, Emitter)
+#define emit_stmt_spread dummy_func
+
+DECL_STMT_FUNC(emit, m_bool, Emitter);
 
 ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt,
                             const m_bool pop) {
@@ -2920,10 +2700,6 @@ ANN static inline VM_Code _emit_func_def_code(const Emitter emit,
                                               const Func    func) {
   if(!strcmp(s_name(func->def->base->xid), "new"))
     emit_add_instr(emit, RegPushMem);
-  if (fbflag(func->def->base, fbflag_variadic)) {
-    Instr instr  = emit_add_instr(emit, ObjectRelease);
-    instr->m_val = func->def->stack_depth - SZ_INT;
-  }
   return !fbflag(func->def->base, fbflag_internal) ? finalyze(emit, FuncReturn)
                                                    : emit_internal(emit, func);
 }
@@ -2938,11 +2714,11 @@ ANN static VM_Code emit_func_def_code(const Emitter emit, const Func func) {
 ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) {
   if (fdef->base->xid == insert_symbol("@dtor")) emit_local(emit, emit->gwion->type[et_int]);
   if (fdef->base->args) emit_func_def_args(emit, fdef->base->args);
-  if (fbflag(fdef->base, fbflag_variadic)) stack_alloc(emit);
   if (fdef->d.code) {
     if(!fdef->builtin) CHECK_BB(scoped_stmt(emit, fdef->d.code, 1));
-    else fdef->base->func->code = (VM_Code)vector_at(&fdef->base->func->value_ref->from->owner_class->nspc->vtable, fdef->base->func->vt_index);
+    else fdef->base->func->code = (VM_Code)vector_at(&fdef->base->func->value_ref->from->owner_class->nspc->vtable, fdef->vt_index);
   }
+  emit_func_def_return(emit);
   return GW_OK;
 }
 
@@ -3007,10 +2783,9 @@ ANN static m_bool emit_fdef(const Emitter emit, const Func_Def fdef) {
   if (f->memoize && fflag(f, fflag_pure))
     CHECK_BB(emit_memoize(emit, fdef));
   nspc_push_value(emit->gwion->mp, emit->env->curr); // handle
-  CHECK_BB(emit_func_def_body(emit, fdef));
-  emit_func_def_return(emit);
+  const m_bool ret = emit_func_def_body(emit, fdef);
   nspc_pop_value(emit->gwion->mp, emit->env->curr); // handle
-  return GW_OK;
+  return ret;
 }
 
 ANN static void emit_fdef_finish(const Emitter emit, const Func_Def fdef) {
@@ -3020,7 +2795,22 @@ ANN static void emit_fdef_finish(const Emitter emit, const Func_Def fdef) {
     func->code->memoize = memoize_ini(emit, func);
 }
 
-ANN m_bool _emit_func_def(const Emitter emit, const Func_Def f) {
+ANN static inline Capture* get_capture(const Emitter emit, const Capture_List captures, const uint32_t i) {
+  Capture *const cap = mp_vector_at(captures, Capture, i);
+  emit_localn(emit, cap->temp->type);
+  return cap;
+}
+
+ANN static void emit_lambda_capture(const Emitter emit, const Func_Def fdef) {
+  for(uint32_t i = 0; i < fdef->captures->len - 1; i++)
+    (void)get_capture(emit, fdef->captures, i);
+  const Capture *cap = get_capture(emit, fdef->captures, fdef->captures->len - 1);
+  const Instr instr = emit_add_instr(emit, Reg2Mem4);
+  instr->m_val = fdef->stack_depth;
+  instr->m_val2 = cap->temp->from->offset + cap->temp->type->size - fdef->stack_depth;
+}
+
+ANN static m_bool _emit_func_def(const Emitter emit, const Func_Def f) {
   if (tmpl_base(f->base->tmpl) && fbflag(f->base, fbflag_op)) return GW_OK;
   const Func     func   = f->base->func;
   const Func_Def fdef   = func->def;
@@ -3051,7 +2841,7 @@ ANN m_bool _emit_func_def(const Emitter emit, const Func_Def f) {
     emit_local(emit, emit->gwion->type[et_int]);
     const Instr instr = emit_add_instr(emit, MemSetImm);
     instr->m_val      = SZ_INT;
-  }
+  } else if(fdef->captures) emit_lambda_capture(emit, fdef);
   const m_bool ret = scanx_fdef(emit->env, emit, fdef, (_exp_func)emit_fdef);
   emit_pop_scope(emit);
   emit->env->func = former;
@@ -3073,10 +2863,11 @@ ANN m_bool emit_func_def(const Emitter emit, const Func_Def fdef) {
   return ret;
 }
 
-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)
+#define emit_extend_def dummy_func
+
+HANDLE_SECTION_FUNC(emit, m_bool, Emitter);
 
 ANN static inline m_bool emit_ast_inner(const Emitter emit, Ast ast) {
   for(m_uint i = 0; i < ast->len; i++) {
@@ -3086,14 +2877,6 @@ ANN static inline m_bool emit_ast_inner(const Emitter emit, Ast ast) {
   return emit_defers(emit);
 }
 
-ANN static m_bool emit_extend_def(const Emitter emit, const Extend_Def xdef) {
-  CHECK_BB(ensure_emit(emit, xdef->t));
-  CHECK_BB(extend_push(emit->env, xdef->t));
-  const m_bool ret = emit_ast_inner(emit, xdef->body);
-  extend_pop(emit->env, xdef->t);
-  return ret;
-}
-
 ANN Code *emit_class_code(const Emitter emit, const m_str name) {
   const m_uint len = strlen(name) + 7;
   char         c[len];
@@ -3165,17 +2948,9 @@ ANN static VM_Code emit_free_stack(const Emitter emit) {
   return NULL;
 }
 
-ANN static inline void emit_clear(const Emitter emit) {
-  emit->info->unroll  = 0;
-  emit->info->line    = 0;
-  emit->this_offset   = 0;
-  emit->vararg_offset = 0;
-}
-
 ANN m_bool emit_ast(const Env env, Ast *ast) {
   const Emitter emit  = env->gwion->emit;
   const Func locale = emit->locale;
-  emit_clear(emit);
   emit->code          = new_code(emit, emit->env->name);
   emit_push_scope(emit);
   const m_bool ret = emit_ast_inner(emit, *ast);
@@ -3183,8 +2958,8 @@ ANN m_bool emit_ast(const Env env, Ast *ast) {
   if (ret > 0)
     emit->info->code = finalyze(emit, EOC);
   else
-    emit_free_stack(emit);
-  emit_clear(emit);
+   emit_free_stack(emit);
+  emit->status = (EmitterStatus){};
   emit->locale = locale;
   return ret;
 }
index 43faa8133725d31249c9aa40abd14d0f5b7fec49..f5669edfa59732423125e69b19290916c7f86208 100644 (file)
@@ -48,7 +48,7 @@ __attribute__((returns_nonnull)) ANN2(1) Instr
   return instr;
 }
 
-ANN2(1) void emit_fast_except(const Emitter emit, const struct ValueFrom_ *vf, const loc_t loc) {
+ANN2(1) void emit_fast_except(const Emitter emit, const ValueFrom *vf, const loc_t loc) {
   const Instr instr = emit_add_instr(emit, fast_except);
   if(vf) {
     struct FastExceptInfo *info = mp_malloc2(emit->gwion->mp, sizeof(struct FastExceptInfo));
index 4f73e29e2902a72bbc5b84e2cf96664cf914c363..fc0b5aa40760164ca09a60b7996434f1f93085bc 100644 (file)
@@ -6,7 +6,9 @@
 #include "clean.h"
 
 ANN void free_context(const Context a, Gwion gwion) {
+  const Nspc global = a->nspc->parent;
   nspc_remref(a->nspc, gwion);
+  if(a->error) nspc_remref(global, gwion);
   free_mstr(gwion->mp, a->name);
   ast_cleaner(gwion, a->tree);
   mp_free(gwion->mp, Context, a);
@@ -34,7 +36,7 @@ ANN void load_context(const Context context, const Env env) {
 
 ANN static void clean(const Nspc nspc, const Env env) {
   env->global_nspc = nspc->parent;
-  nspc_remref(nspc, env->gwion);
+//  nspc_remref(nspc, env->gwion);
 }
 
 ANN void unload_context(const Context ctx, const Env env) {
@@ -48,5 +50,6 @@ ANN void unload_context(const Context ctx, const Env env) {
   else if(!ctx->global) {
     ctx->nspc->parent = global->parent;
     clean(global, env);
+    nspc_remref(global, env->gwion);
   } else vector_set(&env->scope->nspc_stack, 2, (m_uint)global);
 }
index b53a6680056cd57bcbb55f594067b5ea9860bbfd..2f13a128c8c7e45d27f6270e365b8e4f0ad43cf8 100644 (file)
@@ -63,7 +63,7 @@ ANN static void free_env_scope(struct Env_Scope_ *a, Gwion gwion) {
   const Vector v = &a->effects;
   for (m_uint i = 0; i < vector_size(v); i++) {
     MP_Vector *eff = (MP_Vector*)vector_at(v, i);
-    if (eff) free_mp_vector(gwion->mp, sizeof(struct ScopeEffect), eff);
+    if (eff) free_mp_vector(gwion->mp, struct ScopeEffect, eff);
   }
   vector_release(&a->effects);
   mp_free(gwion->mp, Env_Scope, a);
@@ -73,7 +73,7 @@ ANN void env_add_effect(const Env a, const Symbol effect, const loc_t pos) {
   const Vector   v = &a->scope->effects;
   MP_Vector *w = (MP_Vector*)vector_back(v);
   if (!w) {
-    w = new_mp_vector(a->gwion->mp, sizeof(struct ScopeEffect), 0);
+    w = new_mp_vector(a->gwion->mp, struct ScopeEffect, 0);
     VPTR(v, VLEN(v) - 1) = (vtype)w;
   }
   struct ScopeEffect eff = {effect, pos};
@@ -101,7 +101,7 @@ ANN void env_pop(const Env env, const m_uint scope) {
   env->class_def  = (Type)vector_pop(&env->scope->class_stack);
   env->curr       = (Nspc)vector_pop(&env->scope->nspc_stack);
   MP_Vector *const v = (MP_Vector*)vector_pop(&env->scope->effects);
-  if (v) free_mp_vector(env->gwion->mp, sizeof(struct ScopeEffect), v);
+  if (v) free_mp_vector(env->gwion->mp, struct ScopeEffect, v);
   env->scope->depth = scope;
 }
 
index f1131567d89c2b461c1894aec03b535412a71689..8f50dc1ca3b5b018460f8a2bb939fbdfa8fbad09 100644 (file)
@@ -68,8 +68,9 @@ ANN Type find_type(const Env env, Type_Decl *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 || is_class(env->gwion, v->type)) return GW_OK;
-  env_err(env, pos, _("'%s' already declared as variable of type '%s'."),
-          s_name(s), v->type->name);
+  gwerr_basic(_("already declared as variable"), NULL, NULL, env->name, pos, 0);
+  gwerr_secondary_from("declared here", v->from);
+  env_error_footer(env);
   return GW_ERROR;
 }
 
index 321bea69f807e1b290f31271e46e8e5dcc681017..71a30d2be26980e62524547b8ed5475315122c1b 100644 (file)
@@ -9,7 +9,7 @@ ANN Trait new_trait(MemPool mp, const loc_t loc) {
 }
 
 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);
+  if (a->var) free_mp_vector(mp, Value, a->var);
+  if (a->fun) free_mp_vector(mp, Func_Def, a->fun);
   mp_free(mp, Trait, a);
 }
index 577bf69d87dc4ee8d5fef46bb4d7527501397274..453e8fa80d18a87e2231259fa8754ab8fba373c4 100644 (file)
@@ -70,11 +70,6 @@ ANN Type find_common_anc(const restrict Type lhs, const restrict Type rhs) {
 describe_find(value, Value)
     // describe_find(func,  Func)
 
-    ANN Type typedef_base(Type t) {
-  while (tflag(t, tflag_typedef)) t = t->info->parent;
-  return t;
-}
-
 ANN Type array_base(Type type) {
   const Type t = typedef_base(type);
   return t->array_depth ? array_base(t->info->base_type) : t;
@@ -102,7 +97,7 @@ ANN Type array_type(const Env env, const Type src, const m_uint depth) {
   if (type) return type;
   const size_t tdepth     = depth + src->array_depth;
   const Type   base       = tdepth > 1 ? array_type(env, src, tdepth - 1) : src;
-  struct TemplateScan ts  = {.t = base, /*.td=td*/};
+  struct TemplateScan ts  = {.t = base, /*.td=td*/ };
   struct Op_Import    opi = {.op   = insert_symbol("@scan"),
                           .lhs  = env->gwion->type[et_array],
                           .data = (uintptr_t)&ts};
@@ -142,9 +137,7 @@ ANN m_uint get_depth(const Type type) {
 ANN bool is_func(const struct Gwion_ *gwion, const Type t) {
   return isa(actual_type(gwion, t), gwion->type[et_function]) > 0;
 }
-ANN bool is_fptr(const struct Gwion_ *gwion, const Type t) {
-  return isa(actual_type(gwion, t), gwion->type[et_fptr]) > 0;
-}
+
 ANN inline bool is_class(const struct Gwion_ *gwion, const Type t) {
 //  return isa(t, gwion->type[et_class]) > 0;
   return t->info->parent ==  gwion->type[et_class];
index 3813247f8e853d1c56b6004c8bc053f2165239d3..8d1e5e0b1acad0842cc6c4313566f9afe45e33d8 100644 (file)
@@ -29,7 +29,7 @@ ANN Value new_value(const Env env, const Type type, const m_str name, const loc_
   return a;
 }
 
-ANN void valuefrom(const Env env, struct ValueFrom_ *from) {
+ANN void valuefrom(const Env env, ValueFrom *from) {
   from->owner       = env->curr;
   from->owner_class = env->scope->depth ? NULL : env->class_def;
   from->ctx         = env->context;
index 3342f657c392385153ad746ad55af2ec3abc1efb..76b461f93d4b2584beacf5983f1a4340d4503a7a 100644 (file)
@@ -225,7 +225,7 @@ ANN void env_err(const Env env, const loc_t pos, const m_str fmt, ...) {
   env_xxx(env, pos, fmt, arg);
   va_end(arg);
 #endif
-  env_set_error(env);
+  env_set_error(env, true);
 }
 
 ANN struct SpecialId_ *specialid_get(const Gwion gwion, const Symbol sym) {
index 82019c569aa24aa4c38e9f4e9f21b545842c04ea..03860ac4dfbe23b604111f235eef0c40849e8101 100644 (file)
@@ -79,7 +79,7 @@ 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.sl ? new_tmpl_base(gwi->gwion->mp, ck.sl) : NULL;
+  Tmpl *tmpl = ck.sl ? new_tmpl(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);
   const Type_List tl   = td->types;
@@ -114,7 +114,7 @@ ANN Type gwi_struct_ini(const Gwi gwi, const m_str name) {
     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.sl);
+    t->info->cdef->base.tmpl = new_tmpl(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 d2c47714c2236f498497aaa1518dc1204f83c779..b21721aeeefb0d30b6e9d0aa449e2a8bf8934911 100644 (file)
@@ -70,14 +70,13 @@ ANN Symbol str2sym(const Gwion gwion, const m_str path, const loc_t pos) {
   return _str2sym(gwion, &tdc, path);
 }
 
-ANN m_bool str2var(const Gwion gwion, Var_Decl vd, const m_str path, const loc_t pos) {
+ANN m_bool str2var(const Gwion gwion, Var_Decl *vd, const m_str path, const loc_t pos) {
   struct td_checker tdc = {.str = path, .pos = pos};
   DECL_OB(const Symbol, sym, = __str2sym(gwion, &tdc));
   struct AC ac = {.str = tdc.str, .pos = pos};
   CHECK_BB(ac_run(gwion, &ac));
   vd->xid = sym;
   vd->value = NULL;
-  vd->array = ac.depth ? mk_array(gwion->mp, &ac) : NULL;
   vd->pos = pos;
   return GW_OK;
 }
@@ -105,7 +104,7 @@ ANN static Specialized_List __tmpl_list(const Gwion        gwion,
   if (tdc->str[0] != ':') return NULL;
   if (tdc->str[1] != '[') return SPEC_ERROR;
   tdc->str += 2;
-  Specialized_List sl = new_mp_vector(gwion->mp, sizeof(Specialized), 0);
+  Specialized_List sl = new_mp_vector(gwion->mp, Specialized, 0);
   if(!_tmpl_list(gwion, tdc, &sl) || tdc->str[0] != ']') {
     free_specialized_list(gwion->mp, sl);
   }
@@ -144,7 +143,7 @@ ANN static Type_List td_tmpl(const Gwion gwion, struct td_checker *tdc) {
     return (Type_List)GW_ERROR;
   }
   ++tdc->str;
-  Type_List tl = new_mp_vector(gwion->mp, sizeof(Type_Decl*), 0);
+  Type_List tl = new_mp_vector(gwion->mp, Type_Decl*, 0);
   if (!str2tl(gwion, tdc, &tl)) {
     free_type_list(gwion->mp, tl);
     return (Type_List)GW_ERROR;
@@ -170,7 +169,7 @@ ANN static inline uint get_n(struct td_checker *tdc, const char c) {
 ANN static Arg_List fptr_args(const Gwion gwion, struct td_checker *tdc) {
   if(tdc->str[1] == ')')
     return NULL;
-  Arg_List args = new_mp_vector(gwion->mp, sizeof(Arg), 0);
+  Arg_List args = new_mp_vector(gwion->mp, Arg, 0);
   do {
     Type_Decl *td = _str2td(gwion, tdc);
     if(!td) {
@@ -215,6 +214,7 @@ ANN static Type_Decl *str2td_fptr(const Gwion gwion, struct td_checker *tdc) {
   const Fptr_Def fptr = new_fptr_def(gwion->mp, fbase);
   Type_Decl *td = new_type_decl(gwion->mp, insert_symbol(gwion->st, base), tdc->pos);
   td->fptr = fptr;
+  td->types = tl;
   if (ac.depth) td->array = mk_array(gwion->mp, &ac);
   tdc->str = ac.str;
   td->option = option;
@@ -229,10 +229,10 @@ ANN static Type_Decl *_str2td(const Gwion gwion, struct td_checker *tdc) {
     return td;
   }
   DECL_OO(const Symbol, sym, = __str2sym(gwion, tdc));
+  Type_List tl = td_tmpl(gwion, tdc);
   struct AC ac = {.str = tdc->str, .pos = tdc->pos};
   CHECK_BO(ac_run(gwion, &ac));
   tdc->str     = ac.str;
-  Type_List tl = td_tmpl(gwion, tdc);
   if (tl == (Type_List)GW_ERROR) return NULL;
   const uint option = get_n(tdc, '?');
   Type_Decl *next   = NULL;
index 4ec441ff8b90cd1de97f448c09de566a4d7b490f..aac406b2e1189e6e19ad51b8e05102b8d03a2b31 100644 (file)
@@ -24,7 +24,7 @@ ANN m_int gwi_enum_ini(const Gwi gwi, const m_str type) {
   CHECK_BB(ck_ini(gwi, ck_edef));
   CHECK_OB((gwi->ck->xid = gwi_str2sym(gwi, type)));
   vector_init(&gwi->ck->v);
-  gwi->ck->tmpl = new_mp_vector(gwi->gwion->mp, sizeof(Symbol), 0);
+  gwi->ck->tmpl = new_mp_vector(gwi->gwion->mp, Symbol, 0);
   return GW_OK;
 }
 /*
index 4a1109e3416925bef57cb12e9fc87a9db6fccd16..b45eb9799c43c615b5f0904b7047ce529fb4860c 100644 (file)
@@ -22,7 +22,7 @@ static m_bool dl_func_init(const Gwi gwi, const restrict m_str t,
   gwi->ck->name = n;
   CHECK_BB(check_typename_def(gwi, gwi->ck));
   CHECK_OB((gwi->ck->td = gwi_str2td(gwi, t)));
-  gwi->ck->mpv = new_mp_vector(gwi->gwion->mp, sizeof(Arg), 0);
+  gwi->ck->mpv = new_mp_vector(gwi->gwion->mp, Arg, 0);
   return GW_OK;
 }
 
@@ -35,7 +35,6 @@ ANEW ANN static Func_Base *gwi_func_base(const Gwi gwi, ImportCK *ck) {
   Arg_List args = gwi->ck->mpv->len ? cpy_arg_list(gwi->gwion->mp, gwi->ck->mpv) : NULL;
   Func_Base *    base = new_func_base(gwi->gwion->mp, ck->td, ck->sym, args,
                                   ck->flag, gwi->loc);
-  if (ck->variadic) base->fbflag |= fbflag_variadic;
   ck->td = NULL;
   if (ck->tmpl) {
     base->tmpl = gwi_tmpl(gwi);
@@ -60,8 +59,6 @@ ANEW ANN static Func_Def import_fdef(const Gwi gwi, ImportCK *ck) {
 }
 
 ANN static m_bool section_fdef(const Gwi gwi, const Func_Def fdef) {
-//  Section * section = new_section_func_def(gwi->gwion->mp, fdef);
-//  const Ast body    = new_ast(gwi->gwion->mp, section, NULL);
   Section section = (Section) {
     .section_type = ae_section_func,
     .d = { .func_def = fdef }
@@ -79,11 +76,8 @@ ANN m_int gwi_func_valid(const Gwi gwi, ImportCK *ck) {
   const Func_Def fdef = import_fdef(gwi, ck);
   fdef->builtin = true;
   if (safe_tflag(gwi->gwion->env->class_def, tflag_tmpl)) {
-    if(!gwi->gwion->env->class_def->nspc->vtable.ptr)
-      vector_init(&gwi->gwion->env->class_def->nspc->vtable);
     section_fdef(gwi, fdef);
     fdef->d.dl_func_ptr = ck->addr;
-//  builtin_func(gwi->gwion->mp, fdef->base->func, ck->addr);
     return GW_OK;
   }
   if (traverse_func_def(gwi->gwion->env, fdef) < 0)
@@ -104,11 +98,6 @@ ANN m_int gwi_func_end(const Gwi gwi, const f_xfun addr, const ae_flag flag) {
 ANN m_int gwi_func_arg(const Gwi gwi, const restrict m_str t,
                        const restrict m_str n) {
   CHECK_BB(ck_ok(gwi, ck_fdef));
-  if (gwi->ck->variadic) GWI_ERR_B(_("already declared as variadic"));
-  if (!strcmp(n, "...")) {
-    gwi->ck->variadic = 1;
-    return GW_OK;
-  }
   DECL_OB(Type_Decl *, td, = gwi_str2td(gwi, t));
   struct Var_Decl_ var;
   if(gwi_str2var(gwi, &var, n) > 0) {
@@ -116,7 +105,7 @@ ANN m_int gwi_func_arg(const Gwi gwi, const restrict m_str t,
     mp_vector_add(gwi->gwion->mp, &gwi->ck->mpv, Arg, arg);
     return GW_OK;
   }
-  free_type_decl(gwi->gwion->mp, td); // ???
+  free_type_decl(gwi->gwion->mp, td);
   return GW_ERROR;
 }
 
@@ -136,9 +125,6 @@ ANN static m_bool section_fptr(const Gwi gwi, const Fptr_Def fdef) {
     .d = { .fptr_def = fdef }
   };
   gwi_body(gwi, &section);
-//  Section * section = new_section_fptr_def(gwi->gwion->mp, fdef);
-//  const Ast body    = new_ast(gwi->gwion->mp, section, NULL);
-//  gwi_body(gwi, body);
   return GW_OK;
 }
 
@@ -151,17 +137,16 @@ ANN Type gwi_fptr_end(const Gwi gwi, const ae_flag flag) {
     lint_fptr_def(gwi->lint, fptr);
   }
   if (safe_tflag(gwi->gwion->env->class_def,
-                 tflag_tmpl) /* && !fptr->base->tmpl*/) {
+                 tflag_tmpl) /*&& !fptr->base->tmpl*/) {
     section_fptr(gwi, fptr);
     ck_end(gwi);
     return (Type)GW_OK;
   }
   const m_bool ret = traverse_fptr_def(gwi->gwion->env, fptr);
-  if (fptr->base->func) // is it needed ?
-    set_vflag(fptr->base->func->value_ref, vflag_builtin);
-  const Type t = ret > 0 ? fptr->type : NULL;
+//  if (fptr->base->func) // is it needed ?
+//    set_vflag(fptr->base->func->value_ref, vflag_builtin);
+  const Type t = ret > 0 ? fptr->cdef->base.type : NULL;
   free_fptr_def(gwi->gwion->mp, fptr);
-  if (fptr->type) type_remref(fptr->type, gwi->gwion);
   ck_end(gwi);
   return t;
 }
index af161b4cde0bb1817dbbda86d3d08306e9e3e8f5..2a7a52b730596f8ca6178d8f47c1e17286a332d4 100644 (file)
@@ -13,7 +13,7 @@
 void gwi_body(const Gwi gwi, const Section *section) {
   const Class_Def cdef = gwi->gwion->env->class_def->info->cdef;
   if (!cdef->body) {
-    cdef->body = new_mp_vector(gwi->gwion->mp, sizeof(Section), 1);
+    cdef->body = new_mp_vector(gwi->gwion->mp, Section, 1);
     mp_vector_set(cdef->body, Section, 0, *section);
   } else {
     mp_vector_add(gwi->gwion->mp, &cdef->body, Section, (*section));
index 93fbdc674e4c74b9086b13e52c8b71b06134de34..fbf78b3e5534715701e6835b854c365404c1b938 100644 (file)
@@ -18,7 +18,7 @@ ANN m_int gwi_item_ini(const Gwi gwi, const restrict m_str type,
 }
 
 ANN static m_int gwi_item_tmpl(const Gwi gwi) {
-  Stmt_List slist = new_mp_vector(gwi->gwion->mp, sizeof(struct Stmt_), 1);
+  Stmt_List slist = new_mp_vector(gwi->gwion->mp, struct Stmt_, 1);
   mp_vector_set(slist, struct Stmt_, 0,  ((struct Stmt_) {
       .stmt_type = ae_stmt_exp,
       .d = { .stmt_exp = { .val = gwi->ck->exp } },
@@ -52,7 +52,7 @@ m_int gwi_item_end(const Gwi gwi, const ae_flag flag, union value_data addr) {
   if (env->class_def && tflag(env->class_def, tflag_tmpl))
     return gwi_item_tmpl(gwi);
   CHECK_BB(traverse_exp(env, gwi->ck->exp));
-  const Value value = mp_vector_at(gwi->ck->exp->d.exp_decl.list, struct Var_Decl_, 0)->value;
+  const Value value = gwi->ck->exp->d.exp_decl.vd.value;
   value->d          = addr;
   set_vflag(value, vflag_builtin);
   if (!env->class_def) SET_FLAG(value, global);
index cc1932efc77709fcf69f486c9c8656edf0cd566f..df1b9b2e502753fa02ed5d164ac8eee529f3bd53 100644 (file)
@@ -22,16 +22,14 @@ ANN Exp make_exp(const Gwi gwi, const m_str type, const m_str name) {
     free_type_decl(gwi->gwion->mp, td);
     return NULL;
   }
-  const Var_Decl_List list = new_mp_vector(gwi->gwion->mp, sizeof(struct Var_Decl_), 1);
-  mp_vector_set(list, struct Var_Decl_, 0, vd);
-  return new_exp_decl(gwi->gwion->mp, td, list, gwi->loc);
+  return new_exp_decl(gwi->gwion->mp, td, &vd, gwi->loc);
 }
 
 ANN m_int gwi_union_ini(const Gwi gwi, const m_str name) {
   CHECK_BB(ck_ini(gwi, ck_udef));
   gwi->ck->name = name;
   CHECK_BB(check_typename_def(gwi, gwi->ck));
-  gwi->ck->mpv = new_mp_vector(gwi->gwion->mp, sizeof(Union_Member), 0);
+  gwi->ck->mpv = new_mp_vector(gwi->gwion->mp, Union_Member, 0);
   return GW_OK;
 }
 
@@ -84,6 +82,6 @@ ANN Type gwi_union_end(const Gwi gwi, const ae_flag flag) {
 }
 
 ANN void ck_clean_udef(MemPool mp, ImportCK *ck) {
-  if (ck->mpv) free_mp_vector(mp, sizeof(Union_Member), ck->mpv);
+  if (ck->mpv) free_mp_vector(mp, Union_Member, ck->mpv);
   if (ck->tmpl) free_id_list(mp, ck->tmpl);
 }
index 7400d1999a8185e1dd91b14eaf7df5f923fcbbfc..9e73daa250de10c52ed1126197fb26b93e75d056 100644 (file)
@@ -120,12 +120,11 @@ static OP_CHECK(opck_array_at) {
       ERR_N(exp_self(bin)->pos, _("array depths do not match."));
   }
   if (bin->rhs->exp_type == ae_exp_decl) {
-    Var_Decl vd = mp_vector_at(bin->rhs->d.exp_decl.list, struct Var_Decl_, 0);
-    if (vd->array &&
-        vd->array->exp)
+    Type_Decl *td = bin->rhs->d.exp_decl.td;
+    if (td->array && td->array->exp)
       ERR_N(exp_self(bin)->pos,
             _("do not provide array for 'xxx => declaration'."));
-    SET_FLAG(vd->value, late);
+    SET_FLAG(bin->rhs->d.exp_decl.vd.value, late);
   }
   bin->rhs->ref = bin->lhs;
 //  bin->rhs->data = bin->lhs;
@@ -414,13 +413,14 @@ static const struct VM_Code_ foldr_run_code = {.name     = "foldr_run_code",
 
 typedef struct FunctionalFrame {
   VM_Code  code;
+  M_Object o;
   uint16_t pc;
   uint16_t offset;
   uint16_t index;
   uint16_t ret_size;
 } FunctionalFrame;
 
-ANN static inline void _init(const VM_Shred shred, const struct VM_Code_ *code,
+ANN static inline void _init(const VM_Shred shred, const struct VM_Code_ *code, const M_Object o,
                              const m_uint offset, const m_uint start) {
   FunctionalFrame *frame = &*(FunctionalFrame *)MEM(SZ_INT * 2 + start);
   frame->pc              = shred->pc;
@@ -431,6 +431,8 @@ ANN static inline void _init(const VM_Shred shred, const struct VM_Code_ *code,
   shred->code = (VM_Code)code;
   shred->pc   = 0;
   shredule(shred->tick->shreduler, shred, 0);
+  if(!(*(VM_Code *)REG(0) = *(VM_Code*)o->data))
+    handle(shred, "MissingCodeException");
 }
 
 ANN static inline void _next(const VM_Shred shred, const m_uint offset) {
@@ -538,8 +540,8 @@ static MFUN(vm_vector_map) {
   const M_Object ret =
       new_array(shred->info->mp, o->type_ref, ARRAY_LEN(ARRAY(o)));
   if (ARRAY_LEN(ARRAY(o))) {
-    _init(shred, &map_run_code, offset, SZ_INT);
     *(M_Object *)MEM(SZ_INT * 2) = ret;
+    _init(shred, &map_run_code, *(M_Object*)MEM(SZ_INT*1), offset, SZ_INT);
   } else
     *(M_Object *)RETURN = ret;
 }
@@ -549,7 +551,7 @@ static MFUN(vm_vector_compactmap) {
   const m_uint   offset = *(m_uint *)REG(SZ_INT * 3);
   const M_Object ret    = new_array(shred->info->mp, code->ret_type, 0);
   if (ARRAY_LEN(ARRAY(o))) {
-    _init(shred, &compactmap_run_code, offset, SZ_INT);
+    _init(shred, &compactmap_run_code, *(M_Object*)MEM(SZ_INT*1), offset, SZ_INT);
     *(M_Object *)MEM(SZ_INT * 2) = ret;
   } else
     *(M_Object *)RETURN = ret;
@@ -559,7 +561,7 @@ static MFUN(vm_vector_filter) {
   const m_uint   offset = *(m_uint *)REG(SZ_INT * 3);
   const M_Object ret    = new_array(shred->info->mp, o->type_ref, 0);
   if (ARRAY_LEN(ARRAY(o))) {
-    _init(shred, &filter_run_code, offset, SZ_INT);
+    _init(shred, &filter_run_code, *(M_Object*)MEM(SZ_INT*1), offset, SZ_INT);
     *(M_Object *)MEM(SZ_INT * 2) = ret;
   } else
     *(M_Object *)RETURN = ret;
@@ -568,7 +570,7 @@ static MFUN(vm_vector_filter) {
 static MFUN(vm_vector_count) {
   const m_uint offset = *(m_uint *)REG(SZ_INT * 3);
   if (ARRAY_LEN(ARRAY(o))) {
-    _init(shred, &count_run_code, offset, SZ_INT);
+    _init(shred, &count_run_code, *(M_Object*)MEM(SZ_INT*1), offset, SZ_INT);
     *(m_uint *)MEM(SZ_INT * 2) = 0;
   } else
     *(m_uint *)RETURN = 0;
@@ -609,7 +611,7 @@ static INSTR(fold_run_end) {
   shred->mem -= MAP_CODE_OFFSET + SZ_INT;
   FunctionalFrame *const frame   = &*(FunctionalFrame *)MEM(SZ_INT * 3);
   const M_Object         self    = *(M_Object *)MEM(0);
-  const VM_Code          code    = *(VM_Code *)MEM(SZ_INT);
+  const VM_Code          code    = *(VM_Code *)(*(M_Object*)MEM(SZ_INT))->data;
   const m_uint           sz      = code->stack_depth - ARRAY_SIZE(ARRAY(self));
   const m_uint           base_sz = code->stack_depth - sz;
   POP_REG(shred, base_sz); // ret_sz?
@@ -630,7 +632,7 @@ static MFUN(vm_vector_foldl) {
   const m_uint acc_sz = *(m_uint *)(byte + SZ_INT);
   const m_uint offset = *(m_uint *)REG(SZ_INT * 3 + acc_sz);
   if (ARRAY_LEN(ARRAY(o))) {
-    _init(shred, &foldl_run_code, offset, SZ_INT);
+    _init(shred, &foldl_run_code, *(M_Object*)MEM(SZ_INT*1), offset, SZ_INT);
     memcpy(shred->mem + MAP_CODE_OFFSET + SZ_INT * 3 + acc_sz, MEM(SZ_INT * 2),
            acc_sz);
   } else
@@ -642,7 +644,7 @@ static MFUN(vm_vector_foldr) {
   const m_uint acc_sz = *(m_uint *)(byte + SZ_INT);
   const m_uint offset = *(m_uint *)REG(SZ_INT * 3 + acc_sz);
   if (ARRAY_LEN(ARRAY(o))) {
-    _init(shred, &foldr_run_code, offset, SZ_INT);
+    _init(shred, &foldr_run_code, *(M_Object*)MEM(SZ_INT*1), offset, SZ_INT);
     memcpy(shred->mem + MAP_CODE_OFFSET + SZ_INT * 3 + acc_sz, MEM(SZ_INT * 2),
            acc_sz);
   } else
@@ -650,6 +652,11 @@ static MFUN(vm_vector_foldr) {
 }
 
 #include "template.h"
+static void array_func(const Env env, const Type t, const m_str name, f_xfun fun) {
+  const Value v = nspc_lookup_value0(t->nspc, insert_symbol(name));
+  builtin_func(env->gwion->mp, v->d.func_ref, fun);
+}
+
 static OP_CHECK(opck_array_scan) {
   struct TemplateScan *ts      = (struct TemplateScan *)data;
   const Type           t_array = env->gwion->type[et_array];
@@ -659,19 +666,19 @@ static OP_CHECK(opck_array_scan) {
   if (base->size == 0) {
     gwerr_basic("Can't use type of size 0 as array base", NULL, NULL,
                 "/dev/null", (loc_t) {}, 0);
-    env_set_error(env);
+    env_set_error(env, true);
     return env->gwion->type[et_error];
   }
   if (tflag(base, tflag_ref)) {
     gwerr_basic("Can't use ref types as array base", NULL, NULL, "/dev/null",
                 (loc_t) {}, 0);
-    env_set_error(env);
+    env_set_error(env, true);
     return env->gwion->type[et_error];
   }
   if (!strncmp(base->name, "Option:[", 5)) {
     gwerr_basic("Can't use option types as array base", NULL, NULL, "/dev/null",
                 (loc_t) {}, 0);
-    env_set_error(env);
+    env_set_error(env, true);
     return env->gwion->type[et_error];
   }
   const Symbol sym  = array_sym(env, array_base_simple(base), base->array_depth + 1);
@@ -680,8 +687,7 @@ static OP_CHECK(opck_array_scan) {
   const Class_Def cdef  = cpy_class_def(env->gwion->mp, c);
   cdef->base.ext        = type2td(env->gwion, t_array, (loc_t) {});
   cdef->base.xid        = sym;
-  cdef->base.tmpl->base = 1; // could store depth here?
-  cdef->base.tmpl->call = new_mp_vector(env->gwion->mp, sizeof(Type_Decl*), 1);
+  cdef->base.tmpl->call = new_mp_vector(env->gwion->mp, Type_Decl*, 1);
   mp_vector_set(cdef->base.tmpl->call, Type_Decl*, 0, type2td(env->gwion, base, (loc_t) {}));
   const Context ctx  = env->context;
   env->context       = base->info->value->from->ctx;
@@ -711,27 +717,19 @@ static OP_CHECK(opck_array_scan) {
                      ? !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->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);
+  array_func(env, t, "insert", insert);
+  array_func(env, t, "size", vm_vector_size);
+  array_func(env, t, "depth", vm_vector_depth);
+  array_func(env, t, "cap", vm_vector_cap);
+  array_func(env, t, "random", vm_vector_random);
+
+  array_func(env, t, "map", vm_vector_map);
+  array_func(env, t, "compactMap", vm_vector_compactmap);
+  array_func(env, t, "filter", vm_vector_filter);
+  array_func(env, t, "count", vm_vector_count);
+  array_func(env, t, "foldl", vm_vector_foldl);
+  array_func(env, t, "foldr", vm_vector_foldr);
+
   if (isa(base, env->gwion->type[et_compound]) > 0) {
     t->nspc->dtor = new_vmcode(env->gwion->mp, NULL, NULL,
                                "array component dtor", SZ_INT, true, false);
@@ -796,10 +794,10 @@ static OP_EMIT(opem_array_each) {
 
 ANN static void prepare_run(m_bit *const byte, const f_instr ini,
                             const f_instr end) {
-  *(unsigned *)byte                                 = eOP_MAX;
-  *(f_instr *)(byte + SZ_INT * 2)                   = ini;
-  *(unsigned *)(byte + BYTECODE_SZ)                 = eSetCode;
-  *(uint16_t *)(byte + BYTECODE_SZ + SZ_INT * 2)    = 3;
+  *(unsigned *)(byte)                               = eOP_MAX;
+  *(f_instr *)(byte+ SZ_INT * 2)                   = ini;
+  *(unsigned *)(byte + BYTECODE_SZ)               = eSetCode;
+  *(uint16_t *)(byte + BYTECODE_SZ + SZ_INT * 2)  = 3;
   *(unsigned *)(byte + BYTECODE_SZ * 2)             = eOverflow;
   *(unsigned *)(byte + BYTECODE_SZ * 3)             = eOP_MAX;
   *(f_instr *)(byte + BYTECODE_SZ * 3 + SZ_INT * 2) = end;
@@ -823,7 +821,7 @@ GWION_IMPORT(array) {
   prepare_map_run(count_byte, count_run_end);
   prepare_fold_run(foldl_byte, foldl_run_ini);
   prepare_fold_run(foldr_byte, foldr_run_ini);
-  const Type t_array = gwi_class_ini(gwi, "@Array:[T]", "Object");
+  const Type t_array = gwi_class_ini(gwi, "Array:[T]", "Object");
   set_tflag(t_array, tflag_infer);
   gwi->gwion->type[et_array] = t_array;
   gwi_class_xtor(gwi, NULL, array_dtor);
@@ -831,20 +829,20 @@ GWION_IMPORT(array) {
 
   GWI_BB(gwi_fptr_ini(gwi, "A", "map_t:[A]"))
   GWI_BB(gwi_func_arg(gwi, "T", "elem"))
-  GWI_BB(gwi_fptr_end(gwi, ae_flag_global))
+  GWI_BB(gwi_fptr_end(gwi, ae_flag_static))
 
   GWI_BB(gwi_fptr_ini(gwi, "Option:[A]", "compactmap_t:[A]"))
   GWI_BB(gwi_func_arg(gwi, "T", "elem"))
-  GWI_BB(gwi_fptr_end(gwi, ae_flag_global))
+  GWI_BB(gwi_fptr_end(gwi, ae_flag_static))
 
   GWI_BB(gwi_fptr_ini(gwi, "A", "fold_t:[A]"))
   GWI_BB(gwi_func_arg(gwi, "T", "elem"))
   GWI_BB(gwi_func_arg(gwi, "A", "acc"))
-  GWI_BB(gwi_fptr_end(gwi, ae_flag_global))
+  GWI_BB(gwi_fptr_end(gwi, ae_flag_static))
 
   GWI_BB(gwi_fptr_ini(gwi, "bool", "filter_t"))
   GWI_BB(gwi_func_arg(gwi, "T", "elem"))
-  GWI_BB(gwi_fptr_end(gwi, ae_flag_global))
+  GWI_BB(gwi_fptr_end(gwi, ae_flag_static))
 
   // put functions using T first
   GWI_BB(gwi_func_ini(gwi, "bool", "remove"))
@@ -884,54 +882,54 @@ GWION_IMPORT(array) {
   GWI_BB(gwi_func_end(gwi, vm_vector_count, ae_flag_none))
 
   GWI_BB(gwi_func_ini(gwi, "A", "foldl:[A]"))
-  GWI_BB(gwi_func_arg(gwi, "fold_t", "data"))
+  GWI_BB(gwi_func_arg(gwi, "fold_t:[A]", "data"))
   GWI_BB(gwi_func_arg(gwi, "A", "initial"))
   GWI_BB(gwi_func_end(gwi, vm_vector_foldl, ae_flag_none))
 
   GWI_BB(gwi_func_ini(gwi, "A", "foldr:[A]"))
-  GWI_BB(gwi_func_arg(gwi, "fold_t", "data"))
+  GWI_BB(gwi_func_arg(gwi, "fold_t:[A]", "data"))
   GWI_BB(gwi_func_arg(gwi, "A", "initial"))
   GWI_BB(gwi_func_end(gwi, vm_vector_foldr, ae_flag_none))
 
   GWI_BB(gwi_class_end(gwi))
 
-  GWI_BB(gwi_oper_ini(gwi, "@Array", "@Array", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "Array", "Array", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_at))
   GWI_BB(gwi_oper_end(gwi, "=>", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_implicit))
 //  GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
   GWI_BB(gwi_oper_end(gwi, "@implicit", NoOp))
-  GWI_BB(gwi_oper_ini(gwi, "@Array", (m_str)OP_ANY_TYPE, NULL))
+  GWI_BB(gwi_oper_ini(gwi, "Array", (m_str)OP_ANY_TYPE, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_sl))
   GWI_BB(gwi_oper_emi(gwi, opem_array_sl))
   GWI_BB(gwi_oper_end(gwi, "<<", NULL))
-  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@Array", NULL))
+  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "Array", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_sr))
   GWI_BB(gwi_oper_emi(gwi, opem_array_sr))
   GWI_BB(gwi_oper_end(gwi, ">>", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@Array", "@Array", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "Array", "Array", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_cast))
   GWI_BB(gwi_oper_end(gwi, "$", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "int", "@Array", "int"))
+  GWI_BB(gwi_oper_ini(gwi, "int", "Array", "int"))
   GWI_BB(gwi_oper_add(gwi, opck_array_slice))
   GWI_BB(gwi_oper_emi(gwi, opem_array_slice))
   GWI_BB(gwi_oper_end(gwi, "@slice", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "int", "@Array", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "int", "Array", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array))
   GWI_BB(gwi_oper_emi(gwi, opem_array_access))
   GWI_BB(gwi_oper_end(gwi, "@array", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, "void"))
+  GWI_BB(gwi_oper_ini(gwi, "Array", NULL, "void"))
   GWI_BB(gwi_oper_emi(gwi, opem_array_each_init))
   GWI_BB(gwi_oper_end(gwi, "@each_init", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, "int"))
+  GWI_BB(gwi_oper_ini(gwi, "Array", NULL, "int"))
   GWI_BB(gwi_oper_emi(gwi, opem_array_each))
   GWI_BB(gwi_oper_end(gwi, "@each", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, NULL))
+  GWI_BB(gwi_oper_ini(gwi, "Array", NULL, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_each_val))
   GWI_BB(gwi_oper_end(gwi, "@each_val", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, "int"))
+  GWI_BB(gwi_oper_ini(gwi, "Array", NULL, "int"))
   GWI_BB(gwi_oper_end(gwi, "@each_idx", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@Array", NULL, NULL))
+  GWI_BB(gwi_oper_ini(gwi, "Array", NULL, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_scan))
   GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
   gwi_register_freearg(gwi, ArrayAlloc, freearg_array);
similarity index 59%
rename from src/lib/lib_func.c
rename to src/lib/closure.c
index 6e4b50e3666d981b4119e840b3c65a66455c9761..f15d53abfb8fa9e9e580455faa773ad621b38768 100644 (file)
@@ -13,6 +13,8 @@
 #include "template.h"
 #include "parse.h"
 #include "partial.h"
+#include "gack.h"
+#include "tmp_resolve.h"
 
 ANN static Exp uncurry(const Env env, const Exp_Binary *bin) {
   const Stmt stmt = mp_vector_at(bin->rhs->type->info->func->def->d.code->d.stmt_code.stmt_list, struct Stmt_, 0);
@@ -23,7 +25,6 @@ ANN static Exp uncurry(const Env env, const Exp_Binary *bin) {
   Exp base = NULL, tmp = NULL;
   while(args) {
     if(args->exp_type != ae_exp_primary || args->d.prim.prim_type != ae_prim_id || *s_name(args->d.prim.d.var) != '@') {
-      // we should check better => use longer name
       const Exp next = args->next;
       args->next = NULL;
       if(tmp) tmp = (tmp->next = cpy_exp(env->gwion->mp, args));
@@ -68,6 +69,11 @@ static OP_CHECK(opck_func_call) {
   return mk_call(env, exp_self(bin), bin->rhs, bin->lhs);
 }
 
+static OP_CHECK(opck_fptr_call) {
+  Exp_Binary *bin  = (Exp_Binary *)data;
+  return mk_call(env, exp_self(bin), bin->rhs, bin->lhs);
+}
+
 ANN static inline Exp cpy_nonext(const Env env, const Exp e) {
   const MemPool mp   = env->gwion->mp;
   const Exp     next = e->next;
@@ -81,33 +87,87 @@ ANN static inline Exp cpy_nonext(const Env env, const Exp e) {
   return ret;
 }
 
-static inline void fptr_instr(const Emitter emit, const Func f,
-                              const m_uint i) {
-  const Instr set = emit_add_instr(emit, RegSetImm);
-  set->m_val      = (m_uint)f;
-  set->m_val2     = -SZ_INT * i;
+ANN Type upvalue_type(const Env env, Capture *cap) {
+  const Value v = nspc_lookup_value1(env->curr, cap->xid);
+  if(!v) ERR_O(cap->pos, _("non existing value")); // did_you_mean
+  if(cap->is_ref && not_upvalue(env, v))
+    ERR_O(cap->pos, _("can't take ref of a scoped value"));
+  cap->orig = v;
+  const Type base_type = !tflag(v->type, tflag_ref) ? v->type : (Type)vector_front(&v->type->info->tuple->contains);
+  return !cap->is_ref ? base_type :  ref_type(env->gwion, base_type, cap->pos);
 }
 
-static OP_EMIT(opem_func_assign) {
-  Exp_Binary *bin = (Exp_Binary *)data;
-  if (bin->rhs->type->info->func->def->base->tmpl)
-    fptr_instr(emit, bin->lhs->type->info->func, 2);
-  (void)emit_add_instr(emit, int_r_assign);
-  if (vflag(bin->lhs->type->info->func->value_ref, vflag_member) &&
-      !is_fptr(emit->gwion, bin->lhs->type)) {
-    const Instr pop = emit_add_instr(emit, RegMove);
-    pop->m_val      = -SZ_INT;
-    const Instr cpy = emit_add_instr(emit, Reg2Reg);
-    cpy->m_val      = -SZ_INT;
+ANN void free_captures(const VM_Shred shred, m_bit *const caps) {
+  uint32_t sz = 0;
+  const Capture_List captures = (*(Func_Def*)caps)->captures;
+  for(m_uint i = 0; i < captures->len; i++) {
+    Capture *const cap = mp_vector_at(captures, Capture, i);
+    if(isa(cap->temp->type, shred->info->vm->gwion->type[et_compound]) > 0)
+      compound_release(shred, cap->temp->type, caps + SZ_INT + sz);
+    sz += cap->temp->type->size;
+  }
+  mp_free2(shred->info->mp, sz + SZ_INT, caps);
+}
+
+static INSTR(fptr_capture) {
+  POP_REG(shred, instr->m_val);
+  const M_Object o = *(M_Object*)REG(-SZ_INT);
+  m_bit *caps = mp_malloc2(shred->info->mp, SZ_INT + instr->m_val);
+  memcpy(caps + SZ_INT, REG(0), instr->m_val);
+  *(Func_Def*)caps = (Func_Def)instr->m_val2;
+  *(m_bit**)(o->data + SZ_INT) = caps;
+}
+
+static INSTR(fptr_assign) {
+  POP_REG(shred, SZ_INT);
+  const M_Object o = *(M_Object*)REG(0);
+  *(VM_Code*)(o->data + instr->m_val) = *(VM_Code*)REG(-SZ_INT);
+  m_bit *old_caps = *(m_bit**)(o->data + SZ_INT);
+  if(old_caps) free_captures(shred, old_caps);
+  *(VM_Code*)(o->data + instr->m_val + SZ_INT) = NULL;
+  *(M_Object*)REG(-SZ_INT) = o;
+}
+
+ANN static m_bool emit_fptr_assign(const Emitter emit, const Type lhs, const Type rhs) {
+  const Instr instr = emit_add_instr(emit, fptr_assign);
+  if(rhs->info->cdef && rhs->info->cdef->base.tmpl)
+    instr->m_val = SZ_INT*2;
+  if(!lhs->info->func) {
+    const Func_Def fdef = lhs->info->func->def;
+    const Capture_List captures = fdef->captures;
+    if(captures) {
+      uint32_t offset = 0;
+      Exp e = new_prim_id(emit->gwion->mp, fdef->base->xid, fdef->base->pos); // free me
+      for(uint32_t i = 0; i < captures->len; i++) {
+        Capture *const cap = mp_vector_at(captures, Capture, i);
+        e->d.prim.d.var = cap->xid;
+        e->d.prim.value = cap->orig;
+        e->type = cap->orig->type;
+        exp_setvar(e, cap->is_ref);
+        emit_exp(emit, e);
+        if(!cap->is_ref && isa(cap->temp->type, emit->gwion->type[et_compound]) > 0)
+          emit_compound_addref(emit, cap->temp->type, cap->temp->type->size, 0);
+        offset += cap->temp->type->size;
+      }
+      free_exp(emit->gwion->mp, e);
+      const Instr instr = emit_add_instr(emit, fptr_capture);
+      instr->m_val = offset;
+      instr->m_val2 = (m_uint)fdef;
+    }
   }
   return GW_OK;
 }
 
+static OP_EMIT(opem_fptr_assign) {
+  Exp_Binary *bin = (Exp_Binary*)data;
+  return emit_fptr_assign(emit, bin->lhs->type, bin->rhs->type);
+}
+
+
 struct FptrInfo {
   Func        lhs;
   const Func  rhs;
   const Exp   exp;
-  const loc_t pos;
 };
 
 ANN static void _fptr_tmpl_push(const Env env, const Func f) {
@@ -125,15 +185,8 @@ ANN static void _fptr_tmpl_push(const Env env, const Func f) {
 }
 
 ANN static m_bool fptr_tmpl_push(const Env env, struct FptrInfo *info) {
-  //  if(safe_tflag(info->rhs->value_ref->from->owner_class, tflag_tmpl))
   if (!info->rhs->def->base->tmpl) return GW_OK;
   nspc_push_type(env->gwion->mp, env->curr);
-  //  Type owner = info->rhs->value_ref->from->owner_class;
-  //  while(owner) {
-  //    owner = owner->info->value->from->owner_class;
-  //  }
-
-  //  _fptr_tmpl_push(env, info->lhs);
   _fptr_tmpl_push(env, info->rhs);
   return GW_OK;
 }
@@ -152,15 +205,17 @@ ANN static inline bool handle_global(Func_Base *a, Func_Base *b) {
 
 ANN static m_bool fptr_args(const Env env, Func_Base *base[2]) {
   Arg_List args0 = base[0]->args, args1 = base[1]->args;
-  const bool offset0 = handle_global(base[0], base[1]);
-  const bool offset1 = handle_global(base[1], base[0]);
-  const uint32_t len0 = args0 ? args0->len : 0;
-  const uint32_t len1 = args1 ? args1->len : 0;
-  if(len0 - offset0 != len1 - offset1)
-    return GW_ERROR;
-  for(uint32_t i = 0; i < len1 - offset0; i++) {
-    const Arg *arg0 = (Arg*)(args0->ptr + (i + offset0) * sizeof(Arg));
-    const Arg *arg1 = (Arg*)(args1->ptr + (i + offset1) * sizeof(Arg));
+  const bool member = vflag(base[0]->func->value_ref, vflag_member);
+  const uint32_t len0 = mp_vector_len(args0) + member;
+  const uint32_t len1 = mp_vector_len(args1);
+  if(len0 != len1) return GW_ERROR;
+  if(member) {
+    const Arg *arg = mp_vector_at(args1, Arg, 0);
+    CHECK_BB(isa(base[0]->func->value_ref->from->owner_class, arg->type));
+  }
+  for(uint32_t i = member; i < len0; i++) {
+    const Arg *arg0 = mp_vector_at(args0, Arg, (i - member));
+    const Arg *arg1 = mp_vector_at(args1, Arg, i);
     if (arg0->type && arg1->type)
       CHECK_BB(isa(arg0->type, arg1->type));
     else if(!tmpl_base(base[0]->tmpl) && !tmpl_base(base[1]->tmpl)){
@@ -174,14 +229,14 @@ ANN static m_bool fptr_args(const Env env, Func_Base *base[2]) {
 ANN static bool fptr_effects(const Env env, struct FptrInfo *info) {
   if (!info->lhs->def->base->effects.ptr) return true;
   if (!info->rhs->def->base->effects.ptr) {
-    gwerr_secondary("too many effects", env->name, info->pos);
+    gwerr_secondary("too many effects", env->name, info->exp->pos);
     return false;
   }
   const Vector lhs = &info->lhs->def->base->effects;
   const Vector rhs = &info->rhs->def->base->effects;
   for (m_uint i = 0; i < vector_size(lhs); i++) {
     if (vector_find(rhs, vector_at(lhs, 0)) == -1) {
-      gwerr_secondary("effect not handled", env->name, info->pos);
+      gwerr_secondary("effect not handled", env->name, info->exp->pos);
       return false;
     }
   }
@@ -192,38 +247,8 @@ ANN static m_bool fptr_check(const Env env, struct FptrInfo *info) {
   //  if(!info->lhs->def->base->tmpl != !info->rhs->def->base->tmpl)
   //    return GW_ERROR;
   if(!info->lhs)
-    ERR_B(info->pos,
+    ERR_B(info->exp->pos,
           _("can't resolve operator"))
-  const Type l_type = info->lhs->value_ref->from->owner_class;
-  const Type r_type = info->rhs->value_ref->from->owner_class;
-  const Arg *l_arg = info->lhs->def->base->args ? mp_vector_at(info->lhs->def->base->args, Arg, 0) : NULL;
-  const Arg *r_arg = info->rhs->def->base->args ? mp_vector_at(info->rhs->def->base->args, Arg, 0) : NULL;
-// added when parsing bases template
-  const Type l_this = l_arg && l_arg->var_decl.value ? l_arg->var_decl.value->type : NULL;
-  const Type r_this = r_arg && r_arg->var_decl.value? r_arg->var_decl.value->type : NULL;
-
-  if (!r_type && l_type) {
-    if (/*!GET_FLAG(info->lhs, global) && */(!info->rhs->def->base->args ||
-isa(l_type, r_this) < 0)
-)
-    ERR_B(info->pos,
-          _("can't assign member function to non member function pointer"))
-  } else if (!l_type && r_type) {
-    if (!GET_FLAG(info->rhs, global) && (!info->lhs->def->base->args ||
-isa(r_type, l_this) < 0)
-)
-      ERR_B(info->pos,
-            _("can't assign non member function to member function pointer"))
-  } else if (l_type && isa(r_type, l_type) < 0)
-    ERR_B(info->pos,
-          _("can't assign member function to a pointer of an other class"))
-  if (vflag(info->rhs->value_ref, vflag_member)) {
-    if (!vflag(info->lhs->value_ref, vflag_member) && l_type)
-      ERR_B(info->pos,
-            _("can't assign static function to member function pointer"))
-  } else if (vflag(info->lhs->value_ref, vflag_member) && r_type)
-    ERR_B(info->pos,
-          _("can't assign member function to static function pointer"))
   return GW_OK;
 }
 
@@ -232,11 +257,6 @@ ANN static inline m_bool fptr_rettype(const Env env, struct FptrInfo *info) {
   return td_match(env, td);
 }
 
-ANN static inline m_bool fptr_arity(struct FptrInfo *info) {
-  return fbflag(info->lhs->def->base, fbflag_variadic) ==
-         fbflag(info->rhs->def->base, fbflag_variadic);
-}
-
 ANN static Type fptr_type(const Env env, struct FptrInfo *info) {
   const Value v     = info->lhs->value_ref;
   const Nspc  nspc  = v->from->owner;
@@ -260,7 +280,7 @@ ANN static Type fptr_type(const Env env, struct FptrInfo *info) {
     Type       type    = NULL;
     Func_Base *base[2] = {info->lhs->def->base, info->rhs->def->base};
     CHECK_BO(fptr_tmpl_push(env, info));
-    if (fptr_rettype(env, info) > 0 && fptr_arity(info) &&
+    if (fptr_rettype(env, info) > 0 &&
         fptr_args(env, base) > 0 && fptr_effects(env, info))
       type = actual_type(env->gwion, info->lhs->value_ref->type)
                  ?: info->lhs->value_ref->type;
@@ -272,30 +292,35 @@ ANN static Type fptr_type(const Env env, struct FptrInfo *info) {
 
 ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l,
                                 const Func_Def fdef) {
-//   if(l->def->base->func) return GW_OK;
   Arg_List bases = fdef->base->args;
   Arg_List args = l->def->base->args;
-  // arity match
-  if ((bases ? bases->len : 0) != (args ? args->len : 0))
+  if (mp_vector_len(bases) != mp_vector_len(args))
     ERR_B(exp_self(l)->pos, _("argument number does not match for lambda"))
-    if(fdef->captures) {
+
+  if(l->def->captures) {
     // here move to arguments
-    uint32_t offset = 0;
-    for(uint32_t i = 0; i < fdef->captures->len; i++) {
-      Capture *cap = mp_vector_at(fdef->captures, Capture, i);
+    for(uint32_t i = 0; i < l->def->captures->len; i++) {
+      Capture *cap = mp_vector_at(l->def->captures, Capture, i);
       const Value v = nspc_lookup_value1(env->curr, cap->xid);
       if(!v) ERR_B(cap->pos, _("unknown value in capture"));
-      offset += (!cap->is_ref ? SZ_INT : v->type->size);
+      DECL_OB(const Type, t, = upvalue_type(env, cap));
+      cap->temp = new_value(env, t, s_name(cap->xid), cap->pos);
       cap->orig = v;
-      cap->offset = offset;
     }
   }
-  const bool is_tmpl =
-      safe_tflag(fdef->base->func->value_ref->from->owner_class, tflag_tmpl);
-  if (is_tmpl)
-    template_push_types(
-        env,
-        fdef->base->func->value_ref->from->owner_class->info->cdef->base.tmpl);
+
+  Type owner = fdef->base->func->value_ref->from->owner_class;
+  struct EnvSet es    = {.env   = env,
+                      .data  = env,
+                      .func  = (_exp_func)traverse_cdef,
+                      .scope = env->scope->depth,
+                      .flag  = tflag_scan0};
+  CHECK_BB(envset_pushv(&es, owner->info->value));
+  while(owner) {
+    if(owner->info->cdef->base.tmpl)
+      template_push_types(env, owner->info->cdef->base.tmpl);
+    owner = owner->info->value->from->owner_class;
+  }
   if(bases) {
     for(uint32_t i = 0; i < bases->len; i++) {
       Arg *base = mp_vector_at(bases, Arg, i);
@@ -305,25 +330,21 @@ ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l,
   }
   l->def->base->td =
       type2td(env->gwion, known_type(env, fdef->base->td), exp_self(l)->pos);
-  if (is_tmpl) nspc_pop_type(env->gwion->mp, env->curr);
-  l->def->base->flag = fdef->base->flag;
-  //  if(GET_FLAG(def->base, global) && !l->owner &&
-  //  def->base->func->value_ref->from->owner_class)
-  UNSET_FLAG(l->def->base, global);
+  /*Type*/ owner = fdef->base->func->value_ref->from->owner_class;
+
   Upvalues upvalues = {
     .values = env->curr->info->value
   };
+  env->curr->info->value = new_scope(env->gwion->mp);
   l->def->base->values = &upvalues;
   const m_uint scope   = env->scope->depth;
-  if(GET_FLAG(fdef->base, global) && !l->owner &&
-    fdef->base->func->value_ref->from->owner_class)
-   env_push(env, NULL, env->context->nspc);
   env->scope->depth = 0;
+  const bool shadowing = env->scope->shadowing;
+  env->scope->shadowing = true;
+  if(env->class_def)SET_FLAG(l->def->base, static);
   const m_bool ret  = traverse_func_def(env, l->def);
+  env->scope->shadowing = shadowing;
   env->scope->depth = scope;
-    if(GET_FLAG(fdef->base, global) && !l->owner &&
-    fdef->base->func->value_ref->from->owner_class)
-   env_pop(env, scope);
 
   if (l->def->base->func) {
     if (env->curr->info->value != l->def->base->values->values) {
@@ -331,7 +352,13 @@ ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l,
       env->curr->info->value = l->def->base->values->values;
     }
   }
-
+  /*Type*/ owner = fdef->base->func->value_ref->from->owner_class->info->value->from->owner_class;
+  while(owner) {
+    if(owner->info->cdef->base.tmpl)
+    nspc_pop_type(env->gwion->mp, env->curr);
+    owner = owner->info->value->from->owner_class;
+  }
+  if (es.run) envset_pop(&es, owner);
   if(ret < 0) {
     if(args) {
       for(uint32_t i = 0; i < bases->len; i++) {
@@ -345,20 +372,17 @@ ANN static m_bool _check_lambda(const Env env, Exp_Lambda *l,
 }
 
 ANN m_bool check_lambda(const Env env, const Type t, Exp_Lambda *l) {
-//  if (!l->def->base->func) return GW_ERROR;
   const Func_Def fdef = t->info->func->def;
-  if (!GET_FLAG(t->info->func->value_ref, global))
-    l->owner = t->info->value->from->owner_class;
   CHECK_BB(_check_lambda(env, l, fdef));
   exp_self(l)->type = l->def->base->func->value_ref->type;
   return GW_OK;
 }
 
 ANN static m_bool fptr_do(const Env env, struct FptrInfo *info) {
-  if (isa(info->exp->type, env->gwion->type[et_lambda]) < 0) {
+  if(info->exp->type->info->func) {
     CHECK_BB(fptr_check(env, info));
     if (!(info->exp->type = fptr_type(env, info)))
-      ERR_B(info->pos, _("no match found"))
+      ERR_B(info->exp->pos, _("no match found"))
     return GW_OK;
   }
   Exp_Lambda *l = &info->exp->d.exp_lambda;
@@ -372,9 +396,8 @@ ANN static Type partial2auto(const Env env, const Exp_Binary *bin) {
   set_fbflag(fdef->base, fbflag_lambda);
   const Type actual = fdef->base->func->value_ref->type;
   set_fbflag(fdef->base, fbflag_lambda);
-  Var_Decl vd = mp_vector_at(bin->rhs->d.exp_decl.list, struct Var_Decl_, 0);
-  exp_setvar(bin->rhs, true);
-  return vd->value->type = bin->rhs->type = bin->rhs->d.exp_decl.type = actual;
+  Var_Decl vd = bin->rhs->d.exp_decl.vd;
+  return vd.value->type = bin->rhs->type = bin->rhs->d.exp_decl.type = actual;
 }
 
 static OP_CHECK(opck_auto_fptr) {
@@ -398,104 +421,48 @@ static OP_CHECK(opck_auto_fptr) {
           bin->rhs->pos.first.column);
   fptr_def->base->xid = insert_symbol(name);
   const m_bool ret    = traverse_fptr_def(env, fptr_def);
-  const Type   t      = fptr_def->type;
+  const Type   t      = fptr_def->cdef->base.type;
   free_fptr_def(env->gwion->mp, fptr_def);
-//  type_remref(t, env->gwion);
-  Var_Decl vd = mp_vector_at(bin->rhs->d.exp_decl.list, struct Var_Decl_, 0);
-  vd->value->type = bin->rhs->type =
+  Var_Decl vd = bin->rhs->d.exp_decl.vd;
+  vd.value->type = bin->rhs->type =
       bin->rhs->d.exp_decl.type                = t;
-  exp_setvar(bin->rhs, 1);
   return ret > 0 ? t : env->gwion->type[et_error];
 }
 
-static OP_CHECK(opck_fptr_at) {
+static OP_CHECK(opck_fptr_assign) {
   Exp_Binary *bin = (Exp_Binary *)data;
-  if (bin->rhs->exp_type == ae_exp_decl) {
-    Var_Decl vd = mp_vector_at(bin->rhs->d.exp_decl.list, struct Var_Decl_, 0);
-    UNSET_FLAG(vd->value, late);
-  }
-  if (bin->lhs->exp_type == ae_exp_td)
-    ERR_N(bin->lhs->pos, "can't use type_decl expression");
-  //    UNSET_FLAG(bin->rhs->d.exp_decl.list->self->value, late);
-  if (bin->rhs->type->info->func->def->base->tmpl &&
-      bin->rhs->type->info->func->def->base->tmpl->call) {
-    struct FptrInfo info = {bin->lhs->type->info->func ?: bin->lhs->type->info->parent->info->func,
-                            bin->rhs->type->info->parent->info->func, bin->lhs,
-                            exp_self(bin)->pos};
-    CHECK_BN(fptr_do(env, &info));
-    exp_setvar(bin->rhs, 1);
-    return bin->rhs->type;
-  }
-  struct FptrInfo info = {bin->lhs->type->info->func ?: bin->lhs->type->info->parent->info->func,
-                          bin->rhs->type->info->func, bin->lhs,
-                          exp_self(bin)->pos};
+  const Func_Def rhs = closure_def(bin->rhs->type);
+  struct FptrInfo info = {.lhs = bin->lhs->type->info->func,
+                          .rhs = rhs->base->func,
+                          .exp = bin->lhs};
   CHECK_BN(fptr_do(env, &info));
-  exp_setvar(bin->rhs, 1);
   return bin->rhs->type;
 }
 
-/*
-static OP_CHECK(opck_fptr_cast) {
-  Exp_Cast *      cast = (Exp_Cast *)data;
-  const Type      t    = exp_self(cast)->type;
-  struct FptrInfo info = {cast->exp->type->info->func, t->info->func, cast->exp,
-                          exp_self(cast)->pos};
-  CHECK_BN(fptr_do(env, &info));
-  return t;
-}
-*/
-static void member_fptr(const Emitter emit) {
-  const Instr instr = emit_add_instr(emit, RegMove);
-  instr->m_val      = -SZ_INT;
-  const Instr dup   = emit_add_instr(emit, Reg2Reg);
-  dup->m_val        = -SZ_INT;
-}
-
 static inline int is_member(const Type from) {
   return vflag(from->info->func->value_ref, vflag_member);
 }
-/*
-static OP_EMIT(opem_fptr_cast) {
-  const Exp_Cast *cast = (Exp_Cast *)data;
-  if (is_member(cast->exp->type)) member_fptr(emit);
-  if (exp_self(cast)->type->info->func->def->base->tmpl)
-    fptr_instr(emit, cast->exp->type->info->func, 1);
-  return GW_OK;
-}
-*/
+
 static OP_CHECK(opck_fptr_impl) {
   struct Implicit *impl = (struct Implicit *)data;
-  struct FptrInfo  info = {impl->e->type->info->func, impl->t->info->func,
-                          impl->e, impl->e->pos};
+  const Func f = closure_def(impl->t)->base->func;
+  struct FptrInfo  info = {.lhs = impl->e->type->info->func,
+                           .rhs = f,
+                           .exp = impl->e};
   CHECK_BN(fptr_do(env, &info));
   return impl->t;
 }
 
-static OP_CHECK(opck_fptr_cast) {
-  Exp_Cast *cast = (Exp_Cast *)data;
-  const Type t = known_type(env, cast->td);
-  struct FptrInfo  info = {cast->exp->type->info->func, t->info->func,
-                          cast->exp, cast->td->pos};
-  CHECK_BN(fptr_do(env, &info));
-  return t;
-}
-
-// smh the VM should be able to do that
-static INSTR(Func2Code) {
-  *(VM_Code *)REG(-SZ_INT) = (*(Func *)REG(-SZ_INT))->code;
-}
-
 static OP_EMIT(opem_fptr_impl) {
   struct Implicit *impl = (struct Implicit *)data;
-  if (is_member(impl->e->type)) member_fptr(emit);
-  if (impl->t->info->func->def->base->tmpl) {
-    fptr_instr(emit, ((Exp)impl->e)->type->info->func, 1);
-    if (!is_fptr(emit->gwion, impl->e->type) &&
-        safe_tflag(impl->t->info->value->from->owner_class, tflag_tmpl)) {
-      emit_add_instr(emit, Func2Code);
-    }
+  if(!impl->e->type->info->func->def->base->tmpl && impl->t->info->cdef->base.tmpl) {
+    const Instr instr = (Instr)vector_back(&emit->code->instr);
+    instr->opcode = eRegPushImm;
+    instr->m_val = (m_uint)impl->e->type->info->func;
   }
-  return GW_OK;
+  const Instr instr = emit_add_instr(emit, ObjectInstantiate);
+  instr->m_val2 = (m_uint)impl->t;
+  return emit_fptr_assign(emit, impl->e->type, impl->t);
 }
 
 static void op_narg_err(const Env env, const Func_Def fdef, const loc_t loc) {
@@ -504,7 +471,7 @@ static void op_narg_err(const Env env, const Func_Def fdef, const loc_t loc) {
                 _("Decayed operators take two arguments"), NULL, env->name, loc,
                 0);
     if (fdef) defined_here(fdef->base->func->value_ref);
-    env_set_error(env);
+    env_set_error(env, true);
   }
 }
 static m_bool op_call_narg(const Env env, Exp arg, const loc_t loc) {
@@ -534,14 +501,6 @@ ANN Type check_op_call(const Env env, Exp_Call *const exp) {
 
 static m_bool op_impl_narg(const Env env, const Func_Def fdef,
                            const loc_t loc) {
-/*
-  m_uint   narg = 0;
-  Arg_List arg  = fdef->base->args;
-  while (arg) {
-    narg++;
-    arg = arg->next;
-  }
-*/
   Arg_List arg  = fdef->base->args;
   if (!arg && arg->len == 2) return GW_OK;
   op_narg_err(env, fdef, loc);
@@ -568,8 +527,6 @@ static inline void op_impl_ensure_types(const Env env, const Func func) {
   if (func_tmpl) nspc_pop_type(env->gwion->mp, env->curr);
 }
 
-#include "tmp_resolve.h"
-
 static OP_CHECK(opck_op_impl) {
   struct Implicit *impl = (struct Implicit *)data;
   const Func       func = impl->t->info->func;
@@ -590,8 +547,6 @@ static OP_CHECK(opck_op_impl) {
       .type     = arg1->type,
       .pos      = arg1->td->pos};
   struct Exp_ self = {.pos = impl->e->pos};
-  //  Exp_Binary _bin = { .lhs=&_lhs, .op=impl->e->d.prim.d.var, .rhs=&_rhs };//
-  //  .lhs=func->def->base->args // TODO
   self.d.exp_binary.lhs = &_lhs;
   self.d.exp_binary.rhs = &_rhs;
   self.d.exp_binary.op  = impl->e->d.prim.d.var;
@@ -616,7 +571,7 @@ static OP_CHECK(opck_op_impl) {
     env_pop(env, scope);
     if (exists) { // improve me
       if (eff) {
-        free_mp_vector(env->gwion->mp, sizeof(struct ScopeEffect), eff);
+        free_mp_vector(env->gwion->mp, struct ScopeEffect, eff);
         ERR_N(impl->pos,
               _("`{+Y}%s{0}` has effects not present in `{+G}%s{0}`\n"),
               s_name(impl->e->d.prim.d.var), func->name);
@@ -637,7 +592,7 @@ static OP_CHECK(opck_op_impl) {
       struct ScopeEffect *effect = mp_vector_at(eff, struct ScopeEffect, i);
       vector_add(&base->effects, (m_uint)effect->sym);
     }
-    free_mp_vector(env->gwion->mp, sizeof(struct ScopeEffect), eff);
+    free_mp_vector(env->gwion->mp, struct ScopeEffect, eff);
   }
   const Exp lhs =
       new_prim_id(env->gwion->mp, larg0->var_decl.xid, impl->e->pos);
@@ -645,7 +600,7 @@ static OP_CHECK(opck_op_impl) {
       new_prim_id(env->gwion->mp, larg1->var_decl.xid, impl->e->pos);
   const Exp  bin = new_exp_binary(env->gwion->mp, lhs, impl->e->d.prim.d.var,
                                  rhs, impl->e->pos);
-  Stmt_List slist = new_mp_vector(env->gwion->mp, sizeof(struct Stmt_), 1);
+  Stmt_List slist = new_mp_vector(env->gwion->mp, struct Stmt_, 1);
   mp_vector_set(slist, struct Stmt_, 0,
     ((struct Stmt_) {
     .stmt_type = ae_stmt_return, .d = { .stmt_exp = { .val = bin }},
@@ -654,6 +609,8 @@ static OP_CHECK(opck_op_impl) {
   const Stmt      code = new_stmt_code(env->gwion->mp, slist, impl->e->pos);
   const Func_Def  def  = new_func_def(env->gwion->mp, base, code);
   def->base->xid       = impl->e->d.prim.d.var;
+// use envset
+// or better, some function with envset and traverse
   const m_uint scope   = env_push(env, NULL, opi.nspc);
   // we assume succes here
   /*const m_bool ret = */ traverse_func_def(env, def);
@@ -664,100 +621,6 @@ static OP_CHECK(opck_op_impl) {
   return actual_type(env->gwion, func->value_ref->type);
 }
 
-static OP_EMIT(opem_op_impl) {
-  struct Implicit *impl  = (struct Implicit *)data;
-  const Func_Def   fdef  = impl->e->type->info->func->def;
-  const m_bool     ret   = emit_func_def(emit, fdef);
-  const Instr      instr = emit_add_instr(emit, RegSetImm);
-  instr->m_val           = (m_uint)fdef->base->func->code;
-  instr->m_val2          = -SZ_INT;
-  return ret;
-}
-
-ANN static Type fork_type(const Env env, const Exp_Unary *unary) {
-  const Type t = unary->exp->type;
-  if (t == env->gwion->type[et_void]) return env->gwion->type[et_fork];
-  char c[21 + strlen(t->name)];
-  sprintf(c, "TypedFork:[%s]", t->name);
-  const Type fork = env->gwion->type[et_fork];
-  UNSET_FLAG(fork, final);
-  const Type typed = str2type(env->gwion, "TypedFork", exp_self(unary)->pos);
-  // ensure room for retval
-  if (typed->nspc->offset == fork->nspc->offset)
-    typed->nspc->offset += t->size;
-  UNSET_FLAG(typed, final);
-  const Type ret = str2type(env->gwion, c, exp_self(unary)->pos);
-  SET_FLAG(typed, final);
-  SET_FLAG(fork, final);
-  return ret;
-}
-
-ANN Type upvalue_type(const Env env, Capture *cap) {
-  const Value v = nspc_lookup_value1(env->curr, cap->xid);
-  if(!v) ERR_O(cap->pos, _("non existing value")); // did_you_mean
-  if(cap->is_ref && not_upvalue(env, v))
-    ERR_O(cap->pos, _("can't take ref of a scoped value"));
-  cap->orig = v;
-  const Type base_type = !tflag(v->type, tflag_ref) ? v->type : (Type)vector_front(&v->type->info->tuple->contains);
-  return !cap->is_ref ? base_type :  ref_type(env->gwion, base_type, cap->pos);
-}
-
-static OP_CHECK(opck_spork) {
-  const Exp_Unary *unary = (Exp_Unary *)data;
-  if (unary->unary_type == unary_exp && unary->exp->exp_type == ae_exp_call) {
-    const m_bool is_spork = unary->op == insert_symbol("spork");
-    return is_spork ? env->gwion->type[et_shred] : fork_type(env, unary);
-  }
-  if (unary->unary_type == unary_code) {
-    if(unary->captures) {
-      uint32_t offset = !env->class_def ? 0 : SZ_INT;
-      for(uint32_t i = 0; i < unary->captures->len; i++) {
-        Capture *const cap = mp_vector_at(unary->captures, Capture, i);
-        DECL_OO(const Type, t, = upvalue_type(env, cap));
-        cap->temp = new_value(env, t, s_name(cap->xid), cap->pos);
-        cap->temp->from->offset = offset;
-        offset += cap->temp->type->size;
-      }
-    }
-    Upvalues upvalues = { .values = env->curr->info->value };
-    if(env->func && env->func->def->base->values)
-      upvalues.parent = env->func->def->base->values;
-    env->curr->info->value = new_scope(env->gwion->mp);
-    if(unary->captures) {
-      for(uint32_t i = 0; i < unary->captures->len; i++) {
-        Capture *const cap = mp_vector_at(unary->captures, Capture, i);
-        valid_value(env, cap->xid, cap->temp);
-      }
-    }
-    const Func f = env->func;
-    struct Value_ value = { .type = env->gwion->type[et_lambda]};
-    if(env->class_def)
-      set_vflag(&value, vflag_member);
-    struct Func_Base_ fbase = { .xid=insert_symbol("in spork"), .values = &upvalues, .pos = exp_self(unary)->pos};
-    set_fbflag(&fbase, fbflag_lambda);
-    struct Func_Def_ fdef = { .base = &fbase};
-    struct Func_ func = { .name = "in spork", .def = &fdef, .value_ref = &value};
-    env->func = &func;
-//    ++env->scope->depth;
-//nspc_push_value(env->gwion->mp, env->curr);
-    const m_bool ret = check_stmt(env, unary->code);
-// nspc_push_value(env->gwion->mp, env->curr);
-//    --env->scope->depth;
-    env->func = f;
-    free_scope(env->gwion->mp, env->curr->info->value);
-    env->curr->info->value = upvalues.values;
-    CHECK_BN(ret);
-    return env->gwion
-        ->type[unary->op == insert_symbol("spork") ? et_shred : et_fork];
-  }
-  ERR_O(exp_self(unary)->pos, _("only function calls can be sporked..."))
-}
-
-static OP_EMIT(opem_spork) {
-  const Exp_Unary *unary = (Exp_Unary *)data;
-  return emit_exp_spork(emit, unary);
-}
-
 static OP_CHECK(opck_func_partial) {
   Exp_Call *call = (Exp_Call*)data;
   return partial_type(env, call);
@@ -772,51 +635,120 @@ static OP_CHECK(opck_class_partial) {
    return op_check(env, &opi);
 }
 
-static FREEARG(freearg_xork) { vmcode_remref((VM_Code)instr->m_val, gwion); }
-
 static FREEARG(freearg_dottmpl) {
-  struct dottmpl_ *dt = (struct dottmpl_ *)instr->m_val;
-  if (dt->tl) free_type_list(((Gwion)gwion)->mp, dt->tl);
-  mp_free(((Gwion)gwion)->mp, dottmpl, dt);
+  if (instr->m_val2) free_mstr(((Gwion)gwion)->mp, (m_str)instr->m_val2);
+}
+
+#include "tmpl_info.h"
+#include "parse.h"
+#include "traverse.h"
+#include "gwi.h"
+
+ANN bool tmpl_global(const Env env, Type_List tl);
+
+ANN static bool is_base(const Env env, const Type_List tl) {
+  for(uint32_t i = 0; i < tl->len; i++) {
+    Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i);
+    if(known_type(env, td) == env->gwion->type[et_auto])
+      return true;
+  }
+  return false;
+}
+
+static OP_CHECK(opck_closure_scan) {
+  struct TemplateScan *ts   = (struct TemplateScan *)data;
+  struct tmpl_info     info = {
+      .base = ts->t, .td = ts->td, .list = ts->t->info->cdef->base.tmpl->list};
+  const Type exists = tmpl_exists(env, &info);
+  if (exists) return exists != env->gwion->type[et_error] ? exists : NULL;
+  const Func_Base *base = closure_def(ts->t)->base;
+  const Arg_List args = base->args ? cpy_arg_list(env->gwion->mp, base->args) : NULL;
+  Func_Base *const fbase = new_func_base(env->gwion->mp, cpy_type_decl(env->gwion->mp, base->td), info.name, args, ae_flag_none, base->pos);
+  fbase->tmpl = cpy_tmpl(env->gwion->mp, base->tmpl);
+  if(!is_base(env, ts->td->types))
+    fbase->tmpl->call = cpy_type_list(env->gwion->mp, ts->td->types);
+  const Fptr_Def fdef = new_fptr_def(env->gwion->mp, cpy_func_base(env->gwion->mp, fbase));
+  fdef->base->xid = info.name;
+  struct EnvSet es    = {.env   = env,
+                      .data  = env,
+                      .func  = (_exp_func)traverse_cdef,
+                      .scope = env->scope->depth,
+                      .flag  = tflag_scan0};
+  const Type    owner = ts->t;
+  CHECK_BO(envset_pushv(&es, owner->info->value));
+  const m_bool ret = traverse_fptr_def(env, fdef);
+  const Type t = ret > 0 ? fdef->cdef->base.type : NULL;
+  if (es.run) envset_pop(&es, owner->info->value->from->owner_class);
+  free_fptr_def(env->gwion->mp, fdef); // clean?
+  if(t) set_tflag(t, tflag_emit);
+  return t;
 }
 
+static CTOR(fptr_ctor) {
+  *(VM_Code*)o->data = ((Func)vector_front(&o->type_ref->nspc->vtable))->code;
+}
+
+static DTOR(fptr_dtor) {
+  m_bit *const caps = *(m_bit**)(o->data + SZ_INT);
+  if(caps) free_captures(shred, caps);
+}
+
+static MFUN(fptr_default) {
+  handle(shred, "EmptyFunctionPointer");
+}
+
+static GACK(gack_function) { INTERP_PRINTF("%s", t->name); }
+
 GWION_IMPORT(func) {
-  GWI_BB(gwi_oper_cond(gwi, "@func_ptr", BranchEqInt, BranchNeqInt))
-  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@function", NULL))
+  gwidoc(gwi, "the base of all functions.");
+  const Type t_function = gwi_mk_type(gwi, "function", SZ_INT, NULL);
+  GWI_BB(gwi_gack(gwi, t_function, gack_function))
+  GWI_BB(gwi_set_global_type(gwi, t_function, et_function))
+
+  gwidoc(gwi, "the base of decayed operators.");
+  const Type t_op = gwi_mk_type(gwi, "operator", SZ_INT, "function");
+  GWI_BB(gwi_set_global_type(gwi, t_op, et_op))
+
+  gwidoc(gwi, "the base of function pointers.");
+  const Type t_closure = gwi_class_ini(gwi, "funptr", "Object");
+  t_closure->nspc->offset = SZ_INT*3;
+  gwi_class_xtor(gwi, fptr_ctor, fptr_dtor);
+  GWI_BB(gwi_set_global_type(gwi, t_closure, et_closure))
+  GWI_BB(gwi_func_ini(gwi, "void", "default"));
+  GWI_BB(gwi_func_end(gwi, fptr_default, ae_flag_none));
+  gwi_class_end(gwi);
+
+  GWI_BB(gwi_oper_ini(gwi, "funptr", NULL, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_closure_scan))
+  GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
+
+  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "function", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_func_call))
   GWI_BB(gwi_oper_end(gwi, "=>", NULL))
-  GWI_BB(gwi_oper_ini(gwi, NULL, "@func_ptr", "bool"))
-  GWI_BB(gwi_oper_end(gwi, "!", IntNot))
-  GWI_BB(gwi_oper_ini(gwi, "@function", "@func_ptr", NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_fptr_at))
-  GWI_BB(gwi_oper_emi(gwi, opem_func_assign))
+  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "funptr", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_fptr_call))
+  GWI_BB(gwi_oper_end(gwi, "=>", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "function", "funptr", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_fptr_assign))
+  GWI_BB(gwi_oper_emi(gwi, opem_fptr_assign))
   GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_fptr_impl))
   GWI_BB(gwi_oper_emi(gwi, opem_fptr_impl))
   GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_fptr_cast))
-  GWI_BB(gwi_oper_end(gwi, "$", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@op", "@func_ptr", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "operator", "funptr", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_op_impl))
-  GWI_BB(gwi_oper_emi(gwi, opem_op_impl))
   GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
-  GWI_BB(gwi_oper_ini(gwi, NULL, (m_str)OP_ANY_TYPE, NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_spork))
-  GWI_BB(gwi_oper_emi(gwi, opem_spork))
-  GWI_BB(gwi_oper_end(gwi, "spork", NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_spork))
-  GWI_BB(gwi_oper_emi(gwi, opem_spork))
-  GWI_BB(gwi_oper_end(gwi, "fork", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "@function", "@function", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "function", "function", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_auto_fptr))
   GWI_BB(gwi_oper_end(gwi, "@=>", int_r_assign))
-  GWI_BB(gwi_oper_ini(gwi, "@function", NULL, NULL))
+  GWI_BB(gwi_oper_ini(gwi, "function", NULL, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_func_partial))
   GWI_BB(gwi_oper_end(gwi, "@partial", NULL))
   GWI_BB(gwi_oper_ini(gwi, "Class", NULL, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_class_partial))
   GWI_BB(gwi_oper_end(gwi, "@partial", NULL))
-  gwi_register_freearg(gwi, SporkIni, freearg_xork);
+
   gwi_register_freearg(gwi, DotTmpl, freearg_dottmpl);
+  gwi_register_freearg(gwi, GTmpl, freearg_dottmpl);
   return GW_OK;
 }
index 42006ae1682f768f5e97ce22f87fa802d77218ae..4ef0ac653a959aa1b0a8d7ffa6b885914f460221 100644 (file)
@@ -11,7 +11,6 @@
 #include "gwi.h"
 
 static OP_CHECK(opck_ctrl) {
-
   Exp_Binary *bin = (Exp_Binary*)data;
   MemPool mp = env->gwion->mp;
 
@@ -19,12 +18,12 @@ static OP_CHECK(opck_ctrl) {
   Exp exp = exp_self(data);
   Exp func = cpy_exp(mp, exp); // set operator
 
-const Exp dot = new_exp_dot(mp, func->d.exp_binary.lhs, insert_symbol(env->gwion->st, "last"), func->pos);
-const Exp call = new_exp_call(mp, dot, NULL, func->pos);
-func->d.exp_binary.lhs = call;
+  const Exp dot = new_exp_dot(mp, func->d.exp_binary.lhs, insert_symbol(env->gwion->st, "last"), func->pos);
+  const Exp call = new_exp_call(mp, dot, NULL, func->pos);
+  func->d.exp_binary.lhs = call;
 
   func->d.exp_binary.op = chuck;
-traverse_exp(env, func);
+  traverse_exp(env, func);
 
   struct Stmt_ one = { .d = { .stmt_exp = { .val = func }}, .stmt_type = ae_stmt_exp, .pos = func->pos };
 
@@ -32,9 +31,9 @@ traverse_exp(env, func);
   Exp _now = new_prim_id(mp, insert_symbol(env->gwion->st, "now"), func->pos);
   Exp time = new_exp_binary(mp, samp, chuck, _now, func->pos);
   struct Stmt_ two = { .d = { .stmt_exp = { .val = time }}, .stmt_type = ae_stmt_exp, .pos = func->pos };
-traverse_exp(env, time);
+  traverse_exp(env, time);
 
-  Stmt_List slist = new_mp_vector(mp, sizeof(struct Stmt_), 2);
+  Stmt_List slist = new_mp_vector(mp, struct Stmt_, 2);
   mp_vector_set(slist, struct Stmt_, 0, one);
   mp_vector_set(slist, struct Stmt_, 1, two);
 
@@ -61,7 +60,7 @@ GWION_IMPORT(ctrl) {
               "#!-     samp => now;\n"
               "#!-   }\n"
               "#!- }");
-  GWI_BB(gwi_oper_ini(gwi, "UGen", "@function", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "UGen", "function", NULL))
   GWI_BB(gwi_oper_add(gwi, opck_ctrl))
   GWI_BB(gwi_oper_end(gwi, "|>", NULL))
   return GW_OK;
index 28d1ccbb7166fdd4edc326cb8be26f7cc5e9c613..2e6448b046a88cc09e1e1da4b3ac17cc989e71ca 100644 (file)
@@ -48,7 +48,7 @@ static void type_get_member(const Gwion gwion, const Type t, const Vector v) {
   for(m_uint i = 0; i < map_size(m); i++) {
     const Value value = (Value)map_at(m, i);
     if(!vflag(value, vflag_member)) continue;
-    if(is_func(gwion, value->type) && !is_fptr(gwion, value->type)) continue; // is_func
+    if(is_func(gwion, value->type)) continue;
     vector_add(v, (m_uint)value);
   }
 }
@@ -124,9 +124,9 @@ static OP_CHECK(opck_deep_equal) {
   const Symbol op = bin->op;
   bin->op = !strcmp(s_name(bin->op), "?=")
     ? insert_symbol(env->gwion->st, "==") : insert_symbol(env->gwion->st, "!=");
-  env->context->error = true;
+  env_set_error(env,  true);
   const Type ret_type = check_exp(env, exp_self(bin));
-  env->context->error = false;
+  env_set_error(env,  false);
   if(ret_type) return env->gwion->type[et_bool];
   ERR_N(exp_self(bin)->pos, "no deep operation for: {G+/}%s{0} {+}%s{0} {G+/}%s{0}",
       bin->lhs->type->name, s_name(op), bin->rhs->type->name);
index 98d4f121a0fabde8ae80554ba4dd216f89190aa9..3fb819890fa825f7c892a4c8902a1d27b521eecb 100644 (file)
@@ -632,7 +632,6 @@ static OP_CHECK(opck_dict_scan) {
   const Class_Def cdef  = cpy_class_def(env->gwion->mp, env->gwion->type[et_dict]->info->cdef);
   cdef->base.ext        = type2td(env->gwion, env->gwion->type[et_dict], (loc_t) {});
   cdef->base.xid        = info.name;
-  cdef->base.tmpl->base = 1; // could store depth here?
   cdef->base.tmpl->call = cpy_type_list(env->gwion->mp, info.td->types);
 
   (void)scan0_class_def(env, cdef);
index 894f68b7330ab284bf33549ce4a00c4b402d811c..98d633a76425345e253381646dcc3a52b023c8b0 100644 (file)
@@ -19,16 +19,6 @@ static GACK(gack_class) {
   INTERP_PRINTF("%s", type->name)
 }
 
-static GACK(gack_function) { INTERP_PRINTF("%s", t->name) }
-
-static GACK(gack_fptr) {
-  const VM_Code code = *(VM_Code *)VALUE;
-  if (code)
-    INTERP_PRINTF("%s", code->name)
-  else
-    INTERP_PRINTF("%s", t->name)
-}
-
 static GACK(gack_void) { INTERP_PRINTF("void"); }
 
 static GACK(gack_int) { INTERP_PRINTF("%" INT_F, *(m_uint *)VALUE); }
@@ -121,25 +111,7 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   GWI_BB(import_object(gwi))
 
   GWI_BB(import_prim(gwi))
-  gwidoc(gwi, "the base of all functions.");
-  const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL);
-  GWI_BB(gwi_gack(gwi, t_function, gack_function))
-  GWI_BB(gwi_set_global_type(gwi, t_function, et_function))
-
-  gwidoc(gwi, "the base of function pointers.");
-  const Type t_fptr = gwi_mk_type(gwi, "@func_ptr", SZ_INT, "@function");
-  GWI_BB(gwi_gack(gwi, t_fptr, gack_fptr))
-  GWI_BB(gwi_set_global_type(gwi, t_fptr, et_fptr))
-
-  gwidoc(gwi, "the base of decayed operators.");
-  const Type t_op = gwi_mk_type(gwi, "@op", SZ_INT, "@function");
-  GWI_BB(gwi_set_global_type(gwi, t_op, et_op))
-
-  gwidoc(gwi, "the base of lamdbas.");
-  const Type t_lambda = gwi_mk_type(gwi, "@lambda", SZ_INT, "@function");
-  /*set_tflag(t_lambda, tflag_infer);*/
-  GWI_BB(gwi_set_global_type(gwi, t_lambda, et_lambda))
-
+  GWI_BB(import_func(gwi))
   GWI_BB(import_object_op(gwi))
   GWI_BB(import_values(gwi))
   GWI_BB(import_union(gwi))
@@ -148,12 +120,11 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   GWI_BB(import_event(gwi))
   GWI_BB(import_ugen(gwi))
   GWI_BB(import_ptr(gwi))
-  GWI_BB(import_func(gwi))
+  GWI_BB(import_xork(gwi))
   GWI_BB(gwi_oper_ini(gwi, NULL, (m_str)OP_ANY_TYPE, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_new))
   GWI_BB(gwi_oper_emi(gwi, opem_new))
   GWI_BB(gwi_oper_end(gwi, "new", NULL))
-  GWI_BB(import_vararg(gwi))
   GWI_BB(import_string(gwi))
   GWI_BB(import_shred(gwi))
   GWI_BB(import_modules(gwi))
index f9f546e44e6a903c1f1b200495c28932b31cdc14..f827d10151f1f9ef03ab196fc2954fe9925a1dca 100644 (file)
 #include "gwion_env.h"
 #include "vm.h"
 #include "instr.h"
-#include "shreduler_private.h"
 #include "gwion.h"
 #include "object.h"
-#include "array.h"
 #include "operator.h"
 #include "import.h"
 #include "emit.h"
-#include "template.h"
-/*
-INSTR(DTOR_EOC) {
-  const M_Object o = *(M_Object *)MEM(0);
-  o->type_ref      = o->type_ref->info->parent;
-  _release(o, shred);
-  shred->info->me->ref = 1;
-  vm_shred_exit(shred);
-}
-*/
-ANN static Func_Def from_base(const Env env, struct dottmpl_ *const dt,
+
+ANN static Func_Def traverse_tmpl(const Emitter emit, Func_Def fdef, Func_Def fbase,
                               const Nspc nspc) {
-  const Func_Def fdef = dt->def ?: dt->base;
+  const Env env = emit->env;
   const Symbol   sym  = func_symbol(env, nspc->name, s_name(fdef->base->xid),
-                                 "template", dt->base->base->tmpl->base);
+                                 "template", fbase->vt_index);
   DECL_OO(const Value, v, = nspc_lookup_value0(nspc, sym)
                                 ?: nspc_lookup_value0(nspc, fdef->base->xid));
-  if (is_class(env->gwion, v->type)) return NULL;
-  if (vflag(v, vflag_builtin)) {
-    dt->xfun                          = v->d.func_ref->def->d.dl_func_ptr;
-    v->d.func_ref->def->d.dl_func_ptr = NULL;
-  }
+  const f_xfun xfun = v->d.func_ref->def->d.dl_func_ptr;
+  if (vflag(v, vflag_builtin))
+    v->d.func_ref->def->d.dl_func_ptr = NULL; // why
   const Func_Def def = cpy_func_def(env->gwion->mp, v->d.func_ref->def);
-  if (vflag(v, vflag_builtin)) v->d.func_ref->def->d.dl_func_ptr = dt->xfun;
-  def->base->tmpl->call = cpy_type_list(env->gwion->mp, dt->tl);
-  def->base->tmpl->base = dt->base->base->tmpl->base;
-  dt->def               = def;
-  dt->owner             = v->from->owner;
-  dt->owner_class       = v->from->owner_class;
+  if (vflag(v, vflag_builtin)) v->d.func_ref->def->d.dl_func_ptr = xfun;
+  def->base->tmpl->call = cpy_type_list(env->gwion->mp, fbase->base->tmpl->call);
+  CHECK_BO(traverse_dot_tmpl(emit, def, v));
+  if (vflag(v, vflag_builtin)) builtin_func(emit->gwion->mp, def->base->func, xfun);
   return def;
 }
 
-ANN static Func_Def traverse_tmpl(const Emitter emit, struct dottmpl_ *const dt,
-                                  const Nspc nspc) {
-  DECL_OO(const Func_Def, def, = from_base(emit->env, dt, nspc));
-  CHECK_BO(traverse_dot_tmpl(emit, dt));
-  if (dt->xfun) builtin_func(emit->gwion->mp, def->base->func, dt->xfun);
-  return def;
+ANN static void foo(const VM_Shred shred, Type t, const Func_Def fbase, const m_str tmpl_name) {
+  const Emitter emit = shred->info->vm->gwion->emit;
+  emit->env->name    = "runtime";
+  do {
+    const Func base = fbase->base->func;
+    const Symbol sym  = func_symbol(emit->env, t->name, base->name, tmpl_name, base->def->vt_index);
+    const Func f = nspc_lookup_func0(t->nspc, sym);
+    if (f) {
+      if(!f->code) exit(15); //continue;
+      if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT;
+      *(VM_Code *)(shred->reg - SZ_INT) = f->code;
+      return;
+    } else {
+      const Func_Def def = traverse_tmpl(emit, fbase, fbase, t->nspc);
+      if (!def) continue;
+      const Func f = def->base->func;
+      if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT;
+      *(VM_Code *)(shred->reg - SZ_INT) = f->code;
+      return;
+    }
+  } while ((t = t->info->parent));
+  handle(shred, "MissigTmplPtrException");
 }
 
 INSTR(GTmpl) {
-  struct dottmpl_ *dt = (struct dottmpl_ *)instr->m_val;
+  const Func_Def fbase = (Func_Def)instr->m_val;
+  const m_str tmpl = (m_str)instr->m_val2;
   const Func       f  = *(Func *)REG(-SZ_INT);
+  const Func       _f  = *(Func *)REG(-SZ_INT);
   if (!f) {
     handle(shred, "EmptyFuncPointerException");
-    return;
+     return;
   }
   if (f->code) {
     *(VM_Code *)(shred->reg - SZ_INT) = f->code;
     return;
   }
-  const m_str   name      = f->name;
   const Emitter emit      = shred->info->vm->gwion->emit;
   emit->env->name         = "runtime";
-  struct loc_t_ pos       = {};
-  m_str         tmpl_name = tl2str(emit->gwion, dt->tl, pos);
-  for (m_uint i = 0; i <= f->value_ref->from->offset; ++i) {
-    const Symbol sym  = func_symbol(emit->env, f->value_ref->from->owner->name,
-                                   name, tmpl_name, i);
-    const Func   base = nspc_lookup_func0(f->value_ref->from->owner, sym);
-    if (base) {
-      free_mstr(emit->gwion->mp, tmpl_name);
-      assert(base->code);
-      *(VM_Code *)(shred->reg - SZ_INT) = base->code;
+  Type t = f->value_ref->from->owner_class;
+  if(!t) {
+    const Nspc nspc = f->value_ref->from->owner;
+    for (m_uint i = 0; i <= f->value_ref->from->offset; ++i) {
+      const Symbol sym  = func_symbol(emit->env, nspc->name, f->name, tmpl, i);
+      const Func   base = nspc_lookup_func0(nspc, sym);
+      if (base) {
+        assert(base->code);
+        *(VM_Code *)(shred->reg - SZ_INT) = base->code;
+        return;
+      }
+    }
+    const Func_Def def = traverse_tmpl(emit, f->def, fbase, nspc);
+    if (def) {
+      *(VM_Code *)(shred->reg - SZ_INT) = def->base->func->code;
       return;
     }
+  } else {
+    do {
+      const Symbol sym  = func_symbol(emit->env, t->name, f->name, tmpl, f->def->vt_index);
+      const Func f = nspc_lookup_func0(t->nspc, sym);
+      if (f) {
+        if (!f->code) exit(15); //continue;
+        *(VM_Code *)(shred->reg - SZ_INT) = f->code;
+        return;
+      } else {
+        const Func_Def def = traverse_tmpl(emit, _f->def, fbase, t->nspc);
+        if (!def) continue;
+        const Func f = def->base->func;
+        *(VM_Code *)(shred->reg - SZ_INT) = f->code;
+        return;
+      }
+    } while ((t = t->info->parent));
   }
-  free_mstr(emit->gwion->mp, tmpl_name);
-  dt->def            = f->def;
-  const Func_Def def = traverse_tmpl(emit, dt, f->value_ref->from->owner);
-  if (def)
-    *(VM_Code *)(shred->reg - SZ_INT) = def->base->func->code;
-  else
-    handle(shred, "MissigTmplPtrException");
 }
 
 INSTR(DotTmpl) {
-  struct dottmpl_ *dt   = (struct dottmpl_ *)instr->m_val;
-  const m_str      name = dt->name;
-  const M_Object   o    = *(M_Object *)REG(-SZ_INT);
-  Type             t    = o->type_ref;
-  do {
-    const Emitter emit = shred->info->vm->gwion->emit;
-    emit->env->name    = "runtime";
-    char str[instr->m_val2 + strlen(t->name) + 1];
-    strcpy(str, name);
-    strcpy(str + instr->m_val2, t->name);
-    const Func f =
-        nspc_lookup_func0(t->nspc, insert_symbol(emit->env->gwion->st, str));
-    if (f) {
-      if (!f->code) continue;
-      if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT;
-      *(VM_Code *)(shred->reg - SZ_INT) = f->code;
-      return;
-    } else {
-      const Func_Def def = traverse_tmpl(emit, dt, t->nspc);
-      if (!def) continue;
-      const Func f = def->base->func;
-      if (vflag(f->value_ref, vflag_member)) shred->reg += SZ_INT;
-      *(VM_Code *)(shred->reg - SZ_INT) = f->code;
-      return;
-    }
-  } while ((t = t->info->parent));
-  handle(shred, "MissigTmplException");
+  const Func_Def fbase = (Func_Def)instr->m_val;
+  const m_str tmpl = (m_str)instr->m_val2;
+  const M_Object   o    = *(M_Object *)REG(-SZ_INT); // orig
+  foo(shred, o->type_ref, fbase, tmpl);
 }
 
 #define VAL  (*(m_uint *)(byte + SZ_INT))
@@ -126,8 +119,7 @@ INSTR(DotTmpl) {
   *(m_uint *)byte = a;
 
 INSTR(SetFunc) {
-//  BYTE(eRegPushImm)
-  m_bit *byte    = shred->code->bytecode + (shred->pc - 1) * BYTECODE_SZ;       \
+  m_bit *byte    = shred->code->bytecode + (shred->pc - 1) * BYTECODE_SZ;
   *(m_uint *)byte = instr->opcode;
   instr->opcode = eRegPushImm;
   const Func f = (Func)instr->m_val;
index 21f8e0ea841a3566b7775682ea1b6a40f6d1373b..73dd192cbae8cd76f8e83e53c1a2264691ad7e7e 100644 (file)
@@ -282,7 +282,7 @@ static GWION_IMPORT(usrugen) {
   GWI_BB(gwi_func_ini(gwi, "int", "default_tick"))
   GWI_BB(gwi_func_end(gwi, default_tick, 0))
   GWI_BB(gwi_class_end(gwi))
-  GWI_BB(gwi_oper_ini(gwi, "@function", "UsrUGen", "UsrUGen"))
+  GWI_BB(gwi_oper_ini(gwi, "function", "UsrUGen", "UsrUGen"))
   GWI_BB(gwi_oper_add(gwi, opck_usrugen))
   GWI_BB(gwi_oper_emi(gwi, opem_usrugen))
   GWI_BB(gwi_oper_end(gwi, "~=>", NULL))
index 6db3f0606d30b911e85f2e2d4407a3934ff04b1a..8289303f7c3e08aae7473e7ecb66d27208614478 100644 (file)
@@ -108,7 +108,7 @@ static ID_EMIT(opem_this) {
     return (Instr)GW_OK;
   }
   const Instr instr = emit_add_instr(emit, RegPushMem);
-  instr->m_val      = emit->this_offset;
+  instr->m_val      = emit->status.this_offset;
   return instr;
 }
 
index d748b5e472668cd4c48ccdf91564edae93508e34..336d39845e6697742a39384a5a5c0b18946e506c 100644 (file)
@@ -31,8 +31,8 @@ static OP_CHECK(opck_object_at) {
   if (opck_rassign(env, data) == env->gwion->type[et_error])
     return env->gwion->type[et_error];
   if (bin->rhs->exp_type == ae_exp_decl) {
-    Var_Decl vd = mp_vector_at(bin->rhs->d.exp_decl.list, struct Var_Decl_, 0);
-    SET_FLAG(vd->value, late);
+    Var_Decl vd = bin->rhs->d.exp_decl.vd;
+    SET_FLAG(vd.value, late);
   }
   exp_setvar(bin->rhs, 1);
   CHECK_BO(isa(bin->lhs->type, bin->rhs->type));
@@ -95,6 +95,7 @@ ANN static void emit_dot_static_import_data(const Emitter emit, const Value v,
   } else
     emit_dot_static_data(emit, v, emit_addr);
 }
+
 ANN static void emit_member_func(const Emitter emit, const Exp_Dot *member) {
   const Func f = exp_self(member)->type->info->func;
 
@@ -105,9 +106,18 @@ ANN static void emit_member_func(const Emitter emit, const Exp_Dot *member) {
     }
     return;
   }
-  if (f->def->base->tmpl)
-    emit_add_instr(emit, DotTmplVal);
-  else if (is_static_call(emit, exp_self(member))) {
+  if (f->def->base->tmpl) {
+    if(member->is_call) emit_add_instr(emit, DotTmplVal);
+    else {
+      if(vflag(f->value_ref, vflag_member)) {
+        const Instr instr = emit_add_instr(emit, RegMove);
+        instr->m_val = -SZ_INT;
+      }
+      const Instr instr = emit_add_instr(emit, RegPushImm);
+      instr->m_val = (m_uint)f;
+      return;
+    }
+  } else if (is_static_call(emit, exp_self(member))) {
     if (member->is_call && f == emit->env->func) return;
     const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : SetFunc);
     func_i->m_val      = (m_uint)f->code ?: (m_uint)f;
@@ -123,18 +133,14 @@ ANN static void emit_member_func(const Emitter emit, const Exp_Dot *member) {
       return;
     }
     const Instr instr = emit_add_instr(emit, DotFunc);
-    instr->m_val      = f->vt_index;
+    instr->m_val      = f->def->vt_index;
     if (!vflag(f->value_ref, vflag_member))
       instr->m_val2 = -SZ_INT;
     else {
       if(member->is_call){
         const Instr instr = emit_add_instr(emit, RegMove);
         instr->m_val      = SZ_INT;
-      } else {
-        const Instr instr = (Instr)vector_back(&emit->code->instr);
-        instr->opcode = eRegPushImm;
-        instr->m_val = (m_uint)f->code;
-      }
+      } else instr->m_val2 = -SZ_INT;
     }
   }
   return;
@@ -222,7 +228,7 @@ OP_CHECK(opck_object_dot) {
                   exp_self(member)->pos, 0);
       env_error_footer(env);
       defined_here(value);
-      env_set_error(env);
+      env_set_error(env, true);
     } else if (GET_FLAG(value, protect))
       exp_setprot(exp_self(member), 1);
   }
@@ -255,13 +261,12 @@ OP_EMIT(opem_object_dot) {
   }
   if (!is_class(emit->gwion, member->base->type) &&
       (vflag(value, vflag_member) ||
-       (is_func(emit->gwion, exp_self(member)->type) && // is_func
-        !is_fptr(emit->gwion, exp_self(member)->type)))) {
+       (is_func(emit->gwion, exp_self(member)->type)))) {
     if (!tflag(t_base, tflag_struct) && vflag(value, vflag_member))
       CHECK_BB(emit_exp(emit, member->base));
   }
   if (is_func(emit->gwion, exp_self(member)->type) && // is_func
-      !is_fptr(emit->gwion, exp_self(member)->type))
+      !fflag(exp_self(member)->type->info->func, fflag_fptr))
     emit_member_func(emit, member);
   else if (vflag(value, vflag_member)) {
     if (!tflag(t_base, tflag_struct))
@@ -277,7 +282,7 @@ OP_EMIT(opem_object_dot) {
     const Instr instr = emit_add_instr(emit, RegPushImm);
     instr->m_val      = (m_uint)value->type;
   }
-  if((isa(value->type, emit->gwion->type[et_object]) > 0 || is_fptr(emit->gwion, value->type)) &&
+  if(isa(value->type, emit->gwion->type[et_object]) > 0 &&
      !exp_getvar(exp_self(member)) &&
     (GET_FLAG(value, static) || GET_FLAG(value, late)))
     emit_fast_except(emit, value->from, exp_self(member)->pos);
@@ -348,7 +353,7 @@ ANN Type scan_class(const Env env, const Type t, const Type_Decl *td) {
                       .data  = env,
                       .func  = (_exp_func)scan0_cdef,
                       .scope = env->scope->depth,
-                      .flag  = tflag_scan0};
+                      .flag  = tflag_check};
   const Type    owner = t->info->value->from->owner_class;
   CHECK_BO(envset_pushv(&es, t->info->value));
   const bool local = !owner && !tmpl_global(env, td->types) && from_global_nspc(env, env->curr);
@@ -430,7 +435,7 @@ GWION_IMPORT(object_op) {
   GWI_BB(gwi_oper_end(gwi, "$", NULL))
   GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool"))
   GWI_BB(gwi_oper_emi(gwi, opem_uncond_object))
-  GWI_BB(gwi_oper_end(gwi, "@unconditionnal", NULL))
+  GWI_BB(gwi_oper_end(gwi, "@unconditional", NULL))
   GWI_BB(gwi_oper_emi(gwi, opem_cond_object))
   GWI_BB(gwi_oper_end(gwi, "@conditional", NULL))
   GWI_BB(gwi_oper_emi(gwi, opem_not_object))
index 8ecc99c64bb2b03a1cb877963ee7aeab512b2476..ce1cfe99fcd7722925e36fcac5cc7e72be00a704 100644 (file)
@@ -52,7 +52,7 @@ static OP_CHECK(opck_ctrl) {
 
   free_exp(mp, bin->lhs);
   free_exp(mp, bin->rhs);
-  Stmt_List slist = new_mp_vector(mp, sizeof(struct Stmt_), 2);
+  Stmt_List slist = new_mp_vector(mp, struct Stmt_, 2);
   mp_vector_set(slist, struct Stmt_, 0, one);
   mp_vector_set(slist, struct Stmt_, 1, two);
   const Stmt stmt = new_stmt_code(mp, slist, func->pos);
@@ -81,11 +81,19 @@ GWION_IMPORT(sift) {
               "#!-     samp => now;\n"
               "#!-   }\n"
               "#!- }");
-  GWI_BB(gwi_oper_ini(gwi, "UGen", "@function", "Sift"));
+  GWI_BB(gwi_oper_ini(gwi, "UGen", "function", "Sift"));
   GWI_BB(gwi_oper_add(gwi, opck_ctrl));
   GWI_BB(gwi_oper_end(gwi, "|>", NULL));
 
-  GWI_BB(gwi_oper_ini(gwi, "Sift", "@function", "Sift"));
+  GWI_BB(gwi_oper_ini(gwi, "Sift", "function", "Sift"));
+  GWI_BB(gwi_oper_add(gwi, opck_sift));
+  GWI_BB(gwi_oper_end(gwi, "|>", NULL));
+
+  GWI_BB(gwi_oper_ini(gwi, "UGen", "funptr", "Sift"));
+  GWI_BB(gwi_oper_add(gwi, opck_ctrl));
+  GWI_BB(gwi_oper_end(gwi, "|>", NULL));
+
+  GWI_BB(gwi_oper_ini(gwi, "Sift", "funptr", "Sift"));
   GWI_BB(gwi_oper_add(gwi, opck_sift));
   GWI_BB(gwi_oper_end(gwi, "|>", NULL));
   return GW_OK;
index a3cf314ef1dc1587e72c40c95e19e60e1fe19653..8bd38f19e96882a28c8d7639252313814ce4b60b 100644 (file)
@@ -39,7 +39,7 @@ static OP_EMIT(opem_union_dot) {
     instr->m_val = (m_uint)f->code;
     return GW_OK;
   }
-  if (!strcmp(s_name(member->xid), "@index")) {
+  if (!strcmp(s_name(member->xid), "index")) {
     emit_add_instr(emit, DotMember);
     return GW_OK;
   }
@@ -86,7 +86,7 @@ static OP_CHECK(opck_union_is) {
       e->exp_type         = ae_exp_binary;
       e->d.exp_binary.lhs = cpy_exp(env->gwion->mp, exp_func);
       e->d.exp_binary.lhs->d.exp_dot.xid =
-          insert_symbol(env->gwion->st, "@index");
+          insert_symbol(env->gwion->st, "index");
       //      e->d.exp_binary.rhs = new_prim_int(env->gwion->mp, i+1, e->pos);
       e->d.exp_binary.rhs = new_prim_int(env->gwion->mp, i, e->pos);
       free_exp(env->gwion->mp, exp_func);
@@ -154,12 +154,12 @@ ANN GWION_IMPORT(union) {
   GWI_BB(gwi_oper_emi(gwi, opem_none))
   GWI_BB(gwi_oper_end(gwi, "=>", NoOp))
 
-  const Type t_union = gwi_class_ini(gwi, "@Union", "Object");
+  const Type t_union = gwi_class_ini(gwi, "union", "Object");
   gwi_class_xtor(gwi, NULL, UnionDtor);
   gwi->gwion->type[et_union] = t_union;
 
-  GWI_BB(gwi_item_ini(gwi, "int", "@index"))
-  GWI_BB(gwi_item_end(gwi, ae_flag_none, num, 0))
+  GWI_BB(gwi_item_ini(gwi, "int", "index"))
+  GWI_BB(gwi_item_end(gwi, ae_flag_const, num, 0))
   GWI_BB(gwi_func_ini(gwi, "bool", "is"))
   GWI_BB(gwi_func_arg(gwi, "int", "member"))
   GWI_BB(gwi_func_end(gwi, union_is, ae_flag_none))
@@ -193,7 +193,7 @@ ANN GWION_IMPORT(union) {
 builtin_func(gwi->gwion->mp, f1, union_new);
   gwi->gwion->type[et_union] = t_union;
 
-  GWI_BB(gwi_oper_ini(gwi, "@Union", (m_str)OP_ANY_TYPE, NULL))
+  GWI_BB(gwi_oper_ini(gwi, "union", (m_str)OP_ANY_TYPE, NULL))
   GWI_BB(gwi_oper_emi(gwi, opem_union_dot))
   GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
 
diff --git a/src/lib/vararg.c b/src/lib/vararg.c
deleted file mode 100644 (file)
index 58467f8..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "gwion_env.h"
-#include "vm.h"
-#include "instr.h"
-#include "emit.h"
-#include "vararg.h"
-#include "gwion.h"
-#include "object.h"
-#include "operator.h"
-#include "import.h"
-#include "gwi.h"
-#include "specialid.h"
-#include "traverse.h"
-#include "parse.h"
-#include "gack.h"
-
-void free_vararg(MemPool p, struct Vararg_ *arg) {
-  if (arg->t.ptr) {
-    xfree(arg->d);
-    vector_release(&arg->t);
-  }
-  mp_free(p, Vararg, arg);
-}
-
-static DTOR(vararg_dtor) {
-  struct Vararg_ *arg = *(struct Vararg_ **)o->data;
-  if (*(m_uint *)(o->data + SZ_INT * 2)) {
-    m_uint offset = 0;
-    for (m_uint i = 0; i < vector_size(&arg->t); ++i) {
-      // could be compound release
-      const Type t = (Type)vector_at(&arg->t, i);
-      if (isa(t, shred->info->vm->gwion->type[et_object]) > 0)
-        release(*(M_Object *)(arg->d + offset), shred);
-      else if (tflag(t, tflag_struct))
-        struct_release(shred, t, *(m_bit **)(arg->d + offset));
-      offset += t->size;
-    }
-  }
-  free_vararg(shred->info->mp, arg);
-}
-
-static MFUN(mfun_vararg_cpy) {
-  struct Vararg_ *src = *(struct Vararg_ **)o->data;
-  struct Vararg_ *arg = mp_calloc(shred->info->mp, Vararg);
-  if(*(m_uint*)(o->data + SZ_INT * 2)) {
-    vector_copy2(&src->t, &arg->t);
-    arg->d = (m_bit *)xmalloc(round2szint(*(m_uint *)(o->data + SZ_INT * 2)));
-  m_uint offset = 0;
-  for (m_uint i = 0; i < vector_size(&arg->t); ++i) {
-    const Type t = (Type)vector_at(&arg->t, *(m_uint *)(o->data + SZ_INT * 4));
-    *(m_uint *)(arg->d + offset) = *(m_uint *)(src->d + offset);
-    if (isa(t, shred->info->vm->gwion->type[et_object]) > 0)
-      ++(*(M_Object *)(arg->d + offset))->ref;
-    offset += t->size;
-  }
-  }
-  const M_Object obj = new_object(shred->info->mp, o->type_ref);
-  *(struct Vararg_ **)obj->data       = arg;
-  *(m_uint *)(obj->data + SZ_INT * 2) = *(m_uint *)(o->data + SZ_INT * 2);
-  *(m_uint *)(obj->data + SZ_INT * 3) = *(m_uint *)(o->data + SZ_INT * 3);
-  *(m_uint *)(obj->data + SZ_INT * 4) = *(m_uint *)(o->data + SZ_INT * 4);
-  *(m_uint *)(obj->data + SZ_INT * 4) = arg->t.ptr ? vector_size(&arg->t) : 0; // can we copy?
-  *(M_Object *)RETURN                 = obj;
-}
-
-INSTR(VarargIni) {
-  const M_Object  o           = new_object(shred->info->mp, shred->info->vm->gwion->type[et_vararg]);
-  struct Vararg_ *arg         = mp_calloc(shred->info->mp, Vararg);
-  *(struct Vararg_ **)o->data = arg;
-  POP_REG(shred, instr->m_val - SZ_INT)
-  if ((*(m_uint *)(o->data + SZ_INT * 2) = instr->m_val)) {
-    arg->d             = (m_bit *)xmalloc(round2szint(instr->m_val));
-    const Vector kinds = (Vector)&instr->m_val2;
-    vector_copy2(kinds, &arg->t);
-    m_uint offset = 0;
-    for (m_uint i = 0; i < vector_size(&arg->t); ++i) {
-      const Type t                 = (Type)vector_at(&arg->t, i);
-      *(m_uint *)(arg->d + offset) = *(m_uint *)(shred->reg - SZ_INT + offset);
-      if (isa(t, shred->info->vm->gwion->type[et_object]) > 0) {
-        const M_Object obj = *(M_Object *)(arg->d + offset);
-        if (obj) ++obj->ref;
-      }
-      offset += t->size;
-    }
-    *(m_uint *)(o->data + SZ_INT * 5) = vector_size(kinds);
-  }
-  *(M_Object *)REG(-SZ_INT) = o;
-//  ++o->ref;
-}
-
-static INSTR(VarargEnd) {
-  const M_Object  o   = *(M_Object *)REG(0);
-  struct Vararg_ *arg = *(struct Vararg_ **)o->data;
-  *(m_uint *)(o->data + SZ_INT * 3) +=
-      arg->t.ptr
-          ? ((Type)vector_at(&arg->t, *(m_uint *)(o->data + SZ_INT * 4)))->size
-          : 0;
-  if (++*(m_uint *)(o->data + SZ_INT * 4) ==
-      *(m_uint *)(o->data + SZ_INT * 5)) {
-    //  if(++*(m_uint*)(o->data + SZ_INT*4) < *(m_uint*)(o->data + SZ_INT * 5))
-    //    shred->pc = instr->m_val;
-    //  else
-    *(m_uint *)(o->data + SZ_INT * 4) = *(m_uint *)(o->data + SZ_INT * 3) = 0;
-    ++shred->pc;
-  }
-}
-
-static OP_CHECK(opck_vararg_cast) {
-  const Exp_Cast *cast = (Exp_Cast *)data;
-  return known_type(env, cast->td);
-}
-
-static INSTR(VarargCast) {
-  const M_Object o = *(M_Object *)REG(-SZ_INT);
-  if (!*(m_uint *)(o->data + SZ_INT)) {
-    handle(shred, "Using Vararg outside varloop");
-    return;
-  }
-  struct Vararg_ *arg = *(struct Vararg_ **)o->data;
-  const Type      t   = (Type)instr->m_val,
-             u = (Type)vector_at(&arg->t, *(m_uint *)(o->data + SZ_INT * 4));
-  if (isa(u, t) > 0 || (u == shred->info->vm->gwion->type[et_error] &&
-                        isa(t, shred->info->vm->gwion->type[et_object]) > 0)) {
-    for (m_uint i = 0; i < t->size; i += SZ_INT)
-      *(m_uint *)REG(i - SZ_INT) =
-          *(m_uint *)(arg->d + *(m_uint *)(o->data + SZ_INT * 3) + i);
-  } else
-    handle(shred, "InvalidVariadicAccess");
-}
-
-static OP_EMIT(opem_vararg_cast) {
-  const Exp_Cast *cast  = (Exp_Cast *)data;
-  const Instr     instr = emit_add_instr(emit, VarargCast);
-  instr->m_val          = (m_uint)exp_self(cast)->type;
-  const Instr push      = emit_add_instr(emit, RegMove);
-  push->m_val           = exp_self(cast)->type->size - SZ_INT;
-  return GW_OK;
-}
-
-static FREEARG(freearg_vararg) {
-  if (instr->m_val2) vector_release((Vector)&instr->m_val2);
-}
-
-static ID_CHECK(idck_vararg) {
-  if (env->func && fbflag(env->func->def->base, fbflag_variadic))
-    return exp_self(prim)->type;
-  ERR_O(exp_self(prim)->pos,
-        _("'vararg' must be used inside variadic function"))
-}
-
-static ID_EMIT(idem_vararg) {
-  const Instr instr = emit_add_instr(emit, RegPushMem);
-  instr->m_val      = emit->vararg_offset + emit->code->stack_depth - SZ_INT;
-  return instr;
-}
-
-static GACK(gack_vararg) { INTERP_PRINTF("%p", *(M_Object *)VALUE); }
-
-ANN void emit_vararg_end(const Emitter emit, const m_uint pc) {
-  const Instr pop = emit_add_instr(emit, RegMove);
-  pop->m_val      = -SZ_INT;
-  (void)emit_add_instr(emit, VarargEnd);
-  const Instr instr = emit_add_instr(emit, Goto);
-  instr->m_val      = pc;
-}
-
-GWION_IMPORT(vararg) {
-  const Type t_vararg = gwi_class_ini(gwi, "Vararg", "Object");
-  gwi_class_xtor(gwi, NULL, vararg_dtor);
-  gwi_gack(gwi, t_vararg, gack_vararg);
-  t_vararg->nspc->offset += SZ_INT;
-  GWI_BB(gwi_item_ini(gwi, "int", "@inLoop"))
-  GWI_BB(gwi_item_end(gwi, ae_flag_none, num, 0))
-  GWI_BB(gwi_item_ini(gwi, "int", "@len"))
-  GWI_BB(gwi_item_end(gwi, ae_flag_none, num, 0))
-  GWI_BB(gwi_item_ini(gwi, "int", "@o"))
-  GWI_BB(gwi_item_end(gwi, ae_flag_none, num, 0))
-  GWI_BB(gwi_item_ini(gwi, "int", "@i"))
-  GWI_BB(gwi_item_end(gwi, ae_flag_none, num, 0))
-  GWI_BB(gwi_item_ini(gwi, "int", "@s"))
-  GWI_BB(gwi_item_end(gwi, ae_flag_none, num, 0))
-  GWI_BB(gwi_func_ini(gwi, "Vararg", "cpy"))
-  GWI_BB(gwi_func_end(gwi, mfun_vararg_cpy, ae_flag_none))
-  GWI_BB(gwi_class_end(gwi))
-  SET_FLAG(t_vararg, abstract | ae_flag_final);
-  gwi->gwion->type[et_vararg] = t_vararg;
-  GWI_BB(gwi_oper_ini(gwi, "Vararg", (m_str)OP_ANY_TYPE, NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_vararg_cast))
-  GWI_BB(gwi_oper_emi(gwi, opem_vararg_cast))
-  GWI_BB(gwi_oper_end(gwi, "$", NULL))
-  gwi_register_freearg(gwi, VarargIni, freearg_vararg);
-  struct SpecialId_ spid = {
-      .type = t_vararg, .is_const = 1, .ck = idck_vararg, .em = idem_vararg};
-  gwi_specialid(gwi, "vararg", &spid);
-  return GW_OK;
-}
diff --git a/src/lib/xork.c b/src/lib/xork.c
new file mode 100644 (file)
index 0000000..423b0bb
--- /dev/null
@@ -0,0 +1,96 @@
+#include <string.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "instr.h"
+#include "emit.h"
+#include "object.h"
+#include "operator.h"
+#include "import.h"
+#include "traverse.h"
+#include "parse.h"
+
+ANN static Type fork_type(const Env env, const Exp_Unary *unary) {
+  const Type t = unary->exp->type;
+  if (t == env->gwion->type[et_void]) return env->gwion->type[et_fork];
+  char c[21 + strlen(t->name)];
+  sprintf(c, "TypedFork:[%s]", t->name);
+  const Type fork = env->gwion->type[et_fork];
+  UNSET_FLAG(fork, final);
+  const Type typed = str2type(env->gwion, "TypedFork", exp_self(unary)->pos);
+  if (typed->nspc->offset == fork->nspc->offset)
+    typed->nspc->offset += t->size;
+  UNSET_FLAG(typed, final);
+  const Type ret = str2type(env->gwion, c, exp_self(unary)->pos);
+  SET_FLAG(typed, final);
+  SET_FLAG(fork, final);
+  return ret;
+}
+
+ANN Type upvalue_type(const Env env, Capture *cap);
+static OP_CHECK(opck_spork) {
+  const Exp_Unary *unary = (Exp_Unary *)data;
+  if (unary->unary_type == unary_exp && unary->exp->exp_type == ae_exp_call) {
+    const m_bool is_spork = unary->op == insert_symbol("spork");
+    return is_spork ? env->gwion->type[et_shred] : fork_type(env, unary);
+  }
+  if (unary->unary_type == unary_code) {
+    if(unary->captures) {
+      uint32_t offset = !env->class_def ? 0 : SZ_INT;
+      for(uint32_t i = 0; i < unary->captures->len; i++) {
+        Capture *const cap = mp_vector_at(unary->captures, Capture, i);
+        DECL_OO(const Type, t, = upvalue_type(env, cap));
+        cap->temp = new_value(env, t, s_name(cap->xid), cap->pos);
+        cap->temp->from->offset = offset;
+        offset += cap->temp->type->size;
+      }
+    }
+    Upvalues upvalues = { .values = env->curr->info->value };
+    if(env->func && env->func->def->base->values)
+      upvalues.parent = env->func->def->base->values;
+    env->curr->info->value = new_scope(env->gwion->mp);
+    if(unary->captures) {
+      for(uint32_t i = 0; i < unary->captures->len; i++) {
+        Capture *const cap = mp_vector_at(unary->captures, Capture, i);
+        valid_value(env, cap->xid, cap->temp);
+      }
+    }
+    const Func f = env->func;
+    struct Value_ value = { .type = env->gwion->type[et_function]};
+    if(env->class_def)
+      set_vflag(&value, vflag_member);
+    struct Func_Base_ fbase = { .xid=insert_symbol("in spork"), .values = &upvalues, .fbflag = fbflag_lambda, .pos = exp_self(unary)->pos};
+    struct Func_Def_ fdef = { .base = &fbase};
+    struct Func_ func = { .name = "in spork", .def = &fdef, .value_ref = &value};
+    env->func = &func;
+    const m_bool ret = check_stmt(env, unary->code);
+    env->func = f;
+    free_scope(env->gwion->mp, env->curr->info->value);
+    env->curr->info->value = upvalues.values;
+    CHECK_BN(ret);
+    return env->gwion
+        ->type[unary->op == insert_symbol("spork") ? et_shred : et_fork];
+  }
+  ERR_O(exp_self(unary)->pos, _("only function calls can be sporked..."))
+}
+
+static OP_EMIT(opem_spork) {
+  const Exp_Unary *unary = (Exp_Unary *)data;
+  return emit_exp_spork(emit, unary);
+}
+
+static FREEARG(freearg_xork) { vmcode_remref((VM_Code)instr->m_val, gwion); }
+
+GWION_IMPORT(xork) {
+  GWI_BB(gwi_oper_ini(gwi, NULL, (m_str)OP_ANY_TYPE, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_spork))
+  GWI_BB(gwi_oper_emi(gwi, opem_spork))
+  GWI_BB(gwi_oper_end(gwi, "spork", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_spork))
+  GWI_BB(gwi_oper_emi(gwi, opem_spork))
+  GWI_BB(gwi_oper_end(gwi, "fork", NULL))
+  gwi_register_freearg(gwi, SporkIni, freearg_xork);
+  return GW_OK;
+}
index f3cb165f0b5dbc395fc50dadf3deea562ecd8c6a..3b470fe2029e44faf49b74e97e02fcca7375b3a2 100644 (file)
@@ -15,6 +15,7 @@
 #include "specialid.h"
 #include "tmp_resolve.h"
 #include "partial.h"
+#include "spread.h"
 
 ANN static m_bool check_stmt_list(const Env env, Stmt_List list);
 ANN m_bool        check_class_def(const Env env, const Class_Def class_def);
@@ -51,7 +52,7 @@ ANN m_bool check_subscripts(Env env, const Array_Sub array,
 }
 
 ANN static inline m_bool check_exp_decl_parent(const Env      env,
-                                               const Var_Decl var) {
+                                               const Var_Decl *var) {
   const Value value = find_value(env->class_def->info->parent, var->xid);
   if (value) {
     env_err(env, var->pos, _("Value defined in parent class"));
@@ -72,22 +73,7 @@ ANN static inline m_bool check_exp_decl_parent(const Env      env,
 describe_check_decl(member, offset, v->vflag |= vflag_member);
 describe_check_decl(static, class_data_size, SET_FLAG(v, static));
 
-ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) {
-  const Value v = var->value;
-  Type        t = v->type;
-  while (tflag(t, tflag_typedef)) t = t->info->parent;
-  if (!t->info->func) return GW_ERROR;
-  if (!env->class_def) return GW_OK;
-  const Func func = t->info->func;
-  const Type type = func->value_ref->from->owner_class;
-  if (type && isa(type, env->class_def) < 0 && !GET_FLAG(func, global))
-    ERR_B(var->pos, _("can't use non global fptr of other class."))
-  if (vflag(func->value_ref, vflag_member) && GET_FLAG(v, static))
-    ERR_B(var->pos, _("can't use static variables for member function."))
-  return GW_OK;
-}
-
-ANN static m_bool check_var(const Env env, const Var_Decl var) {
+ANN static m_bool check_var(const Env env, const Var_Decl *var) {
   if (env->class_def && !env->scope->depth && env->class_def->info->parent)
     CHECK_BB(check_exp_decl_parent(env, var));
   if (var->value->type->effects.ptr) {
@@ -95,12 +81,10 @@ ANN static m_bool check_var(const Env env, const Var_Decl var) {
     for (m_uint i = 0; i < vector_size(v); i++)
       env_add_effect(env, (Symbol)vector_at(v, i), var->pos);
   }
-  if (var->array && var->array->exp)
-    return check_subscripts(env, var->array, 1);
   return GW_OK;
 }
 
-ANN static m_bool check_var_td(const Env env, const Var_Decl var,
+ANN static m_bool check_var_td(const Env env, const Var_Decl *var,
                                Type_Decl *const td) {
   const Value v = var->value;
   if (env->class_def) {
@@ -114,15 +98,11 @@ ANN static m_bool check_var_td(const Env env, const Var_Decl var,
 }
 
 ANN static m_bool check_decl(const Env env, const Exp_Decl *decl) {
-  Var_Decl_List list = decl->list;
-  for(uint32_t i = 0; i < list->len; i++) {
-    const Var_Decl vd = mp_vector_at(list, struct Var_Decl_, i);
-    CHECK_BB(check_var(env, vd));
-    CHECK_BB(check_var_td(env, vd, decl->td));
-    if (is_fptr(env->gwion, decl->type)) CHECK_BB(check_fptr_decl(env, vd));
-    valid_value(env, vd->xid, vd->value);
-    // set_vflag(var->value, vflag_used));
-  }
+  const Var_Decl *vd = &decl->vd;
+  CHECK_BB(check_var(env, vd));
+  CHECK_BB(check_var_td(env, vd, decl->td));
+  valid_value(env, vd->xid, vd->value);
+  // set_vflag(var->value, vflag_used));
   return GW_OK;
 }
 
@@ -175,7 +155,7 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl *decl) {
   const m_bool ret    = check_decl(env, decl);
   if (global) env_pop(env, scope);
   env_weight(env, 1 + isa(decl->type, env->gwion->type[et_object]) > 0);
-  return ret > 0 ? mp_vector_at(decl->list, struct Var_Decl_, 0)->value->type : NULL;
+  return ret > 0 ? decl->vd.value->type : NULL;
 }
 
 ANN static m_bool check_collection(const Env env, Type type, const Exp e,
@@ -186,7 +166,7 @@ ANN static m_bool check_collection(const Env env, Type type, const Exp e,
 
   char fst[20 + strlen(type->name)];
   sprintf(fst, "expected `{+/}%s{0}`", type->name);
-  gwerr_basic(_("literal contains incompatible types"), fst, NULL, env->name,
+  gwerr_basic(_("literal contains incompatible types"), fst, "the first element determines the type", env->name,
               loc, 0);
   // suggested fix: rewrite int 2 as float 2.0"
   char sec[16 + strlen(e->type->name)];
@@ -203,7 +183,7 @@ ANN static inline Type prim_array_match(const Env env, Exp e) {
     if (check_collection(env, type, e, loc) < 0) err = true;
   while ((e = e->next));
   if (!err) return array_type(env, array_base_simple(type), type->array_depth + 1);
-  env_set_error(env);
+  env_set_error(env, true);
   return NULL;
 }
 
@@ -256,7 +236,7 @@ ANN static Type check_prim_dict(const Env env, Exp *data) {
     if (check_collection(env, val, e, loc) < 0) err = true;
   } while ((e = e->next));
   if (!err) return dict_type(env->gwion, key, val, base->pos);
-  env_set_error(env); return NULL;
+  env_set_error(env, true); return NULL;
 }
 
 ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v,
@@ -276,7 +256,7 @@ ANN static inline Value get_value(const Env env, const Symbol sym) {
   }
   if (env->func && env->func->def->base->values) {
     DECL_OO(const Value, v, = upvalues_lookup(env->func->def->base->values, sym));
-    if(isa(env->func->value_ref->type, env->gwion->type[et_lambda]) > 0)
+    if(fbflag(env->func->def->base, fbflag_lambda))
       CHECK_OO(not_upvalue(env, v));
     return v;
   }
@@ -334,8 +314,9 @@ ANN static m_bool check_upvalue(const Env env, const Exp_Primary *prim, const Va
   if(not_upvalue(env, v))
     return GW_OK;
   gwerr_basic(_("value not in lambda scope"), NULL, NULL, env->name, exp_self(prim)->pos, 4242);
-  gwerr_warn("declared here", NULL, _("{-}try adding it to capture list{0}"), v->from->filename, v->from->loc);
-  env->context->error = true;
+  gwerr_secondary_from("declared here", v->from);
+  gw_err("{-}hint:{0} try adding it to capture list");
+  env_set_error(env,  true);
   return GW_ERROR;
 }
 
@@ -371,7 +352,7 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) {
     gwerr_basic(_("Invalid variable"), _("not legit at this point."), NULL,
                 env->name, prim_pos(data), 0);
     did_you_mean_nspc(v ? value_owner(env, v) : env->curr, s_name(sym));
-    env_set_error(env);
+    env_set_error(env, true);
     return NULL;
   }
   prim_self(data)->value = v;
@@ -479,8 +460,7 @@ ANN static inline Type type_list_base_func(const Type type) {
 }
 
 ANN static inline Type type_list_base(const Gwion gwion, const Type type) {
-  return !(is_func(gwion, type) && !is_fptr(gwion, type)) ? // is_func
-    type : type_list_base_func(type);
+  return !(is_func(gwion, type)) ? type : type_list_base_func(type);
 }
 
 ANN static Type_Decl* mk_td(const Env env, const Arg *arg,
@@ -492,20 +472,20 @@ ANN static Type_Decl* mk_td(const Env env, const Arg *arg,
 }
 
 ANN2(1, 2)
-static Func find_func_match_actual(const Env env, Func func, const Exp exp,
+static Func find_func_match_actual(const Env env, const Func f, const Exp exp,
                                    const bool implicit, const bool specific) {
+  Func func = f;
   do {
     Exp e = exp;
     Arg_List args = func->def->base->args;
     m_uint i = 0;
-    const m_uint args_len = args ? args->len : 0;
+    const m_uint args_len = mp_vector_len(args);
     while (e) {
       e->cast_to = NULL;
       if (!e->type) // investigate
         return NULL;
       Arg *arg = i < args_len ? mp_vector_at(args, Arg, i++) : NULL;
       if (!arg) {
-        if (fbflag(func->def->base, fbflag_variadic)) return func;
         CHECK_OO(func->next);
         return find_func_match_actual(env, func->next, exp, implicit,
                                       specific);
@@ -513,15 +493,15 @@ static Func find_func_match_actual(const Env env, Func func, const Exp exp,
       if (tflag(e->type, tflag_ref) && isa(e->type, arg->type) > 0) {
         if(!e->cast_to)e->cast_to = arg->type;
       }
-      if (arg->type == env->gwion->type[et_auto] ||
-          (func->def->base->tmpl &&
-           is_fptr(env->gwion, func->value_ref->type) > 0)) {
+
+      if (arg->type == env->gwion->type[et_auto]) {
         const Type owner = func->value_ref->from->owner_class;
         if (owner) CHECK_BO(template_push(env, owner));
         arg->type = known_type(env, arg->td);
         if (owner) nspc_pop_type(env->gwion->mp, env->curr);
         CHECK_OO(arg->type);
       }
+
       if (!func_match_inner(env, e, arg->type, implicit, specific)) break;
       e  = e->next;
     }
@@ -585,9 +565,9 @@ ANN m_bool check_traverse_fdef(const Env env, const Func_Def fdef) {
 ANN static m_bool check_func_args(const Env env, Arg_List args) {
   for(uint32_t i = 0; i < args->len; i++) {
     Arg *arg = mp_vector_at(args, Arg, i);
-    const Var_Decl decl = &arg->var_decl;
+    const Var_Decl *decl = &arg->var_decl;
     const Value    v    = decl->value;
-    CHECK_BB(already_defined(env, decl->xid, decl->pos));
+    if(decl->xid) CHECK_BB(already_defined(env, decl->xid, decl->pos));
     valid_value(env, decl->xid, v);
   }
   return GW_OK;
@@ -604,33 +584,33 @@ next_arg(Exp)
 
 ANN static void print_current_args(Exp e) {
   gw_err(_("and not\n  "));
-  do gw_err(" {G}%s{0}", e->type ? e->type->name : "{-/}Unknown");
+  do gw_err(" {G}%s{0}", e->type ? e->type->name : "<Unknown>");
   while ((e = next_arg_Exp(e)));
   gw_err("\n");
 }
 
 ANN2(1)
-static void function_alternative(const Env env, const Type f, const Exp args,
+static void function_alternative(const Env env, const Type t, const Exp args,
                                  const loc_t pos) {
   if (env->context && env->context->error) // needed for ufcs
     return;
   gwerr_basic("Argument type mismatch", "call site",
               "valid alternatives:", env->name, pos, 0);
-  Func up = f->info->func;
+  Func up = isa(t, env->gwion->type[et_closure]) < 0
+          ?  t->info->func : closure_def(t)->base->func;
   do print_signature(up);
   while ((up = up->next));
   if (args)
     print_current_args(args);
   else
     gw_err(_("and not:\n  {G}void{0}\n"));
-  env_set_error(env);
+  env_set_error(env, true);
 }
 
 ANN static Func get_template_func(const Env env, Exp_Call *const func,
                                   const Value v) {
   const Func f = find_template_match(env, v, func);
   if (f) {
-    // copy that tmpl->call?
     Tmpl *tmpl               = new_tmpl_call(env->gwion->mp, func->tmpl->call);
     tmpl->list               = v->d.func_ref
                                    ? v->d.func_ref->def->base->tmpl->list
@@ -675,22 +655,21 @@ ANN static Type check_predefined(const Env env, Exp_Call *exp, const Value v,
 
 ANN static Type_List check_template_args(const Env env, Exp_Call *exp,
                                          const Tmpl *tm, const Func_Def fdef) {
-  m_uint       args_number = 0;
-  const m_uint type_number = tm->list->len;
-  Type_List    tl = new_mp_vector(env->gwion->mp, sizeof(Type_Decl*), type_number);
   Specialized_List sl = tm->list;
-  for(uint32_t i = 0; i < sl->len; i++) {
+  const bool spread = is_spread_tmpl(fdef->base->tmpl);
+  const uint32_t len = sl->len - spread;
+  Type_List    tl = new_mp_vector(env->gwion->mp, Type_Decl*, len);
+
+  m_uint       args_number = 0;
+  for(uint32_t i = 0; i < len; i++) {
     Specialized *spec = mp_vector_at(sl, Specialized, i);
     Arg_List args          = fdef->base->args;
-    const uint32_t args_len = args ? args->len : 0;
+    const uint32_t args_len = mp_vector_len(args);
     Exp      template_arg = exp->args;
     uint32_t count = 0;
     while (count < args_len && template_arg) {
       Arg *arg = mp_vector_at(args, Arg, count);
       if (spec->xid == arg->td->xid) {
-        if  (isa(template_arg->type, env->gwion->type[et_lambda]) > 0 &&
-             !template_arg->type->info->func)
-          break;
         mp_vector_set(tl, Type_Decl*, args_number,
           mk_td(env, arg, template_arg->type, fdef->base->pos));
         ++args_number;
@@ -700,13 +679,27 @@ ANN static Type_List check_template_args(const Env env, Exp_Call *exp,
       template_arg = template_arg->next;
     }
   }
-  if (args_number < type_number) // TODO: free type_list
+  if (args_number < len) //TODO: free type_list
     ERR_O(exp->func->pos, _("not able to infer types for template call."))
+
+  if(spread) {
+    Exp e = exp->args;
+    if(fdef->base->args)
+    for(uint32_t i = 0; i < fdef->base->args->len && e; i++) e = e->next;
+    while(e) {
+      mp_vector_add(env->gwion->mp, &tl, Type_Decl*, type2td(env->gwion, e->type, e->pos));
+      e = e->next;
+    }
+  }
   return tl;
 }
 
 ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) {
-  const Type t = exp->func->type;
+  /*const */Type t = exp->func->type;
+  if(isa(t, env->gwion->type[et_closure]) > 0) {
+    const Func_Def fdef = closure_def(t);
+    t = fdef->base->func->value_ref->type;
+  }
   DECL_OO(const Value, value, = type_value(env->gwion, t));
   const Func_Def fdef =
       value->d.func_ref ? value->d.func_ref->def : t->info->func->def;
@@ -743,7 +736,7 @@ ANN2(1) static m_bool lambda_append_args(const Env env, Exp_Call *const call, co
 
 ANN static Exp check_lambda_captures(const Env env, const Func_Def fdef) {
   if(!fdef->base->args)
-    fdef->base->args = new_mp_vector(env->gwion->mp, sizeof(Arg), 0);
+    fdef->base->args = new_mp_vector(env->gwion->mp, Arg, 0);
   Exp args = NULL, tmp;
   for(uint32_t i = 0; i < fdef->captures->len; i++) {
     Capture *const cap = mp_vector_at(fdef->captures, Capture, i);
@@ -761,7 +754,7 @@ ANN static Exp check_lambda_captures(const Env env, const Func_Def fdef) {
     if(args) tmp = tmp->next = exp;
     else args = tmp = exp;
   }
-  free_mp_vector(env->gwion->mp, sizeof(Capture), fdef->captures);
+  free_mp_vector(env->gwion->mp, Capture, fdef->captures);
   fdef->captures = NULL;
   return args;
 }
@@ -806,16 +799,16 @@ ANN m_bool func_check(const Env env, Exp_Call *const exp) {
   if(exp->func->exp_type == ae_exp_dot)
     exp->func->d.exp_dot.is_call = exp;
   CHECK_OB(check_exp(env, exp->func));
+  if(exp->func->exp_type == ae_exp_dot)
+    exp->func->d.exp_dot.is_call = exp;
   if (exp->func->exp_type == ae_exp_decl)
     ERR_B(exp->func->pos, _("Can't call late function pointer at declaration "
                             "site. did you meant to use `@=>`?"))
   const Type t = actual_type(env->gwion, exp->func->type);
-  if(!is_fptr(env->gwion, t)) {
-    if (is_func(env->gwion, t) && exp->func->exp_type == ae_exp_dot && // is_callable
-        !t->info->value->from->owner_class) {
-      if (exp->args) CHECK_OB(check_exp(env, exp->args));
-      return call2ufcs(env, exp, t->info->func->value_ref) ? GW_OK : GW_ERROR;
-    }
+  if (is_func(env->gwion, t) && exp->func->exp_type == ae_exp_dot && // is_callable
+      !t->info->value->from->owner_class) {
+    if (exp->args) CHECK_OB(check_exp(env, exp->args));
+    return call2ufcs(env, exp, t->info->func->value_ref) ? GW_OK : GW_ERROR;
   }
   const Exp        e   = exp_self(exp);
   struct Op_Import opi = {.op   = insert_symbol("@func_check"),
@@ -835,26 +828,22 @@ ANN void call_add_effect(const Env env, const Func func, const loc_t pos) {
   }
 }
 
-ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
-  DECL_BO(const m_bool, ret, = func_check(env, exp));
-  if (!ret) return exp_self(exp)->type;
-  const bool _class = is_class(env->gwion, exp->func->type);
-  const Type t =
-      _class ? actual_type(env->gwion, exp->func->type) : exp->func->type;
+ANN Type _check_exp_call1(const Env env, Exp_Call *const exp) {
+  /* const */Type t = exp->func->type;
   if (!is_func(env->gwion, t)) { // use func flag?
-    struct Op_Import opi = {.op   = insert_symbol("@ctor"),
-                            .rhs  = actual_type(env->gwion, exp->func->type),
-                            .data = (uintptr_t)exp,
-                            .pos  = exp_self(exp)->pos};
-    const Type       t   = op_check(env, &opi);
-    return t;
-  }
-  if (_class) {
-    // need an instance
-    ERR_O(exp->func->pos, "can't call a function pointer type");
+    if(isa(exp->func->type, env->gwion->type[et_closure]) > 0)
+      t = closure_def(t)->base->func->value_ref->type;
+    else {
+      struct Op_Import opi = {.op   = insert_symbol("@ctor"),
+                              .rhs  = actual_type(env->gwion, exp->func->type),
+                              .data = (uintptr_t)exp,
+                              .pos  = exp_self(exp)->pos};
+      const Type       t   = op_check(env, &opi);
+      return t;
+    }
   }
   if (t == env->gwion->type[et_op]) return check_op_call(env, exp);
-  if (t == env->gwion->type[et_lambda]) // TODO: effects?
+  if (!t->info->func) // TODO: effects?
     return check_lambda_call(env, exp);
   if (fflag(t->info->func, fflag_ftmpl)) {
     const Value value = t->info->func->value_ref;
@@ -871,17 +860,16 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
     return check_exp_call_template(env, (Exp_Call *)exp); // TODO: effects?
   const Func func = find_func_match(env, t->info->func, exp);
   if (func) {
-    if (!is_fptr(env->gwion, func->value_ref->type)) // skip function pointers
-      if (func != env->func && func->def && !fflag(func, fflag_valid)) {
-        if(func->value_ref->from->owner_class)
-          CHECK_BO(ensure_check(env, func->value_ref->from->owner_class));
-        else {
-          const m_uint scope = env_push(env, NULL, func->value_ref->from->owner);
-          const m_bool ret = check_func_def(env, func->def);
-          env_pop(env, scope);
-          CHECK_BO(ret);
-        }
+    if (func != env->func && func->def && !fflag(func, fflag_valid)) {
+      if(func->value_ref->from->owner_class)
+        CHECK_BO(ensure_check(env, func->value_ref->from->owner_class));
+      else {
+        const m_uint scope = env_push(env, NULL, func->value_ref->from->owner);
+        const m_bool ret = check_func_def(env, func->def);
+        env_pop(env, scope);
+        CHECK_BO(ret);
       }
+    }
     exp->func->type = func->value_ref->type;
     call_add_effect(env, func, exp->func->pos);
     return func->def->base->ret_type != env->gwion->type[et_auto] ?
@@ -891,7 +879,26 @@ ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
     const Type tt = partial_type(env, exp);
     if(tt) return tt;
   }
-  function_alternative(env, exp->func->type, exp->args, exp->func->pos);
+  return NULL;
+}
+
+ANN Type check_exp_call1(const Env env, Exp_Call *const exp) {
+  DECL_BO(const m_bool, ret, = func_check(env, exp));
+  if (!ret) return exp_self(exp)->type;
+  const Type t = exp->func->type;
+  const Type _ret = _check_exp_call1(env, exp);
+  if(_ret) return _ret;
+  if(isa(exp->func->type, env->gwion->type[et_closure]) > 0) {
+    if(exp->func->exp_type == ae_exp_dot && t->info->value->from->owner_class) {
+      const Exp args = exp->args;
+      const Exp this_arg = cpy_exp(env->gwion->mp, exp->func->d.exp_dot.base);
+      this_arg->next = args;
+      exp->args = this_arg;
+      const Type t = _check_exp_call1(env, exp);
+      if(t) return t;
+    }
+  }
+  function_alternative(env, t, exp->args, exp->func->pos);
   return NULL;
 }
 
@@ -904,7 +911,7 @@ ANN static Type check_exp_binary(const Env env, const Exp_Binary *bin) {
   CHECK_OO(check_exp(env, bin->rhs));
   if (is_auto) {
     assert(bin->rhs->type == bin->lhs->type);
-    set_vflag(mp_vector_at(bin->rhs->d.exp_decl.list, struct Var_Decl_, 0)->value, vflag_assigned);
+    set_vflag(bin->rhs->d.exp_decl.vd.value, vflag_assigned);
   }
   struct Op_Import opi = {.op   = bin->op,
                           .lhs  = bin->lhs->type,
@@ -915,7 +922,7 @@ ANN static Type check_exp_binary(const Env env, const Exp_Binary *bin) {
   exp_setuse(bin->rhs, 1);
   const Type ret = op_check(env, &opi);
   if (!ret && is_auto && exp_self(bin)->exp_type == ae_exp_binary)
-    mp_vector_at(bin->rhs->d.exp_decl.list, struct Var_Decl_, 0)->value->type = env->gwion->type[et_auto];
+    bin->rhs->d.exp_decl.vd.value->type = env->gwion->type[et_auto];
   return ret;
 }
 
@@ -966,10 +973,18 @@ ANN2(1) static inline bool is_partial(const Env env, Exp exp) {
   return false;
 }
 
+ANN static bool tl_match(const Env env, const Type_List tl0, const Type_List tl1) {
+  if (tl0->len != tl1->len) return false;
+  for(uint32_t i = 0; i < tl0->len; i++) {
+    Type_Decl *td0 = *mp_vector_at(tl0, Type_Decl*, i);
+    Type_Decl *td1 = *mp_vector_at(tl1, Type_Decl*, i);
+    if(known_type(env, td0) != known_type(env, td1))
+      return false;
+  }
+  return true;
+}
+
 ANN static Type check_exp_call_tmpl(const Env env, Exp_Call *exp, const Type t) {
-  if(isa(t, env->gwion->type[et_lambda]) > 0)
-    if  (!t->info->func)
-      ERR_O(exp->func->pos, _("invalid lambda use."))
   if (exp->args) CHECK_OO(check_exp(env, exp->args));
   if (!t->info->func->def->base->tmpl)
     ERR_O(exp_self(exp)->pos, _("template call of non-template function."))
@@ -977,8 +992,11 @@ ANN static Type check_exp_call_tmpl(const Env env, Exp_Call *exp, const Type t)
     if (env->func == t->info->func) {
       exp->func->type = env->func->value_ref->type;
       return env->func->def->base->ret_type;
-    } else
+    } else {
+      if(tl_match(env, t->info->func->def->base->tmpl->call, exp->tmpl->call))
+        return check_exp_call1(env, exp);
       CHECK_BO(predefined_call(env, t, exp_self(exp)->pos));
+    }
   }
   const Value v = type_value(env->gwion, t);
   DECL_OO(const Func, f, = find_template_match(env, v, exp));
@@ -998,7 +1016,12 @@ ANN static Type check_exp_call(const Env env, Exp_Call *exp) {
   if (exp->tmpl) {
     DECL_BO(const m_bool, ret, = func_check(env, exp));
     if (!ret) return exp_self(exp)->type;
-    const Type t = actual_type(env->gwion, exp->func->type);
+/*    const */Type t = actual_type(env->gwion, exp->func->type);
+    if(isa(exp->func->type, env->gwion->type[et_closure]) > 0) {
+      t = typedef_base(t);
+      t = mp_vector_at(t->info->cdef->body, Section , 0)->d.func_def->base->func->value_ref->type;
+    }
+// check for closure and b ring it back
     if (!is_func(env->gwion, t)) return check_exp_call1(env, exp);
     if(strcmp("new", s_name(t->info->func->def->base->xid)))
       return check_exp_call_tmpl(env, exp, t);
@@ -1071,7 +1094,7 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
     set_tflag(tdef->type, tflag_contract);
     struct Var_Decl_ decl = { .xid = insert_symbol("self"), .pos = tdef->when->pos };
     Type_Decl *td = cpy_type_decl(env->gwion->mp, tdef->ext);
-    Arg_List args = new_mp_vector(env->gwion->mp, sizeof(Arg), 1);
+    Arg_List args = new_mp_vector(env->gwion->mp, Arg, 1);
     mp_vector_set(args, Arg, 0, ((Arg) { .td = td, .var_decl = decl }));
     Func_Base *fb = new_func_base(
         env->gwion->mp, type2td(env->gwion, tdef->type, tdef->pos),
@@ -1082,7 +1105,7 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
     const Exp when   = tdef->when;
     tdef->when = NULL;
     when->next       = helper;
-    Stmt_List body = new_mp_vector(env->gwion->mp, sizeof(struct Stmt_), 2);
+    Stmt_List body = new_mp_vector(env->gwion->mp, struct Stmt_, 2);
     mp_vector_set(body, struct Stmt_, 0,
       ((struct Stmt_) {
       .stmt_type = ae_stmt_exp, .d = { .stmt_exp = { .val = when }},
@@ -1105,7 +1128,7 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
       char from[strlen(tdef->type->name) + 39];
       sprintf(from, "in `{/+}%s{0}` definition", tdef->type->name);
       gwerr_secondary(from, env->name, tdef->pos);
-      env_set_error(env);
+      env_set_error(env, true);
       return GW_ERROR;
     }
     // we handle the return after, so that we don't get *cant' use implicit
@@ -1122,15 +1145,14 @@ ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
   return GW_OK;
 }
 ANN static Type check_exp_lambda(const Env env, const Exp_If *exp_if NUSED) {
-  return env->gwion->type[et_lambda];
+  return env->gwion->type[et_function];
 }
 
 ANN static Type check_exp_td(const Env env, Type_Decl **td) {
   DECL_OO(const Type, t, = known_type(env, *td));
   if(t == env->gwion->type[et_class])
     ERR_O(exp_self(td)->pos, "can't use {G+}Class{0} in type decl expression");
-  if (!is_func(env->gwion, t) || is_fptr(env->gwion, t))
-    return type_class(env->gwion, t);
+  if (!is_func(env->gwion, t)) return type_class(env->gwion, t);
   return t;
 }
 
@@ -1143,7 +1165,6 @@ ANN Type check_exp(const Env env, const Exp exp) {
     do {
       CHECK_OO((curr->type = check_exp_func[curr->exp_type](env, &curr->d)));
       if (env->func && !is_class(env->gwion, curr->type) &&
-          isa(curr->type, env->gwion->type[et_lambda]) < 0 &&
           is_func(env->gwion, curr->type) &&
           !safe_fflag(curr->type->info->func, fflag_pure))
         unset_fflag(env->func, fflag_pure);
@@ -1169,14 +1190,6 @@ ANN static m_bool check_stmt_code(const Env env, const Stmt_Code stmt) {
   return GW_OK;
 }
 
-ANN static m_bool check_stmt_varloop(const Env env, const Stmt_VarLoop stmt) {
-  CHECK_OB(check_exp(env, stmt->exp));
-  if (isa(stmt->exp->type, env->gwion->type[et_vararg]) < 0)
-    ERR_B(stmt->exp->pos, "varloop expression type must be '%s', not '%s'",
-          env->gwion->type[et_vararg]->name, stmt->exp->type->name)
-  return check_stmt(env, stmt->body);
-}
-
 ANN static inline m_bool _check_breaks(const Env env, const Stmt b) {
     RET_NSPC(check_stmt(env, b))}
 
@@ -1258,7 +1271,7 @@ ANN static inline m_bool repeat_type(const Env env, const Exp e) {
     gwerr_basic(_("invalid repeat condition type"), explain,
                 _("use an integer or cast to int if possible"), env->name,
                 e->pos, 0);
-    env_set_error(env);
+    env_set_error(env, true);
     return GW_ERROR;
   }
   return GW_OK;
@@ -1296,7 +1309,6 @@ ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) {
   DECL_OB(const Type, ret_type,
           = stmt->val ? check_exp(env, stmt->val) : env->gwion->type[et_void]);
   if (!env->func->def->base->ret_type) {
-    assert(isa(env->func->value_ref->type, env->gwion->type[et_lambda]) > 0);
     env->func->def->base->ret_type = ret_type;
     return GW_OK;
   }
@@ -1470,7 +1482,7 @@ ANN static inline m_bool _check_stmt_try(const restrict Env env, const Stmt_Try
       bool found   = find_handler(stmt->handler, eff->sym);
       if (!found) env_add_effect(env, eff->sym, eff->pos);
     }
-    free_mp_vector(env->gwion->mp, sizeof(struct ScopeEffect), v);
+    free_mp_vector(env->gwion->mp, struct ScopeEffect, v);
   }
   return ret;
 }
@@ -1527,6 +1539,7 @@ ANN static m_bool check_stmt_defer(const Env env, const Stmt_Defer stmt) {
 }
 
 #define check_stmt_retry dummy_func
+#define check_stmt_spread dummy_func
 DECL_STMT_FUNC(check, m_bool, Env)
 
 ANN m_bool check_stmt(const Env env, const Stmt stmt) {
@@ -1558,9 +1571,9 @@ ANN static m_bool check_signature_match(const Env env, const Func_Def fdef,
   }
   if(fdef->base->tmpl || isa(fdef->base->ret_type, parent->def->base->ret_type) > 0)
     return GW_OK;
-  gwerr_basic("invalid overriding", NULL, NULL, fdef->base->func->value_ref->from->filename, fdef->base->func->value_ref->from->loc, 0);
-  gwerr_secondary("does not match", parent->value_ref->from->filename, parent->value_ref->from->loc);
-  env->context->error = true;
+  gwerr_basic_from("invalid overriding", NULL, NULL, fdef->base->func->value_ref->from, 0);
+  gwerr_secondary_from("does not match", parent->value_ref->from);
+  env_set_error(env,  true);
   return GW_ERROR;
 }
 
@@ -1572,8 +1585,8 @@ ANN static m_bool parent_match_actual(const Env               env,
     if (parent_func->def->base && compat_func(fdef, parent_func->def) > 0) {
       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->vtable, fdef->base->func->vt_index,
+        fdef->vt_index = parent_func->def->vt_index;
+        vector_set(&env->curr->vtable, fdef->vt_index,
                    (vtype)fdef->base->func);
       }
       return GW_OK;
@@ -1593,7 +1606,7 @@ ANN static m_bool check_parent_match(const Env env, const Func_Def fdef) {
       if (match) return match;
     }
   }
-  func->vt_index = vector_size(&env->curr->vtable);
+  func->def->vt_index = vector_size(&env->curr->vtable);
   vector_add(&env->curr->vtable, (vtype)func);
   return GW_OK;
 }
@@ -1652,7 +1665,7 @@ ANN static m_bool check_func_def_override(const Env env, const Func_Def fdef,
     *ov = override;
   }
   if (func->value_ref->from->offset &&
-      (!fdef->base->tmpl || !fdef->base->tmpl->base))
+      (!fdef->base->tmpl /*|| !fdef->base->tmpl->base*/))
     CHECK_BB(check_func_overload(env, fdef));
   return GW_OK;
 }
@@ -1660,11 +1673,8 @@ ANN static m_bool check_func_def_override(const Env env, const Func_Def fdef,
 ANN m_bool check_fdef(const Env env, const Func_Def fdef) {
   if (fdef->base->args) CHECK_BB(check_func_args(env, fdef->base->args));
   if(fdef->builtin) return GW_OK;
-  if (fdef->d.code) {
-    env->scope->depth--;
+  if (fdef->d.code && fdef->d.code->d.stmt_code.stmt_list)
     CHECK_BB(check_stmt_code(env, &fdef->d.code->d.stmt_code));
-    env->scope->depth++;
-  }
   return GW_OK;
 }
 
@@ -1693,13 +1703,21 @@ ANN m_bool _check_func_def(const Env env, const Func_Def f) {
                                     : env->scope->depth);
   const Func former = env->func;
   env->func         = func;
-  ++env->scope->depth;
   nspc_push_value(env->gwion->mp, env->curr);
   struct Op_Import opi = {};
   if (fbflag(fdef->base, fbflag_op)) {
     func_operator(f, &opi);
     operator_suspend(env->curr, &opi);
   }
+  if(fdef->captures) {
+    uint32_t offset = fdef->stack_depth;
+    for(uint32_t i = 0; i < fdef->captures->len; i++) {
+      Capture *cap = mp_vector_at(fdef->captures, Capture, i);
+      valid_value(env, cap->xid, cap->temp);
+      cap->temp->from->offset = offset;
+      offset += cap->temp->type->size;
+    }
+  }
   vector_add(&env->scope->effects, 0);
   const m_bool ret = scanx_fdef(env, env, fdef, (_exp_func)check_fdef);
   MP_Vector *v = (MP_Vector*)vector_back(&env->scope->effects);
@@ -1713,12 +1731,11 @@ ANN m_bool _check_func_def(const Env env, const Func_Def f) {
       if(!effect_find(v, eff->sym))
         vector_add(base, (m_uint)eff->sym);
     }
-    free_mp_vector(env->gwion->mp, sizeof(struct ScopeEffect), v);
+    free_mp_vector(env->gwion->mp, struct ScopeEffect, v);
   }
   vector_pop(&env->scope->effects);
   if (fbflag(fdef->base, fbflag_op)) operator_resume(&opi);
   nspc_pop_value(env->gwion->mp, env->curr);
-  --env->scope->depth;
   env->func = former;
   if (ret > 0) {
     if (env->class_def && fdef->base->effects.ptr &&
@@ -1743,34 +1760,49 @@ ANN m_bool check_func_def(const Env env, const Func_Def fdef) {
   return ret;
 }
 
+ANN bool check_trait_requests(const Env env, const Type t, const ID_List list, const ValueFrom *from);
 ANN static m_bool check_extend_def(const Env env, const Extend_Def xdef) {
-  CHECK_BB(ensure_check(env, xdef->t));
-  CHECK_BB(extend_push(env, xdef->t));
-  const m_bool ret = check_ast(env, &xdef->body);
-  extend_pop(env, xdef->t);
-  return ret;
+  ValueFrom from = { .filename = env->name, .loc=xdef->td->pos, .ctx=env->context,
+      .owner = env->curr, .owner_class = env->class_def
+  };
+  const bool ret = check_trait_requests(env, xdef->t, xdef->traits, &from);
+  if(ret) {
+    if(!xdef->t->info->traits) {
+      xdef->t->info->traits = new_mp_vector(env->gwion->mp, Symbol, xdef->traits->len);
+      for(uint32_t i = 0; i < xdef->traits->len; i++) {
+        const Symbol sym = *mp_vector_at(xdef->t->info->traits, Symbol, i);
+        mp_vector_set(xdef->t->info->traits, Symbol, i, sym);
+      }
+    } else {
+      for(uint32_t i = 0; i < xdef->traits->len; i++) {
+        const Symbol sym = *mp_vector_at(xdef->t->info->traits, Symbol, i);
+        mp_vector_add(env->gwion->mp, &xdef->t->info->traits, Symbol, sym);
+      }
+    }
+    return GW_OK;
+  }
+  return GW_ERROR;
 }
 
 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;
+  if(!ast) return GW_OK;
   for(m_uint i = 0; i < ast->len; i++) {
     Section * section = mp_vector_at(ast, Section, i);
+    // we should traverse the funcs here also
     if (section->section_type == ae_section_stmt) {
   Stmt_List l = section->d.stmt_list;
   for(m_uint i = 0; i < l->len; i++) {
     const Stmt stmt = mp_vector_at(l, struct Stmt_, i);
         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;
-          for(uint32_t i = 0; i < list->len; i++) {
-            Var_Decl vd = mp_vector_at(list, struct Var_Decl_, i);
-            const Value value = vd->value;
-            valuefrom(env, value->from);
-            if (!trait->requested_values.ptr)
-              vector_init(&trait->requested_values);
-            vector_add(&trait->requested_values, (m_uint)value);
-          }
+          Var_Decl vd = stmt->d.stmt_exp.val->d.exp_decl.vd;
+          const Value value = vd.value;
+          valuefrom(env, value->from);
+          if (!trait->var)
+            trait->var = new_mp_vector(env->gwion->mp, Value, 0);
+          mp_vector_add(env->gwion->mp, &trait->var, Value, value);
         }
       }
     }
@@ -1782,7 +1814,11 @@ 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
+ANN m_bool check_fptr_def(const Env env, const Fptr_Def fptr) {
+  return check_class_def(env, fptr->cdef);
+}
+
+//#define check_fptr_def dummy_func
 HANDLE_SECTION_FUNC(check, m_bool, Env)
 
 ANN static m_bool check_parent(const Env env, const Class_Def cdef) {
@@ -1818,9 +1854,9 @@ ANN m_bool check_abstract(const Env env, const Class_Def cdef) {
                     _("provide an implementation for the following:"),
                     env->name, cdef->pos, 0);
       }
-      struct ValueFrom_ *from = f->value_ref->from;
-      gwerr_secondary("implementation missing", from->filename, from->loc);
-      env_set_error(env);
+      ValueFrom *from = f->value_ref->from;
+      gwerr_secondary_from("implementation missing", from);
+      env_set_error(env, true);
     }
   }
   return !err ? GW_OK : GW_ERROR;
@@ -1835,7 +1871,7 @@ ANN static inline void ctor_effects(const Env env) {
     struct ScopeEffect *eff = mp_vector_at(w, struct ScopeEffect, j);
     vector_add(&env->class_def->effects, (m_uint)eff->sym);
   }
-  free_mp_vector(env->gwion->mp, sizeof(struct ScopeEffect), w);
+  free_mp_vector(env->gwion->mp, struct ScopeEffect, w);
   vector_pop(v);
 }
 
@@ -1859,16 +1895,10 @@ ANN static bool class_def_has_body(const Env env, Ast ast) {
           if (!exp) continue;
           if (exp->exp_type != ae_exp_decl) return true;
           if (GET_FLAG(exp->d.exp_decl.td, late)) continue;
-          Var_Decl_List list = exp->d.exp_decl.list;
-          for(uint32_t i = 0; i < list->len; i++) {
-            Var_Decl vd = mp_vector_at(list, struct Var_Decl_, i);
-            if (GET_FLAG(vd->value, late)) continue;
-            if (isa(vd->value->type, env->gwion->type[et_compound]) >
-                0)
-              //            if(tflag(vd->value->type, tflag_ctor) ||
-              //                     cd->value->type->array_depth)
+          Var_Decl vd = exp->d.exp_decl.vd;
+          if (GET_FLAG(vd.value, late)) continue;
+          if (isa(vd.value->type, env->gwion->type[et_compound]) > 0)
               return true;
-          }
         } else
           return true;
       } //while ((list = list->next));
@@ -1888,7 +1918,7 @@ ANN static bool recursive_value(const Env env, const Type t, const Value v) {
   const Type tgt = array_base(v->type);
   if(type_is_recurs(t, tgt)) {
     env_err(env, v->from->loc, _("recursive type"));
-    env->context->error = false;
+    env_set_error(env,  false);
     gwerr_secondary("in class", t->name, t->info->cdef->base.pos);
 
     const Type first = tgt->info->value->from->loc.first.line < t->info->value->from->loc.first.line ?
@@ -1956,7 +1986,7 @@ ANN static m_bool recursive_type_base(const Env env, const Type t) {
   return error;
 }
 
-ANN bool check_trait_requests(const Env env, const Type t, const ID_List list);
+ANN bool check_trait_requests(const Env env, const Type t, const ID_List list, const ValueFrom *from);
 ANN static m_bool _check_class_def(const Env env, const Class_Def cdef) {
   const Type t = cdef->base.type;
   if (cdef->base.ext) CHECK_BB(cdef_parent(env, cdef));
@@ -1977,10 +2007,10 @@ 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;
-    if (!check_trait_requests(env, t, list)) {
+    if (!check_trait_requests(env, t, list, t->info->value->from)) {
       env->class_def = t;
       env_error_footer(env);
-      env_set_error(env);
+      env_set_error(env, true);
       return GW_ERROR;
     }
   }
@@ -1993,14 +2023,8 @@ ANN m_bool check_class_def(const Env env, const Class_Def cdef) {
   if (tmpl_base(cdef->base.tmpl)) return GW_OK;
   const Type       t   = cdef->base.type;
   if (tflag(t, tflag_check)) return GW_OK;
-  const Class_Def  c   = t->info->cdef;
-  struct Op_Import opi = {.op   = insert_symbol("@class_check"),
-                          .lhs  = t,
-                          .data = (uintptr_t)c,
-                          .pos  = c->pos};
-  CHECK_OB(op_check(env, &opi));
   set_tflag(t, tflag_check);
-  return _check_class_def(env, c);
+  return _check_class_def(env, t->info->cdef);
 }
 
 ANN static inline void check_unhandled(const Env env) {
@@ -2012,12 +2036,22 @@ ANN static inline void check_unhandled(const Env env) {
     if(s_name(eff->sym)[0] == '!')
       continue;
     gwerr_secondary("Unhandled effect", env->name, eff->pos);
-    env->context->error = false;
+    env_set_error(env,  false);
   }
-  free_mp_vector(env->gwion->mp, sizeof(struct ScopeEffect), w);
+  free_mp_vector(env->gwion->mp, struct ScopeEffect, w);
   vector_pop(v);
 }
 
+ANN static void check_extend(const Env env, Ast ast) {
+  for(m_uint i = 0; i < ast->len; i++) {
+    Section * section = mp_vector_at(ast, Section, i);
+    (void)check_section(env, section);
+    mp_vector_add(env->gwion->mp, &env->context->extend, Section, *section);
+  }
+  free_mp_vector(env->gwion->mp, Section, env->context->extend);
+  env->context->extend = NULL;
+}
+
 ANN m_bool check_ast(const Env env, Ast *ast) {
   Ast a = *ast;
   for(m_uint i = 0; i < a->len; i++) {
@@ -2025,5 +2059,6 @@ ANN m_bool check_ast(const Env env, Ast *ast) {
     CHECK_BB(check_section(env, section));
   }
   check_unhandled(env);
+  if(env->context->extend) check_extend(env, env->context->extend);
   return GW_OK;
 }
index 2c0dad3ae5f98ae7ad364c3b279672b4233de1d3..8b8c52f5334335e2be18da3c0ab155528065c55a 100644 (file)
 ANN static bool var_match(const Value a, const Value b) {
   bool error = true;
   if (isa(a->type, a->type) < 0) {
-    gwerr_basic("invalid variable type", NULL, NULL, a->from->filename,
-                a->from->loc, 0);
-    // can we point to the type decl?
+    gwerr_basic_from("invalid variable type", NULL, NULL, a->from, 0);
     error = false;
   }
   if (GET_FLAG(a, const) && !GET_FLAG(b, const)) {
-    gwerr_basic("variable differs in {/}constness{0}", NULL, NULL,
-                a->from->filename, a->from->loc, 0);
-    // can we point to the flag?
+    gwerr_basic_from("variable differs in {/}constness{0}", NULL, NULL, a->from, 0);
     error = false;
   }
   if (GET_FLAG(a, static) && !GET_FLAG(b, static)) {
-    gwerr_basic("variable differs in {/}storage{0}", NULL, NULL,
-                a->from->filename, a->from->loc, 0);
-    // can we point to the flag?
+    gwerr_basic_from("variable differs in {/}storage{0}", NULL, NULL, a->from, 0);
     error = false;
   }
   if (error) return true;
-  gwerr_secondary("from requested variable", b->from->filename, b->from->loc);
+  gwerr_secondary_from("from requested variable", b->from);
   return error;
 }
 
@@ -50,100 +44,155 @@ ANN static bool request_var(const Env env, const Type t, const Value request) {
 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);
+  for (m_uint i = 0; i < trait->var->len; i++) {
+    const Value request = *mp_vector_at(trait->var, Value, i);
     if (!request_var(env, t, request)) error = true;
   }
   return error;
 }
 
-ANN static bool request_fun(const Env env, const Type t,
+ANN static bool trait_inherit(const Env env, const Type t, const Func_Def req) {
+  const bool global = type_global(env, t) || !!nspc_lookup_value1(env->curr->parent, req->base->xid);
+  nspc_push_type(env->gwion->mp, env->curr);
+  nspc_add_type(env->curr, insert_symbol("Self"), t);
+  const Func_Def cpy   = cpy_func_def(env->gwion->mp, req);
+  if(global) SET_FLAG(cpy->base, global);
+  const m_bool ret   = traverse_func_def(env, cpy);
+  nspc_pop_type(env->gwion->mp, env->curr);
+  Section section = MK_SECTION(func, func_def, cpy);
+  if(!env->context->extend)
+    env->context->extend = new_mp_vector(env->gwion->mp, Section, 0);
+  mp_vector_add(env->gwion->mp, &env->context->extend, Section, section);
+  return ret;
+}
+
+ANN static bool check_trait_args(const Env env, const Func f, const Func_Base *req, const bool m) {
+  if (mp_vector_len(f->def->base->args) + m != mp_vector_len(req->args)) return false;
+  if(m) {
+    const Arg *r = mp_vector_at(req->args, Arg, 0);
+    if(strcmp(s_name(r->td->xid), "Self"))
+    return false;
+  }
+  for(m_uint i = m; i < req->args->len; i++) {
+    const Arg *r = mp_vector_at(req->args, Arg, i + m);
+    const Type t = known_type(env, r->td);
+    const Arg *arg = mp_vector_at(f->def->base->args, Arg, i);
+    if(arg->type != t) return false;
+  }
+  return true;
+}
+
+ANN static bool request_found(const Env env, const Type t,
                             const Func_Def request) {
   const Value v = nspc_lookup_value0(t->nspc, request->base->xid);
-  if (v) {
-    if (!is_func(env->gwion, v->type) || is_fptr(env->gwion, v->type)) { // is_fptr
-      gwerr_basic("is not a function", NULL, NULL, v->from->filename,
-                  v->from->loc, 0);
-      return false;
-    }
+  if (!v) return false;
+  if (!is_func(env->gwion, v->type)) {
+    gwerr_basic_from("is not a function", NULL, NULL, v->from, 0);
+    return false;
+  }
+  Func f = v->d.func_ref;
+  do {
+    const Func_Base *req = request->base;
+    const Func_Base *fbase = f->def->base;
+    if (!GET_FLAG(fbase, abstract) &&
+        fbase->ret_type == known_type(env, req->td) &&
+        (!req->args || check_trait_args(env, f, req, vflag(f->value_ref, vflag_member))))
+    return true;
+  } while ((f = f->next));
+  return false;
+}
+
+ANN static bool ufcs_match(const Env env, const Value v,
+                           const Func_Def request, const bool global) {
+  if (!is_func(env->gwion, v->type)) return false; // mayb enot ignore;
     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 = (Section) {
-        .section_type = ae_section_func,
-        .d = { .func_def = cpy }
-      };
-      // ensure body?
-      mp_vector_add(env->gwion->mp, &t->info->cdef->body, Section, section);
-      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;
+      const Func_Base *req = request->base;
+      const Func_Base *fbase = f->def->base;
+      if (!GET_FLAG(fbase, abstract) &&
+          !vflag(f->value_ref, vflag_member) &&
+          fbase->ret_type == known_type(env, req->td) &&
+          mp_vector_len(fbase->args) == mp_vector_len(req->args) &&
+          (!req->args || check_trait_args(env, f, req, 0))) {
+      if(global && !GET_FLAG(fbase, global))
+        return false;
+    return true;
+}
+  } while ((f = f->next));
+  return false;
+}
+
+ANN static bool trait_ufcs(const Env env, const Type t,
+                            const Func_Def request) {
+  const Value v = nspc_lookup_value1(env->curr, request->base->xid);
+  if(v) {
+    const bool global = type_global(env, t) || from_global_nspc(env, v->from->owner);
+    nspc_push_type(env->gwion->mp, env->curr);
+    nspc_add_type(env->curr, insert_symbol("Self"), t);
+    const bool ret = ufcs_match(env, v, request, global);
+    nspc_pop_type(env->gwion->mp, env->curr);
+    if (ret) return true;
   }
-  return true;
+  return false;
+}
+
+ANN static bool request_fun(const Env env, const Type t,
+                            const Func_Def request) {
+  if (t->nspc && request_found(env, t, request)) return true;
+  if (trait_ufcs(env, t, request)) return true;
+  if (!GET_FLAG(request->base, abstract))
+    return trait_inherit(env, t, request);
+  const Value parent = nspc_lookup_value1(env->global_nspc, request->base->xid);
+  if(parent) {
+    const Value v = nspc_lookup_value1(env->curr, request->base->xid);
+    if(!env->context->error) {
+      gwerr_basic_from("is missing {+G}global{0}", NULL, NULL, v->from, 0);
+      gwerr_secondary("from requested func", env->name, request->base->pos);
+      env->context->error = true;
+    }
+  } else gwerr_basic("missing requested function", NULL, NULL, env->name,
+              request->base->pos, 0);
+  return false;
 }
 
 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);
+  for (m_uint i = 0; i < trait->fun->len; i++) {
+    const Func_Def request = *mp_vector_at(trait->fun, Func_Def, i);
     if (!request_fun(env, t, request)) error = true;
   }
   return error;
 }
-/*
-ANN2(1, 2)
-static inline bool trait_nodup(Type t, const Symbol trait, ID_List list) {
-  bool nodup = true;
-  do {
-    for(uint32_t i = 0; i < list->len; i++) {
-      Symbol xid = *mp_vector_at(list, Symbol, i);
-      if (trait == xid) nodup = false;
-    }
-  } while ((t = t->info->parent));
-  return nodup;
-}
-*/
+
 ANN bool trait_nodup(const ID_List list, const uint32_t i) {
-  Symbol fst = *mp_vector_at(list, Symbol, i);
-  for(uint32_t j = i; j < list->len; j++) {
-    Symbol snd = *mp_vector_at(list, Symbol, j);
+  const Symbol fst = *mp_vector_at(list, Symbol, i);
+  for(uint32_t j = i + 1; j < list->len; j++) {
+    const Symbol snd = *mp_vector_at(list, Symbol, j);
     if (fst == snd) return false;
   }
   return true;
 }
 
-ANN bool check_trait_requests(const Env env, const Type t, const ID_List list) {
+ANN static inline bool trait_error(const Env env) {
+  env_set_error(env, true);
+  return false;
+}
+
+ANN bool check_trait_requests(const Env env, const Type t, const ID_List list, const ValueFrom *from) {
   for(uint32_t i = 0; i < list->len; i++) {
-    Symbol xid = *mp_vector_at(list, Symbol, i);
+    const Symbol xid = *mp_vector_at(list, Symbol, i);
     const Trait trait = nspc_lookup_trait1(env->curr, xid);
     if (!trait_nodup(list, i)) {
-      gwerr_secondary("duplicated trait", trait->filename, trait->loc);
-      env_set_error(env);
-      return false;
+      gwerr_secondary_from("class has duplicated trait", from);
+      return trait_error(env);
+    }
+    if (trait->var ? check_trait_variables(env, t, trait) : false ||
+        trait->fun ? check_trait_functions(env, t, trait) : false) {
+      gwerr_secondary("in trait", trait->filename, trait->loc);
+      gwerr_secondary("requested here", from->filename, from->loc);
+      return trait_error(env);
     }
-    const bool value_error = trait->requested_values.ptr  ? check_trait_variables(env, t, trait) : false;
-    const bool funcs_error = trait->requested_funcs.ptr ? check_trait_functions(env, t, trait) : false;
-    if (!value_error && !funcs_error) continue;
-    const Value request = (Value)vector_front(&trait->requested_values);
-    gwerr_secondary("from trait", request->from->filename, trait->loc);
-    env_set_error(env);
-    return false;
   }
   return true;
 }
index 8e6dba6435e1927ad0f302ad2264c773dfb7804e..17bcf279bc03bd945c6538f726b8a87c5c2b7d11 100644 (file)
@@ -31,7 +31,7 @@ ANN static Stmt_List std_code(const MemPool p, Func_Base *base, const Arg_List a
   const Exp efunc = new_prim_id(p, base->xid, base->pos);
   const Exp exp_arg = mk_default_args(p, args, len);
   const Exp ecall = new_exp_call(p, efunc, exp_arg, base->pos);
-  Stmt_List slist = new_mp_vector(p, sizeof(struct Stmt_), 1);
+  Stmt_List slist = new_mp_vector(p, struct Stmt_, 1);
   mp_vector_set(slist, struct Stmt_, 0,
     ((struct Stmt_) {
       .stmt_type = ae_stmt_return, .d = { .stmt_exp = { .val = ecall }},
@@ -46,7 +46,7 @@ ANN static Stmt_List new_code(const Env env, Func_Base *base, const Arg_List arg
   const Exp dot  = new_exp_dot(p, dbase, insert_symbol(env->gwion->st, env->class_def->name), base->pos);
   const Exp exp_args = mk_default_args(p, args, len);
   const Exp ecall = new_exp_call(p, dot, exp_args, base->pos);
-  Stmt_List slist = new_mp_vector(p, sizeof(struct Stmt_), 1);
+  Stmt_List slist = new_mp_vector(p, struct Stmt_, 1);
   mp_vector_set(slist, struct Stmt_, 0,
     ((struct Stmt_) {
       .stmt_type = ae_stmt_exp, .d = { .stmt_exp = { .val = ecall }},
index eddfcf0acae8f7fde107dd5bbf832bac00abbd1c..1978584e45b3cee661424a8952275e39096a4eb6 100644 (file)
@@ -13,6 +13,7 @@
 #include "emit.h"
 #include "specialid.h"
 #include "tmp_resolve.h"
+#include "spread.h"
 
 struct ResolverArgs {
   const Value     v;
@@ -29,28 +30,25 @@ ANN static inline Value template_get_ready(const Env env, const Value v,
 }
 
 ANN static inline bool
-tmpl_valid(const Env env, const Func_Def fdef /*, Exp_Call *const exp*/, const m_str filename) {
+tmpl_valid(const Env env, const Func_Def fdef, const m_str filename) {
   if (safe_fflag(fdef->base->func, fflag_valid)) return true;
   const m_str old_file = env->name;
   env->name = filename;
   const bool ret = check_traverse_fdef(env, fdef) > 0;
   env->name = old_file;
-  if(!fdef->base->func)free_func_def(env->gwion->mp, fdef);
+  if(!fdef->base->func) free_func_def(env->gwion->mp, fdef);
   return ret;
 }
 
 ANN static Func ensure_tmpl(const Env env, const Func_Def fdef,
                             Exp_Call *const exp, const m_str filename) {
-  if (!tmpl_valid(env, fdef /*, exp*/, filename)) return NULL;
+  if (!tmpl_valid(env, fdef, filename)) return NULL;
   if (exp->args && !exp->args->type) return NULL;
   const Func f    = fdef->base->func;
-  const Func next = f->next;
-  f->next         = NULL;
   const Tmpl tmpl = {.list = fdef->base->tmpl->list, .call = exp->tmpl->call};
   CHECK_BO(template_push_types(env, &tmpl));
   const Func func = find_func_match(env, f, exp);
   nspc_pop_type(env->gwion->mp, env->curr);
-  f->next = next;
   if (func) {
     set_fflag(func, fflag_tmpl | fflag_valid);
     call_add_effect(env, func, exp->func->pos);
@@ -74,17 +72,14 @@ ANN static Func fptr_match(const Env env, struct ResolverArgs *ra) {
       v->d.func_ref ? v->d.func_ref->def : ra->e->func->type->info->func->def;
   const Tmpl tmpl = {.list = base->base->tmpl->list, .call = ra->types};
   CHECK_BO(template_push_types(env, &tmpl));
-  ;
   Func_Base *const fbase = cpy_func_base(env->gwion->mp, base->base);
   fbase->xid             = sym;
-  fbase->tmpl->base      = 0;
   fbase->tmpl->call      = cpy_type_list(env->gwion->mp, ra->types);
   const Fptr_Def fptr    = new_fptr_def(env->gwion->mp, fbase);
   const Func     m_func  = ensure_fptr(env, ra, fptr);
   if (m_func)
     nspc_add_type_front(v->from->owner, sym,
                         actual_type(env->gwion, m_func->value_ref->type));
-  if (fptr->type) type_remref(fptr->type, env->gwion);
   free_fptr_def(env->gwion->mp, fptr);
   nspc_pop_type(env->gwion->mp, env->curr);
   return m_func;
@@ -100,13 +95,25 @@ ANN static Func tmpl_exists(const Env env, struct ResolverArgs *ra,
 ANN static Func create_tmpl(const Env env, struct ResolverArgs *ra,
                             const m_uint i) {
   DECL_OO(const Value, value, = template_get_ready(env, ra->v, "template", i));
-  const Func_Def fdef =
-      (Func_Def)cpy_func_def(env->gwion->mp, value->d.func_ref->def);
-  if (vflag(ra->v, vflag_builtin)) set_vflag(value, vflag_builtin);
+  if (value->d.func_ref->def->builtin) set_vflag(value, vflag_builtin);
+  const Func_Def fdef = cpy_func_def(env->gwion->mp, value->d.func_ref->def);
   fdef->base->tmpl->call = cpy_type_list(env->gwion->mp, ra->types);
-  fdef->base->tmpl->base = i;
+
+  fdef->vt_index = i;
+  if(is_spread_tmpl(value->d.func_ref->def->base->tmpl)) {
+    Arg_List args = fdef->base->args ?: new_mp_vector(env->gwion->mp, Arg, 0);
+    for(uint32_t i = 0; i < ra->types->len; i++) {
+      char c[256];
+      sprintf(c, "arg%u", i);
+      Type_Decl *td = *mp_vector_at(ra->types, Type_Decl*, i);
+      Arg arg = { .td = cpy_type_decl(env->gwion->mp, td), .var_decl = {.xid = insert_symbol(c), /*.value = v*/ }};
+      mp_vector_add(env->gwion->mp, &args, Arg, arg);
+    }
+    fdef->base->args = args;
+  }
+
   const Func func        = ensure_tmpl(env, fdef, ra->e, ra->v->from->filename);
-  if (func && vflag(ra->v, vflag_builtin)) {
+  if (func && func->def->builtin) {
     builtin_func(env->gwion->mp, func, (void*)ra->v->d.func_ref->code->native_func);
     set_vflag(func->value_ref, vflag_builtin);
     struct Op_Import opi = { .lhs = ra->v->d.func_ref->value_ref->type, .rhs = func->value_ref->type };
@@ -118,8 +125,9 @@ ANN static Func create_tmpl(const Env env, struct ResolverArgs *ra,
 ANN static Func func_match(const Env env, struct ResolverArgs *ra) {
   for (m_uint i = 0; i < ra->v->from->offset + 1; ++i) {
     const Value exists = template_get_ready(env, ra->v, ra->tmpl_name, i);
-    const Func  func =
-        exists ? tmpl_exists(env, ra, exists) : create_tmpl(env, ra, i);
+    const Func  func = exists
+           ? tmpl_exists(env, ra, exists)
+           : create_tmpl(env, ra, i);
     if (func) return func;
   }
   return NULL;
@@ -141,8 +149,9 @@ ANN static Func find_tmpl(const Env env, const Value v, Exp_Call *const exp,
   (void)env_push(env, v->from->owner_class, v->from->owner);
   if (v->from->owner_class && v->from->owner_class->info->cdef->base.tmpl)
     (void)template_push_types(env, v->from->owner_class->info->cdef->base.tmpl);
-  const Func m_func = !is_fptr(env->gwion, v->type) ? func_match(env, &ra)
-                                                    : fptr_match(env, &ra);
+  const bool is_clos = isa(exp->func->type, env->gwion->type[et_closure]) > 0;
+  const Func m_func = !is_clos ? func_match(env, &ra)
+                               : fptr_match(env, &ra);
   if (v->from->owner_class && v->from->owner_class->info->cdef->base.tmpl)
     nspc_pop_type(env->gwion->mp, env->curr);
   env_pop(env, scope);
index 8f94d9fc4c999309f6aae9a542f5b4fb3f05fb75..e33ae9cd70d18991e4d41eef133dd558c8829092 100644 (file)
@@ -238,7 +238,6 @@ ANN bool tmpl_match(const Env env, const struct Op_Import *opi,
 ANN static Type op_def(const Env env, struct Op_Import *const opi,
                 const Func_Def fdef) {
   const Func_Def tmpl_fdef    = cpy_func_def(env->gwion->mp, fdef);
-  tmpl_fdef->base->tmpl->base = 0;
   tmpl_fdef->base->tmpl->call = new_mp_vector(env->gwion->mp,
     sizeof(Type_Decl*), fdef->base->tmpl->list->len);
   if (opi->lhs) {
@@ -312,10 +311,10 @@ ANN static Type chuck_rewrite(const Env env, const struct Op_Import *opi, const
   base->op = insert_symbol(env->gwion->st, "=>");
   const Type ret = check_exp(env, exp_self(base));
   if(ret) return ret;
-  env->context->error = false;
+  env_set_error(env,  false);
   base->op = orig;
   env_warn(env, opi->pos, _("during rewriting operation"));
-  env->context->error = true;
+  env_set_error(env,  true);
   return NULL;
 }
 
@@ -350,11 +349,9 @@ ANN Type op_check(const Env env, struct Op_Import *opi) {
   if (!strcmp(op, "$") && opi->rhs == opi->lhs)
     return opi->rhs;
   if (!strcmp(op, "@func_check")) return NULL;
-  if (!strcmp(op, "@class_check"))
-    return env->gwion->type[et_error];
   if(!strcmp(op, "=>") && !strcmp(opi->rhs->name, "@now")) {
     gwerr_basic(_("no match found for operator"), "expected duration", "did you try converting to `dur`?", env->name, opi->pos, 0);
-    env->context->error = true;
+    env_set_error(env,  true);
   } else if (strcmp(op, "@implicit")) {
     if (opi->rhs && opi->lhs && is_func(env->gwion, opi->rhs)) { // is_callable
       const size_t len = strlen(op);
index 039cbbf21ea11dc54889d2ac952619cf3c7f4532..76d46898c1b09e3a6954fd6276c9273ba2399e19 100644 (file)
@@ -14,7 +14,7 @@
 #include "partial.h"
 
 ANN static Arg_List partial_arg_list(const Env env, const Arg_List base, const Exp e) {
-  Arg_List args = new_mp_vector(env->gwion->mp, sizeof(Arg), 0);
+  Arg_List args = new_mp_vector(env->gwion->mp, Arg, 0);
   Exp next = e;
   uint32_t i = 0;
   while(next) {
@@ -23,8 +23,7 @@ ANN static Arg_List partial_arg_list(const Env env, const Arg_List base, const E
       sprintf(c, "@%u", args->len);
       const Arg *src = mp_vector_at(base, Arg, i);
       Type_Decl *td = src->td ? cpy_type_decl(env->gwion->mp, src->td) : NULL;
-      const Array_Sub array = src->var_decl.array ? cpy_array_sub(env->gwion->mp, src->var_decl.array) : NULL;
-      Arg arg = { .td = td, .var_decl = { .xid = insert_symbol(c), .array = array }};
+      Arg arg = { .td = td, .var_decl = { .xid = insert_symbol(c) }};
       mp_vector_add(env->gwion->mp, &args, Arg, arg);
     }
     i++;
@@ -45,28 +44,29 @@ ANN2(1, 2) static inline Func_Base *partial_base(const Env env, const Func_Base
   return fb;
 }
 
-ANN static Exp partial_exp(const Env env, Exp e, const uint i) {
+ANN static Exp partial_exp(const Env env, Arg_List args, Exp e, const uint i) {
   if(is_hole(env, e) || is_typed_hole(env, e)) {
     char c[256];
     sprintf(c, "@%u", i);
     const Exp exp = new_prim_id(env->gwion->mp, insert_symbol(c), e->pos);
-    exp->type = e->type;
-    exp->d.prim.value = new_value(env, e->type, c, e->pos);
+    exp->type = known_type(env, mp_vector_at(args, Arg, i)->td);
+    exp->d.prim.value = new_value(env, exp->type, c, e->pos);
     valid_value(env, insert_symbol(c), exp->d.prim.value);
     return exp;
   }
   const Exp next = e->next;
   e->next = NULL;
   const Exp exp = cpy_exp(env->gwion->mp, e);
+  exp->type = e->type;
   e->next = next;
   return exp;
 }
 
-ANN2(1) static Exp partial_call(const Env env, Exp e) {
+ANN2(1) static Exp partial_call(const Env env, Arg_List args, Exp e) {
   Exp base = NULL, arg;
   uint32_t i = 0;
   while(e) {
-    const Exp exp = partial_exp(env, e, i++);
+    const Exp exp = partial_exp(env, args, e, i++);
     if(base) arg = arg->next = exp;
     else arg = base = exp;
     e = e->next;
@@ -81,7 +81,7 @@ ANN Func find_match(const Env env, Func func, const Exp exp, const bool implicit
     Exp e = exp;
     uint32_t i = 0;
     Arg_List args = func->def->base->args;
-    uint32_t len = args ? args->len : 0;
+    uint32_t len = mp_vector_len(args);
     while(e) {
       if (i >= len) break;
       const Arg *arg = mp_vector_at(args, Arg, i++);
@@ -154,7 +154,7 @@ ANN static Func partial_match(const Env env, const Func up, const Exp args, cons
           gw_err(_("\nthose functions could match:\n"));
           print_signature(f);
           ambiguity(env, next, args, loc);
-          env->context->error = true;
+          env_set_error(env,  true);
           return NULL;
         }
       }
@@ -164,10 +164,10 @@ ANN static Func partial_match(const Env env, const Func up, const Exp args, cons
   return NULL;
 }
 
-ANN static Stmt partial_code(const Env env, const Exp efun, const Exp earg) {
-  Stmt_List slist = new_mp_vector(env->gwion->mp, sizeof(struct Stmt_), 1);
-  const Exp arg = partial_call(env, earg);
+ANN static Stmt partial_code(const Env env, Arg_List args, const Exp efun, const Exp earg) {
+  const Exp arg = partial_call(env, args, earg);
   const Exp exp = new_exp_call(env->gwion->mp, efun, arg, efun->pos);
+  Stmt_List slist = new_mp_vector(env->gwion->mp, struct Stmt_, 1);
   Stmt stmt = mp_vector_at(slist, struct Stmt_, 0);
   stmt->stmt_type = ae_stmt_return;
   stmt->d.stmt_exp.val = exp;
@@ -183,7 +183,7 @@ ANN static uint32_t count_args_exp(Exp args) {
 ANN static uint32_t count_args_func(Func f, const uint32_t i) {
   uint32_t max = 0;
   while(f) {
-    const uint32_t len =  f->def->base->args ? f->def->base->args->len : 0;
+    const uint32_t len =  mp_vector_len(f->def->base->args);
     if(len > i && len > max) max = len;
     f = f->next;
   }
@@ -218,11 +218,11 @@ ANN Type partial_type(const Env env, Exp_Call *const call) {
   }
   nspc_push_value(env->gwion->mp, env->curr);
   Func_Base *const fbase = partial_base(env, f->def->base, call->args, call->func->pos);
-  const Stmt code = partial_code(env, call->func, call->args);
+  const Stmt code = partial_code(env, f->def->base->args, call->func, call->args);
   const Exp exp = exp_self(call);
   exp->d.exp_lambda.def = new_func_def(env->gwion->mp, fbase, code);
   exp->exp_type = ae_exp_lambda;
-  CHECK_OO(traverse_func_def(env, exp->d.exp_lambda.def));
+  const m_bool ret = traverse_func_def(env, exp->d.exp_lambda.def);
   nspc_pop_value(env->gwion->mp, env->curr);
-  return exp->d.exp_lambda.def->base->func->value_ref->type;
+  return ret ? exp->d.exp_lambda.def->base->func->value_ref->type : NULL;
 }
index 275966ca989dd086dfe6fa7fe2c9886584e07872..ade9f79e9fa8544f91f8b9a0852a9b1512485527 100644 (file)
@@ -1,4 +1,3 @@
-#include <string.h>
 #include "gwion_util.h"
 #include "gwion_ast.h"
 #include "gwion_env.h"
@@ -11,6 +10,7 @@
 #include "instr.h"
 #include "operator.h"
 #include "import.h"
+#include "spread.h"
 
 static inline void add_type(const Env env, const Nspc nspc, const Type t) {
   nspc_add_type_front(nspc, insert_symbol(t->name), t);
@@ -31,59 +31,47 @@ ANN static inline m_bool scan0_defined(const Env env, const Symbol s,
   return already_defined(env, s, pos);
 }
 
-ANN static void fptr_assign(const Fptr_Def fptr) {
-  const Func_Def def = fptr->type->info->func->def;
-  if (GET_FLAG(fptr->base, global)) {
-    SET_FLAG(fptr->value, global);
-    SET_FLAG(fptr->base->func, global);
-    SET_FLAG(def->base, global);
-  } else if (!GET_FLAG(fptr->base, static)) {
-    set_vflag(fptr->value, vflag_member);
-    set_vflag(fptr->base->func->value_ref, vflag_member);
-    def->stack_depth += SZ_INT;
-  } else {
-    SET_FLAG(fptr->value, static);
-    SET_FLAG(fptr->base->func, static);
-    SET_FLAG(def->base, static);
-  }
-  if (fbflag(def->base, fbflag_variadic)) def->stack_depth += SZ_INT;
-}
-
-static void fptr_def(const Env env, const Fptr_Def fptr) {
-  const Func_Def def = new_func_def(
-      env->gwion->mp, cpy_func_base(env->gwion->mp, fptr->base), NULL);
-  fptr->base->func = new_func(env->gwion->mp, s_name(fptr->base->xid), def);
-  fptr->value->d.func_ref     = fptr->base->func;
-  fptr->base->func->value_ref = fptr->value;
-  fptr->type->info->func      = fptr->base->func;
-  def->base->func             = fptr->base->func;
+ANN static Arg_List fptr_arg_list(const Env env, const Fptr_Def fptr) {
+  if(env->class_def && !GET_FLAG(fptr->base, static)) {
+    Arg arg = { .td = type2td(env->gwion, env->class_def, fptr->base->td->pos) };
+    if(fptr->base->args) {
+      Arg_List args = new_mp_vector(env->gwion->mp, Arg, fptr->base->args->len + 1);
+      mp_vector_set(args, Arg, 0, arg);
+      for(uint32_t i = 0; i < fptr->base->args->len; i++) {
+        Arg *base  = mp_vector_at(fptr->base->args, Arg, i);
+        Arg arg = { .td = cpy_type_decl(env->gwion->mp, base->td) };
+        mp_vector_set(args, Arg, i+1, arg);
+      }
+      return args;
+    } else {
+      Arg_List args = new_mp_vector(env->gwion->mp, Arg, 1);
+      mp_vector_set(args, Arg, 0, arg);
+      return args;
+    }
+  } else if(fptr->base->args)
+    return cpy_arg_list(env->gwion->mp, fptr->base->args);
+  return NULL;
 }
 
 ANN m_bool scan0_fptr_def(const Env env, const Fptr_Def fptr) {
-  CHECK_BB(env_access(env, fptr->base->flag, fptr->base->td->pos));
-  CHECK_BB(scan0_defined(env, fptr->base->xid, fptr->base->td->pos));
-  const m_str name   = s_name(fptr->base->xid);
-  const Type  t      = scan0_type(env, name, env->gwion->type[et_fptr]);
-  if(env->class_def && !strncmp(s_name(fptr->base->xid), "@sig", 4)) {
-    SET_FLAG(fptr->base, static);
-    SET_FLAG(fptr->base, global);
-  }
-  const bool  global = !env->class_def && GET_FLAG(fptr->base, global);
-  t->flag |= fptr->base->flag;
-  fptr->type = t;
-  if (global) {
-    context_global(env);
-    env_push_global(env);
+  const loc_t loc = fptr->base->td->pos;
+  CHECK_BB(env_access(env, fptr->base->flag, loc));
+  CHECK_BB(scan0_defined(env, fptr->base->xid, loc));
+  const Arg_List args = fptr_arg_list(env, fptr);
+  Func_Base *const fbase = new_func_base(env->gwion->mp, cpy_type_decl(env->gwion->mp, fptr->base->td),
+    insert_symbol("func"), args, ae_flag_static | ae_flag_private, loc);
+  const Func_Def fdef = new_func_def(env->gwion->mp, fbase, NULL);
+  Ast body = new_mp_vector(env->gwion->mp, Section, 1);
+  mp_vector_set(body, Section, 0, MK_SECTION(func, func_def, fdef));
+  Type_Decl* td = new_type_decl(env->gwion->mp, insert_symbol(env->gwion->type[et_closure]->name), loc);
+  const Class_Def cdef = new_class_def(env->gwion->mp, ae_flag_final, fptr->base->xid, td, body, loc);
+  if(GET_FLAG(fptr->base, global)) SET_FLAG(cdef, global);
+  if(fptr->base->tmpl) {
+    fbase->tmpl = cpy_tmpl(env->gwion->mp, fptr->base->tmpl);
+    cdef->base.tmpl = cpy_tmpl(env->gwion->mp, fptr->base->tmpl);
   }
-  fptr->value = mk_class(env, t, fptr->base->pos);
-  if (global) env_pop(env, 0);
-  valuefrom(env, fptr->value->from);
-  fptr_def(env, fptr);
-  if (env->class_def) fptr_assign(fptr);
-  set_vflag(fptr->value, vflag_func);
-  add_type(env, t->info->value->from->owner, t);
-  type_addref(t);
-  return GW_OK;
+  fptr->cdef = cdef;
+  return scan0_class_def(env, cdef);
 }
 
 static OP_CHECK(opck_implicit_similar) {
@@ -206,7 +194,7 @@ ANN m_bool scan0_type_def(const Env env, const Type_Def tdef) {
     op_cpy(env, &opi);
     scan0_explicit_distinct(env, base, tdef->type);
     type_addref(tdef->type); // maybe because of scope_iter in nspc_free_values
-  } else if(tdef->ext->array)
+  } else //if(tdef->ext->array)
     set_tflag(tdef->type, tflag_typedef);
   if(tflag(base, tflag_ref)) {
     set_tflag(tdef->type, tflag_ref);
@@ -352,7 +340,7 @@ ANN static m_bool find_traits(const Env env, ID_List traits, const loc_t pos) {
     if (!nspc_lookup_trait1(env->curr, xid)) {
       gwerr_basic(_("can't find trait"), NULL, NULL, env->name, pos, 0);
       did_you_mean_trait(env->curr, s_name(xid));
-      env_set_error(env);
+      env_set_error(env, true);
       return GW_ERROR;
     }
   }
@@ -363,14 +351,13 @@ 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(GET_FLAG(cdef, global) && !type_global(env, parent)) {
+  if(GET_FLAG(cdef, global) && isa(parent, env->gwion->type[et_closure]) < 0 && !type_global(env, parent)) {
     gwerr_basic(_("parent type is not global"), NULL, NULL, env->name, cdef->base.ext ? cdef->base.ext->pos : cdef->base.pos, 0);
     const Value v = parent->info->value;
     gwerr_warn("declared here", NULL, NULL, v->from->filename, v->from->loc);
-    env->context->error = true;
+    env_set_error(env,  true);
     return NULL;
   }
-  //if(parent) type_addref(parent);
   if (cdef->traits) CHECK_BO(find_traits(env, cdef->traits, cdef->pos));
   const Type t = scan0_type(env, s_name(cdef->base.xid), parent);
   if (cflag(cdef, cflag_struct)) {
@@ -382,11 +369,45 @@ ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
   t->nspc->parent = env->curr;
   t->info->cdef   = cdef;
   t->flag |= cdef->flag;
-  //add_type(env, t->info->value->from->owner, t);
   cdef_flag(cdef, t);
   return t;
 }
 
+
+ANN static m_bool _spread_tmpl(const Env env, const Type t, const Spread_Def spread) {
+  if(t->info->value->from->owner_class)
+    CHECK_BB(_spread_tmpl(env, t->info->value->from->owner_class, spread));
+  const Tmpl *tmpl = t->info->cdef->base.tmpl;
+  if(!tmpl || !tmpl->call) return GW_OK;
+  if(is_spread_tmpl(tmpl))
+    CHECK_BB(spread_ast(env, spread, tmpl));
+  return GW_OK;
+}
+
+ANN static m_bool spread_tmpl(const Env env, const Spread_Def spread) {
+  if(env->class_def) CHECK_BB(_spread_tmpl(env, env->class_def, spread));
+  if(!env->func) return GW_OK;
+  const Tmpl *tmpl = env->func->def->base->tmpl;
+  if(!tmpl || !tmpl->call) return GW_OK;
+  if(is_spread_tmpl(tmpl))
+      CHECK_BB(spread_ast(env, spread, tmpl));
+  return GW_OK;
+}
+
+ANN static bool spreadable(const Env env) {
+  const Func f = env->func;
+  if(f && f->def->base->tmpl && is_spread_tmpl(f->def->base->tmpl))
+    return true;
+  Type t = env->class_def;
+  while(t) {
+    const Tmpl *tmpl = t->info->cdef->base.tmpl;
+    if(tmpl && is_spread_tmpl(tmpl))
+      return true;
+    t = t->info->value->from->owner_class;
+  }
+  return false;
+}
+
 ANN static m_bool scan0_stmt_list(const Env env, Stmt_List l) {
   for(m_uint i = 0; i < l->len; i++) {
     const Stmt stmt = mp_vector_at(l, struct Stmt_, i);
@@ -395,26 +416,48 @@ ANN static m_bool scan0_stmt_list(const Env env, Stmt_List l) {
         env->name = stmt->d.stmt_pp.data;
       else if (stmt->d.stmt_pp.pp_type == ae_pp_import)
         CHECK_BB(plugin_ini(env->gwion, stmt->d.stmt_pp.data, stmt->pos));
+    } else if (stmt->stmt_type == ae_stmt_spread) {
+      if(!spreadable(env))
+        ERR_B(stmt->pos, "spread statement outside of variadic environment");
+      if(!env->context->extend)
+         env->context->extend = new_mp_vector(env->gwion->mp, Section, 0);
+      CHECK_BB(spread_tmpl(env, &stmt->d.stmt_spread));
     }
   }
   return GW_OK;
 }
 
-#define scan0_func_def dummy_func
+ANN m_bool scan0_func_def(const Env env, const Func_Def fdef) {
+  const Ast old_extend = env->context ? env->context->extend : NULL;
+  if(!fdef->base->tmpl || !fdef->base->tmpl->call) return GW_OK;
+  if(env->context) {
+    if(fdef->base->tmpl && fdef->base->tmpl->call && is_spread_tmpl(fdef->base->tmpl)) {
+    struct Func_ fake = {.name = s_name(fdef->base->xid), .def = fdef }, *const former =
+                                                            env->func;
+    env->func = &fake;
+    if(!fdef->builtin && fdef->d.code && fdef->d.code->d.stmt_code.stmt_list)
+      scan0_stmt_list(env, fdef->d.code->d.stmt_code.stmt_list);
+    if(env->context->extend)
+      fdef->d.code->d.stmt_code.stmt_list = spread_func(env, fdef->d.code->d.stmt_code.stmt_list);
+    env->func = former;
+    env->context->extend = old_extend;
+  }}
+  return GW_OK;
+}
 
 ANN static m_bool scan0_extend_def(const Env env, const Extend_Def xdef) {
   DECL_OB(const Type, t, = known_type(env, xdef->td));
-  if (isa(t, env->gwion->type[et_compound]) < 0)
-    ERR_B(xdef->td->pos, _("only compound types can be extended"))
-  if (GET_FLAG(t, final)) // TODO: add type initial declaration
-    ERR_B(xdef->td->pos, _("can't extend final type"))
-  Ast ast = xdef->body;
-  for(m_uint i = 0; i < ast->len; i++) {
-    Section * section = mp_vector_at(ast, Section, i);
-    if (section->section_type == ae_section_func &&
-        GET_FLAG(section->d.func_def->base, abstract))
-      ERR_B(section->d.func_def->base->pos,
-            _("can't use {/+}abstract{0} functions in {+/}extends{0}"))
+  if(type_global(env, t)) {
+    for(uint32_t i = 0; i < xdef->traits->len; i++) {
+      const Symbol xid = *mp_vector_at(xdef->traits, Symbol, i);
+      const Trait global = nspc_lookup_trait1(env->global_nspc, xid);
+      if(!global) {
+        const Trait trait = nspc_lookup_trait1(env->curr, xid);
+        gwerr_basic("trait should be declared global", NULL, NULL, trait->filename, trait->loc, 0);
+        gwerr_secondary("from the request ", env->name, xdef->td->pos);
+        env_set_error(env, true);
+      }
+    }
   }
   xdef->t = t;
   return GW_OK;
@@ -425,15 +468,20 @@ ANN static m_bool _scan0_trait_def(const Env env, const Trait_Def pdef) {
   trait->loc        = pdef->pos;
   trait->name       = s_name(pdef->xid);
   trait->filename   = env->name;
-  nspc_add_trait(env->curr, pdef->xid, trait);
+  if(GET_FLAG(pdef, global))
+    nspc_add_trait(env->global_nspc, pdef->xid, trait);
+  else nspc_add_trait(env->curr, pdef->xid, trait);
   Ast ast = pdef->body;
   if(!ast) return GW_OK; // ???
   for(m_uint i = 0; i < ast->len; i++) {
     Section *section = mp_vector_at(ast, Section, i);
     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);
+      if (fdef->base->flag != ae_flag_none &&
+          fdef->base->flag != (ae_flag_none | ae_flag_abstract))
+        ERR_B(fdef->base->pos, "Trait function must be declared without qualifiers");
+      if (!trait->fun) trait->fun = new_mp_vector(env->gwion->mp, Func_Def, 0);
+      mp_vector_add(env->gwion->mp, &trait->fun, Func_Def, fdef);
     }
   }
   return GW_OK;
@@ -445,7 +493,7 @@ ANN static m_bool scan0_trait_def(const Env env, const Trait_Def pdef) {
   if (exists) {
     gwerr_basic("trait already defined", NULL, NULL, env->name, pdef->pos, 0);
     gwerr_secondary("defined here", env->name, exists->loc);
-    env_set_error(env);
+    env_set_error(env, true);
     return already_defined(env, s, pdef->pos);
   }
   if (pdef->traits) CHECK_BB(find_traits(env, pdef->traits, pdef->pos));
@@ -461,14 +509,16 @@ ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
   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);
-//  const m_uint scope = env_push(env, cdef->base.type->info->value->from->owner_class, cdef->base.type->info->value->from->owner);
   const m_bool ret = cdef->body ? env_body(env, cdef, scan0_section) : GW_OK;
-//  env_pop(env, scope);
   return ret;
 }
 
+
+
+ANN Ast spread_class(const Env env, const Ast body);
 ANN m_bool scan0_class_def(const Env env, const Class_Def c) {
   CHECK_BB(scan0_global(env, c->flag, c->pos));
+  const Ast old_extend = env->context ? env->context->extend : NULL;
   const int       cpy  = tmpl_base(c->base.tmpl) || GET_FLAG(c, global);
   const Class_Def cdef = !cpy ? c : cpy_class_def(env->gwion->mp, c);
   if (GET_FLAG(cdef, global)) { // could be updated
@@ -487,8 +537,10 @@ ANN m_bool scan0_class_def(const Env env, const Class_Def c) {
     c->base.type->info->cdef = cdef;
     set_tflag(c->base.type, tflag_cdef);
   }
-//  if (GET_FLAG(cdef, global))
-//    type_addref(c->base.type);
+  if(env->context) {
+    if(!tmpl_base(c->base.tmpl) && env->context->extend) cdef->body = spread_class(env, cdef->body);
+    env->context->extend = old_extend;
+  }
   return ret;
 }
 
index 8438427f1fc5732c06748272d1dffdccc0f868a7..b04f18188bc2e30bf0e86889e92a154a69c4adf8 100644 (file)
@@ -35,17 +35,17 @@ ANN static inline m_bool ensure_scan1(const Env env, const Type t) {
 }
 
 ANN static m_bool check_global(const Env env, const Type t, const loc_t pos) {
-  const struct ValueFrom_ *from = t->info->value->from;
+  const ValueFrom *from = t->info->value->from;
   if(from->owner_class && isa(from->owner_class, env->class_def) > 0)
     return true;
   if(!GET_FLAG(t, global) && !from_global_nspc(env, from->owner)) {
     if(from->owner_class && type_global(env, from->owner_class))
       return true;
     gwerr_basic("can't use non-global type in a global class", NULL, NULL, env->name, pos, 0);
-    gwerr_secondary("not declared global", from->filename, from->loc);
-    const struct ValueFrom_ *ownerFrom = env->class_def->info->value->from;
-    gwerr_secondary("is global", ownerFrom->filename, ownerFrom->loc);
-    env_set_error(env);
+    gwerr_secondary_from("not declared global", from);
+    const ValueFrom *ownerFrom = env->class_def->info->value->from;
+    gwerr_secondary_from("is global", ownerFrom);
+    env_set_error(env, true);
     return false;
   }
   return true;
@@ -79,7 +79,7 @@ ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl *decl) {
   return t;
 }
 
-static inline m_bool scan1_defined(const Env env, const Var_Decl var) {
+static inline m_bool scan1_defined(const Env env, const Var_Decl *var) {
   if (var->value) // from an auto declaration
     return GW_OK;
   if (((!env->class_def || !GET_FLAG(env->class_def, final) ||
@@ -100,60 +100,48 @@ static inline bool array_ref2(const Array_Sub array) {
   return array && !(array->exp && exp_is_zero(array->exp));
 }
 
-ANN static m_bool scan1_decl(const Env env, const Exp_Decl *decl) {
+ANN static m_bool scan1_decl(const Env env, Exp_Decl *const decl) {
   const bool    decl_ref = array_ref(decl->td->array);
-  Var_Decl_List list     = decl->list;
-  for(uint32_t i = 0; i < list->len; i++) {
-    const Var_Decl vd = mp_vector_at(list, struct Var_Decl_, i);
-    CHECK_BB(isres(env, vd->xid, exp_self(decl)->pos));
-    Type t = decl->type;
-    CHECK_BB(scan1_defined(env, vd));
-    if (vd->array) {
-      if (vd->array->exp) CHECK_BB(scan1_exp(env, vd->array->exp));
-      CHECK_OB((t = array_type(env, decl->type, vd->array->depth)));
-    }
-    const Type base = array_base_simple(t);
-    if ((!GET_FLAG(decl->td, late) && GET_FLAG(base, abstract)) &&
-        (array_ref2(vd->array) ||
-        array_ref2(decl->td->array)))
-      ERR_B(vd->pos, _("arrays of abstract type '%s' must be declared empty"),
-            base->name);
-
-    const Value v = vd->value =
-        vd->value ?: new_value(env, t, s_name(vd->xid), vd->pos);
-    nspc_add_value(env->curr, vd->xid, v);
-    if (GET_FLAG(t, abstract) && !GET_FLAG(decl->td, late)) SET_FLAG(v, late);
-    v->type = t;
-    if (decl_ref || array_ref(vd->array)) SET_FLAG(v, late);
-    v->flag |= decl->td->flag;
-    if (!env->scope->depth) {
-      valuefrom(env, v->from);
-      if (env->class_def) {
-        if (env->class_def->info->tuple) tuple_contains(env, v);
-        if (!GET_FLAG(decl->td, static)) {
-          set_vflag(v, vflag_member);
-          if(isa(t, env->gwion->type[et_object]) > 0)
-            set_vflag(v, vflag_release);
-          if (tflag(env->class_def, tflag_struct)) {
-            v->from->offset = env->class_def->size;
-            env->class_def->size += t->size;
-          }
+  Var_Decl *const vd = &decl->vd;
+  CHECK_BB(isres(env, vd->xid, exp_self(decl)->pos));
+  Type t = decl->type;
+  CHECK_BB(scan1_defined(env, vd));
+  const Type base = array_base_simple(t);
+  if ((!GET_FLAG(decl->td, late) && GET_FLAG(base, abstract)) && array_ref2(decl->td->array))
+    ERR_B(vd->pos, _("arrays of abstract type '%s' must be declared empty"),
+          base->name);
+  const Value v = vd->value =
+      vd->value ?: new_value(env, t, s_name(vd->xid), vd->pos);
+  nspc_add_value(env->curr, vd->xid, v);
+  if (GET_FLAG(t, abstract) && !GET_FLAG(decl->td, late)) SET_FLAG(v, late);
+  v->type = t;
+  if (decl_ref) SET_FLAG(v, late);
+  v->flag |= decl->td->flag;
+  if (!env->scope->depth) {
+    valuefrom(env, v->from);
+    if (env->class_def) {
+      if (env->class_def->info->tuple) tuple_contains(env, v);
+      if (!GET_FLAG(decl->td, static)) {
+        set_vflag(v, vflag_member);
+        if(isa(t, env->gwion->type[et_object]) > 0)
+          set_vflag(v, vflag_release);
+        if (tflag(env->class_def, tflag_struct)) {
+          v->from->offset = env->class_def->size;
+          env->class_def->size += t->size;
         }
-      } else
-        set_vflag(v, vflag_fglobal); // file global
-    } else if (GET_FLAG(decl->td, global))
-      SET_FLAG(v, global);
-//    else if(v->type != env->gwion->type[et_auto] && (v->type != env->class_def || env->scope->depth)) {
-    else if(v->type != env->gwion->type[et_auto] && (v->type != env->class_def)) {
+      }
+    } else set_vflag(v, vflag_fglobal); // file global
+  } else if (GET_FLAG(decl->td, global))
+    SET_FLAG(v, global);
+    else if(v->type != env->gwion->type[et_auto] && v->type != env->class_def) {
       type_addref(v->type);
-      set_vflag(v, vflag_inner); // file global
-    }
+    set_vflag(v, vflag_inner); // file global
   }
-  ((Exp_Decl *)decl)->type = mp_vector_at(decl->list, struct Var_Decl_, 0)->value->type;
+  ((Exp_Decl *)decl)->type = decl->vd.value->type;
   return GW_OK;
 }
 
-ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl *decl) {
+ANN m_bool scan1_exp_decl(const Env env, Exp_Decl *const decl) {
   CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos));
   ((Exp_Decl *)decl)->type = scan1_exp_decl_type(env, (Exp_Decl *)decl);
   CHECK_OB(decl->type);
@@ -316,7 +304,7 @@ ANN static inline m_bool shadow_err(const Env env, const Value v,
   gwerr_basic(_("shadowing a previously defined variable"), NULL, NULL,
               env->name, loc, 0);
   defined_here(v);
-  env_set_error(env);
+  env_set_error(env, true);
   return GW_ERROR;
 }
 
@@ -340,8 +328,6 @@ ANN static inline m_bool shadow_var(const Env env, const Symbol sym,
   describe_stmt_func(scan1, name, type, prolog, exp)
 describe_ret_nspc(flow, Stmt_Flow,, !(scan1_exp(env, stmt->cond) < 0 ||
     scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
-describe_ret_nspc(varloop, Stmt_VarLoop,, !(scan1_exp(env, stmt->exp) < 0 ||
-    scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
 describe_ret_nspc(for, Stmt_For,, !(scan1_stmt(env, stmt->c1) < 0 ||
     scan1_stmt(env, stmt->c2) < 0 ||
     (stmt->c3 && scan1_exp(env, stmt->c3) < 0) ||
@@ -389,11 +375,9 @@ ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) {
 }
 
 ANN static Value arg_value(const Env env, Arg *const arg) {
-  const Var_Decl vd = &arg->var_decl;
+  const Var_Decl *vd = &arg->var_decl;
   const Value    v   = new_value(env, arg->type,
                             vd->xid ? s_name(vd->xid) : (m_str) __func__, arg->var_decl.pos);
-  if (vd->array)
-    v->type = arg->type = array_type(env, arg->type, vd->array->depth);
   if (arg->td)
     v->flag = arg->td->flag;
   return v;
@@ -402,11 +386,13 @@ ANN static Value arg_value(const Env env, Arg *const arg) {
 ANN static m_bool scan1_args(const Env env, Arg_List args) {
   for(uint32_t i = 0; i < args->len; i++) {
     Arg *arg = mp_vector_at(args, Arg, i);
-    const Var_Decl vd = &arg->var_decl;
+    Var_Decl *const vd = &arg->var_decl;
     if (vd->xid) CHECK_BB(isres(env, vd->xid, vd->pos));
     if (arg->td) {
       SET_FLAG(arg->td, late);
       CHECK_OB((arg->type = void_type(env, arg->td)));
+      if (GET_FLAG(env->func->def->base, global) && !type_global(env, arg->type))
+        ERR_B(arg->td->pos, "is not global");
       UNSET_FLAG(arg->td, late);
     }
     vd->value = arg_value(env, arg);
@@ -429,13 +415,6 @@ ANN static m_bool _scan1_fbase_tmpl(const Env env, Func_Base *base) {
     nspc_add_type(env->curr, spec->xid, env->gwion->type[et_auto]);
   }
   CHECK_OB((base->ret_type = scan1_noret(env, base)));
-  if (base->args) {
-    Arg_List args = base->args;
-    for(uint32_t i = 0; i < args->len; i++) {
-      Arg *arg = mp_vector_at(args, Arg, i);
-      CHECK_OB(known_type(env, arg->td));
-    }
-  }
   return GW_OK;
 }
 
@@ -464,32 +443,23 @@ ANN static m_bool scan1_fdef_base_tmpl(const Env env, const Func_Def fdef) {
   return GW_OK;
 }
 
+#include "object.h"
+#include "instr.h"
+#include "operator.h"
+#include "import.h"
+
 ANN m_bool scan1_fptr_def(const Env env, const Fptr_Def fptr) {
-  if (tmpl_base(fptr->base->tmpl)) return scan1_fbase_tmpl(env, fptr->base);
-  if (!fptr->base->func) {
-    fptr->base->func =
-        nspc_lookup_value0(env->curr, fptr->base->xid)->d.func_ref;
-    fptr->type = nspc_lookup_type0(env->curr, fptr->base->xid);
-  }
-  const Func_Def fdef = fptr->base->func->def;
-  CHECK_OB((fdef->base->ret_type = scan1_noret(env, fdef->base)));
-  if (!fdef->base->args) return GW_OK;
-  RET_NSPC(scan1_args(env, fdef->base->args))
+  return scan1_class_def(env, fptr->cdef);
 }
 
 ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) {
   if (!tdef->type) tdef->type = nspc_lookup_type0(env->curr, tdef->xid);
   if (tdef->when) CHECK_BB(scan1_exp(env, tdef->when));
-  if (!is_fptr(env->gwion, tdef->type) && !tflag(tdef->type, tflag_cdef)) {
+  if (!tflag(tdef->type, tflag_cdef)) {
     if(!tflag(tdef->type->info->parent, tflag_scan1))
                     return scan1_class_def(env, tdef->type->info->parent->info->cdef);
   }
-  if (!is_fptr(env->gwion, tdef->type) && !tdef->type->info->cdef) {
-    if(!tflag(tdef->type->info->parent, tflag_scan1))exit(12);
-  }
-  return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef)
-             ? scan1_cdef(env, tdef->type)
-             : GW_OK;
+  return tdef->type->info->cdef ? scan1_cdef(env, tdef->type) : GW_OK;
 }
 
 ANN static inline m_bool scan1_union_def_inner_loop(const Env env,
@@ -556,6 +526,10 @@ ANN static m_bool scan1_stmt_defer(const Env env, const Stmt_Defer stmt) {
   return scan1_stmt(env, stmt->stmt);
 }
 
+ANN static m_bool scan1_stmt_spread(const Env env, const Spread_Def spread) {
+  ERR_B(stmt_self(spread)->pos, "spread statement outside of variadic environment");
+}
+
 DECL_STMT_FUNC(scan1, m_bool, Env)
 
 ANN static inline m_bool scan1_stmt(const Env env, const Stmt stmt) {
@@ -684,7 +658,7 @@ ANN static m_bool _scan1_func_def(const Env env, const Func_Def fdef) {
     CHECK_BB(env_storage(env, fdef->base->flag, fdef->base->td->pos));
   CHECK_BB(scan1_fdef_defined(env, fdef));
   if (tmpl_base(fdef->base->tmpl)) return scan1_fdef_base_tmpl(env, fdef);
-  struct Func_ fake = {.name = s_name(fdef->base->xid)}, *const former =
+  struct Func_ fake = {.name = s_name(fdef->base->xid), .def = fdef }, *const former =
                                                              env->func;
   env->func = &fake;
   ++env->scope->depth;
@@ -700,12 +674,13 @@ ANN static m_bool _scan1_func_def(const Env env, const Func_Def fdef) {
   if (fdef->base->xid == insert_symbol("@gack") && !fake.weight) {
     gwerr_basic(_("`@gack` operator does not print anything"), NULL,
       _("use `<<<` `>>>` in the function"), env->name, fdef->base->pos, 0);
-    env->context->error = true;
+    env_set_error(env,  true);
     return GW_ERROR;
   }
   return ret;
 }
 
+
 ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
   const uint16_t depth = env->scope->depth;
   env->scope->depth = 0;
@@ -714,15 +689,8 @@ ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
   return ret;
 }
 
-ANN static m_bool scan1_extend_def(const Env env, const Extend_Def xdef) {
-  CHECK_BB(ensure_scan1(env, xdef->t));
-  CHECK_BB(extend_push(env, xdef->t));
-  const m_bool ret = scan1_ast(env, &xdef->body);
-  extend_pop(env, xdef->t);
-  return ret;
-}
-
 #define scan1_trait_def dummy_func
+#define scan1_extend_def dummy_func
 HANDLE_SECTION_FUNC(scan1, m_bool, Env)
 
 ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) {
@@ -761,8 +729,8 @@ ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
 ANN m_bool scan1_class_def(const Env env, const Class_Def cdef) {
   if (tmpl_base(cdef->base.tmpl)) return GW_OK;
   const Type      t = cdef->base.type;
-  const Class_Def c = t->info->cdef;
   if (tflag(t, tflag_scan1)) return GW_OK;
+  const Class_Def c = t->info->cdef;
   set_tflag(t, tflag_scan1);
   if (c->base.ext) CHECK_BB(cdef_parent(env, c));
   if (c->body) CHECK_BB(env_body(env, c, scan1_section));
index a68f0131d4e65e4d95d0b3e709802447ce5d9ae2..a56afd61200bc2255db2036754ebf040f41e8b45 100644 (file)
@@ -11,6 +11,7 @@
 #include "instr.h"
 #include "import.h"
 #include "default_args.h"
+#include "spread.h"
 
 ANN static m_bool scan2_stmt(const Env, const Stmt);
 ANN static m_bool scan2_stmt_list(const Env, Stmt_List);
@@ -29,13 +30,8 @@ ANN static inline m_bool ensure_scan2(const Env env, const Type t) {
 ANN static m_bool scan2_decl(const Env env, const Exp_Decl *decl) {
   const Type t = decl->type;
   CHECK_BB(ensure_scan2(env, t));
-  Var_Decl_List list = decl->list;
-  for(uint32_t i = 0; i < list->len; i++) {
-    const Var_Decl vd   = mp_vector_at(list, struct Var_Decl_, i);
-    const Exp array = vd->array ? vd->array->exp : NULL;
-    if (array) CHECK_BB(scan2_exp(env, array));
-    nspc_add_value(env->curr, vd->xid, vd->value);
-  }
+  const Var_Decl vd   = decl->vd;
+  nspc_add_value(env->curr, vd.xid, vd.value);
   return GW_OK;
 }
 
@@ -79,25 +75,21 @@ ANN static Value scan2_func_assign(const Env env, const Func_Def d,
 }
 
 ANN m_bool scan2_fptr_def(const Env env NUSED, const Fptr_Def fptr) {
-  if (!tmpl_base(fptr->base->tmpl)) {
-    const Func_Def def = fptr->type->info->func->def;
-    if (def->base->args) { RET_NSPC(scan2_args(def)) }
-  } else
-    set_tflag(fptr->type, tflag_ftmpl);
+  CHECK_BB(scan2_class_def(env, fptr->cdef));
+  const Func_Def fdef = mp_vector_at(fptr->cdef->body, struct Section_ , 0)->d.func_def;
+  if(fdef->base->func) set_fflag(fdef->base->func, fflag_fptr);
   return GW_OK;
 }
 
 ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f);
 ANN m_bool        scan2_type_def(const Env env, const Type_Def tdef) {
   if (tdef->when) CHECK_BB(scan2_exp(env, tdef->when));
-  if (!is_fptr(env->gwion, tdef->type) && !tflag(tdef->type, tflag_cdef)) {
+  if (tflag(tdef->type, tflag_cdef)) {
     if(!tflag(tdef->type->info->parent, tflag_scan2))
                     return scan2_class_def(env, tdef->type->info->parent->info->cdef);
   }
   if (!tdef->type->info->cdef) return GW_OK;
-  return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef)
-                    ? scan2_class_def(env, tdef->type->info->cdef)
-                    : GW_OK;
+  return tdef->type->info->cdef ? scan2_class_def(env, tdef->type->info->cdef) : GW_OK;
 }
 
 ANN static m_bool scan2_range(const Env env, Range *range) {
@@ -132,22 +124,10 @@ ANN static inline m_bool scan2_exp_slice(const Env env, const Exp_Slice *exp) {
   return scan2_range(env, exp->range);
 }
 
-ANN static m_bool multi_decl(const Env env, const Exp e, const Symbol op) {
-  if (e->exp_type == ae_exp_decl) {
-    if (e->d.exp_decl.list->len > 1)
-      ERR_B(e->pos, _("can't '%s' from/to a multi-variable declaration."),
-            s_name(op))
-    //    set_vflag(e->d.exp_decl.list->self->value, vflag_used);
-  }
-  return GW_OK;
-}
-
 ANN static inline m_bool scan2_exp_binary(const Env         env,
                                           const Exp_Binary *bin) {
   CHECK_BB(scan2_exp(env, bin->lhs));
-  CHECK_BB(scan2_exp(env, bin->rhs));
-  CHECK_BB(multi_decl(env, bin->lhs, bin->op));
-  return multi_decl(env, bin->rhs, bin->op);
+  return scan2_exp(env, bin->rhs);
 }
 
 ANN static inline m_bool scan2_exp_cast(const Env env, const Exp_Cast *cast) {
@@ -239,8 +219,6 @@ HANDLE_EXP_FUNC(scan2, m_bool, Env)
   describe_stmt_func(scan2, name, type, prolog, exp)
 scan2_stmt_func(flow, Stmt_Flow,, !(scan2_exp(env, stmt->cond) < 0 ||
     scan2_stmt(env, stmt->body) < 0) ? 1 : -1)
-scan2_stmt_func(varloop, Stmt_VarLoop,, !(scan2_exp(env, stmt->exp) < 0 ||
-    scan2_stmt(env, stmt->body) < 0) ? 1 : -1)
 scan2_stmt_func(for, Stmt_For,, !(scan2_stmt(env, stmt->c1) < 0 ||
     scan2_stmt(env, stmt->c2) < 0 ||
     (stmt->c3 && scan2_exp(env, stmt->c3) < 0) ||
@@ -284,6 +262,8 @@ ANN static m_bool scan2_stmt_defer(const Env env, const Stmt_Defer stmt) {
   return scan2_stmt(env, stmt->stmt);
 }
 
+#define scan2_stmt_spread dummy_func
+
 DECL_STMT_FUNC(scan2, m_bool, Env)
 
 ANN static m_bool scan2_stmt(const Env env, const Stmt stmt) {
@@ -300,16 +280,13 @@ ANN static m_bool scan2_stmt_list(const Env env, Stmt_List l) {
 
 ANN static m_bool scan2_func_def_overload(const Env env, const Func_Def f,
                                           const Value overload) {
-  const m_bool fptr = is_fptr(env->gwion, overload->type);
-  if (!is_func(env->gwion, overload->type) || // is_fptr
-      is_fptr(env->gwion, overload->type)) {
+  if (!is_func(env->gwion, overload->type)) {
     if (!fbflag(f->base, fbflag_internal))
       ERR_B(f->base->pos,
             _("function name '%s' is already used by another value"),
             overload->name)
   }
-  const Func obase =
-      !fptr ? overload->d.func_ref : _class_base(overload->type)->info->func;
+  const Func obase = overload->d.func_ref;
   if (GET_FLAG(obase->def->base, final) && (!env->class_def || (obase->value_ref->from->owner_class != env->class_def))) {
     env_err(env, f->base->pos, _("can't overload final function `{G}%s{0}`"), s_name(f->base->xid));
     env_warn(env, obase->def->base->pos, _("first declared here"));
@@ -319,6 +296,8 @@ ANN static m_bool scan2_func_def_overload(const Env env, const Func_Def f,
   const m_bool tmpl = fflag(obase, fflag_tmpl);
   if ((!tmpl && base) || (tmpl && !base && !f->base->tmpl))
     ERR_B(f->base->pos, _("must overload template function with template"))
+  if (GET_FLAG(f->base, global) != GET_FLAG(obase->def->base, global))
+    ERR_B(f->base->pos, _("function is declared global")) // improve me
   return GW_OK;
 }
 
@@ -333,9 +312,7 @@ ANN static Func scan_new_func(const Env env, const Func_Def f,
 }
 
 ANN static Type func_type(const Env env, const Func func) {
-  const Type base =
-      env->gwion->type[!fbflag(func->def->base, fbflag_lambda) ? et_function
-                                                               : et_lambda];
+  const Type base = env->gwion->type[et_function];
   const Type t    = type_copy(env->gwion->mp, base);
   t->info->parent = base;
   t->name         = func->name;
@@ -368,10 +345,8 @@ static Value func_value(const Env env, const Func f, const Value overload) {
     f->next                    = overload->d.func_ref->next;
     overload->d.func_ref->next = f;
   }
-  if (env->class_def && !GET_FLAG(f->def->base, static)) {
-    t->size += SZ_INT;
+  if (env->class_def && !GET_FLAG(f->def->base, static))
     set_vflag(v, vflag_member);
-  }
   return v;
 }
 
@@ -405,15 +380,11 @@ static m_bool scan2_fdef_tmpl(const Env env, const Func_Def f,
                   "in this namespace",
                   name)
           const Symbol sym =
-              func_symbol(env, env->curr->name, name, "template", ff->vt_index);
+              func_symbol(env, env->curr->name, name, "template", ff->def->vt_index);
           nspc_add_value(env->curr, sym, value);
-          if (!overload) {
-//            value_addref(value);
-            nspc_add_value(env->curr, f->base->xid, value);
-//    nspc_add_func(env->curr, f->base->xid, func);
-          }
-    nspc_add_func(env->curr, sym, func);
-          func->vt_index = ff->vt_index;
+          if (!overload) nspc_add_value(env->curr, f->base->xid, value);
+          nspc_add_func(env->curr, sym, func);
+          func->def->vt_index = ff->def->vt_index;
           return GW_OK;
         }
       } while ((ff = ff->next) && ++i);
@@ -422,13 +393,9 @@ static m_bool scan2_fdef_tmpl(const Env env, const Func_Def f,
   --i;
   const Symbol sym = func_symbol(env, env->curr->name, name, "template", i);
   nspc_add_value(env->curr, sym, value);
-nspc_add_func(env->curr, sym, func);
-  if (!overload) {
-//    value_addref(value);
-    nspc_add_value(env->curr, f->base->xid, value);
-//    nspc_add_func(env->curr, f->base->xid, func);
-  } else
-    func->vt_index = ++overload->from->offset;
+  nspc_add_func(env->curr, sym, func);
+  if (!overload) nspc_add_value(env->curr, f->base->xid, value);
+  else func->def->vt_index = ++overload->from->offset;
   return GW_OK;
 }
 
@@ -460,20 +427,36 @@ ANN static void scan2_func_def_flag(const Env env, const Func_Def f) {
     set_tflag(env->class_def, tflag_dtor);
 }
 
+
 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;
   Specialized_List sl   = f->base->tmpl->list;
   m_uint           tlen = 0;
   vector_init(&v);
-  for(uint32_t i = 0; i < sl->len; i++) {
+  const bool spread = is_spread_tmpl(f->base->tmpl);
+  const uint32_t len = !spread ? sl->len : sl->len - 1;
+  for(uint32_t i = 0; i < len; i++) {
     Specialized * spec = mp_vector_at(sl, Specialized, i);
     const Type t = nspc_lookup_type0(env->curr, spec->xid);
-    if (!t) return NULL;
+    if (!t) return NULL; // leaks vector ?
     vector_add(&v, (vtype)t);
-    tlen += strlen(t->name);
+    tlen += strlen(t->name); // this can be improved to use fully qualified name
     ++tlen;
   } //while ((id = id->next) && ++tlen);
+
+  if(spread && f->base->tmpl->call) {
+    Type_List tl   = f->base->tmpl->call;
+    for(uint32_t i = len; i < tl->len; i++) {
+      Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i);
+      const Type t = known_type(env, td);
+      if (!t) return NULL; // leaks vector?
+      vector_add(&v, (vtype)t);
+      tlen += strlen(t->name); // this can be improved to use fully qualified name
+      ++tlen;
+    }
+  }
+
   char  tmpl_name[tlen + 2];
   m_str str = tmpl_name;
   for (m_uint i = 0; i < vector_size(&v); ++i) {
@@ -485,7 +468,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->base->tmpl->base);
+                                 (m_uint)f->vt_index);
   return s_name(sym);
 }
 
@@ -549,13 +532,7 @@ __attribute__((returns_nonnull)) static ANN Func_Def
 scan2_cpy_fdef(const Env env, const Func_Def fdef) {
   const Func_Def f  = cpy_func_def(env->gwion->mp, fdef);
   f->base->ret_type = fdef->base->ret_type;
-  Arg_List args0 = f->base->args, args1 = fdef->base->args;
-  for(uint32_t i = 0; i < (args0 ? args0->len : 0); i++) {
-    Arg *arg0 = mp_vector_at(args0, Arg, i);
-    Arg *arg1 = mp_vector_at(args1, Arg, i);
-    arg0->var_decl.value = arg1->var_decl.value;
-    arg0->type            = arg1->type;
-  }
+  scan0_func_def(env, f);
   scan1_func_def(env, f);
   return f;
 }
@@ -584,7 +561,6 @@ ANN m_bool _scan2_func_def(const Env env, const Func_Def fdef) {
                     !GET_FLAG(f->base, global))
                        ? SZ_INT
                        : 0;
-  if (fbflag(f->base, fbflag_variadic)) f->stack_depth += SZ_INT;
   const m_bool ret = scanx_fdef(env, env, f, (_exp_func)scan2_fdef);
   if (GET_FLAG(f->base, global)) env_pop(env, scope);
   CHECK_BB(ret);
@@ -600,17 +576,9 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def fdef) {
   return ret;
 }
 
-ANN static m_bool scan2_extend_def(const Env env, const Extend_Def xdef) {
-  CHECK_BB(ensure_scan2(env, xdef->t));
-  CHECK_BB(extend_push(env, xdef->t));
-  const m_bool ret = scan2_ast(env, &xdef->body);
-  extend_pop(env, xdef->t);
-  return ret;
-}
-
 #define scan2_enum_def  dummy_func
 #define scan2_trait_def dummy_func
-
+#define scan2_extend_def dummy_func
 HANDLE_SECTION_FUNC(scan2, m_bool, Env)
 
 ANN static m_bool scan2_parent(const Env env, const Class_Def cdef) {
@@ -652,7 +620,7 @@ ANN m_bool scan2_class_def(const Env env, const Class_Def cdef) {
 
 ANN m_bool scan2_ast(const Env env, Ast *ast) {
   Ast a = *ast;
-  Ast acc = new_mp_vector(env->gwion->mp, sizeof(Section), 0);
+  Ast acc = new_mp_vector(env->gwion->mp, Section, 0);
   m_bool ret = GW_OK;
   for(m_uint i = 0; i < a->len; i++) {
     Section *section = mp_vector_at(a, Section, i);
@@ -667,6 +635,6 @@ ANN m_bool scan2_ast(const Env env, Ast *ast) {
     Section * section = mp_vector_at(acc, Section, i);
     default_args(env, section, ast);
   }
-  free_mp_vector(env->gwion->mp, sizeof(Section), acc);
+  free_mp_vector(env->gwion->mp, Section, acc);
   return ret;
 }
index 03e0d992669ecb6159b6a01a5d9a200f2843716c..068cd149d83ebc669ddc41d9720142f10ca534c4 100644 (file)
@@ -28,7 +28,7 @@ ANN static inline m_int _push(const Env env, const Class_Def c) {
 }
 
 ANN static inline void _pop(const Env e, const Class_Def c, const m_uint s) {
-  if (c->base.tmpl && actual(c->base.tmpl) && c->base.tmpl->list)
+  if (c->base.tmpl && actual(c->base.tmpl))
     nspc_pop_type(e->gwion->mp, e->curr);
   env_pop(e, s);
 }
diff --git a/src/parse/spread.c b/src/parse/spread.c
new file mode 100644 (file)
index 0000000..8d2f10b
--- /dev/null
@@ -0,0 +1,122 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "traverse.h"
+#include "template.h"
+#include "parse.h"
+#include "gwion.h"
+#include "object.h"
+#include "instr.h"
+#include "operator.h"
+#include "import.h"
+
+ANN m_bool spread_ast(const Env env, const Spread_Def spread, const Tmpl *tmpl) {
+  const m_str data = spread->data;
+  char c[256];
+  DECL_OB(FILE *,f, = fmemopen(data, strlen(data), "r"));
+  for(uint32_t i = tmpl->list->len - 1; i < tmpl->call->len; i++) {
+    fseek(f, 0, SEEK_SET);
+    Type_Decl* td = *mp_vector_at(tmpl->call, Type_Decl*, i);
+    DECL_OB(const Type, t, = known_type(env, td));
+    struct AstGetter_ arg =  {env->name, f, env->gwion->st, .ppa = env->gwion->ppa};
+    const m_str type = type2str(env->gwion, t, td->pos);
+    sprintf(c, "%s=%s", s_name(spread->xid), type);
+    free_mstr(env->gwion->mp, type);
+    pparg_add(env->gwion->ppa, c);
+    for(uint32_t j = 0; j < spread->list->len; j++) {
+      const Symbol sym = *mp_vector_at(spread->list, Symbol, j);
+      m_str name = s_name(sym);
+      sprintf(c, "%s=%s%u", name, name, i);
+      pparg_add(env->gwion->ppa, c);
+    }
+    Ast ast = parse(&arg);
+    pparg_rem(env->gwion->ppa, s_name(spread->xid));
+    for(uint32_t j = 0; j < spread->list->len;j++) {
+      const Symbol sym = *mp_vector_at(spread->list, Symbol, j);
+      m_str name = s_name(sym);
+      pparg_rem(env->gwion->ppa, name);
+    }
+    if(!ast) return GW_ERROR;
+    CHECK_BB(scan0_ast(env, &ast));
+    for(uint32_t i = 0; i < ast->len; i++) {
+      const Section section = *mp_vector_at(ast, Section, i);
+      mp_vector_add(env->gwion->mp, &env->context->extend, Section, section);
+    }
+    free_mp_vector(env->gwion->mp, Section , ast);
+  }
+  fclose(f);
+  mp_vector_add(env->gwion->mp, &env->context->extend, Section, MK_SECTION(stmt, stmt_list, NULL));
+  return GW_OK;
+}
+
+ANN Ast spread_class(const Env env, const Ast body) {
+  const Ast extend = env->context->extend;
+  Ast new_body = new_mp_vector(env->gwion->mp, Section, 0);
+  uint32_t offset = 0;
+  for(uint32_t i = 0; i < body->len; i++) {
+    const Section section = *mp_vector_at(body, Section, i);
+    if(section.section_type == ae_section_stmt) {
+      Stmt_List list = section.d.stmt_list;
+      Stmt_List acc = NULL;
+      for(uint32_t j = 0; j < list->len; j++) {
+        const struct Stmt_ stmt = *mp_vector_at(list, struct Stmt_, j);
+        if(stmt.stmt_type == ae_stmt_spread) {
+          if(acc) {
+            mp_vector_add(env->gwion->mp, &new_body, Section, MK_SECTION(stmt, stmt_list, acc));
+            acc = NULL;
+          }
+          const Ast extend = env->context->extend;
+          for(; offset < extend->len; offset++) {
+            const Section section = *mp_vector_at(extend, Section, offset);
+            if(section.section_type == ae_section_stmt && !section.d.stmt_list)
+            {
+              ++offset;
+              break;
+           }
+           mp_vector_add(env->gwion->mp, &new_body, Section, section);
+          }
+        } else {
+          if(!acc)
+            acc = new_mp_vector(env->gwion->mp, struct Stmt_, 0);
+          mp_vector_add(env->gwion->mp, &acc, struct Stmt_, stmt);
+        }
+      }
+      if(acc) {
+        mp_vector_add(env->gwion->mp, &new_body, Section, MK_SECTION(stmt, stmt_list, acc));
+      }
+    }
+  }
+  free_mp_vector(env->gwion->mp, Section, body);
+  free_mp_vector(env->gwion->mp, Section, extend);
+  return new_body;
+}
+
+ANN Stmt_List spread_func(const Env env, const Stmt_List body) {
+  const Ast extend = env->context->extend;
+  Ast new_body = new_mp_vector(env->gwion->mp, struct Stmt_, 0);
+  uint32_t offset = 0;
+  for(uint32_t i = 0; i < body->len; i++) {
+    const struct Stmt_ stmt = *mp_vector_at(body, struct Stmt_, i);
+    if(stmt.stmt_type == ae_stmt_spread) {
+      for(; offset < extend->len; offset++) {
+        const Section section = *mp_vector_at(extend, Section, offset);
+        if(section.section_type == ae_section_stmt && !section.d.stmt_list)
+          break;
+        if(section.section_type != ae_section_stmt)
+          ERR_O(stmt.pos, "invalid section in variadic func");
+        const Stmt_List list = section.d.stmt_list;
+        for(uint32_t j = 0; j < list->len; j++) {
+          const struct Stmt_ stmt = *mp_vector_at(list, struct Stmt_, j);
+          mp_vector_add(env->gwion->mp, &new_body, struct Stmt_, stmt);
+        }
+        break;
+      }
+    } else {
+      mp_vector_add(env->gwion->mp, &new_body, struct Stmt_, stmt);
+    }
+  }
+  free_mp_vector(env->gwion->mp, Stmt_List, body);
+  free_mp_vector(env->gwion->mp, Section, extend);
+  return new_body;
+}
index c3f25aafc9ec026c9c13ccab5ddfdd69d44bc54a..a482747b1fc59eb6341284d17bbd04e2158f8ffe 100644 (file)
 #include "instr.h"
 #include "object.h"
 #include "import.h"
+#include "spread.h"
 
 ANN static m_bool _push_types(const Env env, const Nspc nspc,
                               const Tmpl *tmpl) {
   Specialized_List sl = tmpl->list;
   Type_List        tl = tmpl->call;
+  Specialized *spec = mp_vector_at(sl, Specialized, sl->len - 1);
+
+  const uint32_t len = strcmp(s_name(spec->xid), "...") ? sl->len : sl->len-1;
   if(!tl) return GW_OK;
-  for(uint32_t i = 0; i < sl->len; i++) {
+  for(uint32_t i = 0; i < len; i++) {
     if (i >= tl->len) return GW_OK;
     Type_Decl *td = *mp_vector_at(tl, Type_Decl*, i);
     const Type t = known_type(env, td);
     Specialized *spec = mp_vector_at(sl, Specialized, i);
     nspc_add_type(nspc, spec->xid, t);
   };
+if(len != sl->len) return GW_OK;
   return tl->len == sl->len ? GW_OK : GW_ERROR;
 }
 
@@ -58,19 +63,27 @@ ANN void check_call(const Env env, const Tmpl *tmpl) {
   for(uint32_t i = 0; i < tmpl->call->len; i++) {
     Specialized *spec = mp_vector_at(tmpl->list, Specialized, i);
     Type_Decl *call = *mp_vector_at(tmpl->call, Type_Decl*, i);
-    if(spec->xid == call->xid)
-      call->xid = insert_symbol("auto");
+    if(spec->xid == call->xid) {
+      if (!nspc_lookup_type1(env->curr, spec->xid))
+        call->xid = insert_symbol("auto");
+      else {
+         const Type t = nspc_lookup_type1(env->curr, spec->xid);
+         Type_Decl *td = type2td(env->gwion, t, call->pos);
+         free_type_decl(env->gwion->mp, call);
+         mp_vector_set(tmpl->call, Type_Decl*, i, td);
+      }
+    }
   }
 }
 ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) {
   nspc_push_type(env->gwion->mp, env->curr);
-  if(tmpl->call) check_call(env, tmpl);
+  if (tmpl->call) check_call(env, tmpl);
   if (push_types(env, env->curr, tmpl) > 0) return GW_OK;
   POP_RET(GW_ERROR);
 }
 
 ANN Tmpl *mk_tmpl(const Env env, const Tmpl *tm, const Type_List types) {
-  Tmpl *tmpl = new_tmpl(env->gwion->mp, tm->list, 0);
+  Tmpl *tmpl = new_tmpl(env->gwion->mp, tm->list);
   tmpl->call = cpy_type_list(env->gwion->mp, types);
   return tmpl;
 }
@@ -139,10 +152,11 @@ ANN static Type _scan_type(const Env env, const Type t, Type_Decl *td) {
     Type_List           tl = td->types;
     Specialized_List    sl = t->info->cdef->base.tmpl
         ? t->info->cdef->base.tmpl->list : NULL;
-    for(uint32_t i = 0; i < tl->len; i++) {
+    if (!sl || sl->len > tl->len || (tl->len != sl->len && !is_spread_tmpl(t->info->cdef->base.tmpl)))
+       ERR_O(td->pos, "invalid template type number");
+    for (uint32_t i = 0; i < sl->len; i++) {
       Type_Decl *tmp = *mp_vector_at(tl, Type_Decl*, i);
       DECL_OO(const Type, t, = known_type(env, tmp));
-      if(!sl) continue;
       Specialized *spec = mp_vector_at(sl, Specialized, i);
       if(spec->traits) {
         Symbol missing = miss_traits(t, spec);
index 04bd6351ef496f7facc420e882b910d32cb8ee80..e6e83db3b28c3374ccaec616fca9c0fdeeb4d480 100644 (file)
@@ -17,6 +17,7 @@ ANN m_bool traverse_exp(const Env env, const Exp exp) {
 }
 
 ANN static m_bool _traverse_func_def(const Env env, const Func_Def fdef) {
+  CHECK_BB(scan0_func_def(env, fdef));
   CHECK_BB(scan1_func_def(env, fdef));
   CHECK_BB(scan2_func_def(env, fdef));
   return check_func_def(env, fdef);
@@ -49,8 +50,8 @@ ANN m_bool traverse_enum_def(const Env env, const Enum_Def def) {
 ANN m_bool traverse_fptr_def(const Env env, const Fptr_Def def) {
   CHECK_BB(scan0_fptr_def(env, def));
   CHECK_BB(scan1_fptr_def(env, def));
-  return scan2_fptr_def(env, def);
-  // CHECK_BB(check_fptr_def(env, def));
+  CHECK_BB(scan2_fptr_def(env, def));
+  return check_fptr_def(env, def);
 }
 
 ANN m_bool traverse_type_def(const Env env, const Type_Def def) {
index d77a7c410308de1e8de078ebf7a557bc033404b2..22f4cede3be616f51f86493ad9ae42ef0da3d852 100644 (file)
 #include "import.h"
 
 ANN static Type _option(const Env env, Type_Decl *td, const uint8_t n) {
-  Type_List tl  = new_mp_vector(env->gwion->mp, sizeof(Type_Decl*), 1);
+  Type_List tl  = new_mp_vector(env->gwion->mp, Type_Decl*, 1);
   mp_vector_set(tl, Type_Decl*, 0, td);
   Type_Decl         tmp = {
       .xid = insert_symbol("Option"), .types = tl, .pos = td->pos};
   const Type t = !(n - 1) ? known_type(env, &tmp) : _option(env, &tmp, n - 1);
-  free_mp_vector(env->gwion->mp, sizeof(Type_Decl*), tl);
+  free_mp_vector(env->gwion->mp, Type_Decl*, tl);
   return t;
 }
 
@@ -28,11 +28,11 @@ ANN static Type option(const Env env, Type_Decl *td) {
 }
 
 ANN static Type _ref(const Env env, Type_Decl *td) {
-  Type_List tl  = new_mp_vector(env->gwion->mp, sizeof(Type_Decl*), 1);
+  Type_List tl  = new_mp_vector(env->gwion->mp, Type_Decl*, 1);
   mp_vector_set(tl, Type_Decl*, 0, td);
   Type_Decl tmp = {.xid = insert_symbol("Ref"), .types = tl, .pos = td->pos};
   const Type t = known_type(env, &tmp);
-  free_mp_vector(env->gwion->mp, sizeof(Type_Decl*), tl);
+  free_mp_vector(env->gwion->mp, Type_Decl*, tl);
   return t;
 }
 
@@ -84,18 +84,18 @@ ANN static inline Type find(const Env env, Type_Decl *td) {
       : env_push_global(env);
   const m_bool ret = traverse_fptr_def(env, fptr);
   env_pop(env, scope);
-  const Type t = fptr->type;
+  const Type t = fptr->cdef->base.type;
   free_fptr_def(env->gwion->mp, fptr);
   return ret > 0 ? t : NULL;
 }
 
 ANN static inline Type find1(const Env env, const Type base, Type_Decl *td) {
   if (!td->fptr) return scan_type(env, base, td);
-  if (!td->fptr->type) {
+  if (!td->fptr->cdef->base.type) {
     CHECK_BO(scan0_fptr_def(env, td->fptr));
     CHECK_BO(traverse_fptr_def(env, td->fptr));
   }
-  return td->fptr->type;
+  return td->fptr->cdef->base.type;
 }
 
 ANN static Type resolve(const Env env, Type_Decl *td) {
index e15b86aac3b642ba9b07efb5c456e913b685b297..52c550087fd24b62cd24ef51be01eea9d7508ae4 100644 (file)
@@ -218,7 +218,7 @@ ANN bool vm_running(VM const *vm) {
   return vm->shreduler->bbq->is_running = vm_running(vm->parent);
 }
 
-__attribute__((hot)) ANN static inline void vm_ugen_init(const VM *vm) {
+__attribute__((hot)) ANN static inline void compute_audio(const VM *vm) {
   const Vector v = (Vector)&vm->ugen;
   LOOP_OPTIM
   for (m_uint i = vector_size(v) + 1; --i;) {
@@ -1587,7 +1587,7 @@ ANN void next_bbq_pos(const VM *vm) {
 
 ANN void vm_run_audio(const VM *vm) {
   vm_run(vm);
-  vm_ugen_init(vm);
+  compute_audio(vm);
 }
 
 VM *new_vm(MemPool p, const bool audio) {
index be5740676dd109c5a743d22f3145fbd0f0d7cb18..e0c612790f79fd5ce3fa38bb3b55cee9823a179e 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains] do not provide array
-[1,2,3,4] => var int loop[1];
+[1,2,3,4] => var int[1] loop;
index 70f583cfce2fa58c4e4935a07ea8f6358601a625..3d44cd7565612b63c1d8bc90c6b6f9e2b38fd378 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains] array depths do not match
-[1,2,3,4] => var int k[1][1];
+[1,2,3,4] => var int[1][1] k;
index c73e00da55e761c33afac4c847dd9a97d413e71a..29b28177c6c2a4a7946e0b09f67672cfb2196626 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains] partially empty array init
-var int i[2][];
+var int[2][] i;
index 421f0c161a77ac732c35b8285b20664534edcf0f..7ec804d7e5e90593d4d86a77c2ec9011b907fe50 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains] partially empty array init
-var int i[][3];
+var int[][3] i;
index 39cb6a6017e228be7718b8b896a3377fa6f2f8f3..c40195b95ee794bb07f1dcddac7da2ed93c26b36 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains] NegativeArraySize
-var int i[2][-1];
+var int[2][-1] i;
index 2b2bf8457241b0f5ab6a749b09ec0bbca23b1a24..ae1c9b3a2dc04545bff24776c39141a257eb7254 100644 (file)
@@ -1,3 +1,3 @@
 #! [contains] ArrayOutofBounds
-var Object o[1][1];
+var Object[1][1] o;
 o[1];
index da362bc7f298277a4af94bf5928e57fe0e946ea5..f237971b1cb7f9306e57c538024abf7603a5fbee 100644 (file)
@@ -1,3 +1,3 @@
 #! [contains] has no member
-var int i[2][2];
+var int[2][2] i;
 i[0].test;
index 78df717a149d88ac400249956785c53b599cac27..5ce40d79995bbbec2d84edef602e6fbfb5b9ed62 100644 (file)
@@ -1,3 +1,3 @@
 #! [contains] ArrayOutofBounds
-var Object i[1];
+var Object[1] i;
 i[1];
index 0de037f9e786b88a304139dd9eab520aec0482d5..baf369c9c3dc81027d6dedeb967e9b8fb0a05dc6 100644 (file)
@@ -1,3 +1,3 @@
 #! [contains] ArrayOutofBounds
-var Object i[1][1];
+var Object[1][1] i;
 i[1][0];
index d7876ef6659b0b647f584b88596dc5aa2a4d9206..37cc96788b2352c12cdddbcdf5d4bb6b8c64e329 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains] array types do not match
-[1,2,3,4] => var Object k[1];
+[1,2,3,4] => var Object[1] k;
diff --git a/tests/error/fptr_other_class.gw b/tests/error/fptr_other_class.gw
deleted file mode 100644 (file)
index e00dc1b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#! [contains] can't use non global fptr of other class
-class C {
-  funptr void t_ptr();
-}
-class D {
-  funptr void t_ptr();
-  var C.t_ptr ptr;
-}
index 776033aba8a734475627f7611bac949ca1b4bf59..968368f1ff68db3efd671a6d3d32ff3fc8d7666a 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains] must be defined with empty
-fun int[] my_func(int i[2]){}
+fun int[] my_func(int[2] i){}
index be3996f8a29c58f905cc53dfb7c2f23dfaaf0456..9bf380784cf71d356f004b20e0980f6dd6084d45 100644 (file)
@@ -1,4 +1,4 @@
 #! [contains] Argument type mismatch
 fun void test(){}
-fun void test(int i[], int j[]){}
+fun void test(int[] i, int[] j){}
 test(1,2);
index a705f09a84c6e07d1b62a2cfbbb061f2592e6732..cee8891e021a5241633fa765ee0a9799ff897a8e 100644 (file)
@@ -1,3 +1,3 @@
 #! [contains] invalid array access expression
-var int j[];
+var int[] j;
 j[1,2,3,4] => i;
index bfd1e0e4d76d1435fa2f44c3ce6eb8f29e81a371..3fc193ab754b189d96cd03363781aef5744a3386 100644 (file)
@@ -1,3 +1,3 @@
 #! [contains] array depths do not match
-var int i[2][2];
+var int[2][2] i;
 i << 2;
diff --git a/tests/error/multi_decl.gw b/tests/error/multi_decl.gw
deleted file mode 100644 (file)
index 4b87538..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! [contains] from/to a multi-variable declaration
-var int i, ii => var float f;
index 1bc98c37daddbaf5b638497bec55c11b9ecf8e2a..a9877741a27f78b3ad27b919ceb4d85ba2ddbd53 100644 (file)
@@ -1,3 +1,3 @@
 #! [contains] NegativeArraySize: while allocating arrays
-var int i[-1];
+var int[-1] i;
 <<< i >>>;
index bda30f0c53de4ff333cc8942dca564840ec30b74..cf09feb887829f86fbf4e5faff24ae63c78aeda3 100644 (file)
@@ -1,3 +1,3 @@
 #! [contains] ArrayOutofBounds
-var int i[2][2];
+var int[2][2] i;
 <<< i[1][-1] >>>;
index f719617ea58a35b17625c821db74d3a8558a7293..1dedd93e5bfe8ec2062d00c509bdeeaea4042215 100644 (file)
@@ -4,6 +4,6 @@ class C
 
 }
 
-var C c[1];
-var C d[2][4];
+var C[1] c;
+var C[2][4]d;
 c :=> d;
index ad60abbf149e823e34580c450799b7ef80bddb49..083ac6d5c914cbfa2926f6771c0b58ca9b3b381e 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains] must be defined with empty
-funptr void my_func (int i[4]);
+funptr void my_func (int[4] i);
diff --git a/tests/error/ptr_assign_global.gw b/tests/error/ptr_assign_global.gw
deleted file mode 100644 (file)
index f40b10c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#! [contains] can't assign non member function to member function pointer
-class C {
-  funptr void Test();
-  var Test test;
-}
-
-fun void test(){}
-var C c;
-test @=> c.test;
diff --git a/tests/error/ptr_assign_member.gw b/tests/error/ptr_assign_member.gw
deleted file mode 100644 (file)
index 1a3d9f5..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#! [contains] can't assign member function to non member function pointer
-funptr void Test();
-var Test test;
-class D {
-  fun void test(){}
-}
-
-var D d;
-d.test @=> test;
diff --git a/tests/error/ptr_assign_other.gw b/tests/error/ptr_assign_other.gw
deleted file mode 100644 (file)
index 44f841c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#! [contains] can't assign member function to a pointer of an other class
-class C {
-  funptr void Test();
-  var Test test;
-}
-
-class D {
-  fun void test(){}
-}
-
-var C c;
-var D d;
-<<< d.test @=> c.test >>>;
index 713d2f3217e067fb831fe83ffb0b4a8012f8b7c0..927541c1d256a4aa874917e7adb8df84b0243d17 100644 (file)
@@ -8,4 +8,4 @@ fun void test:[A]() {
 
 test @=> var B b;
 <<< b() >>>;
-<<< b:[int]() >>>;
+<<< b:[float]() >>>;
diff --git a/tests/error/vararg_invalid_acces.gw b/tests/error/vararg_invalid_acces.gw
deleted file mode 100644 (file)
index 36ca072..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#! [contains] InvalidVariadicAccess
-fun void test(...) {
-  varloop vararg {
-    <<<vararg $ int >>>;
-  }
-}
-new Object => test;
diff --git a/tests/error/vararg_outside.gw b/tests/error/vararg_outside.gw
deleted file mode 100644 (file)
index 0959fb0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! [contains] must be used inside variadic function
-vararg;
diff --git a/tests/error/vararg_outside_varloop.gw b/tests/error/vararg_outside_varloop.gw
deleted file mode 100644 (file)
index 1c0abef..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#! [contains] outside varloop
-fun void test(...) {
-  <<<vararg $ int >>>;
-}
-new Object => test;
diff --git a/tests/error/varloop_not_vararg.gw b/tests/error/varloop_not_vararg.gw
deleted file mode 100644 (file)
index 75d5a95..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#! varloop expression type must be
-varloop 1 {
-
-}
diff --git a/tests/extend/extend.gw b/tests/extend/extend.gw
deleted file mode 100644 (file)
index b917796..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-class C {}
-
-extends C {
-  fun void test() { <<< __func__ >>>; }
-}
-
-const C c;
-c.test();
diff --git a/tests/extend/extend_abstract.gw b/tests/extend/extend_abstract.gw
deleted file mode 100644 (file)
index 7397ed8..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#! [contains] abstract functions in extends
-extends Event {
-  fun void test();
-}
diff --git a/tests/extend/extend_final.gw b/tests/extend/extend_final.gw
deleted file mode 100644 (file)
index 0b5dfdc..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#! [contains] extend final type
-class final C {}
-
-extends C {
-  fun void test() {}
-}
diff --git a/tests/extend/extend_not_compound.gw b/tests/extend/extend_not_compound.gw
deleted file mode 100644 (file)
index 8c49269..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#! [contains] only compound types can be extended
-extends int {
-  fun void test(){}
-}
diff --git a/tests/extend/extend_tmpl.gw b/tests/extend/extend_tmpl.gw
deleted file mode 100644 (file)
index 84e990a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-class C:[A] {}
-
-extends C:[int] {
-  fun void test() { <<< __func__ >>>; }
-}
-
-const C:[int] c;
-c.test();
diff --git a/tests/fptr/class_ptr01.gw b/tests/fptr/class_ptr01.gw
deleted file mode 100644 (file)
index 529fee9..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#! [contains] can't assign
-class C {
-  fun static void test(int i) { <<<  "int arg"  >>>; }
-  funptr void PtrType(int i);
-  test @=> var PtrType p;
-  p(1);
-  test @=> p;
-  p(1);
-}
-var C c;
diff --git a/tests/fptr/class_ptr31.gw b/tests/fptr/class_ptr31.gw
deleted file mode 100644 (file)
index 9a64442..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#! [contains] can't assign
-class C {
-  fun void test(int i) { <<<  "int arg"  >>>; }
-  funptr static void PtrType(int i);
-  test @=> var static PtrType p;
-  p(1);
-  test @=> p;
-  p(1);
-}
-
-var C c;
index b0d73c20845f29fdc1468727ae48030cae044edb..328448460ad7ffd7f6f8b1ab007576024d0f51a3 100644 (file)
@@ -1,6 +1,6 @@
 class C {
   funptr void ptr_t(int i,int j);
-  \a b { <<< this, " ", a, " ", b, " test" >>>; } @=> var ptr_t ptr;
+  \a b c { <<< "${a} ${b} ${c}" >>>; } @=> var ptr_t ptr;
   fun void test(int i, int j) { <<< this, " ", i, " ", j >>>; }
 }
 var C c;
index 29e99f184993aa21eb8e862923eb54bb859f1184..a7ddc6a7860ea19d3ed318fb77a67927f2979d9d 100644 (file)
@@ -1,6 +1,6 @@
 class C {
   funptr void ptr_t(int i);
-  \a { <<< this, " ", a >>>; } @=> var ptr_t ptr;
+  \a b { <<< "${a} ${b}" >>>; } @=> var ptr_t ptr;
   fun void t1(int i) { <<< this, " t1 ", i >>>; }
   fun void test(ptr_t p) {
     <<< this >>>;
diff --git a/tests/new/typedef_func_class_variadic.gw b/tests/new/typedef_func_class_variadic.gw
deleted file mode 100644 (file)
index 45fe1e8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-class C {
-  funptr void t_ptr(...);
-
-  var t_ptr iptr;
-
-  fun void test(...) {
-    <<< this, " ", __func__ >>>;
-    varloop vararg {
-      <<< vararg $ int >>>;
-    }
-  }
-
-  test @=> iptr;
-  <<< iptr() >>>;
-  <<< iptr() >>>;
-}
-
-<<<var C c>>>;
-<<< c.iptr >>>;
-<<< c.iptr(1) >>>;
-<<< c.iptr(1,2) >>>;
diff --git a/tests/new/vararg_cpy.gw b/tests/new/vararg_cpy.gw
deleted file mode 100644 (file)
index dc8e149..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fun void test(...) {
-  <<< vararg >>>;
-  <<< vararg.cpy() => var Vararg new_arg >>>;
-}
-test(1);
diff --git a/tests/plug/op_already_imported.c b/tests/plug/op_already_imported.c
deleted file mode 100644 (file)
index d32770d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "gwion_env.h"
-#include "vm.h"
-#include "instr.h"
-#include "vm.h"
-#include "gwion.h"
-#include "object.h"
-#include "operator.h"
-#include "import.h"
-#include "gwi.h"
-
-GWION_IMPORT(op_already_imported) {
-  GWI_BB(gwi_oper_ini(gwi, "int", "int", "int"))
-  GWI_BB(gwi_oper_end(gwi, "=>", NULL))
-  GWI_BB(gwi_oper_ini(gwi, "int", "int", "int"))
-  GWI_BB(gwi_oper_end(gwi, "=>", NULL))
-  return GW_OK;
-}
diff --git a/tests/plug/op_already_imported.gw b/tests/plug/op_already_imported.gw
deleted file mode 100644 (file)
index 5655ed5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#import op_already_imported
-#! [contains] already imported
-<<< 1 >>>;
diff --git a/tests/plug/variadic.c b/tests/plug/variadic.c
deleted file mode 100644 (file)
index 08ddc12..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "gwion_env.h"
-#include "vm.h"
-#include "instr.h"
-#include "gwion.h"
-#include "object.h"
-#include "operator.h"
-#include "import.h"
-#include "vararg.h"
-#include "gwi.h"
-
-static MFUN(m_test) { gw_out("%p\n", *(M_Object *)MEM(0)); }
-
-static MFUN(m_variadic) {
-  M_Object str_obj = *(M_Object *)MEM(SZ_INT);
-  if (!str_obj) return;
-  m_str           str        = STRING(str_obj);
-  const M_Object  vararg_obj = *(M_Object *)MEM(SZ_INT * 2);
-  struct Vararg_ *arg        = *(struct Vararg_ **)vararg_obj->data;
-
-  m_uint       i      = 0;
-  const m_uint offset = *(m_uint *)(vararg_obj->data + SZ_INT * 3);
-  while (i < *(m_uint *)(vararg_obj->data + SZ_INT * 5)) {
-    if (*str == 'i') {
-      gw_out("%" INT_F "\n", *(m_int *)(arg->d + offset));
-      *(m_uint *)(vararg_obj->data + SZ_INT * 3) += SZ_INT;
-    } else if (*str == 'f') {
-      gw_out("%f\n", *(m_float *)(arg->d + offset));
-      *(m_uint *)(vararg_obj->data + SZ_INT * 3) += SZ_FLOAT;
-    } else if (*str == 'o') {
-      gw_out("%p\n", (void *)*(M_Object *)(arg->d + offset));
-      *(m_uint *)(vararg_obj->data + SZ_INT * 3) += SZ_INT;
-    }
-    ++i;
-    str++;
-  }
-}
-
-GWION_IMPORT(variadic test) {
-  GWI_OB(gwi_class_ini(gwi, "Variadic", NULL))
-  GWI_BB(gwi_func_ini(gwi, "void", "member"))
-  GWI_BB(gwi_func_arg(gwi, "string", "format"))
-  GWI_BB(gwi_func_arg(gwi, "does not matter", "..."))
-  GWI_BB(gwi_func_end(gwi, m_variadic, ae_flag_none))
-  GWI_BB(gwi_func_ini(gwi, "void", "test"))
-  GWI_BB(gwi_func_end(gwi, m_test, ae_flag_none))
-  GWI_BB(gwi_class_end(gwi))
-  return GW_OK;
-}
diff --git a/tests/plug/variadic.gw b/tests/plug/variadic.gw
deleted file mode 100644 (file)
index 314379c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#import variadic
-<<< "test builtin variadic fun" >>>;
-var Variadic v;
-"iiii" => var string format;
-<<< v, " ", format $ Object >>>;
-v.member(format, 1,2,3,4);
-v.member(format, 1,2,3,4);
-v.test();
-v.member(format, 1,2,3,4);
-v.member(format, 1,2,3,4);
-v.test();
-v.member(format, 1,2,3,4);
-v.member(format, 1,2,3,4);
-v.test();
index 93aacb3f09aaedab4193c9d2ef18e136aeca3cf2..f5a664f2322a947619bd86cd84e4b2e4dcff0556 100644 (file)
@@ -1,5 +1,5 @@
 #!/bin/bash
-# [test] #79
+# [test] #77
 
 n=0
 [ "$1" ] && n="$1"
diff --git a/tests/spread/spread.gw b/tests/spread/spread.gw
new file mode 100644 (file)
index 0000000..3dc11b3
--- /dev/null
@@ -0,0 +1,15 @@
+#! [contains] bar
+class C:[...] {
+  <<< "foo" >>>;
+  ... T : arg {
+    var T arg;
+  }...
+
+   <<< "bar" >>>;
+  ... T : arg {
+    <<< "${T} ${arg}" >>>;
+  }...
+  <<< "baz" >>>;
+}
+
+var C:[float, int] ci;
diff --git a/tests/spread/spread_error.gw b/tests/spread/spread_error.gw
new file mode 100644 (file)
index 0000000..b5903bd
--- /dev/null
@@ -0,0 +1,16 @@
+#! [contains] syntax error
+
+class C:[...] {
+
+  ... T : arg {
+    zvar T arg;
+  }...
+
+
+  ... T : arg {
+    <<< "${T} ${arg}" >>>;
+  }...
+
+}
+
+var C:[float, int] ci;
diff --git a/tests/spread/spread_func.gw b/tests/spread/spread_func.gw
new file mode 100644 (file)
index 0000000..549639d
--- /dev/null
@@ -0,0 +1,8 @@
+fun void t:[...]() {
+  ... T : arg {
+     <<< "${T} ${arg}" >>>;
+  }...
+}
+
+t(2.2);
+t(2);
diff --git a/tests/spread/spread_outside.gw b/tests/spread/spread_outside.gw
new file mode 100644 (file)
index 0000000..395972c
--- /dev/null
@@ -0,0 +1,5 @@
+#! [contains] spread statement outside of variadic environment
+
+... T : arg {
+  <<< "error" >>>;
+}...
diff --git a/tests/spread/spread_outside_class.gw b/tests/spread/spread_outside_class.gw
new file mode 100644 (file)
index 0000000..1f76b20
--- /dev/null
@@ -0,0 +1,6 @@
+#! [contains] spread statement outside of variadic environment
+class C {
+  ... T : arg {
+    <<< "error" >>>;
+  }...
+}
diff --git a/tests/spread/spread_outside_func.gw b/tests/spread/spread_outside_func.gw
new file mode 100644 (file)
index 0000000..64fe3e6
--- /dev/null
@@ -0,0 +1,7 @@
+#! [contains] spread statement outside of variadic environment
+
+fun void test() {
+  ... T : arg {
+    <<< "error" >>>;
+  }...
+}
index 1dfe1ae7350b4224fd429a32796a8f35c0ff2f69..1051a5de6bdee7f9b227a114aa3d504d30326985 100644 (file)
@@ -1,2 +1,2 @@
-var int i[][][];
+var int[][][] i;
 <<< i >>>;
index 3258b955b8857775c4422e95f802e0569e141a74..ef3d7abe94946a3401d080ab06907e8254b1f754 100644 (file)
@@ -1,6 +1,6 @@
 class C {
-       var int i[];
-       var int j[2];
+       var int[] i;
+       var int[2] j;
 }
 
 var C c;
diff --git a/tests/tree/class_multi_decl.gw b/tests/tree/class_multi_decl.gw
deleted file mode 100644 (file)
index c6503ec..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-class C {
-       var int i, j;
-}
-
index 25c18fb6b737009b6f9a19777382805d159628df..e94fae092e68190514a81f8edfb827ebc975ecda 100644 (file)
@@ -1,7 +1,7 @@
 class C:[A] {
   \a{};
   [ 1 ];
-  var int i,j;
+  var int i;
   'a';
   true $ int;
   i++;
diff --git a/tests/tree/empty_vararg.gw b/tests/tree/empty_vararg.gw
deleted file mode 100644 (file)
index 87b9cb8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-fun int test(...){
-  varloop vararg {
-    <<< "test" >>>;
-    <<< vararg $ int >>>;
-  }
-  return 1;
-}
-<<<  test()  >>>;
-<<<  test()  >>>;
-<<< (1, 7) => test >>>;
-<<< () => test >>>;
diff --git a/tests/tree/fptr_other_class.gw b/tests/tree/fptr_other_class.gw
deleted file mode 100644 (file)
index e00dc1b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#! [contains] can't use non global fptr of other class
-class C {
-  funptr void t_ptr();
-}
-class D {
-  funptr void t_ptr();
-  var C.t_ptr ptr;
-}
diff --git a/tests/tree/multi_decl.gw b/tests/tree/multi_decl.gw
deleted file mode 100644 (file)
index 4129e3a..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-var int i, j;
-<<< i, " ", j >>>;
diff --git a/tests/tree/vararg_empty.gw b/tests/tree/vararg_empty.gw
deleted file mode 100644 (file)
index 1cbb938..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fun void test(...){
-  varloop vararg {
-  }
-}
-test();
diff --git a/tests/tree/variadic_offset.gw b/tests/tree/variadic_offset.gw
deleted file mode 100644 (file)
index 3757d98..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fun void test(int i, float f, ...){
-  varloop vararg {
-  }
-}
-test(1, 2.3, 1);
diff --git a/tests/tree/varobject_assign.gw b/tests/tree/varobject_assign.gw
deleted file mode 100644 (file)
index ee239f6..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-fun void test(...) {
-       var Object o;
-  varloop vararg {
-         vararg $ Object => o;
-  }
-}
diff --git a/util b/util
index 2b55ce354595c33d5cee4a90085feb2a31be1572..8d07a94ba9207ce640d8046c663dbdb2d9860dc1 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 2b55ce354595c33d5cee4a90085feb2a31be1572
+Subproject commit 8d07a94ba9207ce640d8046c663dbdb2d9860dc1