From: fennecdjay Date: Sun, 26 Jun 2022 18:49:32 +0000 (+0200) Subject: :art: Add new Closures, new extends, variadic generics, colored help X-Git-Tag: nightly~268 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=ed766efbb12f27c113f2581956796394f64db46c;p=gwion.git :art: Add new Closures, new extends, variadic generics, colored help --- diff --git a/Makefile b/Makefile index 8d979e21..04568835 100644 --- 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 dc4e477f..b4c4887f 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit dc4e477f0be36712aebefe9ed3c0f06fcffd80d1 +Subproject commit b4c4887fbcc669621e9138e924342981282ca1f7 diff --git a/examples/array_lit.gw b/examples/array_lit.gw index 11cafee6..d41180a7 100644 --- a/examples/array_lit.gw +++ b/examples/array_lit.gw @@ -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]; diff --git a/examples/op2.gw b/examples/op2.gw index 237f96ef..a12f6f3e 100644 --- a/examples/op2.gw +++ b/examples/op2.gw @@ -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 index a8d5ceb7..00000000 --- a/examples/template_vararg.gw +++ /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 index 6b8603f4..00000000 --- a/examples/vararg.gw +++ /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 53b71714..e206236c 160000 --- a/fmt +++ b/fmt @@ -1 +1 @@ -Subproject commit 53b717147dd54f34915dc27ff15660084b7963bf +Subproject commit e206236cb8890dfca9492a7c21ff35f8561a8611 diff --git a/highlighters/gwion.kak b/highlighters/gwion.kak index ce0c2b1b..d2d5ff56 100644 --- a/highlighters/gwion.kak +++ b/highlighters/gwion.kak @@ -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__' diff --git a/include/clean.h b/include/clean.h index c5647836..0c584f63 100644 --- a/include/clean.h +++ b/include/clean.h @@ -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); diff --git a/include/emit.h b/include/emit.h index a5928716..239ca6de 100644 --- a/include/emit.h +++ b/include/emit.h @@ -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); } diff --git a/include/env/context.h b/include/env/context.h index af191283..0b5e3ea8 100644 --- a/include/env/context.h +++ b/include/env/context.h @@ -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 diff --git a/include/env/func.h b/include/env/func.h index db728f35..3316d789 100644 --- a/include/env/func.h +++ b/include/env/func.h @@ -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; }; diff --git a/include/env/trait.h b/include/env/trait.h index 7a1fea48..e9c8307b 100644 --- a/include/env/trait.h +++ b/include/env/trait.h @@ -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); diff --git a/include/env/type.h b/include/env/type.h index 33d05a0e..821fa183 100644 --- a/include/env/type.h +++ b/include/env/type.h @@ -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, diff --git a/include/env/value.h b/include/env/value.h index 67d26942..44d93db2 100644 --- a/include/env/value.h +++ b/include/env/value.h @@ -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 diff --git a/include/gwi.h b/include/gwi.h index 91868de6..35383c81 100644 --- a/include/gwi.h +++ b/include/gwi.h @@ -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); diff --git a/include/gwion_all.h b/include/gwion_all.h index f11b0be8..88a7f15b 100644 --- a/include/gwion_all.h +++ b/include/gwion_all.h @@ -30,6 +30,5 @@ #include "template.h" #include "traverse.h" #include "ugen.h" -#include "vararg.h" #include "vm.h" #endif diff --git a/include/gwion_env.h b/include/gwion_env.h index 70489558..00fc4804 100644 --- a/include/gwion_env.h +++ b/include/gwion_env.h @@ -13,4 +13,12 @@ #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 diff --git a/include/import/checker.h b/include/import/checker.h index 48044749..fbe4b50f 100644 --- a/include/import/checker.h +++ b/include/import/checker.h @@ -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); diff --git a/include/instr.h b/include/instr.h index 2b9b5392..2b42da0c 100644 --- a/include/instr.h +++ b/include/instr.h @@ -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); diff --git a/include/lang_private.h b/include/lang_private.h index 61ea2602..4e8441d7 100644 --- a/include/lang_private.h +++ b/include/lang_private.h @@ -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); diff --git a/include/operator.h b/include/operator.h index 5f3b012d..4c38c0d6 100644 --- a/include/operator.h +++ b/include/operator.h @@ -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 index 00000000..cf1d45c1 --- /dev/null +++ b/include/spread.h @@ -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 diff --git a/include/traverse.h b/include/traverse.h index 18447fc7..176dc24c 100644 --- a/include/traverse.h +++ b/include/traverse.h @@ -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 index bf3aac31..00000000 --- a/include/vararg.h +++ /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 diff --git a/libcmdapp b/libcmdapp index ac63edc2..115e5da4 160000 --- a/libcmdapp +++ b/libcmdapp @@ -1 +1 @@ -Subproject commit ac63edc2b3d3d0ad262486903cde45a4ed5d9a84 +Subproject commit 115e5da46cb49dc285b9ca2daae358954c0e2853 diff --git a/plug b/plug index 2377a71d..ec74718b 160000 --- a/plug +++ b/plug @@ -1 +1 @@ -Subproject commit 2377a71db5f6a711ee2eedbd074f013863694ec8 +Subproject commit ec74718b911d962d274f142fc81c664ac2accf71 diff --git a/src/clean.c b/src/clean.c index 7475da75..66c94aa0 100644 --- a/src/clean.c +++ b/src/clean.c @@ -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); diff --git a/src/emit/emit.c b/src/emit/emit.c index e77094ff..5139e9c8 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -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; } diff --git a/src/emit/emitter.c b/src/emit/emitter.c index 43faa813..f5669edf 100644 --- a/src/emit/emitter.c +++ b/src/emit/emitter.c @@ -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)); diff --git a/src/env/context.c b/src/env/context.c index 4f73e29e..fc0b5aa4 100644 --- a/src/env/context.c +++ b/src/env/context.c @@ -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); } diff --git a/src/env/env.c b/src/env/env.c index b53a6680..2f13a128 100644 --- a/src/env/env.c +++ b/src/env/env.c @@ -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; } diff --git a/src/env/env_utils.c b/src/env/env_utils.c index f1131567..8f50dc1c 100644 --- a/src/env/env_utils.c +++ b/src/env/env_utils.c @@ -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; } diff --git a/src/env/trait.c b/src/env/trait.c index 321bea69..71a30d2b 100644 --- a/src/env/trait.c +++ b/src/env/trait.c @@ -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); } diff --git a/src/env/type.c b/src/env/type.c index 577bf69d..453e8fa8 100644 --- a/src/env/type.c +++ b/src/env/type.c @@ -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]; diff --git a/src/env/value.c b/src/env/value.c index 3813247f..8d1e5e0b 100644 --- a/src/env/value.c +++ b/src/env/value.c @@ -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; diff --git a/src/gwion.c b/src/gwion.c index 3342f657..76b461f9 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -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) { diff --git a/src/import/import_cdef.c b/src/import/import_cdef.c index 82019c56..03860ac4 100644 --- a/src/import/import_cdef.c +++ b/src/import/import_cdef.c @@ -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; diff --git a/src/import/import_checker.c b/src/import/import_checker.c index d2c47714..b21721ae 100644 --- a/src/import/import_checker.c +++ b/src/import/import_checker.c @@ -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; diff --git a/src/import/import_enum.c b/src/import/import_enum.c index 4ec441ff..aac406b2 100644 --- a/src/import/import_enum.c +++ b/src/import/import_enum.c @@ -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; } /* diff --git a/src/import/import_fdef.c b/src/import/import_fdef.c index 4a1109e3..b45eb979 100644 --- a/src/import/import_fdef.c +++ b/src/import/import_fdef.c @@ -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, §ion); -// 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; } diff --git a/src/import/import_internals.c b/src/import/import_internals.c index af161b4c..2a7a52b7 100644 --- a/src/import/import_internals.c +++ b/src/import/import_internals.c @@ -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)); diff --git a/src/import/import_item.c b/src/import/import_item.c index 93fbdc67..fbf78b3e 100644 --- a/src/import/import_item.c +++ b/src/import/import_item.c @@ -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); diff --git a/src/import/import_udef.c b/src/import/import_udef.c index cc1932ef..df1b9b2e 100644 --- a/src/import/import_udef.c +++ b/src/import/import_udef.c @@ -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); } diff --git a/src/lib/array.c b/src/lib/array.c index 7400d199..9e73daa2 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -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); diff --git a/src/lib/lib_func.c b/src/lib/closure.c similarity index 59% rename from src/lib/lib_func.c rename to src/lib/closure.c index 6e4b50e3..f15d53ab 100644 --- a/src/lib/lib_func.c +++ b/src/lib/closure.c @@ -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; } diff --git a/src/lib/ctrl.c b/src/lib/ctrl.c index 42006ae1..4ef0ac65 100644 --- a/src/lib/ctrl.c +++ b/src/lib/ctrl.c @@ -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; diff --git a/src/lib/deep_equal.c b/src/lib/deep_equal.c index 28d1ccbb..2e6448b0 100644 --- a/src/lib/deep_equal.c +++ b/src/lib/deep_equal.c @@ -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); diff --git a/src/lib/dict.c b/src/lib/dict.c index 98d4f121..3fb81989 100644 --- a/src/lib/dict.c +++ b/src/lib/dict.c @@ -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); diff --git a/src/lib/engine.c b/src/lib/engine.c index 894f68b7..98d633a7 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -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)) diff --git a/src/lib/instr.c b/src/lib/instr.c index f9f546e4..f827d101 100644 --- a/src/lib/instr.c +++ b/src/lib/instr.c @@ -5,117 +5,110 @@ #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; diff --git a/src/lib/modules.c b/src/lib/modules.c index 21f8e0ea..73dd192c 100644 --- a/src/lib/modules.c +++ b/src/lib/modules.c @@ -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)) diff --git a/src/lib/object.c b/src/lib/object.c index 6db3f060..8289303f 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -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; } diff --git a/src/lib/object_op.c b/src/lib/object_op.c index d748b5e4..336d3984 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -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)) diff --git a/src/lib/sift.c b/src/lib/sift.c index 8ecc99c6..ce1cfe99 100644 --- a/src/lib/sift.c +++ b/src/lib/sift.c @@ -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; diff --git a/src/lib/union.c b/src/lib/union.c index a3cf314e..8bd38f19 100644 --- a/src/lib/union.c +++ b/src/lib/union.c @@ -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 index 58467f8c..00000000 --- a/src/lib/vararg.c +++ /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 index 00000000..423b0bb6 --- /dev/null +++ b/src/lib/xork.c @@ -0,0 +1,96 @@ +#include +#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; +} diff --git a/src/parse/check.c b/src/parse/check.c index f3cb165f..3b470fe2 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -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 : ""); 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; } diff --git a/src/parse/check_traits.c b/src/parse/check_traits.c index 2c0dad3a..8b8c52f5 100644 --- a/src/parse/check_traits.c +++ b/src/parse/check_traits.c @@ -15,25 +15,19 @@ 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; } diff --git a/src/parse/default_arg.c b/src/parse/default_arg.c index 8e6dba64..17bcf279 100644 --- a/src/parse/default_arg.c +++ b/src/parse/default_arg.c @@ -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 }}, diff --git a/src/parse/func_resolve_tmpl.c b/src/parse/func_resolve_tmpl.c index eddfcf0a..1978584e 100644 --- a/src/parse/func_resolve_tmpl.c +++ b/src/parse/func_resolve_tmpl.c @@ -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); diff --git a/src/parse/operator.c b/src/parse/operator.c index 8f94d9fc..e33ae9cd 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -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); diff --git a/src/parse/partial.c b/src/parse/partial.c index 039cbbf2..76d46898 100644 --- a/src/parse/partial.c +++ b/src/parse/partial.c @@ -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; } diff --git a/src/parse/scan0.c b/src/parse/scan0.c index 275966ca..ade9f79e 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -1,4 +1,3 @@ -#include #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; } diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 8438427f..b04f1818 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -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)); diff --git a/src/parse/scan2.c b/src/parse/scan2.c index a68f0131..a56afd61 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -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; } diff --git a/src/parse/scanx.c b/src/parse/scanx.c index 03e0d992..068cd149 100644 --- a/src/parse/scanx.c +++ b/src/parse/scanx.c @@ -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 index 00000000..8d2f10b5 --- /dev/null +++ b/src/parse/spread.c @@ -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; +} diff --git a/src/parse/template.c b/src/parse/template.c index c3f25aaf..a482747b 100644 --- a/src/parse/template.c +++ b/src/parse/template.c @@ -11,19 +11,24 @@ #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); diff --git a/src/parse/traverse.c b/src/parse/traverse.c index 04bd6351..e6e83db3 100644 --- a/src/parse/traverse.c +++ b/src/parse/traverse.c @@ -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) { diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index d77a7c41..22f4cede 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -10,12 +10,12 @@ #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) { diff --git a/src/vm/vm.c b/src/vm/vm.c index e15b86aa..52c55008 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -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) { diff --git a/tests/error/array_assign_exp.gw b/tests/error/array_assign_exp.gw index be574067..e0c61279 100644 --- a/tests/error/array_assign_exp.gw +++ b/tests/error/array_assign_exp.gw @@ -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; diff --git a/tests/error/array_depth_match.gw b/tests/error/array_depth_match.gw index 70f583cf..3d44cd75 100644 --- a/tests/error/array_depth_match.gw +++ b/tests/error/array_depth_match.gw @@ -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; diff --git a/tests/error/array_err2.gw b/tests/error/array_err2.gw index c73e00da..29b28177 100644 --- a/tests/error/array_err2.gw +++ b/tests/error/array_err2.gw @@ -1,2 +1,2 @@ #! [contains] partially empty array init -var int i[2][]; +var int[2][] i; diff --git a/tests/error/array_err3.gw b/tests/error/array_err3.gw index 421f0c16..7ec804d7 100644 --- a/tests/error/array_err3.gw +++ b/tests/error/array_err3.gw @@ -1,2 +1,2 @@ #! [contains] partially empty array init -var int i[][3]; +var int[][3] i; diff --git a/tests/error/array_failure.gw b/tests/error/array_failure.gw index 39cb6a60..c40195b9 100644 --- a/tests/error/array_failure.gw +++ b/tests/error/array_failure.gw @@ -1,2 +1,2 @@ #! [contains] NegativeArraySize -var int i[2][-1]; +var int[2][-1] i; diff --git a/tests/error/array_multi_oob.gw b/tests/error/array_multi_oob.gw index 2b2bf845..ae1c9b3a 100644 --- a/tests/error/array_multi_oob.gw +++ b/tests/error/array_multi_oob.gw @@ -1,3 +1,3 @@ #! [contains] ArrayOutofBounds -var Object o[1][1]; +var Object[1][1] o; o[1]; diff --git a/tests/error/array_no_member.gw b/tests/error/array_no_member.gw index da362bc7..f237971b 100644 --- a/tests/error/array_no_member.gw +++ b/tests/error/array_no_member.gw @@ -1,3 +1,3 @@ #! [contains] has no member -var int i[2][2]; +var int[2][2] i; i[0].test; diff --git a/tests/error/array_oob.gw b/tests/error/array_oob.gw index 78df717a..5ce40d79 100644 --- a/tests/error/array_oob.gw +++ b/tests/error/array_oob.gw @@ -1,3 +1,3 @@ #! [contains] ArrayOutofBounds -var Object i[1]; +var Object[1] i; i[1]; diff --git a/tests/error/array_oob_multi.gw b/tests/error/array_oob_multi.gw index 0de037f9..baf369c9 100644 --- a/tests/error/array_oob_multi.gw +++ b/tests/error/array_oob_multi.gw @@ -1,3 +1,3 @@ #! [contains] ArrayOutofBounds -var Object i[1][1]; +var Object[1][1] i; i[1][0]; diff --git a/tests/error/array_type_match.gw b/tests/error/array_type_match.gw index d7876ef6..37cc9678 100644 --- a/tests/error/array_type_match.gw +++ b/tests/error/array_type_match.gw @@ -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 index e00dc1b4..00000000 --- a/tests/error/fptr_other_class.gw +++ /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/error/func_arg_array_empty.gw b/tests/error/func_arg_array_empty.gw index 776033ab..968368f1 100644 --- a/tests/error/func_arg_array_empty.gw +++ b/tests/error/func_arg_array_empty.gw @@ -1,2 +1,2 @@ #! [contains] must be defined with empty -fun int[] my_func(int i[2]){} +fun int[] my_func(int[2] i){} diff --git a/tests/error/func_no_match.gw b/tests/error/func_no_match.gw index be3996f8..9bf38078 100644 --- a/tests/error/func_no_match.gw +++ b/tests/error/func_no_match.gw @@ -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); diff --git a/tests/error/invalid_array_acces.gw b/tests/error/invalid_array_acces.gw index a705f09a..cee8891e 100644 --- a/tests/error/invalid_array_acces.gw +++ b/tests/error/invalid_array_acces.gw @@ -1,3 +1,3 @@ #! [contains] invalid array access expression -var int j[]; +var int[] j; j[1,2,3,4] => i; diff --git a/tests/error/invalid_array_shift.gw b/tests/error/invalid_array_shift.gw index bfd1e0e4..3fc193ab 100644 --- a/tests/error/invalid_array_shift.gw +++ b/tests/error/invalid_array_shift.gw @@ -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 index 4b87538c..00000000 --- a/tests/error/multi_decl.gw +++ /dev/null @@ -1,2 +0,0 @@ -#! [contains] from/to a multi-variable declaration -var int i, ii => var float f; diff --git a/tests/error/negative_array.gw b/tests/error/negative_array.gw index 1bc98c37..a9877741 100644 --- a/tests/error/negative_array.gw +++ b/tests/error/negative_array.gw @@ -1,3 +1,3 @@ #! [contains] NegativeArraySize: while allocating arrays -var int i[-1]; +var int[-1] i; <<< i >>>; diff --git a/tests/error/negative_array2.gw b/tests/error/negative_array2.gw index bda30f0c..cf09feb8 100644 --- a/tests/error/negative_array2.gw +++ b/tests/error/negative_array2.gw @@ -1,3 +1,3 @@ #! [contains] ArrayOutofBounds -var int i[2][2]; +var int[2][2] i; <<< i[1][-1] >>>; diff --git a/tests/error/op_test.gw b/tests/error/op_test.gw index f719617e..1dedd93e 100644 --- a/tests/error/op_test.gw +++ b/tests/error/op_test.gw @@ -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; diff --git a/tests/error/ptr_arg_array.gw b/tests/error/ptr_arg_array.gw index ad60abbf..083ac6d5 100644 --- a/tests/error/ptr_arg_array.gw +++ b/tests/error/ptr_arg_array.gw @@ -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 index f40b10c7..00000000 --- a/tests/error/ptr_assign_global.gw +++ /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 index 1a3d9f5d..00000000 --- a/tests/error/ptr_assign_member.gw +++ /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 index 44f841cf..00000000 --- a/tests/error/ptr_assign_other.gw +++ /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 >>>; diff --git a/tests/error/typedef_func_tmpl_types2.gw b/tests/error/typedef_func_tmpl_types2.gw index 713d2f32..927541c1 100644 --- a/tests/error/typedef_func_tmpl_types2.gw +++ b/tests/error/typedef_func_tmpl_types2.gw @@ -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 index 36ca072b..00000000 --- a/tests/error/vararg_invalid_acces.gw +++ /dev/null @@ -1,7 +0,0 @@ -#! [contains] InvalidVariadicAccess -fun void test(...) { - varloop vararg { - <<>>; - } -} -new Object => test; diff --git a/tests/error/vararg_outside.gw b/tests/error/vararg_outside.gw deleted file mode 100644 index 0959fb02..00000000 --- a/tests/error/vararg_outside.gw +++ /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 index 1c0abef9..00000000 --- a/tests/error/vararg_outside_varloop.gw +++ /dev/null @@ -1,5 +0,0 @@ -#! [contains] outside varloop -fun void test(...) { - <<>>; -} -new Object => test; diff --git a/tests/error/varloop_not_vararg.gw b/tests/error/varloop_not_vararg.gw deleted file mode 100644 index 75d5a95a..00000000 --- a/tests/error/varloop_not_vararg.gw +++ /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 index b917796c..00000000 --- a/tests/extend/extend.gw +++ /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 index 7397ed86..00000000 --- a/tests/extend/extend_abstract.gw +++ /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 index 0b5dfdc3..00000000 --- a/tests/extend/extend_final.gw +++ /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 index 8c492697..00000000 --- a/tests/extend/extend_not_compound.gw +++ /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 index 84e990a9..00000000 --- a/tests/extend/extend_tmpl.gw +++ /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 index 529fee98..00000000 --- a/tests/fptr/class_ptr01.gw +++ /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 index 9a64442b..00000000 --- a/tests/fptr/class_ptr31.gw +++ /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; diff --git a/tests/lambdas/lambda.gw b/tests/lambdas/lambda.gw index b0d73c20..32844846 100644 --- a/tests/lambdas/lambda.gw +++ b/tests/lambdas/lambda.gw @@ -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; diff --git a/tests/lambdas/lambda2.gw b/tests/lambdas/lambda2.gw index 29e99f18..a7ddc6a7 100644 --- a/tests/lambdas/lambda2.gw +++ b/tests/lambdas/lambda2.gw @@ -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 index 45fe1e88..00000000 --- a/tests/new/typedef_func_class_variadic.gw +++ /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() >>>; -} - -<<>>; -<<< 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 index dc8e149a..00000000 --- a/tests/new/vararg_cpy.gw +++ /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 index d32770da..00000000 --- a/tests/plug/op_already_imported.c +++ /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 index 5655ed54..00000000 --- a/tests/plug/op_already_imported.gw +++ /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 index 08ddc128..00000000 --- a/tests/plug/variadic.c +++ /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 index 314379c4..00000000 --- a/tests/plug/variadic.gw +++ /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(); diff --git a/tests/sh/import.sh b/tests/sh/import.sh index 93aacb3f..f5a664f2 100644 --- a/tests/sh/import.sh +++ b/tests/sh/import.sh @@ -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 index 00000000..3dc11b3d --- /dev/null +++ b/tests/spread/spread.gw @@ -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 index 00000000..b5903bdf --- /dev/null +++ b/tests/spread/spread_error.gw @@ -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 index 00000000..549639d5 --- /dev/null +++ b/tests/spread/spread_func.gw @@ -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 index 00000000..395972c2 --- /dev/null +++ b/tests/spread/spread_outside.gw @@ -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 index 00000000..1f76b20e --- /dev/null +++ b/tests/spread/spread_outside_class.gw @@ -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 index 00000000..64fe3e6a --- /dev/null +++ b/tests/spread/spread_outside_func.gw @@ -0,0 +1,7 @@ +#! [contains] spread statement outside of variadic environment + +fun void test() { + ... T : arg { + <<< "error" >>>; + }... +} diff --git a/tests/tree/array_empty.gw b/tests/tree/array_empty.gw index 1dfe1ae7..1051a5de 100644 --- a/tests/tree/array_empty.gw +++ b/tests/tree/array_empty.gw @@ -1,2 +1,2 @@ -var int i[][][]; +var int[][][] i; <<< i >>>; diff --git a/tests/tree/class_dot.gw b/tests/tree/class_dot.gw index 3258b955..ef3d7abe 100644 --- a/tests/tree/class_dot.gw +++ b/tests/tree/class_dot.gw @@ -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 index c6503ecf..00000000 --- a/tests/tree/class_multi_decl.gw +++ /dev/null @@ -1,4 +0,0 @@ -class C { - var int i, j; -} - diff --git a/tests/tree/cpy_ast.gw b/tests/tree/cpy_ast.gw index 25c18fb6..e94fae09 100644 --- a/tests/tree/cpy_ast.gw +++ b/tests/tree/cpy_ast.gw @@ -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 index 87b9cb84..00000000 --- a/tests/tree/empty_vararg.gw +++ /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 index e00dc1b4..00000000 --- a/tests/tree/fptr_other_class.gw +++ /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 index 4129e3a9..00000000 --- a/tests/tree/multi_decl.gw +++ /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 index 1cbb938c..00000000 --- a/tests/tree/vararg_empty.gw +++ /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 index 3757d981..00000000 --- a/tests/tree/variadic_offset.gw +++ /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 index ee239f61..00000000 --- a/tests/tree/varobject_assign.gw +++ /dev/null @@ -1,6 +0,0 @@ -fun void test(...) { - var Object o; - varloop vararg { - vararg $ Object => o; - } -} diff --git a/util b/util index 2b55ce35..8d07a94b 160000 --- a/util +++ b/util @@ -1 +1 @@ -Subproject commit 2b55ce354595c33d5cee4a90085feb2a31be1572 +Subproject commit 8d07a94ba9207ce640d8046c663dbdb2d9860dc1