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
@+ ${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
-Subproject commit dc4e477f0be36712aebefe9ed3c0f06fcffd80d1
+Subproject commit b4c4887fbcc669621e9138e924342981282ca1f7
[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];
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 >>>;
+++ /dev/null
-fun void test:[A](...) {
- varloop vararg {
- <<< vararg $ int >>>;
- }
-}
-test:[int](1, 2);
-test:[float](1, 2, 3);
+++ /dev/null
-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);
-Subproject commit 53b717147dd54f34915dc27ff15660084b7963bf
+Subproject commit e206236cb8890dfca9492a7c21ff35f8561a8611
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__'
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);
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);
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;
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);
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);
}
Nspc nspc;
m_str name;
Ast tree;
+ Ast extend;
uint16_t ref;
uint16_t weight;
bool error;
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
fflag_tmpl = 1 << 3,
fflag_valid = 1 << 4,
fflag_emit = 1 << 5,
+ fflag_fptr = 1 << 6,
} __attribute__((packed));
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;
};
#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);
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);
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;
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
}
et_array,
et_gack,
et_function,
- et_fptr,
- et_vararg,
- et_lambda,
+ et_closure,
et_op,
et_class,
et_union,
#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,
struct Value_ {
Type type;
m_str name;
- struct ValueFrom_ *from;
+ ValueFrom *from;
union value_data d;
uint16_t ref;
ae_flag flag;
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
#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);
#include "template.h"
#include "traverse.h"
#include "ugen.h"
-#include "vararg.h"
#include "vm.h"
#endif
#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
Type_Decl *td; // typedef
ID_List curr; // enum
};
- bool variadic;
enum importck_type type;
ae_flag flag; // ????
} ImportCK;
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);
ANN void free_instr(const Gwion, const Instr);
INSTR(EOC);
INSTR(DTOR_EOC);
-INSTR(DtorReturn);
-
-INSTR(ComplexReal);
-INSTR(ComplexImag);
struct FastExceptInfo {
m_str file;
};
INSTR(fast_except);
-/* function */
-INSTR(DtorReturn);
/* array */
INSTR(ArrayBottom);
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);
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);
}
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);
--- /dev/null
+#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
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);
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);
+++ /dev/null
-#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
-Subproject commit ac63edc2b3d3d0ad262486903cde45a4ed5d9a84
+Subproject commit 115e5da46cb49dc285b9ca2daae358954c0e2853
-Subproject commit 2377a71db5f6a711ee2eedbd074f013863694ec8
+Subproject commit ec74718b911d962d274f142fc81c664ac2accf71
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++) {
}
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) {
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) {
--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);
}
#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) {
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) {
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) {
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);
#include "import.h"
#include "match.h"
#include "specialid.h"
-#include "vararg.h"
#include "looper.h"
#include "shreduler_private.h"
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) {
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
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) {
}
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)) {
: 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;
}
#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);
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);
}
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;
}
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)
}
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);
}
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;
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)) {
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 {
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) //{
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);
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);
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;
}
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;
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++) {
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;
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
// 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
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);
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;
}
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;
}
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;
.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)) {
}
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;
}
}
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;
++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);
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;
}
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;
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);
}
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);
}
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));
(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;
}
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));
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])
}
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?
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;
}
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) {
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) {
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;
}
#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) {
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);
}
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;
}
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) {
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;
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;
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++) {
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];
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);
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;
}
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));
#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);
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) {
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);
}
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);
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};
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;
}
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;
}
}
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);
}
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;
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};
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];
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;
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) {
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;
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;
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;
}
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);
}
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;
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) {
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;
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;
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;
}
/*
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;
}
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);
}
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 }
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)
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) {
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;
}
.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;
}
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;
}
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));
}
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 } },
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);
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;
}
}
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);
}
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;
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;
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) {
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;
}
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;
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;
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;
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?
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
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
}
#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];
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);
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;
? !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);
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;
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);
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"))
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);
#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);
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));
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;
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) {
}
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;
}
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)){
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;
}
}
// 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;
}
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;
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;
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);
}
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) {
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++) {
}
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;
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) {
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) {
_("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) {
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);
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;
.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;
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);
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);
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 }},
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);
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);
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;
}
#include "gwi.h"
static OP_CHECK(opck_ctrl) {
-
Exp_Binary *bin = (Exp_Binary*)data;
MemPool mp = env->gwion->mp;
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 };
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);
"#!- 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;
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);
}
}
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);
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);
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); }
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))
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))
#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))
*(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;
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))
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;
}
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));
} 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;
}
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;
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;
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);
}
}
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))
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);
.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);
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))
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);
"#!- 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;
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;
}
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);
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))
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))
+++ /dev/null
-#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;
-}
--- /dev/null
+#include <string.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "instr.h"
+#include "emit.h"
+#include "object.h"
+#include "operator.h"
+#include "import.h"
+#include "traverse.h"
+#include "parse.h"
+
+ANN static Type fork_type(const Env env, const Exp_Unary *unary) {
+ const Type t = unary->exp->type;
+ if (t == env->gwion->type[et_void]) return env->gwion->type[et_fork];
+ char c[21 + strlen(t->name)];
+ sprintf(c, "TypedFork:[%s]", t->name);
+ const Type fork = env->gwion->type[et_fork];
+ UNSET_FLAG(fork, final);
+ const Type typed = str2type(env->gwion, "TypedFork", exp_self(unary)->pos);
+ if (typed->nspc->offset == fork->nspc->offset)
+ typed->nspc->offset += t->size;
+ UNSET_FLAG(typed, final);
+ const Type ret = str2type(env->gwion, c, exp_self(unary)->pos);
+ SET_FLAG(typed, final);
+ SET_FLAG(fork, final);
+ return ret;
+}
+
+ANN Type upvalue_type(const Env env, Capture *cap);
+static OP_CHECK(opck_spork) {
+ const Exp_Unary *unary = (Exp_Unary *)data;
+ if (unary->unary_type == unary_exp && unary->exp->exp_type == ae_exp_call) {
+ const m_bool is_spork = unary->op == insert_symbol("spork");
+ return is_spork ? env->gwion->type[et_shred] : fork_type(env, unary);
+ }
+ if (unary->unary_type == unary_code) {
+ if(unary->captures) {
+ uint32_t offset = !env->class_def ? 0 : SZ_INT;
+ for(uint32_t i = 0; i < unary->captures->len; i++) {
+ Capture *const cap = mp_vector_at(unary->captures, Capture, i);
+ DECL_OO(const Type, t, = upvalue_type(env, cap));
+ cap->temp = new_value(env, t, s_name(cap->xid), cap->pos);
+ cap->temp->from->offset = offset;
+ offset += cap->temp->type->size;
+ }
+ }
+ Upvalues upvalues = { .values = env->curr->info->value };
+ if(env->func && env->func->def->base->values)
+ upvalues.parent = env->func->def->base->values;
+ env->curr->info->value = new_scope(env->gwion->mp);
+ if(unary->captures) {
+ for(uint32_t i = 0; i < unary->captures->len; i++) {
+ Capture *const cap = mp_vector_at(unary->captures, Capture, i);
+ valid_value(env, cap->xid, cap->temp);
+ }
+ }
+ const Func f = env->func;
+ struct Value_ value = { .type = env->gwion->type[et_function]};
+ if(env->class_def)
+ set_vflag(&value, vflag_member);
+ struct Func_Base_ fbase = { .xid=insert_symbol("in spork"), .values = &upvalues, .fbflag = fbflag_lambda, .pos = exp_self(unary)->pos};
+ struct Func_Def_ fdef = { .base = &fbase};
+ struct Func_ func = { .name = "in spork", .def = &fdef, .value_ref = &value};
+ env->func = &func;
+ const m_bool ret = check_stmt(env, unary->code);
+ env->func = f;
+ free_scope(env->gwion->mp, env->curr->info->value);
+ env->curr->info->value = upvalues.values;
+ CHECK_BN(ret);
+ return env->gwion
+ ->type[unary->op == insert_symbol("spork") ? et_shred : et_fork];
+ }
+ ERR_O(exp_self(unary)->pos, _("only function calls can be sporked..."))
+}
+
+static OP_EMIT(opem_spork) {
+ const Exp_Unary *unary = (Exp_Unary *)data;
+ return emit_exp_spork(emit, unary);
+}
+
+static FREEARG(freearg_xork) { vmcode_remref((VM_Code)instr->m_val, gwion); }
+
+GWION_IMPORT(xork) {
+ GWI_BB(gwi_oper_ini(gwi, NULL, (m_str)OP_ANY_TYPE, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_spork))
+ GWI_BB(gwi_oper_emi(gwi, opem_spork))
+ GWI_BB(gwi_oper_end(gwi, "spork", NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_spork))
+ GWI_BB(gwi_oper_emi(gwi, opem_spork))
+ GWI_BB(gwi_oper_end(gwi, "fork", NULL))
+ gwi_register_freearg(gwi, SporkIni, freearg_xork);
+ return GW_OK;
+}
#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);
}
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"));
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) {
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) {
}
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;
}
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,
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)];
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;
}
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,
}
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;
}
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;
}
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;
}
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,
}
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);
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;
}
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;
ANN static void print_current_args(Exp e) {
gw_err(_("and not\n "));
- do gw_err(" {G}%s{0}", e->type ? e->type->name : "{-/}Unknown");
+ do gw_err(" {G}%s{0}", e->type ? e->type->name : "<Unknown>");
while ((e = next_arg_Exp(e)));
gw_err("\n");
}
ANN2(1)
-static void function_alternative(const Env env, const Type f, const Exp args,
+static void function_alternative(const Env env, const Type t, const Exp args,
const loc_t pos) {
if (env->context && env->context->error) // needed for ufcs
return;
gwerr_basic("Argument type mismatch", "call site",
"valid alternatives:", env->name, pos, 0);
- Func up = f->info->func;
+ Func up = isa(t, env->gwion->type[et_closure]) < 0
+ ? t->info->func : closure_def(t)->base->func;
do print_signature(up);
while ((up = up->next));
if (args)
print_current_args(args);
else
gw_err(_("and not:\n {G}void{0}\n"));
- env_set_error(env);
+ env_set_error(env, true);
}
ANN static Func get_template_func(const Env env, Exp_Call *const func,
const Value v) {
const Func f = find_template_match(env, v, func);
if (f) {
- // copy that tmpl->call?
Tmpl *tmpl = new_tmpl_call(env->gwion->mp, func->tmpl->call);
tmpl->list = v->d.func_ref
? v->d.func_ref->def->base->tmpl->list
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;
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;
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);
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;
}
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"),
}
}
-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;
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] ?
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;
}
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,
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;
}
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."))
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));
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);
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),
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 }},
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
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;
}
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);
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))}
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;
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;
}
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;
}
}
#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) {
}
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;
}
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;
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;
}
*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;
}
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;
}
: 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);
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 &&
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);
}
}
}
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) {
_("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;
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);
}
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));
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 ?
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));
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;
}
}
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) {
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++) {
CHECK_BB(check_section(env, section));
}
check_unhandled(env);
+ if(env->context->extend) check_extend(env, env->context->extend);
return GW_OK;
}
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;
}
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;
}
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 }},
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 }},
#include "emit.h"
#include "specialid.h"
#include "tmp_resolve.h"
+#include "spread.h"
struct ResolverArgs {
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);
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;
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 };
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;
(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);
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) {
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;
}
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);
#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) {
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++;
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;
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++);
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;
}
}
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;
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;
}
}
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;
}
-#include <string.h>
#include "gwion_util.h"
#include "gwion_ast.h"
#include "gwion_env.h"
#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);
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) {
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);
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;
}
}
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)) {
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);
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;
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;
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));
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
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;
}
}
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;
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) ||
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);
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;
}
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) ||
}
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;
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);
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;
}
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,
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) {
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;
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;
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) {
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));
#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);
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;
}
}
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) {
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) {
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) ||
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) {
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"));
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;
}
}
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;
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;
}
"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);
--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;
}
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) {
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);
}
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;
}
!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);
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) {
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);
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;
}
}
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);
}
--- /dev/null
+#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;
+}
#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;
}
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;
}
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);
}
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);
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) {
#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;
}
}
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;
}
: 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) {
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;) {
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) {
#! [contains] do not provide array
-[1,2,3,4] => var int loop[1];
+[1,2,3,4] => var int[1] loop;
#! [contains] array depths do not match
-[1,2,3,4] => var int k[1][1];
+[1,2,3,4] => var int[1][1] k;
#! [contains] partially empty array init
-var int i[2][];
+var int[2][] i;
#! [contains] partially empty array init
-var int i[][3];
+var int[][3] i;
#! [contains] NegativeArraySize
-var int i[2][-1];
+var int[2][-1] i;
#! [contains] ArrayOutofBounds
-var Object o[1][1];
+var Object[1][1] o;
o[1];
#! [contains] has no member
-var int i[2][2];
+var int[2][2] i;
i[0].test;
#! [contains] ArrayOutofBounds
-var Object i[1];
+var Object[1] i;
i[1];
#! [contains] ArrayOutofBounds
-var Object i[1][1];
+var Object[1][1] i;
i[1][0];
#! [contains] array types do not match
-[1,2,3,4] => var Object k[1];
+[1,2,3,4] => var Object[1] k;
+++ /dev/null
-#! [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;
-}
#! [contains] must be defined with empty
-fun int[] my_func(int i[2]){}
+fun int[] my_func(int[2] i){}
#! [contains] Argument type mismatch
fun void test(){}
-fun void test(int i[], int j[]){}
+fun void test(int[] i, int[] j){}
test(1,2);
#! [contains] invalid array access expression
-var int j[];
+var int[] j;
j[1,2,3,4] => i;
#! [contains] array depths do not match
-var int i[2][2];
+var int[2][2] i;
i << 2;
+++ /dev/null
-#! [contains] from/to a multi-variable declaration
-var int i, ii => var float f;
#! [contains] NegativeArraySize: while allocating arrays
-var int i[-1];
+var int[-1] i;
<<< i >>>;
#! [contains] ArrayOutofBounds
-var int i[2][2];
+var int[2][2] i;
<<< i[1][-1] >>>;
}
-var C c[1];
-var C d[2][4];
+var C[1] c;
+var C[2][4]d;
c :=> d;
#! [contains] must be defined with empty
-funptr void my_func (int i[4]);
+funptr void my_func (int[4] i);
+++ /dev/null
-#! [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;
+++ /dev/null
-#! [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;
+++ /dev/null
-#! [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 >>>;
test @=> var B b;
<<< b() >>>;
-<<< b:[int]() >>>;
+<<< b:[float]() >>>;
+++ /dev/null
-#! [contains] InvalidVariadicAccess
-fun void test(...) {
- varloop vararg {
- <<<vararg $ int >>>;
- }
-}
-new Object => test;
+++ /dev/null
-#! [contains] must be used inside variadic function
-vararg;
+++ /dev/null
-#! [contains] outside varloop
-fun void test(...) {
- <<<vararg $ int >>>;
-}
-new Object => test;
+++ /dev/null
-#! varloop expression type must be
-varloop 1 {
-
-}
+++ /dev/null
-class C {}
-
-extends C {
- fun void test() { <<< __func__ >>>; }
-}
-
-const C c;
-c.test();
+++ /dev/null
-#! [contains] abstract functions in extends
-extends Event {
- fun void test();
-}
+++ /dev/null
-#! [contains] extend final type
-class final C {}
-
-extends C {
- fun void test() {}
-}
+++ /dev/null
-#! [contains] only compound types can be extended
-extends int {
- fun void test(){}
-}
+++ /dev/null
-class C:[A] {}
-
-extends C:[int] {
- fun void test() { <<< __func__ >>>; }
-}
-
-const C:[int] c;
-c.test();
+++ /dev/null
-#! [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;
+++ /dev/null
-#! [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;
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;
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 >>>;
+++ /dev/null
-class C {
- funptr void t_ptr(...);
-
- var t_ptr iptr;
-
- fun void test(...) {
- <<< this, " ", __func__ >>>;
- varloop vararg {
- <<< vararg $ int >>>;
- }
- }
-
- test @=> iptr;
- <<< iptr() >>>;
- <<< iptr() >>>;
-}
-
-<<<var C c>>>;
-<<< c.iptr >>>;
-<<< c.iptr(1) >>>;
-<<< c.iptr(1,2) >>>;
+++ /dev/null
-fun void test(...) {
- <<< vararg >>>;
- <<< vararg.cpy() => var Vararg new_arg >>>;
-}
-test(1);
+++ /dev/null
-#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;
-}
+++ /dev/null
-#import op_already_imported
-#! [contains] already imported
-<<< 1 >>>;
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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();
#!/bin/bash
-# [test] #79
+# [test] #77
n=0
[ "$1" ] && n="$1"
--- /dev/null
+#! [contains] bar
+class C:[...] {
+ <<< "foo" >>>;
+ ... T : arg {
+ var T arg;
+ }...
+
+ <<< "bar" >>>;
+ ... T : arg {
+ <<< "${T} ${arg}" >>>;
+ }...
+ <<< "baz" >>>;
+}
+
+var C:[float, int] ci;
--- /dev/null
+#! [contains] syntax error
+
+class C:[...] {
+
+ ... T : arg {
+ zvar T arg;
+ }...
+
+
+ ... T : arg {
+ <<< "${T} ${arg}" >>>;
+ }...
+
+}
+
+var C:[float, int] ci;
--- /dev/null
+fun void t:[...]() {
+ ... T : arg {
+ <<< "${T} ${arg}" >>>;
+ }...
+}
+
+t(2.2);
+t(2);
--- /dev/null
+#! [contains] spread statement outside of variadic environment
+
+... T : arg {
+ <<< "error" >>>;
+}...
--- /dev/null
+#! [contains] spread statement outside of variadic environment
+class C {
+ ... T : arg {
+ <<< "error" >>>;
+ }...
+}
--- /dev/null
+#! [contains] spread statement outside of variadic environment
+
+fun void test() {
+ ... T : arg {
+ <<< "error" >>>;
+ }...
+}
-var int i[][][];
+var int[][][] i;
<<< i >>>;
class C {
- var int i[];
- var int j[2];
+ var int[] i;
+ var int[2] j;
}
var C c;
+++ /dev/null
-class C {
- var int i, j;
-}
-
class C:[A] {
\a{};
[ 1 ];
- var int i,j;
+ var int i;
'a';
true $ int;
i++;
+++ /dev/null
-fun int test(...){
- varloop vararg {
- <<< "test" >>>;
- <<< vararg $ int >>>;
- }
- return 1;
-}
-<<< test() >>>;
-<<< test() >>>;
-<<< (1, 7) => test >>>;
-<<< () => test >>>;
+++ /dev/null
-#! [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;
-}
+++ /dev/null
-var int i, j;
-<<< i, " ", j >>>;
+++ /dev/null
-fun void test(...){
- varloop vararg {
- }
-}
-test();
+++ /dev/null
-fun void test(int i, float f, ...){
- varloop vararg {
- }
-}
-test(1, 2.3, 1);
+++ /dev/null
-fun void test(...) {
- var Object o;
- varloop vararg {
- vararg $ Object => o;
- }
-}
-Subproject commit 2b55ce354595c33d5cee4a90085feb2a31be1572
+Subproject commit 8d07a94ba9207ce640d8046c663dbdb2d9860dc1