diff --git a/.bettercodehub.yml b/.bettercodehub.yml index e961b8eee..040c4125a 100644 --- a/.bettercodehub.yml +++ b/.bettercodehub.yml @@ -6,12 +6,13 @@ languages: include: - /src/.*\.c exclude: - - /src/ast/parser\.c - - /src/ast/lexer\.c - - /src/lib/soundpipe\.c + - /src/drvr/.*\.c + - /src/vm/vm.c + - /include/.*\.h + - /tests/import/.*\.c test: include: - - /tests/test_plugins/.*\.c + - /tests/import/.*\.c - name: go production: diff --git a/ast b/ast index 8fe7b1900..787c2856a 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit 8fe7b190037c09cee1b5ff6cca54b4dba88b9d1a +Subproject commit 787c2856a8ec0e24b9d174b003e9b395d01080e7 diff --git a/examples/array_lit.gw b/examples/array_lit.gw index accae62d5..3db22c1a9 100644 --- a/examples/array_lit.gw +++ b/examples/array_lit.gw @@ -12,7 +12,7 @@ Object t[2][12][3][4][5]; int k[1][1]; -<<>>; +<<>>; [ 1.0, 2, 3, 4, 5 ]; [ #(0.0, 0.0) ]; diff --git a/examples/binary_tmpl.gw b/examples/binary_tmpl.gw index 71a1ae83b..60253182f 100644 --- a/examples/binary_tmpl.gw +++ b/examples/binary_tmpl.gw @@ -1,4 +1,4 @@ -template fun void test(A a) { <<>>; } +template<~A~> fun void test(A a) { <<>>; } 1 => test; 1.3 => test; test(1); diff --git a/examples/class_coverage.gw b/examples/class_coverage.gw index 7e19954e7..9bba0ea2e 100644 --- a/examples/class_coverage.gw +++ b/examples/class_coverage.gw @@ -4,8 +4,8 @@ class C float f; complex c; polar p; - Vec3 v; - Vec4 w; + Vec3 v; + Vec4 w; Object o; dtor { <<<"dtor">>>; } } diff --git a/examples/class_spork_func.gw b/examples/class_spork_func.gw index 14b0d02c3..e375e598a 100644 --- a/examples/class_spork_func.gw +++ b/examples/class_spork_func.gw @@ -5,7 +5,7 @@ class C samp => now; <<<"and now">>>; } - spork test(); + spork this.test(); } C c; diff --git a/examples/dyn_switch.gw b/examples/dyn_switch.gw new file mode 100644 index 000000000..0209d2d26 --- /dev/null +++ b/examples/dyn_switch.gw @@ -0,0 +1,10 @@ +3 => const int i; +2 => const int y; +switch(i) { + case 1: <<<1>>>;break; + case 3: <<<3>>>;break; + case y: <<<2>>>;break; + default: + <<<"0">>>; +} +<<>>; diff --git a/examples/op2.gw b/examples/op2.gw index fee33bb90..0f1e51a21 100644 --- a/examples/op2.gw +++ b/examples/op2.gw @@ -12,9 +12,9 @@ operator => Vec3 (Vec3 c, C d){ << d.f>>>; return @(1.2, 6.1, 2.3 operator => Vec4 (Vec4 c, C d){ <<<"Vec4 => C: ", c.w => d.f>>>; return @(1.2, 6.1, 2.3, 9.3);} operator => float (C d, int c){ <<<"int => C: ", c => d.f>>>; return 2.0;} -operator => float (C d, float f){ <<<"float => C: ", f => d.f>>>; return 2.0;} +operator => float (C d, float f){ <<<"C => float: ", f => d.f>>>; return 2.0;} -operator => float (Vec3 v, float f){ <<<"float => C: ", f, v.x => f>>>; return 2.0;} +operator => float (Vec3 v, float f){ <<<"vec3 => C: ", f, " ", v.x => f>>>; return 2.0;} operator => complex (C d, complex c){ <<<"complex => C: ", c.re => d.f>>>; return #(1.2, 6.1);} operator => polar (C d, polar c){ <<<"complex => C: ", c.mod => d.f>>>; return %(2.3, 4.1);} diff --git a/examples/spork_exp.gw b/examples/spork_exp.gw index 1b539b078..8c3e465c9 100644 --- a/examples/spork_exp.gw +++ b/examples/spork_exp.gw @@ -2,11 +2,13 @@ class C { 12 => int i; Object o; +<<>>; spork { "test"; second => now; string s; - <<< "test spork exp." >>>; + <<< this, " test spork exp. " , s>>>; + } @=> Shred @shred; } diff --git a/examples/spork_func.gw b/examples/spork_func.gw index df34c858a..14252342e 100644 --- a/examples/spork_func.gw +++ b/examples/spork_func.gw @@ -1,13 +1,13 @@ class C { - function void test() { - <<<"here">>>; + function void test(int i) { + <<<"here => ", i>>>; samp => now; <<<"and now">>>; } } C c; -spork c.test(); +spork c.test(2); me.yield(); 4::samp => now; diff --git a/examples/template_dyn.gw b/examples/template_dyn.gw new file mode 100644 index 000000000..ebfa2514a --- /dev/null +++ b/examples/template_dyn.gw @@ -0,0 +1,52 @@ +fun void test(C cc) { <<< cc.test(2) >>>; } + +fun void test(C cc, int i) { <<<1>>>; <<>>; } + + +class C { + template<~A~> + fun int test(A a) { <<<" A ", a>>>; } + template<~A~> + fun int test(A a, int i) { <<<" ", a >>>; } + template<~A~> + fun int test(A a, int i, int j) { <<>>; } +} +class D extends C { + template<~A~> + fun int test(A a, int i) { <<>>; } +} +class E extends D { + template<~A~> + fun int test(A a, int i) { <<>>; } +} + + +<<>>; +<<>>; +<<>>; + +test(c); +test(d); +test(e); +test(c,1); +test(d,2); +test(e,3); +<<>>; + + +c.test(1); +c.test(123,1); +c.test(1, 2, 3); + +d.test(2); +d.test(123,3); +d.test(2, 2, 3); + +e.test(3); +e.test(123,3); +e.test(3, 2, 3); + +fun void _test() {<<<"test">>>; } +fun void test() { _test(); } +test(); + diff --git a/examples/vec3.gw b/examples/vec3.gw index 764e5df5c..6119e4a87 100644 --- a/examples/vec3.gw +++ b/examples/vec3.gw @@ -34,3 +34,4 @@ w-10.; w/10.; 10.*w; w*10.; +<<<@(23).x>>>; diff --git a/help/lcov.sh b/help/lcov.sh index b0f181377..539768c1f 100644 --- a/help/lcov.sh +++ b/help/lcov.sh @@ -4,17 +4,6 @@ OUTFILE=lcov/lcov.info [ -d lcov ] || mkdir lcov -#[ -z "$TRAVIS_BUILD_DIR" ] || { -# BASE_DIR=$PWD -# cd tests/test_plugin || return -# for file in *.c -# do -# sed 's/\.c//' <<< "$file" -# test_test_plugin "$(sed 's/\.c//' <<< "$file")" -# done -# cd "$BASE_DIR" || return -#} - lcov --no-external --capture --directory src --output-file "$OUTFILE" [ -z "$TRAVIS_BUILD_DIR" ] || { diff --git a/help/opcode.sh b/help/opcode.sh new file mode 100644 index 000000000..35ee14dba --- /dev/null +++ b/help/opcode.sh @@ -0,0 +1,25 @@ +#!/bin/bash +echo "#ifndef __GWION_OPCODES__" +echo "#define __GWION_OPCODES__" + +list=$(grep -v "#" opcode.txt) +COUNT=0 +echo "enum {" +for a in ${list} +do + [ -z "$a" ] || { + echo " $a," + COUNT=$((COUNT+1)) + } +done +echo "};" +echo "" + +for a in ${list} +do + [ -z "$a" ] || echo "#define $a (f_instr)$a" +done | column -t + +echo "#endif" + +echo "generated" "$COUNT" "opcodes" >&2 diff --git a/include/arg.h b/include/arg.h index 09c4179ac..46f488c37 100644 --- a/include/arg.h +++ b/include/arg.h @@ -6,11 +6,10 @@ typedef struct { struct Vector_ add; struct Vector_ rem; struct Vector_ lib; - Vector ref; + struct Vector_ mod; m_bool loop; - unsigned quit : 1; } Arg; -ANN void arg_init(Arg* arg); ANN void arg_release(Arg* arg); +ANN uint parse_args(Arg*, DriverInfo*); #endif diff --git a/include/array.h b/include/array.h index 7b96e5d3a..b19786eba 100644 --- a/include/array.h +++ b/include/array.h @@ -3,7 +3,6 @@ typedef struct M_Vector_ * M_Vector; typedef struct ArrayInfo_ { m_int depth; -// Type type, base; struct Vector_ type; Type base; M_Object* data; diff --git a/include/context.h b/include/context.h index 60c42603a..2846abcb2 100644 --- a/include/context.h +++ b/include/context.h @@ -12,5 +12,4 @@ struct Context_ { ANN2(2) ANEW Context new_context(const Ast, const m_str); ANN void load_context(const Context, const Env); ANN void unload_context(const Context, const Env); -ANN void free_context(const Context); #endif diff --git a/include/env.h b/include/env.h index 629829285..53ae30f96 100644 --- a/include/env.h +++ b/include/env.h @@ -48,7 +48,6 @@ ANN m_bool compat_func(const __restrict__ Func_Def, const __restrict__ Func_Def) ANN Type known_type(const Env env, const Type_Decl*); ANN m_bool env_access(const Env env, const ae_flag flag); ANN void env_storage(const Env env, ae_flag* flag); -ANN2(1,2) void env_add_value(const Env, const m_str, const Type, const m_bool, void*); ANN void env_add_type(const Env, const Type); ANN Type find_type(const Env, ID_List); ANN m_bool already_defined(const Env env, const Symbol s, const uint pos); diff --git a/include/gack.h b/include/gack.h new file mode 100644 index 000000000..54fc7fcb7 --- /dev/null +++ b/include/gack.h @@ -0,0 +1,4 @@ +#ifndef __GACK +#define __GACK +ANN void gack(const m_bit*, const Instr); +#endif diff --git a/include/gwion.h b/include/gwion.h index 6f68675cd..06c6eaff0 100644 --- a/include/gwion.h +++ b/include/gwion.h @@ -1,7 +1,12 @@ #ifndef __GWION #define __GWION typedef struct Gwion_* Gwion; +#include "plug.h" +#include "driver.h" struct Gwion_ { + PlugInfo plug; + Driver* driver; +// scanner // sym // mem // rnd @@ -10,6 +15,9 @@ struct Gwion_ { Emitter emit; VM* vm; }; -ANN void gwion_init(Gwion gwion); -ANN void gwion_release(Gwion gwion); +ANN void gwion_init(const Gwion, const Vector); +ANN m_bool gwion_audio(const Gwion gwion, DriverInfo* di); +ANN void gwion_run(const Gwion gwion, DriverInfo* di); +ANN m_bool gwion_engine(const Gwion gwion); +ANN void gwion_release(const Gwion gwion, DriverInfo* di); #endif diff --git a/include/import.h b/include/import.h index 453ed9339..a32d4591e 100644 --- a/include/import.h +++ b/include/import.h @@ -2,16 +2,22 @@ #define __IMPORT #define DLARG_MAX 6 -typedef void (*f_xtor)(const M_Object o, const VM_Shred sh); +typedef void (*f_xtor)(const M_Object o, const m_bit*, const VM_Shred); +//typedef void (*f_xtor)(const M_Object o, const VM_Shred); typedef void (*f_mfun)(const M_Object o, const m_bit* RETURN, const VM_Shred sh); typedef void (*f_sfun)(const m_bit* RETURN, const VM_Shred sh); +//typedef void (*f_sfun)(const m_bit*, const m_bit* RETURN, const VM_Shred sh); typedef void (*f_xfun)(); typedef struct Gwi_* Gwi; #define MFUN(a) ANN void a(const M_Object o __attribute__((unused)), const m_bit* RETURN __attribute__((unused)), const VM_Shred shred __attribute__((unused))) #define SFUN(a) ANN void a(const m_bit* RETURN __attribute__((unused)), const VM_Shred shred __attribute__((unused))) -#define CTOR(a) ANN void a(const M_Object o, const VM_Shred shred __attribute__((unused))) -#define DTOR(a) ANN void a(const M_Object o, const VM_Shred shred __attribute__((unused))) +//#define SFUN(a) ANN void a(const m_bit* mem __attribute__((unused)), const m_bit* RETURN +//__attribute__((unused)), const VM_Shred shred __attribute__((unused))) +#define CTOR(a) ANN void a(const M_Object o, const m_bit* _ __attribute__((unused)), const VM_Shred shred __attribute__((unused))) +//#define CTOR(a) ANN void a(const M_Object o, const VM_Shred shred __attribute__((unused))) +#define DTOR(a) ANN void a(const M_Object o, const m_bit* _ __attribute__((unused)), const VM_Shred shred __attribute__((unused))) +//#define DTOR(a) ANN void a(const M_Object o, const VM_Shred shred __attribute__((unused))) #define OP_CHECK(a) ANN Type a(const Env env __attribute__((unused)), void* data __attribute__((unused))) #define OP_EMIT(a) ANN m_bool a(const Emitter emit __attribute__((unused)), void* data __attribute__((unused))) #ifdef GWION_BUILTIN @@ -28,8 +34,6 @@ typedef struct Gwi_* Gwi; ANN VM* gwi_vm(const Gwi); ANN2(1,2) ANEW Type gwi_mk_type(const Gwi, const m_str, const m_uint, const Type); ANN m_int gwi_add_type(const Gwi gwi, Type type); -ANN2(1,2,3)m_int gwi_add_value(const Gwi gwi, const m_str name, Type type, const m_bool is_const, void* data); - ANN2(1,2)m_int gwi_class_ini(const Gwi gwi, const Type type, const f_xtor pre_ctor, const f_xtor dtor); ANN m_int gwi_class_ext(const Gwi gwi, Type_Decl* td); ANN m_int gwi_class_end(const Gwi gwi); @@ -73,4 +77,8 @@ OP_CHECK(opck_basic_cast); OP_CHECK(opck_new); OP_EMIT(opem_basic_cast); OP_EMIT(opem_new); + + +ANN /*static */ Type_List str2tl(const Env env, const m_str s, m_uint *depth); + #endif diff --git a/include/instr.h b/include/instr.h index 9bdbc5cd1..e349f4ba5 100644 --- a/include/instr.h +++ b/include/instr.h @@ -20,109 +20,30 @@ enum Kind { typedef struct Instr_ * Instr; typedef void (*f_instr)(const VM_Shred, const Instr); struct Instr_ { + m_bit opcode; + union { + m_float f; + m_uint m_val; + }; + m_uint m_val2; void (*execute)(const VM_Shred shred, const Instr instr); - m_uint m_val, m_val2; - m_bit ptr[SZ_MINVAL]; }; INSTR(EOC); INSTR(DTOR_EOC); INSTR(DtorReturn); -INSTR(RegPushMe); -INSTR(RegPushNow); -INSTR(RegPushMaybe); - -/* staking */ -INSTR(RegPop); -INSTR(RegPushImm0); -INSTR(RegPushImm); -INSTR(RegPushImm2); -INSTR(RegPushImm3); -INSTR(RegPushImm4); -INSTR(RegPushMemAddr); -INSTR(MemPushImm); -INSTR(MemSetImm); -INSTR(RegPushMem); -INSTR(RegPushMem2); -INSTR(RegPushMem3); -INSTR(RegPushMem4); -INSTR(RegPushBase); -INSTR(RegPushBase2); -INSTR(RegPushBase3); -INSTR(RegPushBase4); -INSTR(RegPushPtr); -INSTR(RegDup); -INSTR(RegAddRef); - /* branching */ INSTR(BranchSwitch); INSTR(SwitchIni); INSTR(SwitchEnd); -INSTR(BranchEqInt); -INSTR(BranchNeqInt); -INSTR(BranchEqFloat); -INSTR(BranchNeqFloat); -INSTR(InitLoopCounter); -INSTR(RegPushDeref); -INSTR(RegPushDeref2); -INSTR(RegPushDeref3); -INSTR(DecIntAddr); -INSTR(Goto); - -/* casting */ -INSTR(CastI2F); -INSTR(CastF2I); - -/* debugging */ -INSTR(Gack); - -INSTR(RegPushStr); - -INSTR(IntNot); -INSTR(FloatTimes); INSTR(ComplexReal); INSTR(ComplexImag); -INSTR(AllocWord); -INSTR(AllocWord2); -INSTR(AllocWord3); -INSTR(AllocWord4); - /* function */ -INSTR(SporkExp); -INSTR(SporkFunc); -INSTR(FuncUsr); -INSTR(DotFunc); -INSTR(FuncStatic); -INSTR(FuncMember); -INSTR(FuncPtr); -INSTR(FuncReturn); INSTR(DtorReturn); -/* object */ -INSTR(PreCtor); -INSTR(ObjectInstantiate); -INSTR(ObjectAssign); -INSTR(PushNull); -INSTR(PushNull2); -INSTR(PushNull3); -INSTR(AllocMember4); -INSTR(DotStatic); -INSTR(DotStatic2); -INSTR(DotStatic3); -INSTR(DotStatic4); -INSTR(DotImport); -INSTR(DotImport2); -INSTR(DotImport3); -INSTR(DotImport4); -INSTR(DotMember); -INSTR(DotMember2); -INSTR(DotMember3); -INSTR(DotMember4); -INSTR(ObjectRelease); - /* array */ INSTR(ArrayTop); INSTR(ArrayBottom); @@ -140,21 +61,25 @@ INSTR(VarargTop); INSTR(VarargEnd); INSTR(VarargMember); -INSTR(MemberFunction); +INSTR(VecCpy); INSTR(VecMember); INSTR(PopArrayClass); -INSTR(GcIni); -INSTR(GcEnd); -INSTR(GcAdd); - INSTR(AutoLoopStart); INSTR(AutoLoopEnd); - +INSTR(DotTmpl); + +struct dottmpl_ { + size_t len; + m_str name; + Func_Def base, def; + size_t overload; // => vtindex ? + Type_List tl; +}; +ANN void free_dottmpl(struct dottmpl_*); // optimizations #ifdef OPTIMIZE INSTR(PutArgsInMem); -INSTR(ConstPropSet); -INSTR(ConstPropGet); #endif +#include "opcode.h" #endif diff --git a/include/nspc.h b/include/nspc.h index ccf7d6360..07c2d5ded 100644 --- a/include/nspc.h +++ b/include/nspc.h @@ -17,7 +17,6 @@ struct Nspc_ { }; extern ANEW ANN Nspc new_nspc(const m_str name); -extern ANN void free_nspc(const Nspc a); extern ANN void nspc_commit(const Nspc); //extern ANN void nspc_rollback(const Nspc); diff --git a/include/object.h b/include/object.h index 20afdbb1e..850a0ad68 100644 --- a/include/object.h +++ b/include/object.h @@ -4,6 +4,8 @@ typedef struct M_Object_ * M_Object; struct M_Object_ { m_bit* data; Type type_ref; +// Nspc nspc;// + Vector vtable; struct pool* p; size_t ref; }; diff --git a/include/oo.h b/include/oo.h index 566898b33..ec55ede30 100644 --- a/include/oo.h +++ b/include/oo.h @@ -1,25 +1,23 @@ #ifndef __OO #define __OO -typedef struct VM_Object_ * VM_Object; typedef struct Type_ * Type; typedef struct Nspc_ * Nspc; typedef struct Value_ * Value; typedef struct Func_ * Func; -typedef enum { - e_nspc_obj, e_context_obj, - e_type_obj, e_value_obj, e_func_obj, e_code_obj -} e_obj; struct VM_Object_ { - size_t ref_count; - e_obj type; -} __attribute__((packed)); - + uint16_t ref_count; // could be an unsigned short + void (*free)(void*); +}; #define HAS_OBJ struct VM_Object_ obj; -#define INIT_OO(a, b) { (a)->obj.type = b; (a)->obj.ref_count = 1; } -#define REM_REF(a) { rem_ref(&(a)->obj, (a)); } +#define INIT_OO(a, b) { (a)->obj.ref_count = 1; (a)->obj.free= (void(*)(void*))b; } +ANN static inline void rem_ref(struct VM_Object_* a, void* ptr) { + if(--a->ref_count) + return; + a->free(ptr); +} #define ADD_REF(a) { ++(a)->obj.ref_count; } -ANN void rem_ref(const VM_Object a, void* ptr); +#define REM_REF(a) { rem_ref(&(a)->obj, (a)); } #endif diff --git a/include/opcode.h b/include/opcode.h new file mode 100644 index 000000000..b10319aae --- /dev/null +++ b/include/opcode.h @@ -0,0 +1,312 @@ +#ifndef __GWION_OPCODES__ +#define __GWION_OPCODES__ +enum { + RegSetImm, + RegPushImm, + RegPushImm2, + RegPushImm3, + RegPushImm4, + RegPushMem, + RegPushMem2, + RegPushMem3, + RegPushMem4, + RegPushNow, + RegPushBase, + RegPushBase2, + RegPushBase3, + RegPushBase4, + RegDup, + MemSetImm, + RegPop, + RegPushMe, + RegPushMaybe, + FuncReturn, + Goto, + AllocWord, + AllocWord2, + AllocWord3, + AllocWord4, + int_plus, + int_minus, + int_mul, + int_div, + int_modulo, + int_eq, + int_neq, + int_and, + int_or, + int_gt, + int_ge, + int_lt, + int_le, + int_sl, + int_sr, + int_sand, + int_sor, + int_xor, + int_negate, + IntNot, + int_cmp, + int_r_assign, + int_r_plus, + int_r_minus, + int_r_mul, + int_r_div, + int_r_modulo, + int_r_sl, + int_r_sr, + int_r_sand, + int_r_sor, + int_r_sxor, + int_pre_inc, + int_pre_dec, + int_post_inc, + int_post_dec, + FloatPlus, + FloatMinus, + FloatTimes, + FloatDivide, + float_and, + float_or, + float_eq, + float_neq, + float_gt, + float_ge, + float_lt, + float_le, + float_negate, + float_not, + float_r_assign, + float_r_plus, + float_r_minus, + float_r_mul, + float_r_div, + int_float_plus, + int_float_minus, + int_float_mul, + int_float_div, + int_float_and, + int_float_or, + int_float_eq, + int_float_neq, + int_float_gt, + int_float_ge, + int_float_lt, + int_float_le, + int_float_r_assign, + int_float_r_plus, + int_float_r_minus, + int_float_r_mul, + int_float_r_div, + float_int_plus, + float_int_minus, + float_int_mul, + float_int_div, + float_int_and, + float_int_or, + float_int_eq, + float_int_neq, + float_int_gt, + float_int_ge, + float_int_lt, + float_int_le, + float_int_r_assign, + float_int_r_plus, + float_int_r_minus, + float_int_r_mul, + float_int_r_div, + CastI2F, + CastF2I, + Time_Advance, + FuncUsr, + FuncMember, + FuncStatic, + SporkIni, + SporkFunc, + SporkThis, + SporkExp, + SporkEnd, + FuncPtr, + BranchEqInt, + BranchNeqInt, + BranchEqFloat, + BranchNeqFloat, + DecIntAddr, + InitLoopCounter, + ObjectInstantiate, + RegAddRef, + ObjectAssign, + ObjectRelease, + GWOP_EXCEPT, + AllocMember4, + DotMember, + DotMember2, + DotMember3, + DotMember4, + DotStatic, + DotStatic2, + DotStatic3, + DotFunc, + PushStaticCode, + RegPushStr, + GcIni, + GcAdd, + GcEnd, + Gack, + OP_MAX, +}; + +#define RegSetImm (f_instr)RegSetImm +#define RegPushImm (f_instr)RegPushImm +#define RegPushImm2 (f_instr)RegPushImm2 +#define RegPushImm3 (f_instr)RegPushImm3 +#define RegPushImm4 (f_instr)RegPushImm4 +#define RegPushMem (f_instr)RegPushMem +#define RegPushMem2 (f_instr)RegPushMem2 +#define RegPushMem3 (f_instr)RegPushMem3 +#define RegPushMem4 (f_instr)RegPushMem4 +#define RegPushNow (f_instr)RegPushNow +#define RegPushBase (f_instr)RegPushBase +#define RegPushBase2 (f_instr)RegPushBase2 +#define RegPushBase3 (f_instr)RegPushBase3 +#define RegPushBase4 (f_instr)RegPushBase4 +#define RegDup (f_instr)RegDup +#define MemSetImm (f_instr)MemSetImm +#define RegPop (f_instr)RegPop +#define RegPushMe (f_instr)RegPushMe +#define RegPushMaybe (f_instr)RegPushMaybe +#define FuncReturn (f_instr)FuncReturn +#define Goto (f_instr)Goto +#define AllocWord (f_instr)AllocWord +#define AllocWord2 (f_instr)AllocWord2 +#define AllocWord3 (f_instr)AllocWord3 +#define AllocWord4 (f_instr)AllocWord4 +#define int_plus (f_instr)int_plus +#define int_minus (f_instr)int_minus +#define int_mul (f_instr)int_mul +#define int_div (f_instr)int_div +#define int_modulo (f_instr)int_modulo +#define int_eq (f_instr)int_eq +#define int_neq (f_instr)int_neq +#define int_and (f_instr)int_and +#define int_or (f_instr)int_or +#define int_gt (f_instr)int_gt +#define int_ge (f_instr)int_ge +#define int_lt (f_instr)int_lt +#define int_le (f_instr)int_le +#define int_sl (f_instr)int_sl +#define int_sr (f_instr)int_sr +#define int_sand (f_instr)int_sand +#define int_sor (f_instr)int_sor +#define int_xor (f_instr)int_xor +#define int_negate (f_instr)int_negate +#define IntNot (f_instr)IntNot +#define int_cmp (f_instr)int_cmp +#define int_r_assign (f_instr)int_r_assign +#define int_r_plus (f_instr)int_r_plus +#define int_r_minus (f_instr)int_r_minus +#define int_r_mul (f_instr)int_r_mul +#define int_r_div (f_instr)int_r_div +#define int_r_modulo (f_instr)int_r_modulo +#define int_r_sl (f_instr)int_r_sl +#define int_r_sr (f_instr)int_r_sr +#define int_r_sand (f_instr)int_r_sand +#define int_r_sor (f_instr)int_r_sor +#define int_r_sxor (f_instr)int_r_sxor +#define int_pre_inc (f_instr)int_pre_inc +#define int_pre_dec (f_instr)int_pre_dec +#define int_post_inc (f_instr)int_post_inc +#define int_post_dec (f_instr)int_post_dec +#define FloatPlus (f_instr)FloatPlus +#define FloatMinus (f_instr)FloatMinus +#define FloatTimes (f_instr)FloatTimes +#define FloatDivide (f_instr)FloatDivide +#define float_and (f_instr)float_and +#define float_or (f_instr)float_or +#define float_eq (f_instr)float_eq +#define float_neq (f_instr)float_neq +#define float_gt (f_instr)float_gt +#define float_ge (f_instr)float_ge +#define float_lt (f_instr)float_lt +#define float_le (f_instr)float_le +#define float_negate (f_instr)float_negate +#define float_not (f_instr)float_not +#define float_r_assign (f_instr)float_r_assign +#define float_r_plus (f_instr)float_r_plus +#define float_r_minus (f_instr)float_r_minus +#define float_r_mul (f_instr)float_r_mul +#define float_r_div (f_instr)float_r_div +#define int_float_plus (f_instr)int_float_plus +#define int_float_minus (f_instr)int_float_minus +#define int_float_mul (f_instr)int_float_mul +#define int_float_div (f_instr)int_float_div +#define int_float_and (f_instr)int_float_and +#define int_float_or (f_instr)int_float_or +#define int_float_eq (f_instr)int_float_eq +#define int_float_neq (f_instr)int_float_neq +#define int_float_gt (f_instr)int_float_gt +#define int_float_ge (f_instr)int_float_ge +#define int_float_lt (f_instr)int_float_lt +#define int_float_le (f_instr)int_float_le +#define int_float_r_assign (f_instr)int_float_r_assign +#define int_float_r_plus (f_instr)int_float_r_plus +#define int_float_r_minus (f_instr)int_float_r_minus +#define int_float_r_mul (f_instr)int_float_r_mul +#define int_float_r_div (f_instr)int_float_r_div +#define float_int_plus (f_instr)float_int_plus +#define float_int_minus (f_instr)float_int_minus +#define float_int_mul (f_instr)float_int_mul +#define float_int_div (f_instr)float_int_div +#define float_int_and (f_instr)float_int_and +#define float_int_or (f_instr)float_int_or +#define float_int_eq (f_instr)float_int_eq +#define float_int_neq (f_instr)float_int_neq +#define float_int_gt (f_instr)float_int_gt +#define float_int_ge (f_instr)float_int_ge +#define float_int_lt (f_instr)float_int_lt +#define float_int_le (f_instr)float_int_le +#define float_int_r_assign (f_instr)float_int_r_assign +#define float_int_r_plus (f_instr)float_int_r_plus +#define float_int_r_minus (f_instr)float_int_r_minus +#define float_int_r_mul (f_instr)float_int_r_mul +#define float_int_r_div (f_instr)float_int_r_div +#define CastI2F (f_instr)CastI2F +#define CastF2I (f_instr)CastF2I +#define Time_Advance (f_instr)Time_Advance +#define FuncUsr (f_instr)FuncUsr +#define FuncMember (f_instr)FuncMember +#define FuncStatic (f_instr)FuncStatic +#define SporkIni (f_instr)SporkIni +#define SporkFunc (f_instr)SporkFunc +#define SporkThis (f_instr)SporkThis +#define SporkExp (f_instr)SporkExp +#define SporkEnd (f_instr)SporkEnd +#define FuncPtr (f_instr)FuncPtr +#define BranchEqInt (f_instr)BranchEqInt +#define BranchNeqInt (f_instr)BranchNeqInt +#define BranchEqFloat (f_instr)BranchEqFloat +#define BranchNeqFloat (f_instr)BranchNeqFloat +#define DecIntAddr (f_instr)DecIntAddr +#define InitLoopCounter (f_instr)InitLoopCounter +#define ObjectInstantiate (f_instr)ObjectInstantiate +#define RegAddRef (f_instr)RegAddRef +#define ObjectAssign (f_instr)ObjectAssign +#define ObjectRelease (f_instr)ObjectRelease +#define GWOP_EXCEPT (f_instr)GWOP_EXCEPT +#define AllocMember4 (f_instr)AllocMember4 +#define DotMember (f_instr)DotMember +#define DotMember2 (f_instr)DotMember2 +#define DotMember3 (f_instr)DotMember3 +#define DotMember4 (f_instr)DotMember4 +#define DotStatic (f_instr)DotStatic +#define DotStatic2 (f_instr)DotStatic2 +#define DotStatic3 (f_instr)DotStatic3 +#define DotFunc (f_instr)DotFunc +#define PushStaticCode (f_instr)PushStaticCode +#define RegPushStr (f_instr)RegPushStr +#define GcIni (f_instr)GcIni +#define GcAdd (f_instr)GcAdd +#define GcEnd (f_instr)GcEnd +#define Gack (f_instr)Gack +#define OP_MAX (f_instr)OP_MAX +#endif diff --git a/include/optim.h b/include/optim.h index 0cbd2a3b0..42e6f2e3f 100644 --- a/include/optim.h +++ b/include/optim.h @@ -1,17 +1,11 @@ #ifndef __OPTIM #define __OPTIM #ifdef OPTIMIZE -#define OPTIMIZE_DEFAULT default: break; #define OPTIMIZE_CONST(a) CHECK_BO(optimize_const(a)) ANN m_bool optimize_const(const Exp_Binary*); -ANN2(1) void constprop_prim(const Exp_Primary* p, m_uint* ptr); -#define OPTIMIZE_PRIM_CONST(a, b) \ -else if(GET_FLAG(v, ae_flag_constprop)) \ - constprop_prim(a,b); +//ANN2(1) void constprop_prim(const Exp_Primary* p, m_uint* ptr); #else -#define OPTIMIZE_DEFAULT #define OPTIMIZE_CONST(a) -#define OPTIMIZE_PRIM_CONST(a, b) #endif m_bool constant_folding(const Exp_Binary* bin); #endif diff --git a/include/parse.h b/include/parse.h index bcd18e3d7..8b5b554a6 100644 --- a/include/parse.h +++ b/include/parse.h @@ -1,13 +1,19 @@ #ifndef __PARSE #define __PARSE #define RET_NSPC(exp) \ -++env->scope; \ +++env->scope; \ nspc_push_value(env->curr); \ const m_bool ret = exp; \ nspc_pop_value(env->curr); \ ---env->scope; \ +--env->scope; \ return ret; +#define SET_ACCESS(a,b) \ +if(GET_FLAG(a, private)) \ + SET_FLAG(b, private); \ +else if(GET_FLAG(a, protect)) \ + SET_FLAG(b, protect); + typedef m_bool (*_exp_func)(const void*, const void*); static inline m_bool dummy_func(const void*a __attribute__((unused)), const void*b __attribute__((unused))) { return 1; } diff --git a/include/plug.h b/include/plug.h index 2d09d313d..4ee5e4ca0 100644 --- a/include/plug.h +++ b/include/plug.h @@ -1,7 +1,29 @@ #ifndef __PLUG #define __PLUG -#define NPLUG_VEC 2 -typedef struct Vector_ PlugInfo[NPLUG_VEC]; + +enum plug_t { + GWPLUG_DL, + GWPLUG_IMPORT, + GWPLUG_MODULE, + GWPLUG_LAST +}; + +typedef struct Vector_ PlugInfo[GWPLUG_LAST]; void plug_ini(PlugInfo, Vector); -void plug_end(PlugInfo); +void plug_end(const Gwion gwion); + +#define GWMODNAME_NAME "gwmodname" +#define GWMODINI_NAME "gwmodini" +#define GWMODEND_NAME "gwmodend" +#define GWMODNAME_FUNC gwmodname +#define GWMODINI_FUNC gwmodini +#define GWMODEND_FUNC gwmodend +#define GWMODNAME(a) m_str GWMODNAME_FUNC() { return a; } +#define GWMODINI(a) ANN void* GWMODINI_FUNC(const Gwion gwion, const Vector args) +#define GWMODEND(a) ANN void GWMODEND_FUNC(const Gwion gwion, void* self) + +//typedef void* (*f_gwmodname)(void); +typedef void* (*f_gwmodini)(const Gwion, const Vector); +typedef void* (*f_gwmodend)(const Gwion, void*); +void module_ini(const Gwion gwion, Vector); #endif diff --git a/include/shreduler_private.h b/include/shreduler_private.h index f5bd37d19..d6d4ad1f5 100644 --- a/include/shreduler_private.h +++ b/include/shreduler_private.h @@ -2,8 +2,8 @@ #define __SHREDULER struct Shreduler_ { VM* vm; - VM_Shred list; - VM_Shred curr; + struct ShredTick_ *list; + struct ShredTick_ *curr; struct Vector_ shreds; size_t shred_ids; m_bool loop; diff --git a/include/value.h b/include/value.h index 541ae2044..403c28548 100644 --- a/include/value.h +++ b/include/value.h @@ -16,5 +16,4 @@ struct Value_ { }; ANEW ANN Value new_value(struct Gwion_* gwion, const Type type, const m_str name); -ANN void free_value(Value a); #endif diff --git a/include/vm.h b/include/vm.h index 628414b27..d8a4c8741 100644 --- a/include/vm.h +++ b/include/vm.h @@ -1,18 +1,16 @@ #ifndef __VM #define __VM -#ifdef USE_DOUBLE -#undef USE_DOUBLE -#endif - typedef struct VM_Code_* VM_Code; struct VM_Code_ { - Vector instr; - m_str name; - m_uint native_func; - void* memoize; + union { + Vector instr; + m_uint native_func; + }; size_t stack_depth; ae_flag flag; + void* memoize; + m_str name; HAS_OBJ }; @@ -30,33 +28,42 @@ typedef struct Emitter_ * Emitter; typedef struct VM_ { Shreduler shreduler; struct Vector_ ugen; - struct Gwion_* gwion; struct BBQ_* bbq; + struct Gwion_* gwion; uint32_t rand[2]; volatile unsigned is_running : 1; // => shreduler } VM; typedef struct VM_Shred_* VM_Shred; + +struct ShredInfo_ { + VM* vm; + struct M_Object_* me; + m_str name; + Vector args; +}; + +struct ShredTick_ { + VM_Shred self; + struct ShredTick_ *prev; + struct ShredTick_ *next; + struct ShredTick_ *parent; + struct Vector_ child; + size_t xid; + m_float wake_time; +}; + struct VM_Shred_ { - Vector instr; VM_Code code; - VM_Shred parent; m_bit* reg; m_bit* mem; - m_bit* _reg; m_bit* base; - m_str name; - VM* vm; - VM_Shred prev, next; - Vector args; // passed pointer from compile - struct M_Object_* me; - struct Vector_ child; - struct Vector_ gc;//, gc1; - size_t pc, xid; - m_float wake_time; + size_t pc; + struct Vector_ gc; + struct ShredTick_ * tick; + struct ShredInfo_ * info; }; -ANN2(4) ANEW VM_Code new_vm_code(const Vector instr, const m_uint stack_depth, const m_bool need_this, const m_str name); -ANN void free_vm_code(const VM_Code a); +ANN2(4) ANEW VM_Code new_vm_code(const Vector instr, const m_uint stack_depth, const ae_flag, const m_str name); ANN VM_Shred shreduler_get(const Shreduler s) __attribute__((hot)); ANN void shreduler_remove(const Shreduler s, const VM_Shred out, const m_bool erase)__attribute__((hot)); @@ -66,7 +73,7 @@ ANN void shreduler_add(const Shreduler s, const VM_Shred shred); ANEW ANN VM_Shred new_vm_shred(const VM_Code code) __attribute__((hot)); __attribute__((hot)) -ANN static inline void vm_shred_exit(const VM_Shred shred) { shreduler_remove(shred->vm->shreduler, shred, 1); } +ANN static inline void vm_shred_exit(const VM_Shred shred) { shreduler_remove(shred->info->vm->shreduler, shred, 1); } void free_vm_shred(const VM_Shred shred)__attribute__((hot, nonnull)); ANN void vm_run(const VM* vm) __attribute__((hot)); diff --git a/opcode.txt b/opcode.txt new file mode 100644 index 000000000..bd7150838 --- /dev/null +++ b/opcode.txt @@ -0,0 +1,153 @@ +RegSetImm +RegPushImm +RegPushImm2 +RegPushImm3 +RegPushImm4 +RegPushMem +RegPushMem2 +RegPushMem3 +RegPushMem4 +RegPushNow +RegPushBase +RegPushBase2 +RegPushBase3 +RegPushBase4 +RegDup +MemSetImm +RegPop +RegPushMe +RegPushMaybe +FuncReturn +Goto +AllocWord +AllocWord2 +AllocWord3 +AllocWord4 +int_plus +int_minus +int_mul +int_div +int_modulo +int_eq +int_neq +int_and +int_or +int_gt +int_ge +int_lt +int_le +int_sl +int_sr +int_sand +int_sor +int_xor +int_negate +IntNot +int_cmp +int_r_assign +int_r_plus +int_r_minus +int_r_mul +int_r_div +int_r_modulo +int_r_sl +int_r_sr +int_r_sand +int_r_sor +int_r_sxor +int_pre_inc +int_pre_dec +int_post_inc +int_post_dec +FloatPlus +FloatMinus +FloatTimes +FloatDivide +float_and +float_or +float_eq +float_neq +float_gt +float_ge +float_lt +float_le +float_negate +float_not +float_r_assign +float_r_plus +float_r_minus +float_r_mul +float_r_div +int_float_plus +int_float_minus +int_float_mul +int_float_div +int_float_and +int_float_or +int_float_eq +int_float_neq +int_float_gt +int_float_ge +int_float_lt +int_float_le +int_float_r_assign +int_float_r_plus +int_float_r_minus +int_float_r_mul +int_float_r_div +float_int_plus +float_int_minus +float_int_mul +float_int_div +float_int_and +float_int_or +float_int_eq +float_int_neq +float_int_gt +float_int_ge +float_int_lt +float_int_le +float_int_r_assign +float_int_r_plus +float_int_r_minus +float_int_r_mul +float_int_r_div +CastI2F +CastF2I +Time_Advance +FuncUsr +FuncMember +FuncStatic +SporkIni +SporkFunc +SporkThis +SporkExp +SporkEnd +FuncPtr +BranchEqInt +BranchNeqInt +BranchEqFloat +BranchNeqFloat +DecIntAddr +InitLoopCounter +ObjectInstantiate +RegAddRef +ObjectAssign +ObjectRelease +GWOP_EXCEPT +AllocMember4 +DotMember +DotMember2 +DotMember3 +DotMember4 +DotStatic +DotStatic2 +DotStatic3 +DotFunc +PushStaticCode +RegPushStr +GcIni +GcAdd +GcEnd +Gack +OP_MAX diff --git a/opt/constant.c b/opt/constant.c index 668684026..f996c3020 100644 --- a/opt/constant.c +++ b/opt/constant.c @@ -5,11 +5,10 @@ #include "type.h" #include "constant.h" -#define describe_constant_xxx(name, etype, mtype) \ -ANN m_bool constant_##name(const Exp e) { \ - return (e->exp_type == ae_exp_primary && \ - e->d.exp_primary.primary_type == ae_primary_##etype) || \ - (e->exp_type == ae_exp_constprop && isa(e->type , mtype) > 0); \ +#define describe_constant_xxx(name, etype, mtype) \ +ANN m_bool constant_##name(const Exp e) { \ + return (e->exp_type == ae_exp_primary && \ + e->d.exp_primary.primary_type == ae_primary_##etype); \ } describe_constant_xxx(int, num, t_int) describe_constant_xxx(float, float, t_float) diff --git a/opt/optim.c b/opt/optim.c index dfed7639e..b5ba91593 100644 --- a/opt/optim.c +++ b/opt/optim.c @@ -7,83 +7,6 @@ #include "optim.h" #include "constant.h" -void constprop_prim(const Exp_Primary* p, m_uint* ptr) { - Exp_Primary* e = (Exp_Primary*)p; - e->primary_type = ae_primary_constprop; - e->d.num = (m_uint)ptr; // improve me -} - -ANN static m_bool is_constprop_value(const Exp e) { - if (e->exp_type == ae_exp_decl - && isa(e->d.exp_decl.list->self->value->type, t_int) > 0 && - !e->d.exp_decl.list->self->value->type->array_depth && - !e->d.exp_decl.list->self->value->owner_class && - !GET_FLAG(e->d.exp_decl.list->self->value, arg)) - return (e->exp_type == ae_exp_primary && - e->d.exp_primary.primary_type == ae_primary_id && - isa(e->type, t_int) > 0 && - !e->d.exp_primary.value->owner_class) || - e->exp_type == ae_exp_constprop2; - return 0; -} - -ANN static void constprop_exp(const Exp_Binary* bin, long num) { - const Exp e = bin->self, l = bin->lhs, r = bin->rhs; - e->exp_type = ae_exp_constprop; - e->d.exp_primary.d.num = num; - free_exp(l); - free_exp(r); -} - -ANN static void constprop_value(const Value v, const long num) { - v->d.ptr = (m_uint*)num; //fixme - SET_FLAG(v, constprop); -} - -ANN static m_bool constant_propagation(const Exp_Binary* bin) { - const Exp l = bin->lhs, r = bin->rhs; - switch(bin->op) { - case op_chuck: - if(isa(r->type, t_function) < 0) { - if(is_constprop_value(r)) { - if(constant_int(l)) { -if(r->d.exp_primary.primary_type == ae_primary_num) { - constprop_value(r->d.exp_primary.value, - l->d.exp_primary.d.num); - constprop_exp(bin, l->d.exp_primary.d.num); -} - else if(r->exp_type == ae_exp_decl) { - SET_FLAG(r->d.exp_decl.list->self->value, constprop); - *(m_uint*)r->d.exp_decl.list->self->value->d.ptr = l->d.exp_primary.d.num; - } - return GW_OK; - } - } - } /* fallthrough */ - case op_radd: - case op_rsub: - case op_rmul: - case op_rdiv: - case op_rmod: - case op_rsl: - case op_rsr: - case op_rsand: - case op_rsor: - case op_rsxor: - case op_ref: - case op_unref: - case op_trig: - case op_untrig: - if(r->exp_type == ae_exp_constprop2) { - r->d.exp_primary.value->d.ptr = 0; - UNSET_FLAG(r->d.exp_primary.value, constprop); - } - default: break; - } - return GW_OK; -} - m_bool optimize_const(const Exp_Binary* bin) { - constant_propagation(bin); return constant_folding(bin); } diff --git a/src/arg.c b/src/arg.c index ba4ceff98..6d51f2f00 100644 --- a/src/arg.c +++ b/src/arg.c @@ -1,27 +1,24 @@ -#include -#include #include #include #include "gwion_util.h" -#include "gwion_ast.h" -#include "map_private.h" -#include "arg.h" #include "oo.h" #include "vm.h" #include "driver.h" +#include "arg.h" -ANN void arg_init(Arg* arg) { +ANN static void arg_init(Arg* arg) { vector_init(&arg->add); vector_init(&arg->rem); vector_init(&arg->lib); + vector_init(&arg->mod); vector_add(&arg->lib, (vtype)GWPLUG_DIR); - arg->ref = &arg->add; } ANN void arg_release(Arg* arg) { vector_release(&arg->add); vector_release(&arg->rem); vector_release(&arg->lib); + vector_release(&arg->mod); } static const struct option long_option[] = { @@ -48,6 +45,7 @@ static const struct option long_option[] = { { "help", 0, NULL, '?' }, { "version", 0, NULL, 'v' }, { "config", 0, NULL, 'C' }, + { "module", 0, NULL, 'm' }, /* { "status" , 0, NULL, '%' },*/ { NULL, 0, NULL, 0 } }; @@ -79,16 +77,17 @@ static const char usage[] = ; ANN static void arg_add(Arg* arg) { + Vector ref = &arg->add; while(optind < arg->argc) { m_str str = arg->argv[optind++]; if(!strcmp(str, "-")) { - arg->ref = &arg->rem; + ref = &arg->rem; str = arg->argv[optind++]; } else if(!strcmp(str, "+")) { - arg->ref = &arg->add; + ref = &arg->add; str = arg->argv[optind++]; } - vector_add(arg->ref, (vtype)str); + vector_add(ref, (vtype)str); } } @@ -134,9 +133,11 @@ ANN static void arg_drvr(DriverInfo* di, const int i) { } } -ANN void parse_args(Arg* arg, DriverInfo* di) { +ANN uint parse_args(Arg* arg, DriverInfo* di) { + uint quit = 0; int i, index; - while((i = getopt_long(arg->argc, arg->argv, "?vqh:p:i:o:n:b:e:s:d:l:g:-:rc:f:P:C ", + arg_init(arg); + while((i = getopt_long(arg->argc, arg->argv, "?vqh:p:i:o:n:b:e:s:d:l:g:-:rc:f:m:P:C ", long_option, &index)) != -1) { switch(i) { case '?': @@ -147,7 +148,7 @@ ANN void parse_args(Arg* arg, DriverInfo* di) { exit(1); break; case 'q': - arg->quit = 1; + quit = 1; break; case 'l': arg->loop = strtol(optarg, NULL, 10) > 0 ? 1 : -1; @@ -155,9 +156,13 @@ ANN void parse_args(Arg* arg, DriverInfo* di) { case 'P': vector_add(&arg->lib, (vtype)optarg); break; + case 'm': + vector_add(&arg->mod, (vtype)optarg); + break; default: arg_drvr(di, i); } } arg_add(arg); + return quit; } diff --git a/src/compile.c b/src/compile.c index 14f7f5bd4..5e3b1fba1 100644 --- a/src/compile.c +++ b/src/compile.c @@ -74,7 +74,7 @@ static m_uint compile(struct Gwion_* gwion, struct Compiler* c) { gw_err("while compiling file '%s'\n", c->base); else { const VM_Shred shred = new_vm_shred(code); - shred->args = c->args; + shred->info->args = c->args; xid = vm_add_shred(gwion->vm, shred); } compiler_clean(c); diff --git a/src/emit/emit.c b/src/emit/emit.c index bbd7b511e..6dab88398 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -86,12 +86,11 @@ ANN static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool add_ref); ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop); ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List list); ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member); -ANN static m_bool emit_func_def(const Emitter emit, const Func_Def func_def); +ANN /*static */m_bool emit_func_def(const Emitter emit, const Func_Def func_def); ANEW static Code* new_code(const Emitter emit, const m_str name) { Code* code = mp_alloc(Code); code->name = code_name_set(name, emit->env->name); - code->stack_depth = 0; vector_init(&code->instr); vector_init(&code->stack_break); vector_init(&code->stack_cont); @@ -143,21 +142,15 @@ ANN static inline m_uint emit_local(const Emitter emit, const m_uint size, const return frame_local(emit->code->frame, size, is_obj); } -ANN static void emit_pre_ctor_inner(const Emitter emit, const Type type) { GWDEBUG_EXE - const Instr instr = emit_add_instr(emit, PreCtor); - instr->m_val = (m_uint)type->nspc->pre_ctor; - instr->m_val2 = (m_uint)emit_code_offset(emit); -} - ANN static void emit_pre_ctor(const Emitter emit, const Type type) { GWDEBUG_EXE if(type->parent) emit_pre_ctor(emit, type->parent); if(type->nspc->pre_ctor) - emit_pre_ctor_inner(emit, type); + emit_ext_ctor(emit, type->nspc->pre_ctor); if(GET_FLAG(type, template) && GET_FLAG(type, builtin)) { const Type t = template_parent(type); if(t->nspc->pre_ctor) - emit_pre_ctor_inner(emit, t); + emit_ext_ctor(emit, t->nspc->pre_ctor); } } @@ -183,7 +176,7 @@ ANN ArrayInfo* emit_array_extend_inner(const Emitter emit, const Type t, const E info->depth = (m_int)t->array_depth; info->base = base; const Instr alloc = emit_add_instr(emit, ArrayAlloc); - *(ArrayInfo**)alloc->ptr = info; + alloc->m_val = (m_uint)info; if(isa(base, t_object) > 0) { emit_pre_constructor_array(emit, base); info->is_obj = 1; @@ -195,9 +188,9 @@ ANN void emit_ext_ctor(const Emitter emit, const VM_Code code) { GWDEBUG_EXE emit_add_instr(emit, RegDup); const Instr push_f = emit_add_instr(emit, RegPushImm); push_f->m_val = (m_uint)code; - const Instr offset = emit_add_instr(emit, RegPushImm); + const Instr offset = emit_add_instr(emit, RegSetImm); offset->m_val = emit_code_offset(emit); - emit_add_instr(emit, FuncMember); + emit_add_instr(emit, !GET_FLAG(code, builtin) ? FuncUsr : FuncMember); } ANN m_bool emit_array_extend(const Emitter emit, const Type t, const Exp e) { GWDEBUG_EXE @@ -209,7 +202,8 @@ ANN m_bool emit_array_extend(const Emitter emit, const Type t, const Exp e) { GW ANN2(1,2) m_bool emit_instantiate_object(const Emitter emit, const Type type, const Array_Sub array, const uint is_ref) { if(type->array_depth) { - assert(array && array->exp); + assert(array); + assert(array->exp); ArrayInfo* info = emit_array_extend_inner(emit, type, array->exp); CHECK_OB(info) info->is_ref = !!is_ref; @@ -234,14 +228,12 @@ ANN static Instr emit_kind(Emitter emit, const m_uint size, const uint addr, con return instr; } -static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushDeref }; // caution last -static const f_instr regpushderef[] = { RegPushDeref, RegPushDeref2, RegPushDeref3, RegPushDeref }; // caution last +static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 }; static const f_instr regpushmem[] = { RegPushMem, RegPushMem2, RegPushMem3, RegPushMem4 }; static const f_instr regpushbase[] = { RegPushBase, RegPushBase2, RegPushBase3, RegPushBase4 }; -static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, DotStatic4 }; -static const f_instr dotimport[] = { DotImport, DotImport2, DotImport3, DotImport4 }; +static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm }; static const f_instr dotmember[] = { DotMember, DotMember2, DotMember3, DotMember4 }; -static const f_instr allocmember[] = { PushNull, PushNull2, PushNull3, AllocMember4 }; +static const f_instr allocmember[] = { RegPushImm, RegPushImm2, RegPushImm3, AllocMember4 }; static const f_instr allocword[] = { AllocWord, AllocWord2, AllocWord3, AllocWord4 }; ANN static m_bool emit_symbol_owned(const Emitter emit, const Exp_Primary* prim) { GWDEBUG_EXE @@ -266,18 +258,22 @@ ANN static m_bool emit_symbol_builtin(const Emitter emit, const Exp_Primary* pri } if(GET_FLAG(v, union)) { const m_uint size = v->type->size; - const Instr instr = emit_kind(emit, size, prim->self->emit_var, regpushderef); - *(m_uint*)instr->ptr = (m_uint)v->d.ptr; + const Instr instr = emit_kind(emit, size, prim->self->emit_var, dotstatic); + instr->m_val = (m_uint)v->d.ptr; } else { const m_uint size = v->type->size; const Instr instr = emit_kind(emit, size, prim->self->emit_var, regpushimm); - if(size == SZ_INT) { - instr->execute = RegPushImm; - instr->m_val = (m_uint)v->d.ptr; + if(!prim->self->emit_var && size == SZ_INT) { + if(isa(v->type, t_object) > 0) { + instr->execute = RegPushImm; + instr->m_val = (m_uint)v->d.ptr; + } else if(v->d.ptr) + instr->m_val = *(m_uint*)v->d.ptr; } else if(v->d.ptr) - memcpy(instr->ptr, v->d.ptr, v->type->size); + memcpy(&instr->m_val, v->d.ptr, v->type->size); else - *(m_uint**)instr->ptr = v->d.ptr; + instr->m_val = (m_uint)v->d.ptr; + instr->m_val2 = size; } return GW_OK; } @@ -286,8 +282,7 @@ ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary* prim) { GWD const Value v = prim->value; if(v->owner_class) return emit_symbol_owned(emit, prim); - if(GET_FLAG(v, builtin) || GET_FLAG(v, enum) || - GET_FLAG(v, union)) + if(GET_FLAG(v, builtin) || GET_FLAG(v, union)) return emit_symbol_builtin(emit, prim); const m_uint size = v->type->size; const Instr instr = emit_kind(emit, size, prim->self->emit_var, !GET_FLAG(v, global) ? regpushmem : regpushbase); @@ -298,7 +293,7 @@ ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary* prim) { GWD ANEW ANN VM_Code emit_code(const Emitter emit) { GWDEBUG_EXE Code* c = emit->code; const VM_Code code = new_vm_code(&c->instr, c->stack_depth, - GET_FLAG(c, member), c->name); + c->flag, c->name); free_code(c); return code; } @@ -319,10 +314,12 @@ ANN static m_bool prim_array(const Emitter emit, const Exp_Primary * primary) { while((e = e->next)); const Type type = array->type; const Type base = array_base(type); + const Instr push = emit_add_instr(emit, RegSetImm); + push->m_val = count; const Instr instr = emit_add_instr(emit, ArrayInit); - instr->m_val = count; + instr->m_val = (m_uint)type; instr->m_val2 = base->size; - *(Type*)instr->ptr = type; + emit_add_instr(emit, GcAdd); return GW_OK; } @@ -343,11 +340,12 @@ ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) { G instr->m_val = is_var; instr->m_val2 = is_var ? SZ_INT : array->self->type->size; } else { + const Instr push = emit_add_instr(emit, RegSetImm); + push->m_val = depth; const Instr instr = emit_add_instr(emit, ArrayAccessMulti); instr->m_val = is_var || array->self->type->array_depth; instr->m_val2 = (is_var || array->self->type->array_depth) ? SZ_INT : array_base(array->base->type)->size; - *(m_uint*)instr->ptr = depth; } return GW_OK; } @@ -358,7 +356,16 @@ ANN static m_bool prim_vec(const Emitter emit, const Exp_Primary * primary) { GW CHECK_BB(emit_exp(emit, vec->exp, 0)); m_int n = (m_int)((t == ae_primary_vec ? 3 : 2) - vec->dim + 1); while(--n > 0) - emit_add_instr(emit, PushNull2); + emit_add_instr(emit, RegPushImm2); + if(primary->self->emit_var) { + emit_local(emit, primary->self->type->size, 0); + const m_uint offset = emit_local(emit, SZ_INT, 0); + const Instr cpy = emit_add_instr(emit, VecCpy); + cpy->m_val = offset; + cpy->m_val2 = primary->self->type->size; + const Instr instr = emit_add_instr(emit, RegPushMem); + instr->m_val = offset; + } return GW_OK; } @@ -389,7 +396,7 @@ ANN static m_bool prim_num(const Emitter emit, const Exp_Primary * primary) { ANN static m_bool prim_float(const Emitter emit, const Exp_Primary* primary) { const Instr instr = emit_add_instr(emit, RegPushImm2); - *(m_float*)instr->ptr = primary->d.fnum; + instr->f = primary->d.fnum; return GW_OK; } @@ -426,40 +433,26 @@ ANN static m_bool prim_gack(const Emitter emit, const Exp_Primary* primary) { ERR_B(exp->pos, "\t... in 'gack' expression.") } const Instr instr = emit_add_instr(emit, Gack); - *(Vector*)instr->ptr = v; instr->m_val = offset; + instr->m_val2 = (m_uint)v; return GW_OK; } -#ifdef OPTIMIZE -ANN static m_bool prim_constprop(Emitter emit, const Exp_Primary* prim) { - const Instr instr = emit_add_instr(emit, ConstPropSet); - instr->m_val = prim->value->offset; - instr->m_val2 = prim->d.num; - *(m_bool*)instr->ptr = prim->self->emit_var; - return GW_OK; -} -#endif - static const _exp_func prim_func[] = { (_exp_func)prim_id, (_exp_func)prim_num, (_exp_func)prim_float, (_exp_func)prim_str, (_exp_func)prim_array, (_exp_func)prim_gack, (_exp_func)prim_vec, (_exp_func)prim_vec, (_exp_func)prim_vec, (_exp_func)prim_char, (_exp_func)dummy_func, -#ifdef OPTIMIZE - (_exp_func)prim_constprop -#endif }; ANN static m_bool emit_exp_primary(const Emitter emit, const Exp_Primary* prim) { GWDEBUG_EXE return prim_func[prim->primary_type](emit, prim); } -ANN static m_bool emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) { GWDEBUG_EXE - const Instr push = emit_add_instr(emit, RegPushImm); - push->m_val = (m_uint)v->owner_class; +ANN static m_bool emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) { GWDEBUG_EXE const m_uint size = v->type->size; const Instr instr = emit_kind(emit, size, emit_var, dotstatic); - instr->m_val = v->offset; + instr->m_val = (m_uint)(v->owner_class->nspc->class_data + v->offset); + instr->m_val2 = size; return GW_OK; } @@ -495,15 +488,44 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Var_Decl va f_instr *exec = (f_instr*)allocmember; if(!GET_FLAG(v, member)) { v->offset = emit_local(emit, v->type->size, is_obj); - exec = (f_instr*)allocword; + exec = (f_instr*)(allocword); } const Instr instr = emit_kind(emit, v->type->size, emit_addr, exec); instr->m_val = v->offset; + instr->m_val2 = v->type->size; + if(is_obj && (is_array || !is_ref)) { + const Instr assign = emit_add_instr(emit, ObjectAssign); + assign->m_val = (m_uint)emit_var; + if(is_array && !emit->env->scope) + ADD_REF(type) + } + return GW_OK; +} + +ANN static m_bool emit_exp_decl_global(const Emitter emit, const Var_Decl var_decl, + const uint is_ref, const uint emit_var) { GWDEBUG_EXE + const Value v = var_decl->value; + const Type type = v->type; + const Array_Sub array = var_decl->array; + const m_bool is_array = array && array->exp; + const m_bool is_obj = isa(type, t_object) > 0; + const uint emit_addr = ((is_ref && !array) || isa(type, t_object) < 0) ? + emit_var : 1; + if(is_obj && (is_array || !is_ref)) + CHECK_BB(emit_instantiate_object(emit, type, array, is_ref)) + f_instr *exec = (f_instr*)dotstatic; + const Instr instr = emit_kind(emit, v->type->size, emit_addr, exec); + v->d.ptr = _mp_alloc(v->type->size); + SET_FLAG(v, union); + instr->m_val = (m_uint)v->d.ptr; + instr->m_val2 = v->type->size; if(is_obj && (is_array || !is_ref)) { const Instr assign = emit_add_instr(emit, ObjectAssign); assign->m_val = (m_uint)emit_var; if(is_array && !emit->env->scope) ADD_REF(type) + const Instr instr = emit_add_instr(emit, RegAddRef); + instr->m_val = emit_var; } return GW_OK; } @@ -537,8 +559,10 @@ ANN static m_bool emit_exp_decl(const Emitter emit, const Exp_Decl* decl) { GWDE continue; if(GET_FLAG(decl->td, static)) CHECK_BB(emit_exp_decl_static(emit, list->self, r)) - else + else if(!global) CHECK_BB(emit_exp_decl_non_static(emit, list->self, r, var)) +else + CHECK_BB(emit_exp_decl_global(emit, list->self, r, var)) } while((list = list->next)); if(global) emit_pop(emit, scope); @@ -595,7 +619,7 @@ ANN static inline m_int push_tmpl_func(const Emitter emit, const Func f, ANN static m_bool emit_exp_call_template(const Emitter emit, const Exp_Call* exp_call) { if(emit->env->func && emit->env->func == exp_call->m_func) return prepare_call(emit, exp_call); - m_int scope = push_tmpl_func(emit, exp_call->m_func, exp_call->tmpl->types); + const m_int scope = push_tmpl_func(emit, exp_call->m_func, exp_call->tmpl->types); CHECK_BB(scope); CHECK_BB(prepare_call(emit, exp_call)) emit_pop_type(emit); @@ -648,39 +672,87 @@ ANN static m_bool emit_exp_dur(const Emitter emit, const Exp_Dur* dur) { GWDEBUG return GW_OK; } +ANN static m_bool is_special(const Type t) { + if(isa(t, t_complex) > 0 || isa(t, t_polar) > 0 || + isa(t, t_vec3) > 0 || isa(t, t_vec4) > 0 || + isa(t, t_vararg) > 0) + return GW_OK; + return GW_ERROR; +} + +ANN static Type_List tmpl_tl(const Env env, const m_str name) { + const m_str start = strchr(name, '<'); + const m_str end = strchr(name, '@'); + char c[strlen(name)]; + strcpy(c, start + 1); + c[strlen(start) - strlen(end) - 2] = '\0'; + m_uint depth; + return str2tl(env, c, &depth); +} + static inline m_bool push_func_code(const Emitter emit, const Func f) { - const Instr back = (Instr)vector_back(&emit->code->instr); - if(back->execute == RegPushBase) { - back->execute = RegPushImm; - back->m_val = (m_uint)f->code; + if(GET_FLAG(f, template) && f->value_ref->owner_class) { + const Instr _instr = (Instr)vector_back(&emit->code->instr); +assert(_instr->execute == DotTmpl); + size_t len = strlen(f->name); + size_t sz = len - strlen(f->value_ref->owner_class->name); + char c[sz + 1]; + strncpy(c, f->name, sz); + c[sz] = '\0'; + struct dottmpl_ *dt = mp_alloc(dottmpl); + dt->name = s_name(insert_symbol(c)); + dt->overload = f->def->tmpl->base; + dt->tl = tmpl_tl(emit->env, c); + dt->base = f->def; + _instr->m_val = (m_uint)dt; + _instr->m_val2 = strlen(c); return GW_OK; } - const Instr instr = emit_add_instr(emit, RegPushPtr); - return !!(instr->m_val = (m_uint)f->code); + const Instr _instr = (Instr)vector_back(&emit->code->instr); + if(_instr->opcode == (m_bit)(m_uint)RegPushImm) + return !!(_instr->m_val = (m_uint)f->code); + assert(_instr->opcode == (m_bit)(m_uint)RegPushBase); + _instr->m_val = (m_uint)f->code; + _instr->opcode = (m_bit)(m_uint)RegPushImm; + return GW_OK; } static m_bool emit_template_code(const Emitter emit, const Func f) { if(GET_FLAG(f, ref)) CHECK_BB(traverse_template(emit->env, f->value_ref->owner_class->def)) - CHECK_BB(emit_func_def(emit, f->def)) + const Value v = f->value_ref; + size_t scope = emit_push(emit, v->owner_class, v->owner); + CHECK_BB(emit_func_def(emit, f->def)) // orig + emit_pop(emit, scope); return push_func_code(emit, f); } ANN static Instr emit_call(const Emitter emit, const Func f) { MEMOIZE_CALL const Type t = actual_type(f->value_ref->type); - const f_instr exec = isa(t, t_fptr) < 0 ? GET_FLAG(f->def, builtin) ? - GET_FLAG(f, member) ? FuncMember : FuncStatic : FuncUsr : FuncPtr; - return emit_add_instr(emit, exec); + if(isa(t, t_fptr) < 0) { + const f_instr exec = GET_FLAG(f->def, builtin) ? GET_FLAG(f, member) ? + FuncMember : FuncStatic : FuncUsr; + return emit_add_instr(emit, exec); + } + /*const Instr ex = */emit_add_instr(emit, GWOP_EXCEPT); +// ex->m_val = -SZ_INT; + return emit_add_instr(emit, FuncPtr); } ANN m_bool emit_exp_call1(const Emitter emit, const Func f) { GWDEBUG_EXE if(!f->code || (GET_FLAG(f, ref) && !GET_FLAG(f, builtin))) { if(GET_FLAG(f, template) && emit->env->func != f) CHECK_BB(emit_template_code(emit, f)) - } else + } else if((f->value_ref->owner_class && is_special(f->value_ref->owner_class) > 0) || + !f->value_ref->owner_class || GET_FLAG(f, template)) push_func_code(emit, f); - const Instr offset = emit_add_instr(emit, RegPushImm); + else { + const Instr back = (Instr)vector_back(&emit->code->instr); + if((f_instr)back->opcode == DotFunc) + back->m_val = f->vt_index; + } + const Instr offset = emit_add_instr(emit, RegSetImm); offset->m_val = emit_code_offset(emit); const Instr instr = emit_call(emit, f); const m_uint size = instr->m_val = f->def->ret_type->size; @@ -689,9 +761,25 @@ ANN m_bool emit_exp_call1(const Emitter emit, const Func f) { GWDEBUG_EXE ANN2(1,2) static m_bool emit_exp_spork_finish(const Emitter emit, const VM_Code code, const m_uint depth, const m_bool f) { - const Instr spork = emit_add_instr(emit, f ? SporkExp : SporkFunc); - spork->m_val = depth; - spork->m_val2 = (m_uint)code; + const Instr ini = emit_add_instr(emit, SporkIni); + ini->m_val = (m_uint)code; + if(!f) { + const m_uint member = GET_FLAG(code, member) ? SZ_INT : 0; + const Instr pop = emit_add_instr(emit, RegPop); + pop->m_val = depth + member; + if(depth) { + const Instr spork = emit_add_instr(emit, SporkFunc); + spork->m_val = depth; + } + if(member) { + const Instr m = emit_add_instr(emit, SporkThis); + m->m_val = depth; + } + } else { + const Instr spork = emit_add_instr(emit, SporkExp); + spork->m_val = depth; + } + emit_add_instr(emit, SporkEnd); return GW_OK; } @@ -733,9 +821,8 @@ ANN static m_bool spork_func(const Emitter emit, const Exp_Call* exp) { GWDEBUG_ push_spork_code(emit, SPORK_FUNC_PREFIX, exp->self->pos); if(GET_FLAG(exp->m_func, member)) SET_FLAG(emit->code, member); - const Instr op = emit_add_instr(emit, MemPushImm); - op->m_val = emit->code->stack_depth; - emit_add_instr(emit, RegPushImm); // should push func + const Instr p = emit_add_instr(emit, RegPushImm); + p->m_val = (m_uint)exp->m_func->code; CHECK_BB(emit_exp_call1(emit, exp->m_func)) const VM_Code code = finalyze(emit); const m_uint size = exp->m_func->def->stack_depth - (GET_FLAG(exp->m_func, @@ -746,7 +833,7 @@ ANN static m_bool spork_func(const Emitter emit, const Exp_Call* exp) { GWDEBUG_ ANN static m_bool spork_code(const Emitter emit, const Stmt stmt) { GWDEBUG_EXE emit_add_instr(emit, RegPushImm); push_spork_code(emit, SPORK_CODE_PREFIX, stmt->pos); - if(SAFE_FLAG(emit->env->func, member)) + if(!SAFE_FLAG(emit->env->func, member)) stack_alloc_this(emit); CHECK_BB(scoped_stmt(emit, stmt, 0)) const VM_Code code = finalyze(emit); @@ -776,10 +863,8 @@ ANN static m_bool emit_implicit_cast(const Emitter emit, ANN static Instr emit_flow(const Emitter emit, const Type type, const f_instr f1, const f_instr f2) { GWDEBUG_EXE if(isa(type, t_float) > 0) { - emit_add_instr(emit, PushNull2); return emit_add_instr(emit, f2); } - emit_add_instr(emit, PushNull); return emit_add_instr(emit, f1); } @@ -794,28 +879,6 @@ ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If* exp_if) { GWDEBU return ret; } -#ifdef OPTIMIZE -ANN static void emit_exp_constprop(const Emitter emit, const Exp e) { - if(!e->emit_var) { - if(e->exp_type == ae_exp_constprop) { - const Instr instr = emit_add_instr(emit, RegPushMem); - instr->m_val = e->d.exp_primary.value->offset; - *(m_uint*)instr->ptr = GET_FLAG(e->d.exp_primary.value, global); - return; - } - const Instr instr = emit_add_instr(emit, ConstPropGet); - instr->m_val2 = e->d.exp_primary.value->offset; - instr->m_val = e->d.exp_primary.d.num; - *(m_uint*)instr->ptr = 1; - } else { - const Instr instr = emit_add_instr(emit, ConstPropSet); - instr->m_val = e->d.exp_primary.value->offset; - *(m_bool*)instr->ptr = 1; - instr->m_val2 = e->d.exp_primary.d.num; - } -} -#endif - DECL_EXP_FUNC(emit) ANN2(1) static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) { GWDEBUG_EXE @@ -882,6 +945,8 @@ ANN static m_bool emit_stmt_return(const Emitter emit, const Stmt_Exp stmt) { GW if(stmt->val) { OPTIMIZE_TCO CHECK_BB(emit_exp(emit, stmt->val, 0)) + if(isa(stmt->val->type, t_object) > 0) + emit_add_instr(emit, RegAddRef); } vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto)); return GW_OK; @@ -1002,13 +1067,17 @@ ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) { GWD s2->m_val = stmt->v->offset = offset + SZ_INT; CHECK_BB(emit_stmt(emit, stmt->body, 1)) const m_uint end_pc = emit_code_size(emit); + if(stmt->is_ptr) { + const Instr release = emit_add_instr(emit, ObjectRelease); + release->m_val = offset + SZ_INT; + } const Instr end = emit_add_instr(emit, AutoLoopEnd); const Instr tgt = emit_add_instr(emit, Goto); - *(m_uint*)end->ptr = emit_code_size(emit); + end->m_val2 = emit_code_size(emit); tgt->m_val = ini_pc; s1->m_val = end->m_val = loop->m_val = offset; if(stmt->is_ptr) - end->m_val2 = loop->m_val2 = (m_uint)stmt->v->type; + loop->m_val2 = (m_uint)stmt->v->type; emit_pop_stack(emit, end_pc); return GW_OK; } @@ -1020,10 +1089,9 @@ ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) { GWD const Instr init = emit_add_instr(emit, InitLoopCounter); init->m_val = (m_uint)counter; const m_uint index = emit_code_size(emit); - const Instr deref = emit_add_instr(emit, RegPushDeref); + const Instr deref = emit_add_instr(emit, DotStatic); + deref->m_val = (m_uint)counter; deref->m_val2 = SZ_INT; - *(m_int**)deref->ptr = counter; - emit_add_instr(emit, PushNull); const Instr op = emit_add_instr(emit, BranchEqInt); const Instr dec = emit_add_instr(emit, DecIntAddr); dec->m_val = (m_uint)counter; @@ -1072,7 +1140,9 @@ ANN static m_bool emit_switch_instr(const Emitter emit, Instr *instr) { while((e = switch_expget(emit->env))) CHECK_BB(emit_exp(emit, e, 0)) *instr = emit_add_instr(emit, SwitchIni); - (*instr)->m_val = (m_uint)switch_vec(emit->env); + } else { + const Instr instr = emit_add_instr(emit, RegSetImm); + instr->m_val = (m_uint)switch_map(emit->env); } return GW_OK; } @@ -1080,23 +1150,23 @@ ANN static m_bool emit_switch_instr(const Emitter emit, Instr *instr) { ANN static void emit_switch_map(const Instr instr, const Map map) { const Map m = new_map(); for(m_uint i = map_size(map) + 1; --i;) - map_set(m, VKEY(map, i), VVAL(map, i -1)); + map_set(m, VKEY(map, i-1), VVAL(map, i -1)); instr->m_val2 = (m_uint)m; } ANN static m_bool emit_stmt_switch(const Emitter emit, const Stmt_Switch stmt) { GWDEBUG_EXE switch_get(emit->env, stmt); Instr push = NULL; + CHECK_BB(emit_exp(emit, stmt->val, 0)) CHECK_BB(emit_switch_instr(emit, &push)) vector_add(&emit->code->stack_break, (vtype)NULL); - CHECK_BB(emit_exp(emit, stmt->val, 0)) const Instr instr = emit_add_instr(emit, BranchSwitch); instr->m_val2 = (m_uint)switch_map(emit->env); - CHECK_BB(scoped_stmt(emit, stmt->stmt, 1)) + CHECK_BB(emit_stmt(emit, stmt->stmt, 1)) instr->m_val = switch_idx(emit->env) ?: emit_code_size(emit); if(push) { emit_switch_map(push, (Map)instr->m_val2); - *(m_uint*)instr->ptr = SZ_INT; + (push)->m_val = (m_uint)switch_vec(emit->env); } switch_end(emit->env); pop_vector(&emit->code->stack_break, emit_code_size(emit)); @@ -1184,8 +1254,6 @@ ANN static m_bool emit_stmt_union(const Emitter emit, const Stmt_Union stmt) { G exp->d.exp_decl.type = stmt->value->type; var_decl->value = stmt->value; CHECK_BB(emit_exp_decl(emit, &exp->d.exp_decl)) -// if(!emit->env->class_def) -// ADD_REF(stmt->value->type); free_exp(exp); if(global) { const M_Object o = new_object(NULL, stmt->value->type); @@ -1251,14 +1319,6 @@ ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List l) { GWDEBUG_EXE return GW_OK; } -ANN static m_bool is_special(const Type t) { - if(isa(t, t_complex) > 0 || isa(t, t_polar) > 0 || - isa(t, t_vec3) > 0 || isa(t, t_vec4) > 0 || - isa(t, t_vararg) > 0) - return GW_OK; - return GW_ERROR; -} - ANN static m_bool emit_dot_static_import_data(const Emitter emit, const Value v, const uint emit_addr) { GWDEBUG_EXE if(v->d.ptr && GET_FLAG(v, builtin)) { // from C if(GET_FLAG(v, enum)) { @@ -1266,18 +1326,14 @@ ANN static m_bool emit_dot_static_import_data(const Emitter emit, const Value v, func_i->m_val = (m_uint)v->d.ptr; } else { const m_uint size = v->type->size; - const Instr instr = emit_kind(emit, size, emit_addr, dotimport); + const Instr instr = emit_kind(emit, size, emit_addr, regpushimm); instr->m_val = (isa(v->type, t_object) > 0 ? (m_uint)&v->d.ptr : (m_uint)v->d.ptr); + instr->m_val2 = size; } - } else { // from code - const Instr push_i = emit_add_instr(emit, RegPushImm); - push_i->m_val = (m_uint)v->owner_class; - const m_uint size = v->type->size; - const Instr instr = emit_kind(emit, size, emit_addr, dotstatic); - instr->m_val = v->offset; + return GW_OK; } - return GW_OK; + return emit_dot_static_data(emit, v, emit_addr); } ANN static m_bool emit_complex_member(const Emitter emit, const Exp_Dot* member) { GWDEBUG_EXE @@ -1288,15 +1344,14 @@ ANN static m_bool emit_complex_member(const Emitter emit, const Exp_Dot* member) s_name(member->xid)); if(is_complex && member->self->emit_var) // skip return GW_OK; - const Instr instr = is_complex ? emit_add_instr(emit, ComplexReal) : - emit_add_instr(emit, ComplexImag); + const Instr instr = emit_add_instr(emit, is_complex ? ComplexReal : ComplexImag); instr->m_val = member->self->emit_var; return GW_OK; } ANN static inline void emit_vec_func(const Emitter emit, const Value v) { const Instr instr = emit_add_instr(emit, RegPushImm); - instr->m_val = (m_uint)((Func)vector_at(&v->owner_class->nspc->vtable, v->d.func_ref->vt_index))->code; + instr->m_val = (m_uint)v->d.func_ref->code; } ANN static m_bool emit_VecMember(const Emitter emit, const Exp_Dot* member) { @@ -1307,6 +1362,8 @@ ANN static m_bool emit_VecMember(const Emitter emit, const Exp_Dot* member) { emit_vec_func(emit, v); return GW_OK; } + if(!v->offset && member->self->emit_var) // skip + return GW_OK; const Instr instr = emit_add_instr(emit, VecMember); instr->m_val2 = v->offset; instr->m_val = member->self->emit_var; @@ -1329,7 +1386,6 @@ ANN static m_bool emit_vararg_end(const Emitter emit, const m_uint offset) { GWD instr->m_val = offset; instr->m_val2 = emit->env->func->variadic->m_val2; emit->env->func->variadic->m_val2 = emit_code_size(emit); - *(m_uint*)emit->env->func->variadic->ptr = 1; return GW_OK; } @@ -1361,26 +1417,43 @@ ANN static m_bool emit_exp_dot_special(const Emitter emit, const Exp_Dot* member } ANN static m_bool emit_dot_static_func(const Emitter emit, const Func func) { GWDEBUG_EXE - const Instr func_i = emit_add_instr(emit, RegPushImm); - func_i->m_val = (m_uint)func->code; +// if(func->code) { +// const Instr func_i = emit_add_instr(emit, RegPushImm); +// func_i->m_val = (m_uint)func->code; +// } else { + // TODO: improve me + const Instr func_i = emit_add_instr(emit, PushStaticCode); + func_i->m_val = (m_uint)func; +// } return GW_OK; } ANN static m_bool emit_member_func(const Emitter emit, const Exp_Dot* member, const Func func) { GWDEBUG_EXE - if(GET_FLAG(func, member)) { - if(emit_exp(emit, member->base, 0) < 0) - ERR_B(member->self->pos, "... in member function") // LCOV_EXCL_LINE - emit_add_instr(emit, RegDup); + if(emit_exp(emit, member->base, 0) < 0) + ERR_B(member->self->pos, "... in member function") // LCOV_EXCL_LINE + /*const Instr ex = */emit_add_instr(emit, GWOP_EXCEPT); + //ex->m_val = -SZ_INT; + if(GET_FLAG(member->base->type, force)) { + const Instr func_i = emit_add_instr(emit, RegPushImm); + func_i->m_val = (m_uint)func->code; + return GW_OK; + } + if(!func->def->tmpl) { const Instr func_i = emit_add_instr(emit, DotFunc); func_i->m_val = func->vt_index; + return GW_OK; } + emit_add_instr(emit, DotTmpl); return GW_OK; } ANN static inline void emit_member(const Emitter emit, const Value v, const uint emit_addr) { + /*const Instr ex = */emit_add_instr(emit, GWOP_EXCEPT); + //ex->m_val = -SZ_INT; const m_uint size = v->type->size; const Instr instr = emit_kind(emit, size, emit_addr, dotmember); instr->m_val = v->offset; + instr->m_val2 = size; } ANN static m_bool emit_exp_dot_instance(const Emitter emit, const Exp_Dot* member) { GWDEBUG_EXE @@ -1391,19 +1464,13 @@ ANN static m_bool emit_exp_dot_instance(const Emitter emit, const Exp_Dot* membe if(GET_FLAG(value, member)) { // member if(emit_exp(emit, member->base, 0) < 0) ERR_B(member->self->pos, "... in member function") // LCOV_EXCL_LINE - if(!GET_FLAG(value->type->d.func, global)) - emit_add_instr(emit, RegDup); emit_member(emit, value, emit_addr); return GW_OK; } else return emit_dot_static_data(emit, value, emit_addr); - } else if(isa(member->self->type, t_function) > 0) { // function - const Func func = value->d.func_ref; - if(GET_FLAG(func, member)) { - return emit_member_func(emit, member, func); - } else - return emit_dot_static_func(emit, func); - } else { // variable + } else if(isa(member->self->type, t_function) > 0) + return emit_member_func(emit, member, value->d.func_ref); + else { // variable if(GET_FLAG(value, member)) { // member CHECK_BB(emit_exp(emit, member->base, 0)) emit_member(emit, value, emit_addr); @@ -1432,7 +1499,7 @@ ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) { GWDE ANN static inline void emit_func_def_global(const Emitter emit, const Value value) { GWDEBUG_EXE const Instr set_mem = emit_add_instr(emit, MemSetImm); - set_mem->m_val = value->offset = emit_local(emit, value->type->size, 0); // size -> SZ_INT ? + set_mem->m_val = value->offset = emit_local(emit, SZ_INT, 0); set_mem->m_val2 = (m_uint)value->d.func_ref->code; } @@ -1456,10 +1523,8 @@ ANN static void emit_func_def_args(const Emitter emit, Arg_List a) { GWDEBUG_EXE ANN static void emit_func_def_ensure(const Emitter emit, const Func_Def func_def) { GWDEBUG_EXE const m_uint size = func_def->ret_type->size; if(size) { - if(size == SZ_INT) - emit_add_instr(emit, RegPushImm); - else - emit_kind(emit, size, 0, regpushimm); + const Instr instr = emit_kind(emit, size, 0, regpushimm); + instr->m_val2 = size; } vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto)); } @@ -1498,11 +1563,11 @@ ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def func_def return GW_OK; } -ANN static m_bool emit_func_def(const Emitter emit, const Func_Def func_def) { GWDEBUG_EXE +ANN /*static */m_bool emit_func_def(const Emitter emit, const Func_Def func_def) { GWDEBUG_EXE const Func func = get_func(emit->env, func_def); if(func->code)return GW_OK; if(tmpl_list_base(func_def->tmpl)) { // don't check template definition - UNSET_FLAG(func_def, template);; + UNSET_FLAG(func_def, template); return GW_OK; } if(SAFE_FLAG(emit->env->class_def, builtin) && GET_FLAG(emit->env->class_def, template)) @@ -1514,14 +1579,13 @@ ANN static m_bool emit_func_def(const Emitter emit, const Func_Def func_def) { G const Func former = emit->env->func; emit->env->func = func; CHECK_BB(emit_func_def_body(emit, func_def)) - if(GET_FLAG(func_def, variadic) && (!emit->env->func->variadic || - !*(m_uint*)emit->env->func->variadic->ptr)) + if(GET_FLAG(func_def, variadic) && !emit->env->func->variadic) ERR_B(func_def->td->xid->pos, "invalid variadic use") emit_func_def_return(emit); emit_func_def_code(emit, func); emit->env->func = former; emit_pop_code(emit); - if(!emit->env->class_def) + if(!emit->env->class_def && !GET_FLAG(func_def, global) && !func_def->tmpl) emit_func_def_global(emit, func->value_ref); MEMOIZE_INI return GW_OK; diff --git a/src/emit/emitter.c b/src/emit/emitter.c index 4c46f6430..f84b9ab53 100644 --- a/src/emit/emitter.c +++ b/src/emit/emitter.c @@ -23,7 +23,12 @@ ANN void free_emitter(Emitter a) { __attribute__((returns_nonnull)) ANN2(1) Instr emit_add_instr(const Emitter emit, const f_instr f) { const Instr instr = mp_alloc(Instr); - instr->execute = f; + if((m_uint)f < 255) + instr->opcode = (m_uint)f; + else { + instr->opcode = (m_uint)OP_MAX; + instr->execute = f; + } vector_add(&emit->code->instr, (vtype)instr); return instr; } diff --git a/src/emit/memoize.c b/src/emit/memoize.c index dee3664f4..08db52c03 100644 --- a/src/emit/memoize.c +++ b/src/emit/memoize.c @@ -70,15 +70,16 @@ static inline void memoize_set(Memoize m, const m_bit* arg) { } m_bool memoize_get(VM_Shred shred) { - const VM_Code code = *(VM_Code*)REG(-SZ_INT * 2); +// const VM_Code code = *(VM_Code*)REG(-SZ_INT * 2); + const VM_Code code = *(VM_Code*)REG(-SZ_INT); const Memoize m = code->memoize; - const m_bit* arg = REG(-(SZ_INT*2 + m->arg_sz + (m_uint)m->member)); + const m_bit* arg = REG(-(SZ_INT + m->arg_sz + (m_uint)m->member)); const m_uint size = vector_size(&m->v); for(m_uint i = 0; i < size; ++i) { m_bit* data = (m_bit*)vector_at(&m->v, i); if(memcmp(arg, data, m->arg_sz)) continue; - POP_REG(shred, SZ_INT*2 + (m->arg_sz - m->ret_sz) + (m_uint)m->member) + POP_REG(shred, SZ_INT + (m->arg_sz - m->ret_sz) + (m_uint)m->member) mreturn[m->kind](shred->reg-m->ret_sz, data + m->arg_sz, m->ret_sz); return GW_OK; } diff --git a/src/gwion.c b/src/gwion.c index d8ab56676..3a149cfd0 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -5,18 +5,59 @@ #include "env.h" #include "instr.h" #include "emit.h" +#include "engine.h" #include "gwion.h" +#include "arg.h" -ANN void gwion_init(const Gwion gwion) { + +#ifdef VMBENCH +#include +#include +#define VMBENCH_INI struct timespec ini, end, ret; \ + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ini); +#define VMBENCH_END clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); \ + timespecsub(&end, &ini, &ret); \ + printf("timespec %lu.%09lu\n", ret.tv_sec, ret.tv_nsec); +#else +#define VMBENCH_INI +#define VMBENCH_END +#endif + +ANN void gwion_init(const Gwion gwion, const Vector args) { gwion->vm = new_vm(); gwion->emit = new_emitter(); gwion->env = new_env(); gwion->emit->env = gwion->env; gwion->vm->gwion = gwion; gwion->env->gwion = gwion; + gwion->driver = (Driver*)xcalloc(1, sizeof(Driver)); + plug_ini(gwion->plug, args); +} + +ANN m_bool gwion_audio(const Gwion gwion, DriverInfo* di) { + di->func(gwion->driver); + VM* vm = gwion->vm; + return gwion->driver->ini(vm, di) > 0 && + (vm->bbq = new_bbq(di)); +} + +ANN m_bool gwion_engine(const Gwion gwion) { + return type_engine_init(gwion->vm, &gwion->plug[GWPLUG_IMPORT]) > 0; +} + +ANN void gwion_run(const Gwion gwion, DriverInfo* di) { + VM* vm = gwion->vm; + vm->is_running = 1; + VMBENCH_INI + gwion->driver->run(vm, di); + VMBENCH_END } -ANN void gwion_release(const Gwion gwion) { +ANN void gwion_release(const Gwion gwion, DriverInfo* di) { + if(gwion->driver->del) + gwion->driver->del(gwion->vm, di); + xfree(gwion->driver); + plug_end(gwion); free_env(gwion->env); free_emitter(gwion->emit); free_vm(gwion->vm); diff --git a/src/lib/array.c b/src/lib/array.c index 550fcbf0f..7793b9cdd 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -28,12 +28,26 @@ ANN m_uint m_vector_size(const M_Vector v) { M_Vector new_m_vector(const m_uint size) { const M_Vector array = mp_alloc(M_Vector); - array->ptr = (m_bit*)xcalloc(ARRAY_OFFSET + 2, size); +const size_t sz = (ARRAY_OFFSET*SZ_INT) + (2*size); + array->ptr = (m_bit*)xcalloc(1, sz); ARRAY_CAP(array) = 2; ARRAY_SIZE(array) = size; return array; } +M_Vector new_m_vector2(const m_uint size, const m_uint len) { + const M_Vector array = mp_alloc(M_Vector); + const size_t sz = (ARRAY_OFFSET*SZ_INT) + (len*size); + array->ptr = (m_bit*)xcalloc(1, sz); + m_uint cap = 1; + while(cap < len) + cap *= 2; + ARRAY_CAP(array) = cap; + ARRAY_SIZE(array) = size; + ARRAY_LEN(array) = len; + return array; +} + void free_m_vector(M_Vector a) { xfree(a->ptr); mp_free(M_Vector, a); @@ -52,14 +66,9 @@ static DTOR(array_dtor) { ANN M_Object new_array(const Type t, const m_uint length) { const M_Object a = new_object(NULL, t); - m_uint cap = 1; - while(cap < length) - cap *= 2; const m_uint depth = t->array_depth; const m_uint size = depth > 1 ? SZ_INT : array_base(t)->size; - const M_Vector array = ARRAY(a) = new_m_vector(size); - ARRAY_CAP(array) = cap; - ARRAY_LEN(array) = length; + ARRAY(a) = new_m_vector2(size,length); ADD_REF(t); return a; } @@ -244,11 +253,11 @@ INSTR(ArrayPost) { GWDEBUG_EXE } INSTR(ArrayInit) { GWDEBUG_EXE // for litteral array - const m_uint off = instr->m_val * instr->m_val2; - const Type t = *(Type*)instr->ptr; + const Type t = (Type)instr->m_val; + const m_uint sz = *(m_uint*)REG(0); + const m_uint off = instr->m_val2 * sz; POP_REG(shred, off - SZ_INT); - const M_Object obj = new_array(t, instr->m_val); - vector_add(&shred->gc, (vtype)obj); + const M_Object obj = new_array(t, sz); memcpy(ARRAY(obj)->ptr + ARRAY_OFFSET, REG(-SZ_INT), off); *(M_Object*)REG(-SZ_INT) = obj; } @@ -305,7 +314,7 @@ ANN static M_Object* init_array(const VM_Shred shred, const ArrayInfo* info, m_u } INSTR(ArrayAlloc) { GWDEBUG_EXE - const ArrayInfo* info = *(ArrayInfo**)instr->ptr; + const ArrayInfo* info = (ArrayInfo*)instr->m_val; m_uint num_obj = 1; m_int idx = 0; const m_bool is_obj = info->is_obj && !info->is_ref; @@ -315,7 +324,7 @@ INSTR(ArrayAlloc) { GWDEBUG_EXE aai.data = init_array(shred, info, &num_obj); const M_Object ref = do_alloc_array(shred, &aai); if(!ref) { - gw_err("[Gwion](VM): (note: in shred[id=%" UINT_F ":%s])\n", shred->xid, shred->name); + gw_err("[Gwion](VM): (note: in shred[id=%" UINT_F ":%s])\n", shred->tick->xid, shred->info->name); vm_shred_exit(shred); return; // TODO make exception vararg } @@ -362,8 +371,8 @@ INSTR(ArrayAccess) { GWDEBUG_EXE #define DIM(a) gw_err("\t... at dim [%" INT_F "]\n", (a)) INSTR(ArrayAccessMulti) { GWDEBUG_EXE - const m_uint depth = *(m_uint*)instr->ptr; - POP_REG(shred, SZ_INT * (depth + 1)); + const m_uint depth = *(m_uint*)REG(0); + POP_REG(shred, SZ_INT * (depth + 1)) const M_Object base = *(M_Object*)REG(0); M_Object obj = base; if(!obj) diff --git a/src/lib/event.c b/src/lib/event.c index eaa1415b2..832f01b67 100644 --- a/src/lib/event.c +++ b/src/lib/event.c @@ -21,7 +21,7 @@ static INSTR(EventWait) { GWDEBUG_EXE const M_Object event = *(M_Object*)REG(-SZ_INT); if(!event) Except(shred, "NullEventWait"); - shreduler_remove(shred->vm->shreduler, shred, 0); + shreduler_remove(shred->info->vm->shreduler, shred, 0); const Vector v = EV_SHREDS(event); vector_add(v, (vtype)shred); *(m_int*)REG(-SZ_INT) = 1; @@ -32,7 +32,7 @@ static MFUN(event_signal) { const Vector v = EV_SHREDS(o); const VM_Shred sh = (VM_Shred)vector_front(v); if(sh) { - shredule(shred->vm->shreduler, sh, .5); + shredule(shred->info->vm->shreduler, sh, .5); vector_rem(v, 0); } } @@ -40,7 +40,7 @@ static MFUN(event_signal) { ANN void broadcast(const M_Object o) { for(m_uint i = 0; i < vector_size(EV_SHREDS(o)); i++) { const VM_Shred sh = (VM_Shred)vector_at(EV_SHREDS(o), i); - shredule(sh->vm->shreduler, sh, .5); + shredule(sh->info->vm->shreduler, sh, .5); } vector_clear(EV_SHREDS(o)); } diff --git a/src/lib/float.c b/src/lib/float.c index 8f2023d15..74a0b27af 100644 --- a/src/lib/float.c +++ b/src/lib/float.c @@ -11,147 +11,12 @@ #include "emit.h" #include "operator.h" -#define describe(name, op) \ -INSTR(Float##name) { GWDEBUG_EXE \ - POP_REG(shred, SZ_FLOAT); \ - *(m_float*)REG(-SZ_FLOAT) op##= *(m_float*)REG(0); \ -} - -static describe(Plus, +) -static describe(Minus, -) -describe(Times, *) -static describe(Divide, /) - -#define describe_logical(name, op) \ -static INSTR(float_##name) { GWDEBUG_EXE \ - POP_REG(shred, SZ_FLOAT * 2 - SZ_INT); \ - *(m_int*)REG(-SZ_INT) = (*(m_float*)REG(-SZ_INT) op *(m_float*)REG(SZ_FLOAT -SZ_INT)); \ -} -describe_logical(and, &&) -describe_logical(or, ||) -describe_logical(eq, ==) -describe_logical(neq, !=) -describe_logical(gt, >) -describe_logical(ge, >=) -describe_logical(lt, <) -describe_logical(le, <=) - -INSTR(float_negate) { GWDEBUG_EXE - *(m_float*)REG(-SZ_FLOAT) = -*(m_float*)REG(-SZ_FLOAT); -} - - OP_CHECK(opck_unary_meta2) { const Exp_Unary* unary = (Exp_Unary*)data; unary->self->meta = ae_meta_value; return t_int; } -INSTR(float_not) { GWDEBUG_EXE - POP_REG(shred, SZ_FLOAT - SZ_INT) - *(m_int*)REG(-SZ_INT) = !*(m_float*)REG(-SZ_INT); -} - -static INSTR(float_r_assign) { GWDEBUG_EXE - POP_REG(shred, SZ_INT); - **(m_float**)REG(0) = *(m_float*)REG(-SZ_FLOAT); -} - -#define describe_r(name, op) \ -static INSTR(float_r_##name) { GWDEBUG_EXE \ - POP_REG(shred, SZ_INT); \ - *(m_float*)REG(-SZ_FLOAT) = (**(m_float**)REG(0) op##= (*(m_float*)REG(-SZ_FLOAT))); \ -} - -describe_r(plus, +) -describe_r(minus, -) -describe_r(mul, *) -describe_r(div, /) - -#define describe_if(name, op) \ -static INSTR(int_float_##name) { GWDEBUG_EXE \ - POP_REG(shred, SZ_INT); \ - *(m_float*)REG(-SZ_FLOAT) = (m_float)*(m_int*)REG(-SZ_FLOAT) op \ - *(m_float*)REG(SZ_INT-SZ_FLOAT); \ -} -describe_if(plus, +) -describe_if(minus, -) -describe_if(mul, *) -describe_if(div, /) - -#define describe_logical_if(name, op) \ -static INSTR(int_float_##name) { GWDEBUG_EXE \ - POP_REG(shred, SZ_FLOAT); \ - *(m_int*)REG(-SZ_INT) = (*(m_int*)REG(-SZ_INT) op (m_int)*(m_float*)REG(0)); \ -} -describe_logical_if(and, &&) -describe_logical_if(or, ||) -describe_logical_if(eq, ==) -describe_logical_if(neq, !=) -describe_logical_if(gt, >) -describe_logical_if(ge, >=) -describe_logical_if(lt, <) -describe_logical_if(le, <=) - -#define describe_r_if(name, op) \ -static INSTR(int_float_r_##name) { GWDEBUG_EXE \ - POP_REG(shred, SZ_INT * 2 - SZ_FLOAT); \ - *(m_float*)REG(-SZ_FLOAT) = (**(m_float**)REG(SZ_INT - SZ_FLOAT) op##= \ - (m_float)*(m_int*)REG(-SZ_FLOAT)); \ -} -describe_r_if(assign, ) -describe_r_if(plus, +) -describe_r_if(minus, -) -describe_r_if(mul, *) -describe_r_if(div, /) - -#define describe_fi(name, op) \ -static INSTR(float_int_##name) { GWDEBUG_EXE \ - POP_REG(shred, SZ_INT); \ - *(m_float*)REG(-SZ_FLOAT) op##= (m_float)*(m_int*)REG(0); \ -} -describe_fi(plus, +) -describe_fi(minus, -) -describe_fi(mul, *) -describe_fi(div, /) - -#define describe_logical_fi(name, op) \ -static INSTR(float_int_##name) { GWDEBUG_EXE \ - POP_REG(shred, SZ_FLOAT); \ - *(m_int*)REG(-SZ_INT) = ((m_int)*(m_float*)REG(-SZ_INT) op *(m_int*)REG(SZ_FLOAT-SZ_INT)); \ -} -describe_logical_fi(and, &&) -describe_logical_fi(or, ||) -describe_logical_fi(eq, ==) -describe_logical_fi(neq, !=) -describe_logical_fi(gt, >) -describe_logical_fi(ge, >=) -describe_logical_fi(lt, <) -describe_logical_fi(le, <=) - -static INSTR(float_int_r_assign) { GWDEBUG_EXE - POP_REG(shred, SZ_FLOAT); - *(m_int*)REG(-SZ_INT) = **(m_int**)REG(SZ_FLOAT-SZ_INT) = - (m_int)*(m_float*)REG(-SZ_INT); -} - -#define describe_r_fi(name, op) \ -static INSTR(float_int_r_##name) { GWDEBUG_EXE \ - POP_REG(shred, SZ_FLOAT); \ - *(m_int*)REG(-SZ_INT) = (**(m_int**)REG(SZ_FLOAT -SZ_INT) op##= (m_int)(*(m_float*)REG(-SZ_INT))); \ -} -describe_r_fi(plus, +) -describe_r_fi(minus, -) -describe_r_fi(mul, *) -describe_r_fi(div, /) - -static INSTR(Time_Advance) { GWDEBUG_EXE - POP_REG(shred, SZ_FLOAT); - const m_float f = *(m_float*)REG(-SZ_FLOAT); - *(m_float*)REG(-SZ_FLOAT) = (shred->wake_time += f); - shredule(shred->vm->shreduler, shred, f); -} - static GWION_IMPORT(values) { VM* vm = gwi_vm(gwi); ALLOC_PTR(d_zero, m_float, 0.0); @@ -213,17 +78,6 @@ static OP_EMIT(opem_f2i) { return GW_OK; } -INSTR(CastI2F) { GWDEBUG_EXE - POP_REG(shred, SZ_INT - SZ_FLOAT); - *(m_float*)REG(-SZ_FLOAT) = (m_float)*(m_int*)REG(-SZ_FLOAT); -} - - -INSTR(CastF2I) { GWDEBUG_EXE - POP_REG(shred, SZ_FLOAT - SZ_INT); - *(m_int*)REG(-SZ_INT) = (m_int)*(m_float*)REG(-SZ_INT); -} - #define CHECK_OP(op, check, func) _CHECK_OP(op, check, float_##func) #define CHECK_IF(op, check, func) _CHECK_OP(op, check, int_float_##func) #define CHECK_FI(op, check, func) _CHECK_OP(op, check, float_int_##func) diff --git a/src/lib/func.c b/src/lib/func.c index 61975a738..6a8bdbd03 100644 --- a/src/lib/func.c +++ b/src/lib/func.c @@ -17,10 +17,9 @@ ANN Type check_exp_call1(const Env env, const Exp_Call *exp); ANN m_bool emit_exp_spork(const Emitter, const Exp_Unary*); -static INSTR(assign_func) { GWDEBUG_EXE - const Func f = **(Func**)REG(-SZ_INT) = *(Func*)REG(-(SZ_INT*2+instr->m_val2)); - POP_REG(shred, instr->m_val + instr->m_val2) - *(Func*)REG(-SZ_INT) = f; // do we need this ? +static INSTR(FuncAssign) { GWDEBUG_EXE + POP_REG(shred, SZ_INT) + **(Func**)REG(0) = *(Func*)REG(-SZ_INT); } static OP_CHECK(opck_func_call) { @@ -106,19 +105,6 @@ static OP_CHECK(opck_spork) { ERR_O(unary->self->pos, "only function calls can be sporked...") return NULL; } -static OP_EMIT(opem_fptr_at) { - const Exp_Binary* bin = (Exp_Binary*)data; - const Instr instr = emit_add_instr(emit, assign_func); - if(GET_FLAG(bin->rhs->type->d.func, global)) - instr->m_val = SZ_INT; - else if(GET_FLAG(bin->rhs->type->d.func, member)) { - if(bin->rhs->exp_type != ae_exp_decl) - instr->m_val2 = SZ_INT; - instr->m_val = SZ_INT*2; - } else - instr->m_val = SZ_INT; - return GW_OK; -} static OP_EMIT(opem_spork) { const Exp_Unary* unary = (Exp_Unary*)data; @@ -131,8 +117,7 @@ GWION_IMPORT(func) { CHECK_BB(gwi_oper_end(gwi, op_chuck, NULL)) CHECK_BB(gwi_oper_ini(gwi, "@function", "@func_ptr", NULL)) CHECK_BB(gwi_oper_add(gwi, opck_fptr_at)) - CHECK_BB(gwi_oper_emi(gwi, opem_fptr_at)) - CHECK_BB(gwi_oper_end(gwi, op_ref, NULL)) + CHECK_BB(gwi_oper_end(gwi, op_ref, FuncAssign)) CHECK_BB(gwi_oper_add(gwi, opck_fptr_cast)) CHECK_BB(gwi_oper_emi(gwi, opem_basic_cast)) CHECK_BB(gwi_oper_end(gwi, op_cast, NULL)) diff --git a/src/lib/gack.c b/src/lib/gack.c index 0e53bdc93..c2e2185a9 100644 --- a/src/lib/gack.c +++ b/src/lib/gack.c @@ -46,7 +46,7 @@ static inline void print_polar(const m_complex c) { gw_out("*pi)"); } -static inline void print_vec(const m_bit* f, const m_uint size) { +ANN static inline void print_vec(const m_bit* f, const m_uint size) { gw_out("@("); for(m_uint i = 0; i < size; i++) { print_float(creal(*(m_float*)(f + i * SZ_FLOAT))); @@ -64,20 +64,20 @@ static inline void print_string(const M_Object obj) { print_string1(obj ? STRING(obj) : "(null string)"); } -static inline void print_object(const Type type, const M_Object obj) { +ANN2(1) static inline void print_object(const Type type, const M_Object obj) { if(isa(type, t_string) > 0) print_string(obj); else gw_out("%p", (void*)obj); } -static inline void print_func(const Type type, const m_bit* stack) { +ANN static inline void print_func(const Type type, const m_bit* stack) { const VM_Code code = isa(type, t_fptr) > 0 ? *(VM_Code*)stack : type->d.func->code; gw_out("%s %p", type->name, (void*)code); } -static void print_prim(const Type type, const m_bit* stack) { +ANN static void print_prim(const Type type, const m_bit* stack) { if(isa(type, t_int) > 0) print_int(*(m_int*)stack); else if(isa(type, t_complex) > 0) @@ -92,24 +92,24 @@ static void print_prim(const Type type, const m_bit* stack) { print_float(*(m_float*)stack); } -INSTR(Gack) { GWDEBUG_EXE - const Vector v = *(Vector*)instr->ptr; - const m_uint size = vector_size(v); +ANN void gack(const m_bit* reg, const Instr instr) { m_uint offset = instr->m_val; + const Vector v = (Vector)instr->m_val2; + const m_uint size = vector_size(v); for(m_uint i = size + 1; --i;) { const Type type = (Type)vector_at(v, size - i); if(size == 1) print_type(type); if(isa(type, t_object) > 0) - print_object(type, *(M_Object*)REG(-offset)); + print_object(type, *(M_Object*)(reg-offset)); else if(isa(type, t_function) > 0) - print_func(type, REG(-offset)); + print_func(type, (reg-offset)); else if(isa(type, t_class) > 0) print_type(type->d.base_type); else if(isa(type, t_void) > 0) print_string1("void"); else - print_prim(type, REG(-offset)); + print_prim(type, (reg-offset)); offset -= type->size; } gw_out("\n"); diff --git a/src/lib/import.c b/src/lib/import.c index 392a46759..397e6d3d6 100644 --- a/src/lib/import.c +++ b/src/lib/import.c @@ -166,9 +166,8 @@ ANN static ID_List str2list(const m_str path, m_uint* array_depth) { ANN static m_bool mk_xtor(const Type type, const m_uint d, const ae_flag e) { VM_Code* code = e == ae_flag_ctor ? &type->nspc->pre_ctor : &type->nspc->dtor; const m_str name = type->name; - *code = new_vm_code(NULL, SZ_INT, 1, name); + *code = new_vm_code(NULL, SZ_INT, e | ae_flag_member | ae_flag_builtin, name); (*code)->native_func = (m_uint)d; - (*code)->flag = (e | ae_flag_member | ae_flag_builtin); type->flag |= e; return GW_OK; } @@ -353,7 +352,7 @@ static Array_Sub make_dll_arg_list_array(Array_Sub array_sub, return array_sub; } -ANN static Type_List str2tl(const Env env, const m_str s, m_uint *depth) { +ANN /*static */ Type_List str2tl(const Env env, const m_str s, m_uint *depth) { Type_Decl* td = str2decl(env, s, depth); td->array = make_dll_arg_list_array(NULL, depth, 0); return new_type_list(td, NULL); @@ -637,8 +636,3 @@ ANN m_int gwi_enum_end(const Gwi gwi) { free_stmt(stmt); return GW_OK; } - -m_int gwi_add_value(Gwi gwi, const m_str name, Type type, const m_bool is_const, void* value) { - env_add_value(gwi->env, name, type, is_const, value); - return GW_OK; -} diff --git a/src/lib/instr.c b/src/lib/instr.c index 9e689c161..b56d81ab4 100644 --- a/src/lib/instr.c +++ b/src/lib/instr.c @@ -13,30 +13,6 @@ #include "array.h" #include "nspc.h" -ANN static inline m_bool overflow_(const VM_Shred c) { - return c->mem > ((c->_reg + SIZEOF_REG) + (SIZEOF_MEM) - (MEM_STEP)); -} - -static inline void dl_return_push(const m_bit* retval, const VM_Shred shred, - const m_uint size __attribute__((unused))) { - *(m_uint*)REG(0) = *(m_uint*)retval; - PUSH_REG(shred, SZ_INT); -} - -static inline void dl_return_push2(const m_bit* retval, const VM_Shred shred, - const m_uint size __attribute__((unused))) { - *(m_float*)REG(0) = *(m_float*)retval; - PUSH_REG(shred, SZ_FLOAT); -} - -static inline void dl_return_push3(const m_bit* retval, const VM_Shred shred, const m_uint size) { - memcpy(REG(0), retval, size); - PUSH_REG(shred, size); -} - -static void (*dl_return[])(const m_bit*, const VM_Shred, const m_uint) = - { dl_return_push, dl_return_push2, dl_return_push3 }; - INSTR(EOC) { GWDEBUG_EXE vm_shred_exit(shred); } @@ -46,482 +22,30 @@ INSTR(DTOR_EOC) { GWDEBUG_EXE o->type_ref = o->type_ref->parent; o->ref = 1; _release(o, shred); - _release(shred->me, shred); + _release(shred->info->me, shred); vm_shred_exit(shred); } INSTR(EOC2) { GWDEBUG_EXE shred->pc = 0; - shreduler_remove(shred->vm->shreduler, shred, 0); -} - -INSTR(RegPop) { GWDEBUG_EXE - POP_REG(shred, instr->m_val); -} - -INSTR(RegPushImm) { GWDEBUG_EXE - *(m_uint*)shred->reg = instr->m_val; - shred->reg += SZ_INT; -} -#define describe_regpushimmxxx(name, type, size) \ -INSTR(RegPush##name) { GWDEBUG_EXE \ - *(type*)REG(0) = *(type*)instr->ptr; \ - PUSH_REG(shred, size); \ -} - -describe_regpushimmxxx(Imm2, m_float, SZ_FLOAT) -INSTR(RegPushImm3) { GWDEBUG_EXE - memcpy(REG(0), instr->ptr, instr->m_val2); - PUSH_REG(shred, instr->m_val2); -} - -INSTR(MemPushImm) { GWDEBUG_EXE - *(m_uint*)MEM(0) = instr->m_val; - PUSH_MEM(shred, SZ_INT); -} - -INSTR(MemSetImm) { GWDEBUG_EXE - *(m_uint*)MEM(instr->m_val) = instr->m_val2; -} - -#define describe_regpushxxx(name, type, size) \ -INSTR(RegPush##name) { GWDEBUG_EXE \ - *(type*)REG(0) = *(type*)(shred->mem + instr->m_val); \ - PUSH_REG(shred, size); \ -} - -describe_regpushxxx(Mem, m_int, SZ_INT) -describe_regpushxxx(Mem2, m_float, SZ_FLOAT) -INSTR(RegPushMem3) { GWDEBUG_EXE - memcpy(REG(0), (shred->mem + instr->m_val), instr->m_val2); - PUSH_REG(shred, instr->m_val2); -} -INSTR(RegPushMem4) { GWDEBUG_EXE - *(m_bit**)REG(0) = (m_bit*)(shred->mem + instr->m_val); - PUSH_REG(shred, SZ_INT); -} - -#define describe_regpushbase(name, type, size) \ -INSTR(RegPush##name) { GWDEBUG_EXE \ - *(type*)REG(0) = *(type*)(shred->base + instr->m_val); \ - PUSH_REG(shred, size); \ -} - -describe_regpushbase(Base, m_int, SZ_INT) -describe_regpushbase(Base2, m_float, SZ_FLOAT) -INSTR(RegPushBase3) { GWDEBUG_EXE - memcpy(REG(0), (shred->base + instr->m_val), instr->m_val2); - PUSH_REG(shred, instr->m_val2); -} -INSTR(RegPushBase4) { GWDEBUG_EXE - *(m_bit**)REG(0) = (m_bit*)(shred->base + instr->m_val); - PUSH_REG(shred, SZ_INT); -} - -INSTR(RegPushPtr) { GWDEBUG_EXE - *(m_uint*)REG(-SZ_INT) = instr->m_val; -} - -INSTR(RegDup) { GWDEBUG_EXE - *(M_Object*)REG(0) = *(M_Object*)REG(-SZ_INT); - PUSH_REG(shred, SZ_INT); -} - -INSTR(RegAddRef) { GWDEBUG_EXE - const M_Object obj = instr->m_val ? **(M_Object**)REG(-SZ_INT) : - *(M_Object*)REG(-SZ_INT); - if(obj) - ++obj->ref; -} - -INSTR(RegPushMe) { GWDEBUG_EXE - *(M_Object*)REG(0) = shred->me; - PUSH_REG(shred, SZ_INT); -} - -INSTR(RegPushNow) { GWDEBUG_EXE - *(m_float*)REG(0) = (m_float)shred->vm->bbq->pos; - PUSH_REG(shred, SZ_FLOAT); -} - -INSTR(RegPushMaybe) { GWDEBUG_EXE - *(m_uint*)REG(0) = gw_rand(shred->vm->rand) > (UINT32_MAX / 2); - PUSH_REG(shred, SZ_INT); -} - -INSTR(AllocWord) { GWDEBUG_EXE - *(m_uint*)MEM(instr->m_val) = 0; - *(m_uint*)REG(0) = 0; // MEM(instr->m_val); - PUSH_REG(shred, SZ_INT); -} - -INSTR(AllocWord2) { GWDEBUG_EXE - *(m_float*)MEM(instr->m_val) = 0.0; - *(m_float*)REG(0) = 0.0; // MEM(instr->m_val); - PUSH_REG(shred, SZ_FLOAT); -} - -INSTR(AllocWord3) { GWDEBUG_EXE - memset(MEM(instr->m_val), 0, instr->m_val2); - memset(REG(0), 0, instr->m_val2); // MEM(instr->m_val) - PUSH_REG(shred, instr->m_val2); -} - -INSTR(AllocWord4) { GWDEBUG_EXE - memset(MEM(instr->m_val), 0, instr->m_val2); - *(m_bit**)REG(0) = (m_bit*)MEM(instr->m_val); - PUSH_REG(shred, SZ_INT); + shreduler_remove(shred->info->vm->shreduler, shred, 0); } /* branching */ INSTR(SwitchIni) { const Vector v = (Vector)instr->m_val; - const m_uint size = vector_size(v);; + const m_uint size = vector_size(v); const Map m = (Map)instr->m_val2; - POP_REG(shred, SZ_INT * (size - 1)); + POP_REG(shred, SZ_INT * (size)); for(m_uint i = 0; i < size; ++i) - map_set(m, *(vtype*)REG((i-1) * SZ_INT), vector_at(v, i)); - *(Map*)REG(-SZ_INT) = m; + map_set(m, *(vtype*)REG((i) * SZ_INT), vector_at(v, i)); + *(Map*)REG(0) = m; } INSTR(BranchSwitch) { GWDEBUG_EXE - const m_uint offset = *(m_uint*)instr->ptr; - POP_REG(shred, SZ_INT + offset); - const Map map = !offset ?(Map)instr->m_val2 : *(Map*)REG(0); - shred->pc = map_get(map, (vtype)*(m_int*)REG(offset)); - if(!shred->pc) - shred->pc = instr->m_val; -} - -#define branch(name, type, sz, op) \ -INSTR(Branch##name) { GWDEBUG_EXE \ - POP_REG(shred, sz * 2); \ - if(*(type*)REG(0) op *(type*)REG(sz)) \ - shred->pc = instr->m_val; \ -} -branch(EqInt, m_int, SZ_INT, ==) -branch(NeqInt, m_int, SZ_INT, !=) -branch(EqFloat, m_float, SZ_FLOAT, ==) -branch(NeqFloat, m_float, SZ_FLOAT, !=) - -INSTR(InitLoopCounter) { GWDEBUG_EXE POP_REG(shred, SZ_INT); - (*(m_int*)instr->m_val) = labs(*(m_int*)REG(0)); -} - -INSTR(RegPushDeref) { GWDEBUG_EXE - *(m_uint*)REG(0) = **(m_uint**)instr->ptr; - PUSH_REG(shred, SZ_INT); -} - -INSTR(RegPushDeref2) { GWDEBUG_EXE - *(m_float*)REG(0) = *(m_float*)instr->ptr; - PUSH_REG(shred, SZ_FLOAT); -} - -INSTR(RegPushDeref3) { GWDEBUG_EXE - memcpy(REG(0), *(void**)instr->ptr, instr->m_val2); - PUSH_REG(shred, instr->m_val2); -} - -INSTR(DecIntAddr) { GWDEBUG_EXE - --(*((m_int*)(instr->m_val))); -} - -INSTR(Goto) { GWDEBUG_EXE - shred->pc = instr->m_val; -} - -ANN static VM_Shred init_spork_shred(const VM_Shred shred, const VM_Code code) { - const VM_Shred sh = new_vm_shred(code); - ADD_REF(code) - sh->parent = shred; - if(!shred->child.ptr) - vector_init(&shred->child); - vector_add(&shred->child, (vtype)sh); - sh->base = shred->base; - vm_add_shred(shred->vm, sh); - return sh; -} -#include "value.h" -static inline void push_me(VM_Shred shred, VM_Shred sh) { - *(M_Object*)REG(0) = sh->me; - PUSH_REG(shred, SZ_INT); -} - -INSTR(SporkFunc) { GWDEBUG_EXE - POP_REG(shred, SZ_INT); - const VM_Code code = (VM_Code)instr->m_val2; - const VM_Shred sh = init_spork_shred(shred, code); - const m_uint need = GET_FLAG(code, member) ? SZ_INT : 0; - shred->reg -= instr->m_val + need; - if(instr->m_val) { - for(m_uint i = 0; i < instr->m_val; i+= SZ_INT) - *(m_uint*)(sh->reg + i) = *(m_uint*)REG(i); - sh->reg += instr->m_val; - } - if(need) { - *(M_Object*)sh->reg = *(M_Object*)REG(instr->m_val); - PUSH_REG(sh, SZ_INT); - } - push_me(shred, sh); -} - -INSTR(SporkExp) { GWDEBUG_EXE - POP_REG(shred, SZ_INT); - const VM_Code code = (VM_Code)instr->m_val2; - const VM_Shred sh = init_spork_shred(shred, code); - for(m_uint i = 0; i < instr->m_val; i+= SZ_INT) - *(m_uint*)(sh->mem + i) = *(m_uint*)MEM(i); - push_me(shred, sh); -} - -ANN static void shred_func_prepare(const VM_Shred shred) { - POP_REG(shred, SZ_INT * 2); - // local depth + previous stack - const m_uint push = *(m_uint*)REG(SZ_INT) + *(m_uint*)MEM(-SZ_INT); - PUSH_MEM(shred, push + SZ_INT*3); - *(m_uint*) MEM(-SZ_INT*3) = push; - *(VM_Code*) MEM(-SZ_INT*2) = shred->code; - *(m_uint*) MEM(-SZ_INT) = shred->pc; - shred->pc = 0; - shred->code = *(VM_Code*)REG(0); - shred->instr = shred->code->instr; -} - -ANN static inline void shred_func_need_this(const VM_Shred shred) { - *(m_uint*)MEM(0) = *(m_uint*)REG(shred->code->stack_depth - SZ_INT); - PUSH_MEM(shred, SZ_INT); -} - -INSTR(FuncPtr) { GWDEBUG_EXE - const VM_Code code = *(VM_Code*)REG(-SZ_INT*2); - if(!code) - Except(shred, "NullFuncPtrException"); - if(!GET_FLAG(code, builtin)) - FuncUsr(shred, instr); - else if(GET_FLAG(code, member)) - FuncMember(shred, instr); - else - FuncStatic(shred, instr); -} - -INSTR(FuncUsr) { GWDEBUG_EXE - shred_func_prepare(shred); - const VM_Code code = shred->code; - m_uint stack_depth = code->stack_depth; - if(stack_depth) { - POP_REG(shred, stack_depth); - if(GET_FLAG(code, member)) { - shred_func_need_this(shred); - stack_depth -= SZ_INT; - } - for(m_uint i = 0; i < stack_depth; i+= SZ_INT) - *(m_uint*)MEM(i) = *(m_uint*)REG(i); - if(GET_FLAG(code, member)) - POP_MEM(shred, SZ_INT); - } - if(overflow_(shred)) - Except(shred, "StackOverflow"); -} - -INSTR(DotFunc) { GWDEBUG_EXE - const M_Object obj = *(M_Object*)REG(-SZ_INT); - if(!obj) - Except(shred, "NullPtrException"); - *(VM_Code*)REG(-SZ_INT) = ((Func)vector_at(&obj->type_ref->nspc->vtable, instr->m_val))->code; -} - -INSTR(FuncStatic) { GWDEBUG_EXE - POP_REG(shred, SZ_INT * 2); - const VM_Code code = *(VM_Code*)REG(0); - const m_uint local_depth = *(m_uint*)REG(SZ_INT); - PUSH_MEM(shred, local_depth); - const m_uint stack_depth = code->stack_depth; - if(stack_depth) { - POP_REG(shred, stack_depth); - for(m_uint i = 0; i < stack_depth; i+= SZ_INT) - *(m_uint*)MEM(i) = *(m_uint*)REG(i); - } - if(overflow_(shred)) - Except(shred, "StackOverflow"); - const m_bit retval[instr->m_val]; - const f_sfun f = (f_sfun)code->native_func; - f(retval, shred); - if(instr->m_val) - dl_return[instr->m_val2](retval, shred, instr->m_val); - POP_MEM(shred, local_depth); -} - -ANN static inline void copy_member_args(const VM_Shred shred, const VM_Code func) { - const m_uint stack_depth = func->stack_depth; - const m_uint depth = stack_depth -SZ_INT; - POP_REG(shred, stack_depth); - *(m_uint*)MEM(0) = *(m_uint*)REG(depth); - for(m_uint i = 0; i < stack_depth; i+= SZ_INT) - *(m_uint*)MEM(i+SZ_INT) = *(m_uint*)REG(i); -} - -INSTR(FuncMember) { GWDEBUG_EXE - POP_REG(shred, SZ_INT * 2); - const VM_Code code = *(VM_Code*)REG(0); - const m_uint local_depth = *(m_uint*)REG(SZ_INT); - PUSH_MEM(shred, local_depth); - copy_member_args(shred, code); - if(overflow_(shred)) - Except(shred, "StackOverflow"); - if(GET_FLAG(code, ctor)) { - const f_xtor f = (f_xtor)code->native_func; - f(*(M_Object*)MEM(0), shred); - } else { - assert(instr); - const m_bit retval[instr->m_val]; - const f_mfun f = (f_mfun)code->native_func; - f((*(M_Object*)MEM(0)), retval, shred); - if(instr->m_val) - dl_return[instr->m_val2](retval, shred, instr->m_val); - } - POP_MEM(shred, local_depth); -} - -INSTR(FuncReturn) { GWDEBUG_EXE - shred->pc = *(m_uint*)MEM(-SZ_INT); - shred->code = *(VM_Code*)MEM(-SZ_INT*2); - shred->instr = shred->code->instr; - POP_MEM(shred, *(m_uint*)MEM(-SZ_INT*3) + SZ_INT*3); -} - -INSTR(PreCtor) { GWDEBUG_EXE - const VM_Code pre_ctor = (VM_Code)instr->m_val; - *(m_uint*)REG(0) = *(m_uint*)REG(-SZ_INT); - *(VM_Code*)REG(SZ_INT) = pre_ctor; - *(m_uint*)REG(SZ_INT*2) = instr->m_val2; - PUSH_REG(shred, SZ_INT*3); - if(GET_FLAG(pre_ctor, builtin)) - FuncMember(shred, NULL); - else - FuncUsr(shred, NULL); -} - -INSTR(ObjectInstantiate) { GWDEBUG_EXE - const M_Object o = new_object(shred, (Type)instr->m_val); - *(M_Object*)REG(0) = o; - PUSH_REG(shred, SZ_INT); -} - -INSTR(PushNull) { GWDEBUG_EXE - *(m_uint*)REG(0) = 0; - PUSH_REG(shred, SZ_INT); -} - -INSTR(PushNull2) { GWDEBUG_EXE - *(m_float*)REG(0) = 0.0; - PUSH_REG(shred, SZ_FLOAT); -} - -INSTR(PushNull3) { GWDEBUG_EXE - memset(REG(0), 0, instr->m_val2); // 0 <=> *data - PUSH_REG(shred, instr->m_val2); -} - -INSTR(AllocMember4) { GWDEBUG_EXE - const M_Object obj = *(M_Object*)MEM(0); - *(const m_bit**)REG(0) = obj->data + instr->m_val; - PUSH_REG(shred, SZ_INT); -} - -INSTR(DotStatic) { GWDEBUG_EXE - const Type t = *(Type*)REG(-SZ_INT); - m_uint *const data = (m_uint*)(t->nspc->class_data + instr->m_val); - *(m_uint*)REG(-SZ_INT) = data ? *data : 0; -} - -INSTR(DotStatic2) { GWDEBUG_EXE - const Type t = *(Type*)REG(-SZ_INT); - m_float *const data = (m_float*)(t->nspc->class_data + instr->m_val); - *(m_float*)REG(-SZ_INT) = *data; - PUSH_REG(shred, SZ_FLOAT - SZ_INT); -} - -INSTR(DotStatic3) { GWDEBUG_EXE - const Type t = *(Type*)REG(-SZ_INT); - const m_bit* data = t->nspc->class_data + instr->m_val; - memcpy(REG(-SZ_INT), data, instr->m_val2); - PUSH_REG(shred, instr->m_val2 - SZ_INT); -} - -INSTR(DotStatic4) { GWDEBUG_EXE - const Type t = *(Type*)REG(-SZ_INT); - const m_bit* data = t->nspc->class_data + instr->m_val; - *(m_bit**)REG(-SZ_INT) = (m_bit*)data; -} - -INSTR(DotImport) { GWDEBUG_EXE - *(m_uint*)REG(0) = *(m_uint*)instr->m_val; - PUSH_REG(shred, SZ_INT); -} - -INSTR(DotImport2) { GWDEBUG_EXE - *(m_float*)REG(0) = *(m_float*)instr->m_val; - PUSH_REG(shred, SZ_FLOAT); -} - -INSTR(DotImport3) { GWDEBUG_EXE - memcpy(REG(0), (m_bit*)instr->m_val, instr->m_val2); - PUSH_REG(shred, instr->m_val2); -} - -INSTR(DotImport4) { GWDEBUG_EXE - *(m_bit**)REG(0) = (m_bit*)(instr->m_val); - PUSH_REG(shred, SZ_INT); -} - -INSTR(DotMember) { GWDEBUG_EXE - const M_Object obj = *(M_Object*)REG(-SZ_INT); - if(!obj) - Except(shred, "NullPtrException"); - *(m_uint*)REG(-SZ_INT) = *(m_uint*)(obj->data + instr->m_val); -} - -INSTR(DotMember2) { GWDEBUG_EXE - const M_Object obj = *(M_Object*)REG(-SZ_INT); - if(!obj) - Except(shred, "NullPtrException"); - *(m_float*)REG(-SZ_INT) = *(m_float*)(obj->data + instr->m_val); - PUSH_REG(shred, SZ_FLOAT - SZ_INT); -} - -INSTR(DotMember3) { GWDEBUG_EXE - const M_Object obj = *(M_Object*)REG(-SZ_INT); - if(!obj) - Except(shred, "NullPtrException"); - memcpy(REG(-SZ_INT), (obj->data + instr->m_val), instr->m_val2); - PUSH_REG(shred, instr->m_val2 - SZ_INT); -} - -INSTR(DotMember4) { GWDEBUG_EXE - const M_Object obj = *(M_Object*)REG(-SZ_INT); - if(!obj) - Except(shred, "NullPtrException"); - *(m_bit**)REG(-SZ_INT) = (m_bit*)(obj->data + instr->m_val); -} - -INSTR(ObjectRelease) { GWDEBUG_EXE - release(*(M_Object*)MEM(instr->m_val), shred); -} - -INSTR(GcIni) { GWDEBUG_EXE - vector_add(&shred->gc, (vtype)NULL); -} - -INSTR(GcAdd) { GWDEBUG_EXE - vector_add(&shred->gc, *(vtype*)REG(-SZ_INT)); -} - -INSTR(GcEnd) { GWDEBUG_EXE - M_Object o; - while((o = (M_Object)vector_pop(&shred->gc))) - _release(o, shred); + const Map map = *(Map*)REG(SZ_INT); + shred->pc = map_get(map, *(m_uint*)REG(0)) ?: instr->m_val; } INSTR(AutoLoopStart) { GWDEBUG_EXE @@ -542,15 +66,11 @@ INSTR(AutoLoopStart) { GWDEBUG_EXE } INSTR(AutoLoopEnd) { GWDEBUG_EXE - if(instr->m_val2) { - const M_Object ptr = *(M_Object*)MEM(instr->m_val + SZ_INT); - _release(ptr, shred); - } m_uint* idx = (m_uint*)MEM(instr->m_val); ++*idx; const M_Object o = *(M_Object*)REG(-SZ_INT); if(*idx >= m_vector_size(ARRAY(o))) { - shred->pc = *(m_uint*)instr->ptr; + shred->pc = instr->m_val2; POP_REG(shred, SZ_INT); } } @@ -560,29 +80,6 @@ INSTR(PutArgsInMem) { GWDEBUG_EXE POP_REG(shred, instr->m_val) memcpy(shred->mem, shred->reg, instr->m_val); } - -INSTR(ConstPropSet) { GWDEBUG_EXE - if(*(m_uint*)instr->ptr >= 2) { - *(m_int**)(shred->reg) = (m_int*)(shred->mem + instr->m_val); - PUSH_REG(shred, SZ_INT); - return; - } - *(m_int*)(shred->mem + instr->m_val) = instr->m_val2; - if(*(m_bool*)instr->ptr) - *(m_int**)(shred->reg) = (m_int*)(shred->mem + instr->m_val); - else - *(m_int*)(shred->reg) = instr->m_val2; - PUSH_REG(shred, SZ_INT); - *(m_uint*)instr->ptr = 2 + *(m_uint*)instr->ptr; -} - -INSTR(ConstPropGet) { GWDEBUG_EXE - if(!*(m_uint*)instr->ptr) - memcpy(REG(0), MEM(instr->m_val2), SZ_INT); - else - memcpy(REG(0), &instr->m_val, SZ_INT); - PUSH_REG(shred, SZ_INT); -} #endif INSTR(PopArrayClass) { GWDEBUG_EXE @@ -593,3 +90,68 @@ INSTR(PopArrayClass) { GWDEBUG_EXE free_object(tmp); ADD_REF(obj->type_ref) // add ref to typedef array type } +#include "gwion.h" +#include "emit.h" +#include "value.h" +#include "template.h" + +ANN static Func_Def from_base(const struct dottmpl_ *dt, const Type t) { + const Symbol sym = func_symbol(t->name, s_name(dt->base->name), + "template", dt->overload); + const Value v = nspc_lookup_value1(t->nspc, sym); + CHECK_OO(v) + const Func_Def base = v->d.func_ref->def; + const Func_Def def = new_func_def(base->td, insert_symbol(v->name), + base->arg_list, base->d.code, base->flag); + def->tmpl = new_tmpl_list(base->tmpl->list, dt->overload); + SET_FLAG(def, template); + return def; +} + +INSTR(DotTmpl) { + const 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_func1(t->nspc, insert_symbol(str)); + if(f) { + if(!f->code) { + const m_uint scope = env_push_type(emit->env, t); + m_bool ret = GW_ERROR; + if(traverse_func_template(emit->env, f->def, dt->tl) > 0) { + ret = emit_func_def(emit, f->def); + nspc_pop_type(emit->env->curr); + } + env_pop(emit->env, scope); + if(ret < 0) + continue; + } + *(VM_Code*)shred->reg = f->code; + shred->reg += SZ_INT; + return; + } else { + const Func_Def def = from_base(dt, t); + if(!def) + continue; + const m_uint scope = env_push_type(emit->env, t); + m_bool ret = GW_ERROR; + if(traverse_func_template(emit->env, def, dt->tl) > 0) { + ret = emit_func_def(emit, def); + nspc_pop_type(emit->env->curr); + } + env_pop(emit->env, scope); + if(ret > 0) { + *(VM_Code*)shred->reg = def->func->code; + shred->reg += SZ_INT; + return; + } + } + } while((t = t->parent)); + Except(shred, "MissigTmplException[internal]"); //unreachable +} diff --git a/src/lib/int.c b/src/lib/int.c deleted file mode 100644 index bcb4acb10..000000000 --- a/src/lib/int.c +++ /dev/null @@ -1,134 +0,0 @@ -#include "gwion_util.h" -#include "gwion_ast.h" -#include "oo.h" -#include "vm.h" -#include "env.h" -#include "type.h" -#include "instr.h" -#include "object.h" -#include "import.h" - -#define TEST0(pos) if(!*(m_int*)REG(pos))Except(shred, "ZeroDivideException") -#define PREFIX int - -#define _describe(prefix, sz, name, action, ...) \ -static INSTR(prefix##_##name) { GWDEBUG_EXE \ - POP_REG(shred, sz); \ - __VA_ARGS__ \ - action \ -} - -#define describe(name, op, ...) _describe(int, SZ_INT, name, \ - {*(m_int*)REG(-SZ_INT) op##= *(m_int*)REG(0); }, __VA_ARGS__) - -#define describe_r(name, op, ...) _describe(int_r, SZ_INT, name, \ - {*(m_int*)REG(-SZ_INT) = (**(m_int**)REG(0) op##= (*(m_int*)REG(-SZ_INT)));}, __VA_ARGS__) - -#define describe_logical(name, op) _describe(int, SZ_INT, name, \ - {*(m_int*)REG(-SZ_INT) = (*(m_int*)REG(-SZ_INT) op *(m_int*)REG(0));},) -#define describe_pre(name, op) \ -static INSTR(int_pre_##name) { *(m_int*)REG(- SZ_INT) = op(**(m_int**)REG(- SZ_INT)); } -#define describe_post(name, op) \ -static INSTR(int_post_##name) { GWDEBUG_EXE *(m_int*)REG(- SZ_INT) = (**(m_int**)REG(- SZ_INT))op; } - -static INSTR(int_negate) { GWDEBUG_EXE *(m_int*)REG(-SZ_INT) *= -1; } -static INSTR(int_cmp) { GWDEBUG_EXE *(m_int*)REG(-SZ_INT) = ~*(m_int*)REG(-SZ_INT); } - -INSTR(IntNot) { GWDEBUG_EXE *(m_int*)REG(-SZ_INT) = !*(m_int*)REG(-SZ_INT); } - -static INSTR(int_r_assign) { GWDEBUG_EXE - POP_REG(shred, SZ_INT); - **(m_int**)REG(0) = *(m_int*)REG(-SZ_INT); -} - -describe(plus, +,) -describe(minus, -,) -describe(mul, *,) -describe(div, /, TEST0(0)) -describe(modulo, %, TEST0(0)) - -describe_logical(and, &&) -describe_logical(or, ||) -describe_logical(eq, ==) -describe_logical(neq, !=) -describe_logical(gt, >) -describe_logical(ge, >=) -describe_logical(lt, <) -describe_logical(le, <=) -describe_logical(sl, <<) -describe_logical(sr, >>) -describe_logical(sand, &) -describe_logical(sor, |) -describe_logical(xor, ^) - -describe_pre(inc, ++) -describe_pre(dec, --) -//describe_pre(cmp, ~) -describe_post(inc, ++) -describe_post(dec, --) - -describe_r(plus, +,) -describe_r(minus, -,) -describe_r(mul, *,) -describe_r(div, /, TEST0(-SZ_INT)) -describe_r(modulo, %, TEST0(-SZ_INT)) -describe_r(sl, <<,) -describe_r(sr, >>,) -describe_r(sand, &,) -describe_r(sor, |,) -describe_r(sxor, ^,) - -#define CHECK_OP(op, check, func) _CHECK_OP(op, check, int_##func) - -GWION_IMPORT(int) { - CHECK_BB(gwi_oper_ini(gwi, "int", "int", "int")) - CHECK_BB(gwi_oper_end(gwi, op_add, int_plus)) - CHECK_BB(gwi_oper_end(gwi, op_sub, int_minus)) - CHECK_BB(gwi_oper_end(gwi, op_mul, int_mul)) - CHECK_BB(gwi_oper_end(gwi, op_div, int_div)) - CHECK_BB(gwi_oper_end(gwi, op_mod, int_modulo)) - CHECK_BB(gwi_oper_end(gwi, op_and, int_and)) - CHECK_BB(gwi_oper_end(gwi, op_or, int_or)) - CHECK_BB(gwi_oper_end(gwi, op_eq, int_eq)) - CHECK_BB(gwi_oper_end(gwi, op_ne, int_neq)) - CHECK_BB(gwi_oper_end(gwi, op_gt, int_gt)) - CHECK_BB(gwi_oper_end(gwi, op_ge, int_ge)) - CHECK_BB(gwi_oper_end(gwi, op_lt, int_lt)) - CHECK_BB(gwi_oper_end(gwi, op_le, int_le)) - CHECK_BB(gwi_oper_end(gwi, op_shr, int_sr)) - CHECK_BB(gwi_oper_end(gwi, op_shl, int_sl)) - CHECK_BB(gwi_oper_end(gwi, op_sand, int_sand)) - CHECK_BB(gwi_oper_end(gwi, op_sor, int_sor)) - CHECK_BB(gwi_oper_end(gwi, op_sxor, int_xor)) - CHECK_OP(chuck, rassign, r_assign) - CHECK_OP(radd, rassign, r_plus) - CHECK_OP(rsub, rassign, r_minus) - CHECK_OP(rmul, rassign, r_mul) - CHECK_OP(rdiv, rassign, r_div) - CHECK_OP(rmod, rassign, r_modulo) - CHECK_OP(rsl, rassign, r_sl) - CHECK_OP(rsr, rassign, r_sr) - CHECK_OP(rsand, rassign, r_sand) - CHECK_OP(rsor, rassign, r_sor) - CHECK_OP(rsxor, rassign, r_sxor) - CHECK_BB(gwi_oper_ini(gwi, NULL, "int", "int")) - CHECK_BB(gwi_oper_add(gwi, opck_unary_meta)) - CHECK_BB(gwi_oper_end(gwi, op_sub, int_negate)) - CHECK_BB(gwi_oper_add(gwi, opck_unary_meta)) - CHECK_BB(gwi_oper_end(gwi, op_not, IntNot)) -// CHECK_OP(not, unary_meta, not) - CHECK_OP(inc, unary, pre_inc) - CHECK_OP(dec, unary, pre_dec) - CHECK_BB(gwi_oper_end(gwi, op_cmp, int_cmp)) -// CHECK_OP(cmp, unary, pre_cmp) - CHECK_BB(gwi_oper_ini(gwi, "int", NULL, "int")) - CHECK_OP(inc, post, post_inc) - CHECK_OP(dec, post, post_dec) - CHECK_BB(gwi_enum_ini(gwi, "bool")) - CHECK_BB(gwi_enum_add(gwi, "false", 0)) - CHECK_BB(gwi_enum_add(gwi, "true", 1)) - CHECK_BB(gwi_enum_end(gwi)) - gwi_item_ini(gwi, "bool", "maybe"); - gwi_item_end(gwi, 0, NULL); - return GW_OK; -} diff --git a/src/lib/object.c b/src/lib/object.c index b390eaebc..1094b0030 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -15,7 +15,7 @@ ANN void exception(const VM_Shred shred, const m_str c) { err_msg(0, "%s: shred[id=%" UINT_F ":%s], PC=[%" UINT_F "]", - c, shred->xid, shred->name, shred->pc - 1); + c, shred->tick->xid, shred->info->name, shred->pc - 1); vm_shred_exit(shred); } @@ -23,6 +23,7 @@ M_Object new_object(const VM_Shred shred, const Type t) { const M_Object a = mp_alloc(M_Object); a->ref = 1; a->type_ref = t; + a->vtable = &t->nspc->vtable; if(t->nspc->offset) { Type type = t; while(!type->p) @@ -62,14 +63,14 @@ ANN static void handle_dtor(const M_Object object, const VM_Shred shred) { *(M_Object*)sh->mem = object; sh->mem += SZ_INT; *(M_Object*)sh->mem = object; - vm_add_shred(shred->vm, sh); - ++sh->me->ref; + vm_add_shred(shred->info->vm, sh); + ++sh->info->me->ref; } __attribute__((hot)) ANN void __release(const M_Object obj, const VM_Shred shred) { Type t = obj->type_ref; - do { + while(t->parent) { struct scope_iter iter = { &t->nspc->value, 0, 0 };\ Value v; while(scope_iter(&iter, &v) > 0) { @@ -77,36 +78,24 @@ ANN void __release(const M_Object obj, const VM_Shred shred) { release(*(M_Object*)(obj->data + v->offset), shred); } if(GET_FLAG(t, dtor)) { - if(t->nspc->dtor->native_func) - ((f_xtor)t->nspc->dtor->native_func)(obj, shred); + if(GET_FLAG(t->nspc->dtor, builtin)) + ((f_xtor)t->nspc->dtor->native_func)(obj, NULL, shred); else { handle_dtor(obj, shred); return; } } - } while((t = t->parent)); + t = t->parent; + } + free_object(obj); } -void free_object(const M_Object o) { +ANN void free_object(const M_Object o) { if(o->data) _mp_free2(o->p, o->data); mp_free(M_Object, o); } -static DTOR(object_dtor) { free_object(o); } -INSTR(ObjectAssign) { GWDEBUG_EXE - POP_REG(shred, SZ_INT); - const M_Object src = *(M_Object*)REG(-SZ_INT); - const M_Object tgt = **(M_Object**)REG(0); - if(tgt) { - --tgt->ref; - _release(tgt, shred); - } - if(instr->m_val) - *(m_bit**)REG(-SZ_INT) = REG(-SZ_INT); - **(M_Object**)REG(0) = src; -} - #define describe_logical(name, op) \ static INSTR(name##Object) { GWDEBUG_EXE \ POP_REG(shred, SZ_INT); \ @@ -138,7 +127,14 @@ static OP_CHECK(opck_object_cast) { const Exp_Cast* cast = (Exp_Cast*)data; const Type l = cast->exp->type; const Type r = cast->self->type; - return isa(l, r) > 0 ? r : t_null; +// return isa(l, r) > 0 ? r : t_null; + if(isa(l, r) > 0) { + const Type t = type_copy(r); + SET_FLAG(t, force); + env_add_type(env, t); + return t; + } + return t_null; } static OP_CHECK(opck_implicit_null2obj) { @@ -148,7 +144,7 @@ static OP_CHECK(opck_implicit_null2obj) { GWION_IMPORT(object) { CHECK_OB((t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL))) - CHECK_BB(gwi_class_ini(gwi, t_object, NULL, object_dtor)) + CHECK_BB(gwi_class_ini(gwi, t_object, NULL, NULL)) CHECK_BB(gwi_class_end(gwi)) CHECK_BB(gwi_oper_ini(gwi, "@null", "Object", "Object")) CHECK_BB(gwi_oper_add(gwi, at_object)) diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index d4cde019c..4af00e998 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -50,15 +50,6 @@ OP_CHECK(opck_rassign) { OP_CHECK(opck_unary_meta) { const Exp_Unary* unary = (Exp_Unary*)data; unary->self->meta = ae_meta_value; -#ifdef OPTIMIZE - if(unary->exp->exp_type == ae_exp_constprop2) { - unary->exp->exp_type =ae_exp_primary; - unary->exp->d.exp_primary.primary_type = ae_primary_id; - unary->exp->d.exp_primary.d.num = (m_uint)unary->exp->d.exp_primary.value->d.ptr; - UNSET_FLAG(unary->exp->d.exp_primary.value, constprop); - unary->exp->d.exp_primary.value->d.ptr = 0; - } -#endif return unary->exp->type; } @@ -70,21 +61,6 @@ OP_CHECK(opck_unary) { op2str(unary->op), access(unary->exp->meta)) unary->exp->emit_var = 1; unary->self->meta = ae_meta_value; -#ifdef OPTIMIZE -if(unary->exp->exp_type == ae_exp_primary && - GET_FLAG(unary->exp->d.exp_primary.value, constprop)) { - UNSET_FLAG(unary->exp->d.exp_primary.value, constprop); - unary->exp->d.exp_primary.value->d.ptr = 0; - return unary->exp->type; -} - if(unary->exp->exp_type == ae_exp_constprop) { - unary->exp->exp_type = ae_exp_primary; - unary->exp->d.exp_primary.primary_type = ae_primary_constprop; - unary->exp->d.exp_primary.d.num = (m_uint)unary->exp->d.exp_primary.value->d.ptr; - UNSET_FLAG(unary->exp->d.exp_primary.value, constprop); - unary->exp->d.exp_primary.value->d.ptr = 0; - } -#endif return unary->exp->type; } @@ -95,28 +71,6 @@ OP_CHECK(opck_post) { op2str(post->op), access(post->exp->meta)) post->exp->emit_var = 1; post->self->meta = ae_meta_value; -#ifdef OPTIMIZE -if(post->exp->exp_type == ae_exp_primary && - GET_FLAG(post->exp->d.exp_primary.value, constprop)) { - UNSET_FLAG(post->exp->d.exp_primary.value, constprop); - post->exp->d.exp_primary.value->d.ptr = 0; - return post->exp->type; -} - if(post->exp->exp_type == ae_exp_constprop2) {exit(3); - post->exp->exp_type =ae_exp_primary; - post->exp->d.exp_primary.primary_type = ae_primary_constprop; - post->exp->d.exp_primary.d.num = (m_uint)post->exp->d.exp_primary.value->d.ptr; - UNSET_FLAG(post->exp->d.exp_primary.value, constprop); - post->exp->d.exp_primary.value->d.ptr = 0; -} - if(post->exp->exp_type == ae_exp_constprop) {exit(2); - post->exp->exp_type =ae_exp_primary; - post->exp->d.exp_primary.primary_type = ae_primary_constprop; - post->exp->d.exp_primary.d.num = (m_uint)post->exp->d.exp_primary.value->d.ptr; - UNSET_FLAG(post->exp->d.exp_primary.value, constprop); - post->exp->d.exp_primary.value->d.ptr = 0; -} -#endif return post->exp->type; } diff --git a/src/lib/prim.c b/src/lib/prim.c new file mode 100644 index 000000000..ce575e13d --- /dev/null +++ b/src/lib/prim.c @@ -0,0 +1,85 @@ +#include "gwion_util.h" +#include "gwion_ast.h" +#include "oo.h" +#include "vm.h" +#include "env.h" +#include "type.h" +#include "instr.h" +#include "object.h" +#include "import.h" + +#define CHECK_OP(op, check, func) _CHECK_OP(op, check, int_##func) + +GWION_IMPORT(int_op) { + CHECK_BB(gwi_oper_ini(gwi, "int", "int", "int")) + CHECK_BB(gwi_oper_end(gwi, op_add, int_plus)) + CHECK_BB(gwi_oper_end(gwi, op_sub, int_minus)) + CHECK_BB(gwi_oper_end(gwi, op_mul, int_mul)) + CHECK_BB(gwi_oper_end(gwi, op_div, int_div)) + return gwi_oper_end(gwi, op_mod, int_modulo); +} + +static GWION_IMPORT(int_logical) { + CHECK_BB(gwi_oper_end(gwi, op_and, int_and)) + CHECK_BB(gwi_oper_end(gwi, op_or, int_or)) + CHECK_BB(gwi_oper_end(gwi, op_eq, int_eq)) + CHECK_BB(gwi_oper_end(gwi, op_ne, int_neq)) + CHECK_BB(gwi_oper_end(gwi, op_gt, int_gt)) + CHECK_BB(gwi_oper_end(gwi, op_ge, int_ge)) + CHECK_BB(gwi_oper_end(gwi, op_lt, int_lt)) + CHECK_BB(gwi_oper_end(gwi, op_le, int_le)) + CHECK_BB(gwi_oper_end(gwi, op_shr, int_sr)) + CHECK_BB(gwi_oper_end(gwi, op_shl, int_sl)) + CHECK_BB(gwi_oper_end(gwi, op_sand, int_sand)) + CHECK_BB(gwi_oper_end(gwi, op_sor, int_sor)) + return gwi_oper_end(gwi, op_sxor, int_xor); +} + +static GWION_IMPORT(int_r) { + CHECK_OP(chuck, rassign, r_assign) + CHECK_OP(radd, rassign, r_plus) + CHECK_OP(rsub, rassign, r_minus) + CHECK_OP(rmul, rassign, r_mul) + CHECK_OP(rdiv, rassign, r_div) + CHECK_OP(rmod, rassign, r_modulo) + CHECK_OP(rsl, rassign, r_sl) + CHECK_OP(rsr, rassign, r_sr) + CHECK_OP(rsand, rassign, r_sand) + CHECK_OP(rsor, rassign, r_sor) + CHECK_OP(rsxor, rassign, r_sxor) + return GW_OK; +} + +static GWION_IMPORT(int_unary) { + CHECK_BB(gwi_oper_ini(gwi, NULL, "int", "int")) + CHECK_BB(gwi_oper_add(gwi, opck_unary_meta)) + CHECK_BB(gwi_oper_end(gwi, op_sub, int_negate)) + CHECK_BB(gwi_oper_add(gwi, opck_unary_meta)) + CHECK_BB(gwi_oper_end(gwi, op_not, IntNot)) + CHECK_OP(inc, unary, pre_inc) + CHECK_OP(dec, unary, pre_dec) + CHECK_BB(gwi_oper_end(gwi, op_cmp, int_cmp)) + CHECK_BB(gwi_oper_ini(gwi, "int", NULL, "int")) + CHECK_OP(inc, post, post_inc) + CHECK_BB(gwi_oper_add(gwi, opck_post)) + CHECK_BB(gwi_oper_end(gwi, op_dec, int_post_dec)) + return GW_OK; +} + +static GWION_IMPORT(int_values) { + CHECK_BB(gwi_enum_ini(gwi, "bool")) + CHECK_BB(gwi_enum_add(gwi, "false", 0)) + CHECK_BB(gwi_enum_add(gwi, "true", 1)) + CHECK_BB(gwi_enum_end(gwi)) + CHECK_BB(gwi_item_ini(gwi, "bool", "maybe")) + return gwi_item_end(gwi, 0, NULL); +} + +GWION_IMPORT(int) { + CHECK_BB(gwi_oper_ini(gwi, "int", "int", "int")) + CHECK_BB(import_int_op(gwi)) + CHECK_BB(import_int_logical(gwi)) + CHECK_BB(import_int_r(gwi)) + CHECK_BB(import_int_unary(gwi)) + return import_int_values(gwi); +} diff --git a/src/lib/shred.c b/src/lib/shred.c index 2f7bdd17f..ba7225e3e 100644 --- a/src/lib/shred.c +++ b/src/lib/shred.c @@ -23,12 +23,12 @@ static MFUN(gw_shred_exit) { static MFUN(vm_shred_id) { const VM_Shred s = ME(o); - *(m_int*)RETURN = s ? (m_int)s->xid : -1; + *(m_int*)RETURN = s ? (m_int)s->tick->xid : -1; } static MFUN(vm_shred_is_running) { const VM_Shred s = ME(o); - *(m_uint*)RETURN = (s->next || s->prev) ? 1 : 0; + *(m_uint*)RETURN = (s->tick->next || s->tick->prev) ? 1 : 0; } static MFUN(vm_shred_is_done) { @@ -37,31 +37,33 @@ static MFUN(vm_shred_is_done) { static MFUN(shred_yield) { const VM_Shred s = ME(o); - const Shreduler sh = shred->vm->shreduler; + const Shreduler sh = shred->info->vm->shreduler; shredule(sh, s, .5); +// shred->mem += (m_bit*)o - shred->mem; +// shred->mem -= SZ_INT;//!!! } #include "shreduler_private.h" static SFUN(vm_shred_from_id) { const m_int index = *(m_int*)MEM(0); - const VM_Shred s = (VM_Shred)vector_at(&shred->vm->shreduler->shreds, (vtype)index); + const VM_Shred s = (VM_Shred)vector_at(&shred->info->vm->shreduler->shreds, (vtype)index); if(s) { - *(M_Object*)RETURN = s->me; - s->me->ref++; - vector_add(&shred->gc, (vtype) s->me); + *(M_Object*)RETURN = s->info->me; + s->info->me->ref++; + vector_add(&shred->gc, (vtype) s->info->me); } else *(m_uint*)RETURN = 0; } static MFUN(shred_args) { const VM_Shred s = ME(o); - *(m_uint*)RETURN = s->args ? vector_size(s->args) : 0; + *(m_uint*)RETURN = s->info->args ? vector_size(s->info->args) : 0; } static MFUN(shred_arg) { const VM_Shred s = ME(o); const m_int idx = *(m_int*)MEM(SZ_INT); - if(s->args && idx >= 0) { - const m_str str = (m_str)vector_at(s->args, *(m_uint*)MEM(SZ_INT)); + if(s->info->args && idx >= 0) { + const m_str str = (m_str)vector_at(s->info->args, *(m_uint*)MEM(SZ_INT)); *(M_Object*)RETURN = str ? new_string(shred, str) : NULL; } else *(m_uint*)RETURN = 0; @@ -81,7 +83,7 @@ static MFUN(shred##name##_dir) { \ strcpy(c, str); \ *(m_uint*)RETURN = (m_uint)new_string(shred, dirname(c)); \ } -describe_path_and_dir(, s->name) +describe_path_and_dir(, s->info->name) describe_path_and_dir(_code, s->code->name) GWION_IMPORT(shred) { diff --git a/src/lib/string.c b/src/lib/string.c index 7818a2158..87f24563d 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -161,11 +161,6 @@ describe_string_plus(Vec4_, SZ_VEC4, m_vec4,, describe_string_plus(Object_, SZ_INT, M_Object, release(lhs, shred), 11, "%p", (void*)lhs) -INSTR(RegPushStr) { GWDEBUG_EXE - *(M_Object*)REG(0) = new_string2(shred, (m_str)instr->m_val); - PUSH_REG(shred, SZ_INT); -} - static CTOR(string_ctor) { STRING(o) = ""; } diff --git a/src/lib/ugen.c b/src/lib/ugen.c index 9ca5ea819..8e84e1b2b 100644 --- a/src/lib/ugen.c +++ b/src/lib/ugen.c @@ -203,7 +203,7 @@ describe_connect_instr(Trig, Disconnect, TRIG_EX) static CTOR(ugen_ctor) { UGEN(o) = new_UGen(); - vector_add(&shred->vm->ugen, (vtype)UGEN(o)); + vector_add(&shred->info->vm->ugen, (vtype)UGEN(o)); } #define describe_release_func(src, tgt, opt) \ @@ -231,7 +231,7 @@ ANN static void release_multi(const UGen ug, const VM_Shred shred) { static DTOR(ugen_dtor) { const UGen ug = UGEN(o); - vector_rem2(&shred->vm->ugen, (vtype)ug); + vector_rem2(&shred->info->vm->ugen, (vtype)ug); if(!ug->multi) release_mono(ug); else diff --git a/src/lib/vec.c b/src/lib/vec.c index 59dcba4ed..045c336fd 100644 --- a/src/lib/vec.c +++ b/src/lib/vec.c @@ -8,6 +8,13 @@ #include "object.h" #include "import.h" +INSTR(VecCpy) { + POP_REG(shred, instr->m_val2); + for(m_uint i = 0; i < instr->m_val2; i += SZ_FLOAT) + *(m_float*)(shred->mem +instr->m_val-instr->m_val2+i) = *(m_float*)(shred->reg+i); + *(m_bit**)(shred->mem + instr->m_val) = (shred->mem + instr->m_val - instr->m_val2); +} + INSTR(VecMember) { GWDEBUG_EXE if(instr->m_val) *(m_float**)REG(-SZ_INT) = (m_float*)(*(m_bit**)REG(-SZ_INT) + instr->m_val2); @@ -61,7 +68,7 @@ static MFUN(vec3_##name) { \ } describe_vec3_x(interp, + v->x) describe_vec3_x(float, * v->z * (*(m_float*)MEM(SZ_INT)) + v->x) -describe_vec3_x(dur, * (*(m_float*)MEM(SZ_INT) / (m_float)shred->vm->bbq->sr) + v->x) +describe_vec3_x(dur, * (*(m_float*)MEM(SZ_INT) / (m_float)shred->info->vm->bbq->sr) + v->x) static MFUN(vec3_update) { m_vec3* v = *(m_vec3**)MEM(0); diff --git a/src/main.c b/src/main.c index 6a148ea6a..973e95f77 100644 --- a/src/main.c +++ b/src/main.c @@ -1,101 +1,43 @@ -#include -#include -//#include #include -#include -#include -#include #include "gwion_util.h" #include "gwion_ast.h" #include "oo.h" #include "vm.h" #include "env.h" -#include "type.h" -#include "instr.h" #include "compile.h" #include "driver.h" +#include "gwion.h" #include "arg.h" -#include "engine.h" - -#ifdef VMBENCH -#include -#include -#define VMBENCH_INI \ - struct timespec ini, end, ret; \ - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ini); -#define VMBENCH_END \ - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); \ - timespecsub(&end, &ini, &ret); \ - printf("timespec %lu.%09lu\n", ret.tv_sec, ret.tv_nsec); -#else -#define VMBENCH_INI -#define VMBENCH_END -#endif - -#include "plug.h" -#include -#include -extern void parse_args(Arg*, DriverInfo*); -static VM* some_static_vm; +static struct Gwion_ gwion; static void sig(int unused __attribute__((unused))) { - some_static_vm->is_running = 0; + gwion.vm->is_running = 0; } -#include "gwion.h" int main(int argc, char** argv) { - Driver d; - Arg arg; + Arg arg = { .argc = argc, .argv=argv, .loop=-1 }; DriverInfo di = { 2, 2, 2, 48000, 256, 3, "default:CARD=CODEC", 0, 0, D_FUNC, vm_run, 0, 0}; - - d.del = NULL; - memset(&arg, 0, sizeof(Arg)); - arg.argc = argc; - arg.argv = argv; - arg.loop = -1; - arg_init(&arg); -//__fsetlocking(stdout, FSETLOCKING_BYCALLER); -//__fsetlocking(stderr, FSETLOCKING_BYCALLER); - - parse_args(&arg, &di); -struct Gwion_ gwion; - - if(arg.quit) - goto clean; +//#define BUFSZ 10000 +//char outbuf[BUFSZ], errbuf[BUFSZ]; +//setvbuf(stdout, outbuf, _IOFBF, BUFSZ); +//setvbuf(stderr, errbuf, _IOFBF, BUFSZ); + if(parse_args(&arg, &di)) { + arg_release(&arg); + return 0; + } + gwion_init(&gwion, &arg.lib); signal(SIGINT, sig); signal(SIGTERM, sig); - -// init_symbols(); - PlugInfo pi; -// gwion.pi = pi; - plug_ini(pi, &arg.lib); - - - gwion_init(&gwion); - some_static_vm = gwion.vm; - di.func(&d); - shreduler_set_loop(gwion.vm->shreduler, arg.loop); - if(d.ini(gwion.vm, &di) < 0 || !(gwion.vm->bbq = new_bbq(&di))) - goto clean; - if(type_engine_init(gwion.vm, &pi[1]) < 0) - goto clean; - srand((uint)time(NULL)); - for(m_uint i = 0; i < vector_size(&arg.add); i++) - compile_filename(&gwion, (m_str)vector_at(&arg.add, i)); - gwion.vm->is_running = 1; - VMBENCH_INI - d.run(gwion.vm, &di); - VMBENCH_END -clean: + if(gwion_audio(&gwion, &di) && gwion_engine(&gwion)) { + module_ini(&gwion, &arg.mod); + for(m_uint i = 0; i < vector_size(&arg.add); i++) + compile_filename(&gwion, (m_str)vector_at(&arg.add, i)); + shreduler_set_loop(gwion.vm->shreduler, arg.loop); + gwion_run(&gwion, &di); + } arg_release(&arg); - if(d.del) - d.del(gwion.vm, &di); -#ifndef __linux__ - sleep(1); -#endif - plug_end(pi); - gwion_release(&gwion); + gwion_release(&gwion, &di); return 0; } diff --git a/src/oo/context.c b/src/oo/context.c index eff355b1e..370b3b632 100644 --- a/src/oo/context.c +++ b/src/oo/context.c @@ -6,22 +6,20 @@ #include "nspc.h" #include "context.h" +ANN static void free_context(const Context a) { + REM_REF(a->nspc) + mp_free(Context, a); +} + ANN2(2) Context new_context(const Ast ast, const m_str str) { const Context context = mp_alloc(Context); context->nspc = new_nspc(str); context->tree = ast; context->name = str; - INIT_OO(context, e_context_obj); + INIT_OO(context, free_context); return context; } -ANN void free_context(const Context a) { -//if(a->nspc->obj.ref_count > 1)exit(2); -// REM_REF(a->nspc); - free_nspc(a->nspc); - mp_free(Context, a); -} - ANN void load_context(const Context context, const Env env) { ADD_REF((env->context = context)) vector_add(&env->nspc_stack, (vtype)env->curr); diff --git a/src/oo/env.c b/src/oo/env.c index ffa8de24b..de50af360 100644 --- a/src/oo/env.c +++ b/src/oo/env.c @@ -23,8 +23,6 @@ Env new_env() { vector_init(&env->nspc_stack); vector_init(&env->known_ctx); env->type_xid = 0; -// scope_init(&env->swi); -// vector_pop((Vector)&env->swi); vector_init((Vector)&env->swi); map_init(&env->swi.map); @@ -48,10 +46,10 @@ ANN void env_reset(const Env env) { ANN void free_env(const Env a) { const m_uint size = vector_size(&a->known_ctx); - for(m_uint i = 0; i < size; i++) - REM_REF((Context)vector_at(&a->known_ctx, i)); - REM_REF(a->global_nspc); + for(m_uint i = size + 1; --i;) + REM_REF((Context)vector_at(&a->known_ctx, i - 1)); vector_release(&a->known_ctx); + REM_REF(a->global_nspc); vector_release(&a->nspc_stack); vector_release(&a->class_stack); vector_release(&a->breaks); @@ -77,16 +75,6 @@ ANN void env_pop(const Env env, const m_uint scope) { env->scope = scope; } -ANN2(1,2) void env_add_value(const Env env, const m_str name, const Type type, - const m_bool is_const, void* data) { - const Value v = new_value(env->gwion, type, name); - ae_flag flag = ae_flag_checked | ae_flag_global | ae_flag_builtin | (is_const ? ae_flag_const : 0); - v->flag = flag; - v->d.ptr = data; - v->owner = env->global_nspc; - nspc_add_value(env->global_nspc, insert_symbol(name), v); -} - ANN void env_add_type(const Env env, const Type type) { const Type v_type = type_copy(t_class); v_type->d.base_type = type; diff --git a/src/oo/nspc.c b/src/oo/nspc.c index 0b3c730a8..7d15ef373 100644 --- a/src/oo/nspc.c +++ b/src/oo/nspc.c @@ -18,24 +18,14 @@ ANN void nspc_commit(const Nspc nspc) { scope_commit(&nspc->type); } -ANN Nspc new_nspc(const m_str name) { - const Nspc a = mp_alloc(Nspc); - a->name = name; - scope_init(&a->value); - scope_init(&a->type); - scope_init(&a->func); - INIT_OO(a, e_nspc_obj); - return a; -} - ANN static void nspc_release_object(const Nspc a, Value value) { if(value->d.ptr || (GET_FLAG(value, static) && a->class_data) || (value->d.ptr && GET_FLAG(value, builtin))) { - const VM_Code code = new_vm_code(NULL, 0, 0, "in code dtor"); + const VM_Code code = new_vm_code(NULL, 0, ae_flag_builtin, "in code dtor"); const VM_Shred s = new_vm_shred(code); const M_Object obj = value->d.ptr ? (M_Object)value->d.ptr : *(M_Object*)(a->class_data + value->offset); - s->vm = value->gwion->vm; + s->info->vm = value->gwion->vm; release(obj, s); free_vm_shred(s); } @@ -67,10 +57,10 @@ ANN static void nspc_free_##b(Nspc n) {\ describe_nspc_free(Func, func) describe_nspc_free(Type, type) -ANN void free_nspc(Nspc a) { - free_nspc_value(a); +ANN static void free_nspc(Nspc a) { nspc_free_func(a); nspc_free_type(a); + free_nspc_value(a); if(a->class_data) free(a->class_data); @@ -84,3 +74,13 @@ ANN void free_nspc(Nspc a) { free_op_map(&a->op_map); mp_free(Nspc, a); } + +ANN Nspc new_nspc(const m_str name) { + const Nspc a = mp_alloc(Nspc); + a->name = name; + scope_init(&a->value); + scope_init(&a->type); + scope_init(&a->func); + INIT_OO(a, free_nspc); + return a; +} diff --git a/src/oo/oo.c b/src/oo/oo.c deleted file mode 100644 index 657ad330f..000000000 --- a/src/oo/oo.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "gwion_util.h" -#include "gwion_ast.h" -#include "oo.h" - -extern ANN void free_nspc(void* a); -extern ANN void free_type(void* a); -extern ANN void free_value(void* a); -extern ANN void free_context(void* a); -extern ANN void free_func(void* a); -extern ANN void free_vm_code(void* a); - -typedef void (*cleaner)(void*); -static cleaner cleaners[] = { free_nspc, free_context, free_type, - free_value, free_func, free_vm_code }; - -ANN void rem_ref(const VM_Object a, void* ptr) { - if(--a->ref_count) - return; - cleaners[a->type](ptr); -} diff --git a/src/oo/switch.c b/src/oo/switch.c index 4fa98087d..ec2389778 100644 --- a/src/oo/switch.c +++ b/src/oo/switch.c @@ -141,7 +141,7 @@ ANN Map switch_map(const Env env) { ANN Vector switch_vec(const Env env) { const Switch sw = (Switch)vector_back((Vector)&env->swi); - return sw->vec; // new_vector(); // dyn only + return vector_copy(sw->vec); // new_vector(); // dyn only } ANN m_uint switch_idx(const Env env) { diff --git a/src/oo/type.c b/src/oo/type.c index 9aa04e0a1..e7e2877ca 100644 --- a/src/oo/type.c +++ b/src/oo/type.c @@ -6,6 +6,14 @@ #include "type.h" #include "nspc.h" +ANN static void free_type(Type a) { + if(GET_FLAG(a, template)) + free_class_def(a->def); + if(a->nspc) + REM_REF(a->nspc); + mp_free(Type, a); +} + ANN2(2) Type new_type(const m_uint xid, const m_str name, const Type parent) { const Type type = mp_alloc(Type); type->xid = xid; @@ -13,18 +21,10 @@ ANN2(2) Type new_type(const m_uint xid, const m_str name, const Type parent) { type->parent = parent; if(type->parent) type->size = parent->size; - INIT_OO(type, e_type_obj); + INIT_OO(type, free_type); return type; } -ANN void free_type(Type a) { - if(GET_FLAG(a, template)) - free_class_def(a->def); - if(a->nspc) - REM_REF(a->nspc); - mp_free(Type, a); -} - ANN Type type_copy(const Type type) { const Type a = new_type(type->xid, type->name, type->parent); a->nspc = type->nspc; diff --git a/src/oo/value.c b/src/oo/value.c index 91afaa90f..879b4d197 100644 --- a/src/oo/value.c +++ b/src/oo/value.c @@ -6,24 +6,21 @@ #include "value.h" #include "type.h" +ANN static void free_value(Value a) { + if(!GET_FLAG(a, func) && a->d.ptr && + !(GET_FLAG(a, enum) && GET_FLAG(a, builtin) && a->owner_class) + && isa(a->type, t_object) < 0) + _mp_free(a->type->size, a->d.ptr); + if(isa(a->type, t_class) > 0 || isa(a->type, t_function) > 0 || GET_FLAG(a->type, op)) + REM_REF(a->type) + mp_free(Value, a); +} + ANN Value new_value(struct Gwion_* gwion, const Type type, const m_str name) { const Value a = mp_alloc(Value); a->type = type; a->name = name; a->gwion = gwion; - INIT_OO(a, e_value_obj); + INIT_OO(a, free_value); return a; } -ANN void free_value(Value a) { -// if(!GET_FLAG(a, func) && !GET_FLAG(a, constprop) && a->d.ptr && isa(a->type, t_object) < 0) - if(!GET_FLAG(a, func) && !GET_FLAG(a, constprop) && a->d.ptr && -!(GET_FLAG(a, enum) && GET_FLAG(a, builtin) && a->owner_class) -&& isa(a->type, t_object) < 0) - _mp_free(a->type->size, a->d.ptr); - if(isa(a->type, t_class) > 0 || isa(a->type, t_function) > 0) - REM_REF(a->type) - if(GET_FLAG(a->type, op)) - REM_REF(a->type) - mp_free(Value, a); -} - diff --git a/src/parse/check.c b/src/parse/check.c index da48ad874..f9a6ab580 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -103,6 +103,8 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) { GWDEBUG_EXE decl_member(env->curr, v); else if(GET_FLAG(decl->td, static)) decl_static(env->curr, v); + else if(global || (env->func && GET_FLAG(env->func->def, global))) + SET_FLAG(v, abstract); if(isa(decl->type, t_fptr) > 0) CHECK_BO(check_fptr_decl(env, var)) SET_FLAG(v, checked | ae_flag_used); @@ -148,6 +150,10 @@ ANN static Value check_non_res_value(const Env env, const Exp_Primary* primary) ERR_O(primary->self->pos, "non-static member '%s' used from static function.", s_name(primary->d.var)) return v; + } else if(env->func && GET_FLAG(env->func->def, global)) { + if(!SAFE_FLAG(value, abstract) && !SAFE_FLAG(value, arg)) + ERR_O(primary->self->pos, + "non-global variable '%s' used from global function.", s_name(primary->d.var)) } return value; } @@ -358,6 +364,9 @@ ANN2(1, 2) static Func find_func_match(const Env env, const Func up, const Exp e } ANN static m_bool check_call(const Env env, const Exp_Call* exp) { + ae_exp_t et = exp->func->exp_type; + if(et != ae_exp_primary && et != ae_exp_dot && et != ae_exp_cast) + ERR_B(exp->func->pos, "invalid expression for function call.") CHECK_OB(check_exp(env, exp->func)) return exp->args ? !!check_exp(env, exp->args) : -1; } @@ -368,7 +377,7 @@ ANN static inline Value template_get_ready(const Value v, const m_str tmpl, cons nspc_lookup_value1(v->owner, sym); } -ANN Func find_template_match(const Env env, const Value v, const Exp_Call* exp) { +ANN static Func _find_template_match(const Env env, const Value v, const Exp_Call* exp) { const Exp args = exp->args; const Type_List types = exp->tmpl->types; Func m_func = exp->m_func; @@ -385,15 +394,25 @@ ANN Func find_template_match(const Env env, const Value v, const Exp_Call* exp) return env->func; } base = def = value->d.func_ref->def; +if(!def->tmpl) { + if(!(value = template_get_ready(v, "template", i))) + continue; + base = value->d.func_ref->def; + def->tmpl = new_tmpl_list(base->tmpl->list, (m_int)i); +} } else { if(!(value = template_get_ready(v, "template", i))) continue; base = value->d.func_ref->def; def = new_func_def(base->td, insert_symbol(v->name), +// def = new_func_def(base->td, insert_symbol(v->name), base->arg_list, base->d.code, base->flag); +//create = 1; +//assert(base->tmpl); def->tmpl = new_tmpl_list(base->tmpl->list, (m_int)i); SET_FLAG(def, template); } +//assert(def->tmpl); if(traverse_func_template(env, def, types) > 0) { nspc_pop_type(env->curr); if(check_call(env, exp) > 0) { @@ -402,21 +421,47 @@ ANN Func find_template_match(const Env env, const Value v, const Exp_Call* exp) m_func = find_func_match(env, def->func, args); def->func->next = next; if(m_func) { +if(!m_func->def->ret_type) { +if(!m_func->def->td)exit(76); +m_func->def->ret_type = type_decl_resolve(env, m_func->def->td); +exit(77); +} SET_FLAG(m_func, checked | ae_flag_template); goto end; } } } SET_FLAG(base, template); - free_func_def(def); +//if(create) +// free_func_def(def); } - assert(exp->self); - err_msg(exp->self->pos, "arguments do not match for template call"); +// assert(exp->self); +// err_msg(exp->self->pos, "arguments do not match for template call"); end: free(tmpl_name); env_pop(env, scope); return m_func; } +ANN Func find_template_match(const Env env, const Value value, const Exp_Call* exp) { + Type t = value->owner_class; + const Func f = _find_template_match(env, value, exp); + if(f) + return f; + while(t) { + Value v = nspc_lookup_value1(t->nspc, value->d.func_ref->def->name); + if(!v) + goto next; + const Func f = _find_template_match(env, v, exp); + if(f) + return f; + next: + t = t->parent; + } + assert(exp->self); + err_msg(exp->self->pos, "arguments do not match for template call"); + return NULL; +} + ANN static void print_current_args(Exp e) { gw_err("and not\n\t"); @@ -590,7 +635,7 @@ ANN static Type check_exp_dur(const Env env, const Exp_Dur* exp) { GWDEBUG_EXE ANN static Type check_exp_call(const Env env, Exp_Call* exp) { GWDEBUG_EXE if(exp->tmpl) { - CHECK_OO(check_exp(env, exp->func)) // → puts this up ? + CHECK_OO(check_exp(env, exp->func)) const Type t = actual_type(exp->func->type); const Value v = nspc_lookup_value1(t->owner, insert_symbol(t->name)); if(!v) @@ -926,7 +971,8 @@ ANN static m_bool check_stmt_list(const Env env, Stmt_List l) { GWDEBUG_EXE } ANN static m_bool check_signature_match(const Func_Def f, const Func parent) { GWDEBUG_EXE - if(GET_FLAG(parent->def, static) || GET_FLAG(f, static)) { +// if(GET_FLAG(parent->def, static) || GET_FLAG(f, static)) { + if(GET_FLAG(parent->def, static) != GET_FLAG(f, static)) { // wath me const m_str c_name = f->func->value_ref->owner_class->name; const m_str p_name = parent->value_ref->owner_class->name; const m_str f_name = s_name(f->name); @@ -936,7 +982,9 @@ ANN static m_bool check_signature_match(const Func_Def f, const Func parent) { G c_name, f_name, p_name, c_name, GET_FLAG(f, static) ? c_name : p_name, f_name) } - return isa(f->ret_type, parent->def->ret_type); + if(!f->tmpl) // ??? + return isa(f->ret_type, parent->def->ret_type); + return GW_OK; } ANN static m_bool parent_match_actual(const Env env, const restrict Func_Def f, @@ -945,8 +993,10 @@ ANN static m_bool parent_match_actual(const Env env, const restrict Func_Def f, do { if(compat_func(f, parent_func->def) > 0) { CHECK_BB(check_signature_match(f, parent_func)) - f->func->vt_index = parent_func->vt_index; - vector_set(&env->curr->vtable, f->func->vt_index, (vtype)func); + if(!f->tmpl) { + f->func->vt_index = parent_func->vt_index; + vector_set(&env->curr->vtable, f->func->vt_index, (vtype)f->func); + } return GW_OK; } } while((parent_func = parent_func->next)); @@ -964,12 +1014,12 @@ ANN static m_bool check_parent_match(const Env env, const Func_Def f) { GWDEBUG_ return match; } } - if(GET_FLAG(func, member)) { - if(!env->curr->vtable.ptr) - vector_init(&env->curr->vtable); - func->vt_index = vector_size(&env->curr->vtable); - vector_add(&env->curr->vtable, (vtype)func); - } +// if(GET_FLAG(func, member)) { + if(!env->curr->vtable.ptr) + vector_init(&env->curr->vtable); + func->vt_index = vector_size(&env->curr->vtable); + vector_add(&env->curr->vtable, (vtype)func); +// } return GW_OK; } @@ -1039,12 +1089,14 @@ ANN static void operator_func(Func f) { ANN m_bool check_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE const Func func = get_func(env, f); - m_bool ret = 1; + m_bool ret = GW_OK; if(tmpl_list_base(f->tmpl)) return env->class_def ? check_parent_match(env, f) : 1; CHECK_BB(check_func_def_override(env, f)) if(env->class_def) CHECK_BB(check_parent_match(env, f)) + else if(GET_FLAG(f, global)) + env_push_global(env); const Func former = env->func; env->func = func; ++env->scope; @@ -1063,6 +1115,8 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE nspc_pop_value(env->curr); --env->scope; env->func = former; + if(GET_FLAG(f, global)) + env_push_global(env); return ret; } diff --git a/src/parse/func.c b/src/parse/func.c index 4bf0a42c3..23fb0a9d3 100644 --- a/src/parse/func.c +++ b/src/parse/func.c @@ -8,26 +8,24 @@ #include "nspc.h" #include "func.h" +ANN static void free_func(Func a) { + if(GET_FLAG(a, template)) { + free_tmpl_list(a->def->tmpl); + mp_free(Func_Def, a->def); + } + if(a->code) + REM_REF(a->code); + mp_free(Func, a); +} + ANN Func new_func(const m_str name, const Func_Def def) { Func func = mp_alloc(Func); func->name = name; func->def = def; - INIT_OO(func, e_func_obj); + INIT_OO(func, free_func); return func; } -ANN void free_func(Func a) { - if(GET_FLAG(a, ref)) { - if(GET_FLAG(a, template)) { - free_tmpl_list(a->def->tmpl); - mp_free(Func_Def, a->def); - } - } - if(a->code) - REM_REF(a->code); - mp_free(Func, a); -} - #include #include "env.h" #include "type.h" diff --git a/src/parse/operator.c b/src/parse/operator.c index 2c2b7df32..fb59741d1 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -173,7 +173,7 @@ ANN m_bool operator_set_func(const struct Op_Import* opi) { ANN static m_bool handle_instr(const Emitter emit, const M_Operator* mo) { if(mo->func) { const Instr instr = emit_add_instr(emit, RegPushImm); - instr->m_val = (m_uint)mo->func; + instr->m_val = (m_uint)mo->func->code; return emit_exp_call1(emit, mo->func); } emit_add_instr(emit, mo->instr); diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 742ef6e1c..166fe4463 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -16,12 +16,6 @@ ANN static m_bool scan1_stmt_list(const Env env, Stmt_List list); ANN m_bool scan1_class_def(const Env env, const Class_Def class_def); ANN static m_bool scan1_stmt(const Env env, Stmt stmt); -ANN static void scan1_exp_decl_template(const Type t, const Exp_Decl* decl) { - Exp_Decl* d = (Exp_Decl*)decl; - d->base = t->def; - d->type = t; -} - ANN static Type void_type(const Env env, const Type_Decl* td, const uint pos) { const Type t = known_type(env, td); CHECK_OO(t) @@ -30,7 +24,7 @@ ANN static Type void_type(const Env env, const Type_Decl* td, const uint pos) { ERR_O(pos, "cannot declare variables of size '0' (i.e. 'void')...") } -ANN static Type scan1_exp_decl_type(const Env env, const Exp_Decl* decl) { +ANN static Type scan1_exp_decl_type(const Env env, Exp_Decl* decl) { const Type t = void_type(env, decl->td, decl->self->pos); CHECK_OO(t); if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref)) @@ -49,17 +43,18 @@ ANN static Type scan1_exp_decl_type(const Env env, const Exp_Decl* decl) { if(GET_FLAG(decl->td, global) && env->class_def) // forbid this ? UNSET_FLAG(decl->td, global); } - if(GET_FLAG(t, template)) - scan1_exp_decl_template(t, decl); + // for template + decl->base = t->def; + decl->type = t; return t; } -ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) { GWDEBUG_EXE +ANN m_bool scan1_exp_decl(const Env env, Exp_Decl* decl) { GWDEBUG_EXE CHECK_BB(env_access(env, decl->td->flag)) env_storage(env, &decl->td->flag); Var_Decl_List list = decl->list; m_uint scope; - ((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, decl); + ((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl); CHECK_OB(decl->type) const m_bool global = GET_FLAG(decl->td, global); const Nspc nspc = !global ? env->curr : env->global_nspc; @@ -90,7 +85,7 @@ ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) { GWDEBUG_EXE v->owner = !env->func ? env->curr : NULL; v->owner_class = env->scope ? NULL : env->class_def; } while((list = list->next)); - ((Exp_Decl*)decl)->type = decl->list->self->value->type; + decl->type = decl->list->self->value->type; if(global) env_pop(env, scope); return GW_OK; @@ -192,10 +187,7 @@ ANN m_bool scan1_stmt_enum(const Env env, const Stmt_Enum stmt) { GWDEBUG_EXE v->owner_class = env->class_def; v->owner = env->curr; SET_FLAG(v, static); - if(GET_FLAG(stmt, private)) - SET_FLAG(v, private); - else if(GET_FLAG(stmt, protect)) - SET_FLAG(v, protect); + SET_ACCESS(stmt, v) } SET_FLAG(v, const | ae_flag_enum | ae_flag_checked); nspc_add_value(stmt->t->owner, list->xid, v); @@ -304,6 +296,9 @@ ANN static m_bool scan1_class_parent(const Env env, const Class_Def class_def) { CHECK_BB(scan1_exp(env, class_def->ext->array->exp)) const Type parent = class_def->type->parent = known_type(env, class_def->ext); CHECK_OB(parent) + if(parent == class_def->type) + ERR_B(class_def->ext->xid->pos, "class '%s' cannot extend itself", + class_def->type->name); if(isa(class_def->type->parent, t_object) < 0) ERR_B(class_def->ext->xid->pos, "cannot extend primitive type '%s'", class_def->type->parent->name) diff --git a/src/parse/scan2.c b/src/parse/scan2.c index 5de5a3ecc..0246c64c3 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -82,10 +82,7 @@ ANN static Value scan2_func_assign(const Env env, const Func_Def d, if(GET_FLAG(f, member)) SET_FLAG(v, member); else SET_FLAG(v, static); - if(GET_FLAG(d, private)) - SET_FLAG(v, private); - else if(GET_FLAG(d, protect)) - SET_FLAG(v, protect); + SET_ACCESS(d, v) } d->func = v->d.func_ref = f; return f->value_ref = v; @@ -133,9 +130,19 @@ ANN static inline Value prim_value(const Env env, const Symbol s) { } ANN static inline m_bool scan2_exp_primary(const Env env, const Exp_Primary* prim) { GWDEBUG_EXE - if(prim->primary_type == ae_primary_hack) + if(prim->primary_type == ae_primary_hack) { CHECK_BB(scan2_exp(env, prim->d.exp)) - else if(prim->primary_type == ae_primary_id) { + Exp e = prim->d.exp; + do { + if(e->exp_type == ae_exp_decl) { + Var_Decl_List l = e->d.exp_decl.list; + do { + const Value v = l->self->value; + SET_FLAG(v, used); + }while ((l = l->next)); + } + } while((e = e->next)); + } else if(prim->primary_type == ae_primary_id) { const Value v = prim_value(env, prim->d.var); if(v) SET_FLAG(v, used); @@ -335,28 +342,61 @@ ANN2(1,2) static Value func_value(const Env env, const Func f, if(!overload) { ADD_REF(v); nspc_add_value(env->curr, f->def->name, v); - } else { + } else /* if(!GET_FLAG(f->def, template)) */ { f->next = overload->d.func_ref->next; overload->d.func_ref->next = f; } return v; } -ANN2(1, 2) static m_bool scan2_func_def_template (const Env env, const Func_Def f, const Value overload) { GWDEBUG_EXE +ANN2(1, 2) static m_bool scan2_func_def_template(const Env env, const Func_Def f, const Value overload) { GWDEBUG_EXE const m_str func_name = s_name(f->name); const Func func = scan_new_func(env, f, func_name); const Value value = func_value(env, func, overload); SET_FLAG(value, checked | ae_flag_template); SET_FLAG(value->type, func); // the only types with func flag, name could be better - const Symbol sym = func_symbol(env->curr->name, func_name, "template", overload ? ++overload->offset : 0); + Type type = env->class_def; + Nspc nspc = env->curr; + uint i = 0; + do { + const Value v = nspc_lookup_value1(nspc, f->name); + if(v) { + Func ff = v->d.func_ref; + do { + if(ff->def == f) { + ++i; + continue; + } + m_bool ret = compat_func(ff->def, f); + if(ret > 0) { + const Symbol sym = func_symbol(env->curr->name, func_name, + "template", ff->vt_index); + nspc_add_value(env->curr, sym, value); + if(!overload) { + ADD_REF(value) + nspc_add_value(env->curr, f->name, value); + } + func->vt_index = ff->vt_index; + return GW_OK; + } + } while((ff = ff->next) && ++i); + } + } while(type && (type = type->parent) && (nspc = type->nspc)); + --i; + const Symbol sym = func_symbol(env->curr->name, func_name, "template", i); nspc_add_value(env->curr, sym, value); + if(!overload) { + func->vt_index = i; + ADD_REF(value) + nspc_add_value(env->curr, f->name, value); + } else + func->vt_index = ++overload->offset; return GW_OK; } ANN static m_bool scan2_func_def_builtin(const Func func, const m_str name) { GWDEBUG_EXE SET_FLAG(func, builtin); - func->code = new_vm_code(NULL, func->def->stack_depth, GET_FLAG(func, member), name); - SET_FLAG(func->code, builtin); + func->code = new_vm_code(NULL, func->def->stack_depth, func->flag, name); func->code->native_func = (m_uint)func->def->d.dl_func_ptr; return GW_OK; } @@ -431,6 +471,7 @@ ANN2(1,2,4) static Value func_create(const Env env, const Func_Def f, scan2_func_def_flag(f); if(GET_FLAG(f, builtin)) CHECK_BO(scan2_func_def_builtin(func, func->name)) +// if(GET_FLAG(func, member) && !GET_FLAG(func->def, func)) if(GET_FLAG(func, member)) f->stack_depth += SZ_INT; if(GET_FLAG(func->def, variadic)) @@ -442,6 +483,9 @@ ANN2(1,2,4) static Value func_create(const Env env, const Func_Def f, ANN m_bool scan2_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE Value value = NULL; f->stack_depth = 0; + m_uint scope = env->scope; + if(GET_FLAG(f, global)) + scope = env_push_global(env); const Value overload = nspc_lookup_value0(env->curr, f->name); m_str func_name = s_name(f->name); if(overload) @@ -452,23 +496,22 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE const Symbol sym = func_symbol(env->curr->name, func_name, NULL, overload ? ++overload->offset : 0); func_name = s_name(sym); } else { - func_name = func_tmpl_name(env, f); + if(f->func) + func_name = f->func->name; + else + func_name = func_tmpl_name(env, f); const Func func = nspc_lookup_func1(env->curr, insert_symbol(func_name)); if(func) { f->ret_type = type_decl_resolve(env, f->td); - return f->arg_list ? scan2_args(env, f) : 1; + return f->arg_list ? scan2_args(env, f) : GW_OK; } } const Func base = get_func(env, f); if(!base) { - m_uint scope = env->scope; - if(GET_FLAG(f, global)) - scope = env_push_global(env); CHECK_OB((value = func_create(env, f, overload, func_name))) - if(GET_FLAG(f, global)) - env_pop(env, scope); - } else + } else { f->func = base; +} if(f->arg_list) CHECK_BB(scan2_args(env, f)) if(!GET_FLAG(f, builtin) && f->d.code->d.stmt_code.stmt_list) @@ -478,6 +521,8 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE CHECK_BB(scan2_func_def_op(env, f)) SET_FLAG(value, checked); } + if(GET_FLAG(f, global)) + env_pop(env, scope); return GW_OK; } diff --git a/src/plug.c b/src/plug.c index 8728faffe..2593bd8c2 100644 --- a/src/plug.c +++ b/src/plug.c @@ -11,26 +11,42 @@ #include "instr.h" #include "object.h" #include "import.h" -#include "plug.h" +#include "gwion.h" static inline int so_filter(const struct dirent* dir) { return strstr(dir->d_name, ".so") ? 1 : 0; } +struct Plug_ { + m_str name; + f_gwmodini ini; + f_gwmodend end; + void* self; +}; + ANN static void handle_plug(PlugInfo v, const m_str c) { void* handler = dlopen(c, RTLD_LAZY); if(handler) { - vector_add(&v[0], (vtype)handler); - m_bool(*import)(Gwi) = (m_bool(*)(Gwi))(intptr_t)dlsym(handler, "import"); + vector_add(&v[GWPLUG_DL], (vtype)handler); + m_bool (*import)(Gwi) = (m_bool(*)(Gwi))(intptr_t)dlsym(handler, "import"); if(import) - vector_add(&v[1], (vtype)import); + vector_add(&v[GWPLUG_IMPORT], (vtype)import); + const f_gwmodini ini = (f_gwmodini)(intptr_t)dlsym(handler, GWMODINI_NAME); + if(ini) { + struct Plug_ *plug = mp_alloc(Plug); + plug->ini = ini; + m_str (*name)() = (m_str(*)())(intptr_t)dlsym(handler, GWMODNAME_NAME); + plug->name = name(); + plug->end = (f_gwmodend)(intptr_t)dlsym(handler, GWMODEND_NAME); + vector_add(&v[GWPLUG_MODULE], (vtype)plug); + } } else err_msg(0, "error in %s.", dlerror()); } void plug_ini(PlugInfo v, Vector list) { - vector_init(&v[0]); - vector_init(&v[1]); + for(m_uint i = 0; i < GWPLUG_LAST; ++i) + vector_init(&v[i]); for(m_uint i = 0; i < vector_size(list); i++) { const m_str dirname = (m_str)vector_at(list, i); struct dirent **namelist; @@ -47,9 +63,50 @@ void plug_ini(PlugInfo v, Vector list) { } } -void plug_end(PlugInfo v) { - for(m_uint i = 0; i < vector_size(&v[0]); ++i) - dlclose((void*)vector_at(&v[0], i)); - vector_release(&v[0]); - vector_release(&v[1]); +void plug_end(const Gwion gwion) { + struct Vector_ *v = gwion->plug; + for(m_uint i = 0; i < vector_size(&v[GWPLUG_MODULE]); ++i) { + struct Plug_ *plug = (struct Plug_*)vector_at(&v[GWPLUG_MODULE], i); + if(plug->end) + plug->end(gwion, plug->self); + mp_free(Plug, plug); + } + for(m_uint i = 0; i < vector_size(&v[GWPLUG_DL]); ++i) + dlclose((void*)vector_at(&v[GWPLUG_DL], i)); + for(m_uint i = 0; i < GWPLUG_LAST; ++i) + vector_release(&v[i]); +} + +ANN static Vector get_arg(const m_str name, const Vector v) { + const size_t len = strlen(name); + for(m_uint i = vector_size(v) + 1; --i;) { + const m_str str = (m_str)vector_at(v, i - 1); + if(!strncmp(name, str, len)) { + const m_str arg = strchr(str, '='); + m_str c, d = strdup(arg+1); + c = d; + const Vector args = new_vector(); + while(d) + vector_add(args, (vtype)strdup(strsep(&d, ","))); + free(d); + free(c); + vector_rem(v, i-1); + return args; + } + } + return NULL; +} + +void module_ini(const Gwion gwion, Vector args) { + Vector v = &gwion->plug[GWPLUG_MODULE]; + for(m_uint i = 0; i < vector_size(v); ++i) { + struct Plug_ *plug = (struct Plug_*)vector_at(v, i); + const Vector arg = get_arg(plug->name, args); + plug->self = plug->ini(gwion, arg); + if(arg) { + for(m_uint i = 0; i < vector_size(arg); ++i) + xfree((m_str)vector_at(arg, i)); + free_vector(arg); + } + } } diff --git a/src/vm/shreduler.c b/src/vm/shreduler.c index c0a586c63..ea3ecde1c 100644 --- a/src/vm/shreduler.c +++ b/src/vm/shreduler.c @@ -12,18 +12,19 @@ ANN void shreduler_set_loop(const Shreduler s, const m_bool loop) { ANN VM_Shred shreduler_get(const Shreduler s) { VM* vm = s->vm; - const VM_Shred shred = s->list; - if(!shred) { + struct ShredTick_ *tk = s->list; + if(!tk) { if(!vector_size(&s->shreds) && !s->loop) vm->is_running = 0; return NULL; } const m_float time = (m_float)vm->bbq->pos + (m_float).5; - if(shred->wake_time <= time) { - if((s->list = shred->next)) + if(tk->wake_time <= time) { + if((s->list = tk->next)) s->list->prev = NULL; - shred->next = shred->prev = NULL; - return s->curr = shred; + tk->next = tk->prev = NULL; + s->curr = tk; + return tk->self; } return NULL; } @@ -32,9 +33,8 @@ ANN static void shreduler_parent(const VM_Shred out, const Vector v) { vector_rem2(v, (vtype)out); if(!vector_size(v)) { vector_release(v); - out->parent->child.ptr = NULL; + out->tick->parent->child.ptr = NULL; } - out->parent = NULL; } ANN static void shreduler_child(const Shreduler s, const Vector v) { @@ -44,56 +44,59 @@ ANN static void shreduler_child(const Shreduler s, const Vector v) { } } -ANN static void shreduler_erase(const Shreduler s, const VM_Shred out) { - if(out->parent) - shreduler_parent(out, &out->parent->child); - if(out->child.ptr) - shreduler_child(s, &out->child); - vector_rem2(&s->shreds, (vtype)out); +ANN static void shreduler_erase(const Shreduler s, struct ShredTick_ *tk) { + if(tk->parent) + shreduler_parent(tk->self, &tk->parent->child); + if(tk->child.ptr) + shreduler_child(s, &tk->child); + vector_rem2(&s->shreds, (vtype)tk->self); } ANN void shreduler_remove(const Shreduler s, const VM_Shred out, const m_bool erase) { - if(s->curr == out) + struct ShredTick_ *tk = out->tick; + assert(tk); + if(tk == s->curr) s->curr = NULL; - else if(out == s->list) - s->list = out->next; - if(out->prev) - out->prev->next = out->next; - if(out->next) - out->next->prev = out->prev; - out->prev = out->next = NULL; + else if(tk == s->list) + s->list = tk->next; + if(tk->prev) + tk->prev->next = tk->next; + if(tk->next) + tk->next->prev = tk->prev; + tk->prev = tk->next = NULL; if(erase) { - shreduler_erase(s, out); + shreduler_erase(s, tk); free_vm_shred(out); } } ANN void shredule(const Shreduler s, const VM_Shred shred, const m_float wake_time) { const m_float time = wake_time + (m_float)s->vm->bbq->pos; - shred->wake_time = time; + struct ShredTick_ *tk = shred->tick; + tk->wake_time = time; if(s->list) { - VM_Shred curr = s->list, prev = NULL; + struct ShredTick_ *curr = s->list, *prev = NULL; do { if(curr->wake_time > time) break; prev = curr; } while((curr = curr->next)); if(!prev) { - shred->next = s->list; - s->list = (s->list->prev = shred); + tk->next = s->list; + s->list = (s->list->prev = tk); } else { - if((shred->next = prev->next)) - prev->next->prev = shred; - shred->prev = prev; - prev->next = shred; + if((tk->next = prev->next)) + prev->next->prev = tk; + tk->prev = prev; + prev->next = tk; } } else - s->list = shred; - if(s->curr == shred) + s->list = tk; + if(tk == s->curr) s->curr = NULL; } ANN void shreduler_add(const Shreduler s, const VM_Shred shred) { - shred->xid = ++s->shred_ids; + shred->tick->xid = ++s->shred_ids; vector_add(&s->shreds, (vtype)shred); } diff --git a/src/vm/vm.c b/src/vm/vm.c index 4fddafe82..b297d8477 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -6,13 +6,22 @@ #include "oo.h" #include "vm.h" #include "env.h" +#include "nspc.h"//dot func +#include "func.h"//dot func #include "type.h" #include "instr.h" #include "object.h" +#include "import.h" #include "ugen.h" #include "shreduler_private.h" #include "emit.h" #include "gwion.h" +#include "map_private.h" + +#include "value.h" +#include "gack.h" + + static inline uint64_t splitmix64_stateless(uint64_t index) { uint64_t z = (index + UINT64_C(0x9E3779B97F4A7C15)); z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9); @@ -54,7 +63,7 @@ void vm_remove(const VM* vm, const m_uint index) { LOOP_OPTIM for(m_uint i = vector_size(v) + 1; i--;) { const VM_Shred sh = (VM_Shred)vector_at(v, i - 1); - if(sh->xid == index) + if(sh->tick->xid == index) Except(sh, "MsgRemove"); } } @@ -70,12 +79,11 @@ ANN void free_vm(VM* vm) { } ANN m_uint vm_add_shred(const VM* vm, const VM_Shred shred) { - shred->vm = (VM*)vm; - shred->me = new_shred(shred); + shred->info->vm = (VM*)vm; + shred->info->me = new_shred(shred); shreduler_add(vm->shreduler, shred); shredule(vm->shreduler, shred, .5); - shred->instr = shred->code->instr; - return shred->xid; + return shred->tick->xid; } __attribute__((hot)) @@ -99,8 +107,9 @@ ANN static inline void vm_ugen_init(const VM* vm) { #ifdef DEBUG_STACK #define VM_INFO \ if(s->curr) \ - gw_err("shred[%" UINT_F "] mem[%" INT_F"] reg[%" INT_F"]\n", shred->xid, \ - shred->mem - (shred->_reg + SIZEOF_REG), shred->reg - shred->_reg); + gw_err("shred[%" UINT_F "] mem[%" INT_F"] reg[%" INT_F"]\n", \ + shred->tick->xid, \ + mem - ((m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG), reg - ((m_bit*)shred + sizeof(struct VM_Shred_))); #else #define VM_INFO #endif @@ -111,20 +120,678 @@ static struct timespec exec_time; #include #endif + +ANN static inline m_bool overflow_(const m_bit* mem, const VM_Shred c) { + return mem > (((m_bit*)c + sizeof(struct VM_Shred_) + SIZEOF_REG) + (SIZEOF_MEM) - (MEM_STEP)); +} + +ANN static inline VM_Shred init_spork_shred(const VM_Shred shred, const VM_Code code) { + const VM_Shred sh = new_vm_shred(code); + ADD_REF(code) + sh->tick->parent = shred->tick; + if(!shred->tick->child.ptr) + vector_init(&shred->tick->child); + vector_add(&shred->tick->child, (vtype)sh); + sh->base = shred->base; + vm_add_shred(shred->info->vm, sh); + return sh; +} + +#define TEST0(t, pos) if(!*(t*)(reg-pos)){ exception(shred, "ZeroDivideException"); break; } +#define DISPATCH()\ + instr =(Instr)(ip[pc++]);\ + VM_INFO;\ + goto *dispatch[instr->opcode]; + +#define OP(t, sz, op, ...) \ + reg -= sz;\ + __VA_ARGS__\ + *(t*)(reg - sz) op##= *(t*)reg;\ + DISPATCH(); + +#define INT_OP(op, ...) OP(m_int, SZ_INT, op, __VA_ARGS__) +#define FLOAT_OP(op) OP(m_float, SZ_FLOAT, op) + +#define LOGICAL(t, sz0, sz, op)\ +reg -= sz0;\ +*(m_int*)(reg-SZ_INT) = (*(t*)(reg - SZ_INT) op *(t*)(reg+sz));\ +DISPATCH() + +#define INT_LOGICAL(op) LOGICAL(m_int, SZ_INT, 0, op) + +#define FLOAT_LOGICAL(op) LOGICAL(m_float, SZ_FLOAT * 2 - SZ_INT, \ + SZ_FLOAT - SZ_INT, op) + +#define SELF(t, sz,op) \ + *(t*)(reg - sz) = op*(t*)(reg - sz);\ + DISPATCH(); + +#define R(t, sz, op, ...) \ +reg -= SZ_INT;\ +__VA_ARGS__\ +*(t*)(reg-sz) = (**(t**)reg op##= (*(t*)(reg-sz)));\ +DISPATCH() +#define INT_R(op, ...) R(m_int, SZ_INT, op, __VA_ARGS__) +#define FLOAT_R(op, ...) R(m_float, SZ_FLOAT, op) + +#define INT_PRE(op) \ +/*assert(*(m_int**)(reg-SZ_INT));*/\ +*(m_int*)(reg- SZ_INT) = op(**(m_int**)(reg-SZ_INT));\ +DISPATCH() + +#define INT_POST(op) \ +/*assert(*(m_int**)(reg-SZ_INT));*/\ +*(m_int*)(reg- SZ_INT) = (**(m_int**)(reg-SZ_INT))op;\ +DISPATCH() + +#define IF_OP(op) \ + reg -=SZ_INT;\ + *(m_float*)(reg-SZ_FLOAT) = (m_float)*(m_int*)(reg-SZ_FLOAT) op \ + *(m_float*)(reg + SZ_INT - SZ_FLOAT); \ + DISPATCH() + +#define IF_LOGICAL(op)\ + reg -= SZ_FLOAT; \ + *(m_int*)(reg-SZ_INT) = (*(m_int*)(reg-SZ_INT) op (m_int)*(m_float*)reg); \ + DISPATCH() __attribute__((hot)) + +#define IF_R(op) \ + reg -= SZ_INT * 2 - SZ_FLOAT; \ + *(m_float*)(reg-SZ_FLOAT) = (**(m_float**)(reg +SZ_INT - SZ_FLOAT) op##= \ + (m_float)*(m_int*)(reg-SZ_FLOAT)); \ + DISPATCH() + +#define FI_OP(op)\ + reg -= SZ_INT; \ + *(m_float*)(reg-SZ_FLOAT) op##= (m_float)*(m_int*)reg; \ + DISPATCH() + +#define FI_LOGICAL(op) \ + reg -= SZ_FLOAT; \ + *(m_int*)(reg-SZ_INT) = ((m_int)*(m_float*)(reg-SZ_INT) op\ + *(m_int*)(reg + SZ_FLOAT-SZ_INT)); \ + DISPATCH() + +#define FI_R(op) \ + reg -= SZ_FLOAT; \ + *(m_int*)(reg-SZ_INT) = (**(m_int**)(reg+SZ_FLOAT -SZ_INT) op##= \ + (m_int)(*(m_float*)(reg-SZ_INT))); \ + DISPATCH() + ANN void vm_run(const VM* vm) { + static const void* dispatch[] = { + &®setimm, + &®pushimm, &®pushfloat, &®pushother, &®pushaddr, + &®pushmem, &®pushmemfloat, &®pushmemother, &®pushmemaddr, + &&pushnow, + &&baseint, &&basefloat, &&baseother, &&baseaddr, + &®dup, + &&memsetimm, + &®pop, &®pushme, &®pushmaybe, + &&funcreturn, + &&_goto, + &&allocint, &&allocfloat, &&allocother, &&allocaddr, + &&intplus, &&intminus, && intmul, &&intdiv, &&intmod, + // int relationnal + &&inteq, &&intne, &&intand, &&intor, + &&intgt, &&intge, &&intlt, &&intle, + &&intsl, &&intsr, &&intsand, &&intsor, &&intxor, + &&intnegate, &&intnot, &&intcmp, + &&intrassign, + &&intradd, &&intrsub, &&intrmul, &&intrdiv, &&intrmod, + &&intrsl, &&intrsr, &&intrsand, &&intrsor, &&intrxor, + &&preinc, &&predec, + &&postinc, &&postdec, + &&floatadd, &&floatsub, &&floatmul, &&floatdiv, +// logical + &&floatand, &&floator, &&floateq, &&floatne, + &&floatgt, &&floatge, &&floatlt, &&floatle, + &&floatneg, &&floatnot, + &&floatrassign, &&floatradd, &&floatrsub, &&floatrmul, &&floatrdiv, + &&ifadd, &&ifsub, &&ifmul, &&ifdiv, + &&ifand, &&ifor, &&ifeq, &&ifne, &&ifgt, &&ifge, &&iflt, &&ifle, + &&ifrassign, &&ifradd, &&ifrsub, &&ifrmul, &&ifrdiv, + &&fiadd, &&fisub, &&fimul, &&fidiv, + &&fiand, &&fior, &&fieq, &&fine, &&figt, &&fige, &&filt, &&file, + &&firassign, &&firadd, &&firsub, &&firmul, &&firdiv, + &&itof, &&ftoi, + &&timeadv, + &&funcusr, &&funcmember, &&funcstatic, + &&sporkini, &&sporkfunc, &&sporkthis, &&sporkexp, &&sporkend, + &&funcptr, + &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat, + &&decintaddr, &&initloop, + &&newobj, + &&addref, &&assign, &&remref, + &&except, &&allocmemberaddr, &&dotmember, &&dotfloat, &&dotother, &&dotaddr, + &&staticint, &&staticfloat, &&staticother, + &&dotfunc,&&staticcode, &&pushstr, + &&gcini, &&gcadd, &&gcend, + &&gack, &&other + }; const Shreduler s = vm->shreduler; - VM_Shred shred; + register VM_Shred shred; + while((shred = shreduler_get(s))) { +register VM_Code code = shred->code; +register +m_uint* ip = code->instr->ptr + OFFSET; +register +size_t pc = shred->pc; +register +m_bit* reg = shred->reg; +register +m_bit* mem = shred->mem; + +register union { +M_Object obj; +VM_Code code; +VM_Shred child; +} a; + #ifdef VMBENCH struct timespec exec_ini, exec_end, exec_ret; clock_gettime(CLOCK_THREAD_CPUTIME_ID, &exec_ini); #endif do { -// const Instr instr = (Instr)vector_at(shred->code->instr, shred->pc++); - const Instr instr = (Instr)vector_at(shred->instr, shred->pc++); + register Instr instr; DISPATCH(); +regsetimm: + *(m_uint*)reg = instr->m_val; + DISPATCH(); +regpushimm: + *(m_uint*)reg = instr->m_val; + reg += SZ_INT; + DISPATCH(); +regpushfloat: + *(m_float*)reg = instr->f; + reg += SZ_FLOAT; + DISPATCH(); +regpushother: +// LOOP_OPTIM + for(m_uint i = 0; i <= instr->m_val2; i+= SZ_INT) + *(m_bit**)(reg+i) = (m_bit*)(instr->m_val + i); + reg += instr->m_val2; + DISPATCH(); +regpushaddr: + *(m_uint**)reg = &instr->m_val; + reg += SZ_INT; + DISPATCH() +regpushmem: + *(m_uint*)reg = *(m_uint*)(mem + instr->m_val); + reg += SZ_INT; + DISPATCH(); +regpushmemfloat: + *(m_float*)reg = *(m_float*)(mem + instr->m_val); + reg += SZ_FLOAT; + DISPATCH(); +regpushmemother: +// LOOP_OPTIM + for(m_uint i = 0; i <= instr->m_val2; i+= SZ_INT) + *(m_uint*)(reg+i) = *(m_uint*)((mem + instr->m_val) + i); + reg += instr->m_val2; + DISPATCH(); +regpushmemaddr: + *(m_bit**)reg = (mem + instr->m_val); + reg += SZ_INT; + DISPATCH() +pushnow: + *(m_float*)reg = vm->bbq->pos; + reg += SZ_FLOAT; + DISPATCH(); +baseint: + *(m_uint*)reg = *(m_uint*)(shred->base + instr->m_val); + reg += SZ_INT; + DISPATCH(); +basefloat: + *(m_float*)reg = *(m_float*)(shred->base + instr->m_val); + reg += SZ_FLOAT; + DISPATCH(); +baseother: +// LOOP_OPTIM + for(m_uint i = 0; i <= instr->m_val2; i+= SZ_INT) + *(m_uint*)(reg+i) = *(m_uint*)((shred->base + instr->m_val) + i); + reg += instr->m_val2; + DISPATCH(); +baseaddr: + *(m_bit**)reg = (shred->base + instr->m_val); + reg += SZ_INT; + DISPATCH(); +regdup: + *(m_uint*)reg = *(m_uint*)(reg-SZ_INT); + reg += SZ_INT; + DISPATCH() +memsetimm: + *(m_uint*)(mem+instr->m_val) = instr->m_val2; + DISPATCH(); +regpop: + reg -= instr->m_val; + DISPATCH(); +regpushme: + *(M_Object*)reg = shred->info->me; + reg += SZ_INT; + DISPATCH() +regpushmaybe: + *(m_uint*)reg = gw_rand((uint32_t*)vm->rand) > (UINT32_MAX / 2); + reg += SZ_INT; + DISPATCH(); +funcreturn: + pc = *(m_uint*)(mem-SZ_INT); + code = *(VM_Code*)(mem-SZ_INT*2); + mem -= (*(m_uint*)(mem-SZ_INT*3) + SZ_INT*3); + ip = code->instr->ptr + OFFSET; + DISPATCH(); +_goto: + pc = instr->m_val; + DISPATCH(); +allocint: + *(m_uint*)reg = *(m_uint*)(mem+instr->m_val) = 0; + reg += SZ_INT; + DISPATCH() +allocfloat: + *(m_float*)reg = *(m_float*)(mem+instr->m_val) = 0; + reg += SZ_FLOAT; + DISPATCH() +allocother: +// LOOP_OPTIM + for(m_uint i = 0; i <= instr->m_val; i += SZ_INT) + *(m_uint*)(reg+i) = (*(m_uint*)(mem+instr->m_val+i) = 0); + reg += instr->m_val2; + DISPATCH() +allocaddr: + *(m_uint*)(mem+instr->m_val) = 0; // just set object to null in + *(m_bit**)reg = mem + instr->m_val; + reg += SZ_INT; + DISPATCH() +intplus: INT_OP(+) +intminus: INT_OP(-) +intmul: INT_OP(*) +intdiv: INT_OP(/, TEST0(m_int, 0)) +intmod: INT_OP(%, TEST0(m_int, 0)) + +inteq: INT_LOGICAL(==) +intne: INT_LOGICAL(!=) +intand: INT_LOGICAL(&&) +intor: INT_LOGICAL(||) +intgt: INT_LOGICAL(>) +intge: INT_LOGICAL(>=) +intlt: INT_LOGICAL(<) +intle: INT_LOGICAL(<=) +intsl: INT_LOGICAL(<<) +intsr: INT_LOGICAL(>>) +intsand: INT_LOGICAL(&) +intsor: INT_LOGICAL(|) +intxor: INT_LOGICAL(^) + +intnegate: + *(m_int*)(reg - SZ_INT) *= -1; + DISPATCH() +intnot: SELF(m_int, SZ_INT, !) +intcmp: SELF(m_int, SZ_INT, ~) + +intrassign: + reg -= SZ_INT; +/*assert(*(m_int**)reg);*/ + **(m_int**)reg = *(m_int*)(reg-SZ_INT); + DISPATCH() + +intradd: INT_R(+) +intrsub: INT_R(-) +intrmul: INT_R(*) +intrdiv: INT_R(/, TEST0(m_int, -SZ_INT)) +intrmod: INT_R(%, TEST0(m_int, -SZ_INT)) +intrsl: INT_R(<<) +intrsr: INT_R(>>) +intrsand: INT_R(&) +intrsor: INT_R(|) +intrxor: INT_R(^) + +preinc: INT_PRE(++) +predec: INT_PRE(--) + +postinc: INT_POST(++) +postdec: INT_POST(--) + +floatadd: FLOAT_OP(+) +floatsub: FLOAT_OP(-) +floatmul: FLOAT_OP(*) +floatdiv: FLOAT_OP(/) + +floatand: FLOAT_LOGICAL(&&) +floator: FLOAT_LOGICAL(||) +floateq: FLOAT_LOGICAL(==) +floatne: FLOAT_LOGICAL(!=) +floatgt: FLOAT_LOGICAL(>) +floatge: FLOAT_LOGICAL(>=) +floatlt: FLOAT_LOGICAL(<) +floatle: FLOAT_LOGICAL(<=) + +floatneg: SELF(m_float, SZ_FLOAT, -) + +floatnot: + reg -= SZ_FLOAT - SZ_INT; + *(m_int*)(reg - SZ_INT) = !*(m_float*)(reg - SZ_INT); + DISPATCH() + +floatrassign: + reg -= SZ_INT; + **(m_float**)reg = *(m_float*)(reg-SZ_FLOAT); + DISPATCH() + +floatradd: FLOAT_R(+) +floatrsub: FLOAT_R(-) +floatrmul: FLOAT_R(*) +floatrdiv: FLOAT_R(/) + +ifadd: IF_OP(+) +ifsub: IF_OP(-) +ifmul: IF_OP(*) +ifdiv: IF_OP(/) + +ifand: IF_LOGICAL(&&) +ifor: IF_LOGICAL(||) +ifeq: IF_LOGICAL(==) +ifne: IF_LOGICAL(!=) +ifgt: IF_LOGICAL(>) +ifge: IF_LOGICAL(>=) +iflt: IF_LOGICAL(<) +ifle: IF_LOGICAL(<=) + +ifrassign: IF_R() +ifradd: IF_R(+) +ifrsub: IF_R(-) +ifrmul: IF_R(*) +ifrdiv: IF_R(/) + +fiadd: FI_OP(+) +fisub: FI_OP(-) +fimul: FI_OP(*) +fidiv: FI_OP(/) + +fiand: FI_LOGICAL(&&) +fior: FI_LOGICAL(||) +fieq: FI_LOGICAL(==) +fine: FI_LOGICAL(!=) +figt: FI_LOGICAL( >) +fige: FI_LOGICAL(>=) +filt: FI_LOGICAL( <) +file: FI_LOGICAL(<=) + +firassign: + reg -=SZ_FLOAT; + *(m_int*)(reg-SZ_INT) = **(m_int**)(reg + SZ_FLOAT-SZ_INT) = + (m_int)*(m_float*)(reg-SZ_INT); + DISPATCH() + +firadd: FI_R(+) +firsub: FI_R(-) +firmul: FI_R(*) +firdiv: FI_R(/) + +itof: + reg -= SZ_INT - SZ_FLOAT; + *(m_float*)(reg-SZ_FLOAT) = (m_float)*(m_int*)(reg-SZ_FLOAT); + DISPATCH() +ftoi: + reg -= SZ_FLOAT - SZ_INT; + *(m_int*)(reg-SZ_INT) = (m_int)*(m_float*)(reg-SZ_INT); + DISPATCH() + +timeadv: + reg -= SZ_FLOAT; +{ + register const m_float f = *(m_float*)(reg-SZ_FLOAT); + *(m_float*)(reg-SZ_FLOAT) = (shred->tick->wake_time += f); + shredule(s, shred, f); +} +shred->code = code; +shred->reg = reg; +shred->mem = mem; +shred->pc = pc; + break; + +funcusr: +{ + reg -= SZ_INT; + register const m_uint push = *(m_uint*)(reg + SZ_INT) + *(m_uint*)(mem-SZ_INT); + mem += push; + *(m_uint*) mem = push;mem += SZ_INT; + *(VM_Code*) mem = code; mem += SZ_INT; + *(m_uint*) mem = pc; mem += SZ_INT; + pc = 0; + code = *(VM_Code*)reg; + ip = code->instr->ptr + OFFSET; + m_uint stack_depth = code->stack_depth; + if(stack_depth) { + register const m_uint f = GET_FLAG(code, member) ? SZ_INT : 0; + if(f) { + *(m_uint*)mem = *(m_uint*)(reg - SZ_INT); + stack_depth -= SZ_INT; + } + reg-=code->stack_depth; +// LOOP_OPTIM + for(m_uint i = 0; i < stack_depth; i+= SZ_INT) + *(m_uint*)(mem+i+f) = *(m_uint*)(reg+i); + } + if(overflow_(mem, shred)) + Except(shred, "StackOverflow"); +} +DISPATCH(); +funcmember: +{ + reg -= SZ_INT; + a.code = *(VM_Code*)reg; + register const m_uint local_depth = *(m_uint*)(reg + SZ_INT); + register m_bit* m = mem + local_depth; +// assert(a.code); + register const m_uint stack_depth = a.code->stack_depth; + register const m_uint depth = stack_depth -SZ_INT; + reg -= stack_depth; + *(m_uint*)m = *(m_uint*)(reg + depth); +// LOOP_OPTIM + for(m_uint i = 0; i < depth; i+= SZ_INT) + *(m_uint*)(m+i+SZ_INT) = *(m_uint*)(reg+i); + if(overflow_(m, shred)) + Except(shred, "StackOverflow"); + shred->mem = m; + shred->pc = pc; + if(GET_FLAG(a.code, ctor)) { + register const f_xtor f = (f_xtor)a.code->native_func; + f(*(M_Object*)m, NULL, shred);// callnat + goto funcend2;//2 + } + register const f_mfun f = (f_mfun)a.code->native_func; + f((*(M_Object*)m), reg, shred);//call native + goto funcend; +} +funcstatic: +{ + reg -= SZ_INT; + a.code = *(VM_Code*)reg; + register const m_uint local_depth = *(m_uint*)(reg + SZ_INT); + register m_bit* m = mem + local_depth; + //assert(a.code); + register const m_uint stack_depth = a.code->stack_depth; + if(stack_depth) { + reg -= stack_depth; +// LOOP_OPTIM + for(m_uint i = 0; i < stack_depth; i+= SZ_INT) + *(m_uint*)(m+i) = *(m_uint*)(reg+i); + } + if(overflow_(m, shred)) + Except(shred, "StackOverflow"); +// shred->reg = reg; + shred->mem = m; + shred->pc = pc; + register const f_sfun f = (f_sfun)a.code->native_func; + f(reg, shred); +funcend: + reg += instr->m_val; +funcend2: + shred->mem = mem; + if(!s->curr)break; + pc = shred->pc; + DISPATCH() +} +sporkini: + a.child = init_spork_shred(shred, (VM_Code)instr->m_val); + DISPATCH() +sporkfunc: +// LOOP_OPTIM + for(m_uint i = 0; i < instr->m_val; i+= SZ_INT) + *(m_uint*)(a.child->reg + i) = *(m_uint*)(reg + i - SZ_INT); + a.child->reg += instr->m_val; + DISPATCH() +sporkthis: + *(M_Object*)a.child->reg = *(M_Object*)(reg + instr->m_val); + a.child->reg += SZ_INT; + DISPATCH() +sporkexp: +// LOOP_OPTIM + for(m_uint i = 0; i < instr->m_val; i+= SZ_INT) + *(m_uint*)(a.child->mem + i) = *(m_uint*)(mem+i); + DISPATCH() +sporkend: + *(M_Object*)(reg-SZ_INT) = a.child->info->me; + DISPATCH() +funcptr: + if(!GET_FLAG((VM_Code)a.code, builtin)) + goto funcusr; + else if(GET_FLAG((VM_Code)a.code, member)) + goto funcmember; + else + goto funcstatic; +brancheqint: + reg -= SZ_INT; + if(!*(m_uint*)reg) + pc = instr->m_val; + DISPATCH(); +branchneint: + reg -= SZ_INT; + if(*(m_uint*)reg) + pc = instr->m_val; + DISPATCH(); +brancheqfloat: + reg -= SZ_FLOAT; + if(!*(m_float*)reg) + pc = instr->m_val; + DISPATCH(); +branchnefloat: + reg -= SZ_FLOAT; + if(*(m_float*)reg) + pc = instr->m_val; + DISPATCH(); +decintaddr: + --(*((m_uint*)(instr->m_val))); + DISPATCH() +initloop: + reg -= SZ_INT; + (*(m_uint*)instr->m_val) = labs(*(m_int*)reg); + DISPATCH() +newobj: + *(M_Object*)reg = new_object(shred, (Type)instr->m_val); + reg += SZ_INT; + DISPATCH() +addref: +// assert(instr->m_val ? *(m_bit**)(reg-SZ_INT) : reg); // scan-build + if((a.obj = instr->m_val ? **(M_Object**)(reg-SZ_INT) : + *(M_Object*)(reg-SZ_INT))) + ++a.obj->ref; + DISPATCH() +assign: + reg -= SZ_INT; + a.obj = *(M_Object*)(reg-SZ_INT); +// assert(*(M_Object**)reg); // scan-build + const M_Object tgt = **(M_Object**)reg; + if(tgt) { + --tgt->ref; + _release(tgt, shred); + } + **(M_Object**)reg = a.obj; + DISPATCH() +remref: + release(*(M_Object*)(mem + instr->m_val), shred); + DISPATCH() +except: + if(!(a.obj = *(M_Object*)(reg-SZ_INT))) + Except(shred, "NullPtrException"); + DISPATCH(); +allocmemberaddr: + a.obj = *(M_Object*)mem; + *(m_bit**)reg = a.obj->data + instr->m_val; + reg += SZ_INT; + DISPATCH() +dotmember: + *(m_uint*)(reg-SZ_INT) = *(m_uint*)(a.obj->data + instr->m_val); + DISPATCH() +dotfloat: + *(m_float*)(reg-SZ_INT) = *(m_float*)(a.obj->data + instr->m_val); + reg += SZ_FLOAT - SZ_INT; + DISPATCH() +dotother: +// LOOP_OPTIM + for(m_uint i = 0; i <= instr->m_val2; i += SZ_INT) + *(m_uint*)(reg+i-SZ_INT) = *(m_uint*)((a.obj->data + instr->m_val) + i); + reg += instr->m_val2 - SZ_INT; + DISPATCH() +dotaddr: + *(m_bit**)(reg-SZ_INT) = (a.obj->data + instr->m_val); + DISPATCH() +staticint: + *(m_uint*)reg = *(m_uint*)instr->m_val; + reg += SZ_INT; + DISPATCH() +staticfloat: + *(m_float*)reg = *(m_float*)instr->m_val; + reg += SZ_FLOAT; + DISPATCH() +staticother: +// LOOP_OPTIM + for(m_uint i = 0; i <= instr->m_val2; i += SZ_INT) + *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)instr->m_val + i); + reg += instr->m_val2; + DISPATCH() +dotfunc: + assert(a.obj); + *(VM_Code*)(reg) = ((Func)vector_at(a.obj->vtable, instr->m_val))->code; + reg += SZ_INT; + DISPATCH() +staticcode: + (*(VM_Code*)reg = ((Func)instr->m_val)->code); + reg += SZ_INT; + DISPATCH() +pushstr: + *(M_Object*)reg = new_string2(shred, (m_str)instr->m_val); + reg += SZ_INT; + DISPATCH(); +gcini: + vector_add(&shred->gc, 0); + DISPATCH(); +gcadd: + vector_add(&shred->gc, *(vtype*)(reg-SZ_INT)); + DISPATCH(); +gcend: + while((a.obj = (M_Object)vector_pop(&shred->gc))) { + assert(a.obj); + _release(a.obj, shred); + } + DISPATCH() +gack: + gack(reg, instr); + DISPATCH() +other: +shred->code = code; +shred->reg = reg; +shred->mem = mem; +shred->pc = pc; instr->execute(shred, instr); - VM_INFO; +if(!s->curr)break; +code = shred->code; +ip = shred->code->instr->ptr + OFFSET; +reg = shred->reg; +mem = shred->mem; +pc = shred->pc; +DISPATCH() } while(s->curr); #ifdef VMBENCH clock_gettime(CLOCK_THREAD_CPUTIME_ID, &exec_end); @@ -135,8 +802,9 @@ timespecadd(&exec_time, &exec_ret, &exec_time); if(!vm->is_running) { #ifdef VMBENCH printf("[VM] exec time %lu.%09lu\n", exec_time.tv_sec, exec_time.tv_nsec); + printf("[VM] exec time %09lu\n", exec_time.tv_nsec/1000); #endif return; - } +} vm_ugen_init(vm); } diff --git a/src/vm/vm_code.c b/src/vm/vm_code.c index bc93a29f9..fbac5529f 100644 --- a/src/vm/vm_code.c +++ b/src/vm/vm_code.c @@ -12,21 +12,8 @@ #include "array.h" #include "memoize.h" -VM_Code new_vm_code(const Vector instr, const m_uint stack_depth, - const m_bool need_this, const m_str name) { - VM_Code code = mp_alloc(VM_Code); - code->instr = instr ? vector_copy(instr) : NULL; - code->name = strdup(name); - code->stack_depth = stack_depth; - code->native_func = 0; - if(need_this) - SET_FLAG(code, member); - INIT_OO(code, e_code_obj) - return code; -} - ANN static void free_code_instr_gack(const Instr instr) { - const Vector v = *(Vector*)instr->ptr; + const Vector v = (Vector)instr->m_val2; for(m_uint i = vector_size(v) + 1; --i;) REM_REF(((Type)vector_at(v, i - 1))); free_vector(v); @@ -41,20 +28,23 @@ ANN static void free_array_info(ArrayInfo* info) { ANN static void free_code_instr(const Vector v) { for(m_uint i = vector_size(v) + 1; --i;) { const Instr instr = (Instr)vector_at(v, i - 1); - if(instr->execute == SporkExp) - REM_REF((VM_Code)instr->m_val2) - else if(instr->execute == SporkFunc) - REM_REF((VM_Code)instr->m_val2) + if(instr->opcode == (m_uint)SporkIni) + REM_REF((VM_Code)instr->m_val) else if(instr->execute == ArrayAlloc) - free_array_info(*(ArrayInfo**)instr->ptr); - else if(instr->execute == Gack) + free_array_info((ArrayInfo*)instr->m_val); + else if(instr->opcode == (m_uint)Gack) free_code_instr_gack(instr); else if(instr->execute == BranchSwitch) free_map((Map)instr->m_val2); + else if(instr->execute == DotTmpl) { + struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val; + free_type_list(dt->tl); + mp_free(dottmpl, dt); + } else if(instr->execute == SwitchIni) { free_vector((Vector)instr->m_val); free_map((Map)instr->m_val2); - } else if(instr->execute == InitLoopCounter) + } else if(instr->opcode == (m_uint)InitLoopCounter) free((m_int*)instr->m_val); else if(instr->execute == VarargIni) { if(instr->m_val2) @@ -65,13 +55,25 @@ ANN static void free_code_instr(const Vector v) { free_vector(v); } -void free_vm_code(VM_Code a) { +ANN static void free_vm_code(VM_Code a) { #ifndef NOMEMOIZE if(a->memoize) memoize_end(a->memoize); #endif - if(a->instr) + if(!GET_FLAG(a, builtin)) free_code_instr(a->instr); free(a->name); mp_free(VM_Code, a); } + +VM_Code new_vm_code(const Vector instr, const m_uint stack_depth, + const ae_flag flag, const m_str name) { + VM_Code code = mp_alloc(VM_Code); + code->instr = instr ? vector_copy(instr) : NULL; + code->name = strdup(name); + code->stack_depth = stack_depth; + code->flag = flag; + INIT_OO(code, free_vm_code) + return code; +} + diff --git a/src/vm/vm_shred.c b/src/vm/vm_shred.c index 9325400e5..48b17473a 100644 --- a/src/vm/vm_shred.c +++ b/src/vm/vm_shred.c @@ -10,44 +10,48 @@ #include "object.h" struct Stack_ { -// VM_Shred shred; + VM_Shred shred; char c[SIZEOF_REG]; char d[SIZEOF_MEM]; }; +static inline struct ShredInfo_ *new_shredinfo(const m_str name) { + struct ShredInfo_ *info = mp_alloc(ShredInfo); + info->name = strdup(name); + return info; +} + +static inline void free_shredinfo(struct ShredInfo_ *info, const VM_Shred shred) { + free(info->name); + release(info->me, shred); + if(info->args) { + const Vector v = info->args; + LOOP_OPTIM + for(m_uint i = vector_size(v) + 1; --i;) + free((void*)vector_at(v, i - 1)); + free_vector(v); + } + mp_free(ShredInfo, info); +} + VM_Shred new_vm_shred(VM_Code c) { - const VM_Shred shred = mp_alloc(VM_Shred); - shred->_reg = mp_alloc(Stack); -// const VM_Shred shred = mp_alloc(Stack); -// shred->reg = (m_bit*)shred + sizeof(struct VM_Shred_); - shred->mem = shred->_reg + SIZEOF_REG; - shred->reg = shred->_reg; - shred->base = shred->mem; -// shred->_mem = shred->base; + const VM_Shred shred = mp_alloc(Stack); shred->code = c; - shred->name = strdup(c->name); + shred->reg = (m_bit*)shred + sizeof(struct VM_Shred_); + shred->base = shred->mem = shred->reg + SIZEOF_REG; + shred->tick = mp_alloc(ShredTick); + shred->tick->self = shred; + shred->info = new_shredinfo(c->name); vector_init(&shred->gc); return shred; } -static void vm_shred_free_args(Vector v) { - LOOP_OPTIM - for(m_uint i = vector_size(v) + 1; --i;) - free((void*)vector_at(v, i - 1)); - free_vector(v); -} - void free_vm_shred(VM_Shred shred) { for(m_uint i = vector_size(&shred->gc) + 1; --i;) release((M_Object)vector_at(&shred->gc, i - 1), shred); vector_release(&shred->gc); - release(shred->me, shred); - mp_free(Stack, shred->_reg); -// mp_free(Stack, shred->mem); REM_REF(shred->code); - free(shred->name); - if(shred->args) - vm_shred_free_args(shred->args); - mp_free(VM_Shred, shred); -// mp_free(Stack, shred); + mp_free(ShredTick, shred->tick); + free_shredinfo(shred->info, shred); + mp_free(Stack, shred); } diff --git a/tests/error/empty_member_ptr.gw b/tests/error/empty_member_ptr.gw index b2b9b24f1..4f233108b 100644 --- a/tests/error/empty_member_ptr.gw +++ b/tests/error/empty_member_ptr.gw @@ -1,4 +1,4 @@ -// [contains] NullFuncPtrException +// [contains] NullPtrException class C { typedef void test(); diff --git a/tests/error/func_ptr_empty.gw b/tests/error/func_ptr_empty.gw index 879ac9a0a..e31849738 100644 --- a/tests/error/func_ptr_empty.gw +++ b/tests/error/func_ptr_empty.gw @@ -1,4 +1,4 @@ -// [contains] NullFuncPtrException +// [contains] NullPtrException typedef void Test() Test test; test(); diff --git a/tests/error/self_extend.gw b/tests/error/self_extend.gw new file mode 100644 index 000000000..e6d5a55b4 --- /dev/null +++ b/tests/error/self_extend.gw @@ -0,0 +1,4 @@ +// [contains] cannot extend itself +class C extends C { + +} diff --git a/tests/tree/template_ternary.gw b/tests/error/template_ternary.gw similarity index 56% rename from tests/tree/template_ternary.gw rename to tests/error/template_ternary.gw index 606877145..792855329 100644 --- a/tests/tree/template_ternary.gw +++ b/tests/error/template_ternary.gw @@ -1,3 +1,4 @@ +// [contains] invalid expression for function call template<~A~> function void test(A a){} diff --git a/tests/test_plugins/Makefile b/tests/import/Makefile similarity index 100% rename from tests/test_plugins/Makefile rename to tests/import/Makefile diff --git a/tests/test_plugins/array.c b/tests/import/array.c similarity index 100% rename from tests/test_plugins/array.c rename to tests/import/array.c diff --git a/tests/import/basic_module.c b/tests/import/basic_module.c new file mode 100644 index 000000000..ac464588f --- /dev/null +++ b/tests/import/basic_module.c @@ -0,0 +1,21 @@ +#include "gwion_util.h" +#include "gwion_ast.h" +#include "oo.h" +#include "vm.h" +#include "env.h" +#include "gwion.h" + +GWMODNAME("basic_module") + +GWMODINI(basic_module) { + puts("ini module"); + if(args) { + puts("have arguments"); + for(vtype i = 0; i < vector_size(args); ++i) + puts((m_str)vector_at(args, i)); + } +} + +GWMODEND(basic_module) { + puts("end module"); +} diff --git a/tests/test_plugins/begin_class.c b/tests/import/begin_class.c similarity index 100% rename from tests/test_plugins/begin_class.c rename to tests/import/begin_class.c diff --git a/tests/test_plugins/callback.c b/tests/import/callback.c similarity index 80% rename from tests/test_plugins/callback.c rename to tests/import/callback.c index aeeb07595..9faa39c15 100644 --- a/tests/test_plugins/callback.c +++ b/tests/import/callback.c @@ -12,20 +12,24 @@ struct ret_info { Instr instr; + VM_Code code; m_uint offset; m_uint size; + size_t pc; }; static INSTR(my_ret) { GWDEBUG_EXE struct ret_info* info = (struct ret_info*)instr->m_val; POP_MEM(shred, info->offset); vector_set(shred->code->instr, shred->pc, (vtype)info->instr); - shred->code = *(VM_Code*)instr->ptr; + shred->code = info->code; +//*(VM_Code*)instr->ptr; POP_REG(shred, info->size) - if(shred->mem == shred->_reg + SIZEOF_REG) + if(shred->mem == (m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG) POP_REG(shred, SZ_INT) POP_REG(shred, shred->code->stack_depth); - shred->pc = instr->m_val2; +// shred->pc = instr->m_val2; + shred->pc = info->pc; free(info); *(m_int*)shred->reg = 2; PUSH_REG(shred, SZ_INT); @@ -37,16 +41,18 @@ static SFUN(cb_func) { if(!f){ Except(shred, "NullCallbackException"); } - m_uint offset = shred->mem - (shred->_reg + SIZEOF_REG); + m_uint offset = shred->mem - ((m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG); PUSH_MEM(shred, offset); Instr instr = mp_alloc(Instr); struct ret_info* info = (struct ret_info*)xmalloc(sizeof(struct ret_info)); info->offset = offset; + info->code = shred->code; info->size = f->def->ret_type->size; + info->pc = shred->pc; instr->execute = my_ret; - *(VM_Code*)instr->ptr = shred->code; +// *(VM_Code*)instr->ptr = shred->code; instr->m_val = (m_uint)info; - instr->m_val2 = shred->pc; +// instr->m_val2 = shred->pc; for(i = 0; i < vector_size(f->code->instr); i++) { Instr in = (Instr)vector_at(f->code->instr, i); if(in->execute == FuncReturn || diff --git a/tests/test_plugins/callback.gwold b/tests/import/callback.gwold similarity index 100% rename from tests/test_plugins/callback.gwold rename to tests/import/callback.gwold diff --git a/tests/test_plugins/callback2.gw b/tests/import/callback2.gw similarity index 100% rename from tests/test_plugins/callback2.gw rename to tests/import/callback2.gw diff --git a/tests/test_plugins/class_template.c b/tests/import/class_template.c similarity index 100% rename from tests/test_plugins/class_template.c rename to tests/import/class_template.c diff --git a/tests/test_plugins/class_template.gw b/tests/import/class_template.gw similarity index 100% rename from tests/test_plugins/class_template.gw rename to tests/import/class_template.gw diff --git a/tests/test_plugins/coverage.c b/tests/import/coverage.c similarity index 100% rename from tests/test_plugins/coverage.c rename to tests/import/coverage.c diff --git a/tests/test_plugins/coverage.gw b/tests/import/coverage.gw similarity index 100% rename from tests/test_plugins/coverage.gw rename to tests/import/coverage.gw diff --git a/tests/test_plugins/end_class.c b/tests/import/end_class.c similarity index 100% rename from tests/test_plugins/end_class.c rename to tests/import/end_class.c diff --git a/tests/test_plugins/enum.c b/tests/import/enum.c similarity index 100% rename from tests/test_plugins/enum.c rename to tests/import/enum.c diff --git a/tests/test_plugins/enum.gw b/tests/import/enum.gw similarity index 100% rename from tests/test_plugins/enum.gw rename to tests/import/enum.gw diff --git a/tests/test_plugins/extend_array.c b/tests/import/extend_array.c similarity index 100% rename from tests/test_plugins/extend_array.c rename to tests/import/extend_array.c diff --git a/tests/test_plugins/extend_array.gw b/tests/import/extend_array.gw similarity index 100% rename from tests/test_plugins/extend_array.gw rename to tests/import/extend_array.gw diff --git a/tests/test_plugins/extend_event.c b/tests/import/extend_event.c similarity index 100% rename from tests/test_plugins/extend_event.c rename to tests/import/extend_event.c diff --git a/tests/test_plugins/extend_event.gw b/tests/import/extend_event.gw similarity index 100% rename from tests/test_plugins/extend_event.gw rename to tests/import/extend_event.gw diff --git a/tests/test_plugins/extend_pair.c b/tests/import/extend_pair.c similarity index 100% rename from tests/test_plugins/extend_pair.c rename to tests/import/extend_pair.c diff --git a/tests/test_plugins/extend_pair.gw b/tests/import/extend_pair.gw similarity index 100% rename from tests/test_plugins/extend_pair.gw rename to tests/import/extend_pair.gw diff --git a/tests/test_plugins/global_func.c b/tests/import/global_func.c similarity index 100% rename from tests/test_plugins/global_func.c rename to tests/import/global_func.c diff --git a/tests/test_plugins/global_func.gw b/tests/import/global_func.gw similarity index 56% rename from tests/test_plugins/global_func.gw rename to tests/import/global_func.gw index 5b594034a..4fa22811f 100644 --- a/tests/test_plugins/global_func.gw +++ b/tests/import/global_func.gw @@ -1 +1,3 @@ +<<>>; <<<1 => test>>>; + diff --git a/tests/test_plugins/global_var.c b/tests/import/global_var.c similarity index 100% rename from tests/test_plugins/global_var.c rename to tests/import/global_var.c diff --git a/tests/test_plugins/global_var.gw b/tests/import/global_var.gw similarity index 100% rename from tests/test_plugins/global_var.gw rename to tests/import/global_var.gw diff --git a/tests/test_plugins/invalid_arg.c b/tests/import/invalid_arg.c similarity index 100% rename from tests/test_plugins/invalid_arg.c rename to tests/import/invalid_arg.c diff --git a/tests/test_plugins/invalid_array.c b/tests/import/invalid_array.c similarity index 100% rename from tests/test_plugins/invalid_array.c rename to tests/import/invalid_array.c diff --git a/tests/test_plugins/invalid_func.c b/tests/import/invalid_func.c similarity index 100% rename from tests/test_plugins/invalid_func.c rename to tests/import/invalid_func.c diff --git a/tests/test_plugins/invalid_type1.c b/tests/import/invalid_type1.c similarity index 100% rename from tests/test_plugins/invalid_type1.c rename to tests/import/invalid_type1.c diff --git a/tests/test_plugins/invalid_type2.c b/tests/import/invalid_type2.c similarity index 100% rename from tests/test_plugins/invalid_type2.c rename to tests/import/invalid_type2.c diff --git a/tests/test_plugins/invalid_type3.c b/tests/import/invalid_type3.c similarity index 100% rename from tests/test_plugins/invalid_type3.c rename to tests/import/invalid_type3.c diff --git a/tests/test_plugins/map2.gw b/tests/import/map2.gw similarity index 100% rename from tests/test_plugins/map2.gw rename to tests/import/map2.gw diff --git a/tests/test_plugins/no_import.c b/tests/import/no_import.c similarity index 100% rename from tests/test_plugins/no_import.c rename to tests/import/no_import.c diff --git a/tests/test_plugins/op_err.c b/tests/import/op_err.c similarity index 100% rename from tests/test_plugins/op_err.c rename to tests/import/op_err.c diff --git a/tests/test_plugins/static_string.c b/tests/import/static_string.c similarity index 100% rename from tests/test_plugins/static_string.c rename to tests/import/static_string.c diff --git a/tests/test_plugins/static_string.gw b/tests/import/static_string.gw similarity index 100% rename from tests/test_plugins/static_string.gw rename to tests/import/static_string.gw diff --git a/tests/test_plugins/template_arg.c b/tests/import/template_arg.c similarity index 100% rename from tests/test_plugins/template_arg.c rename to tests/import/template_arg.c diff --git a/tests/test_plugins/typedef.c b/tests/import/typedef.c similarity index 100% rename from tests/test_plugins/typedef.c rename to tests/import/typedef.c diff --git a/tests/test_plugins/typedef.gw b/tests/import/typedef.gw similarity index 100% rename from tests/test_plugins/typedef.gw rename to tests/import/typedef.gw diff --git a/tests/test_plugins/union.c b/tests/import/union.c similarity index 100% rename from tests/test_plugins/union.c rename to tests/import/union.c diff --git a/tests/test_plugins/union.gw b/tests/import/union.gw similarity index 100% rename from tests/test_plugins/union.gw rename to tests/import/union.gw diff --git a/tests/test_plugins/variadic.c b/tests/import/variadic.c similarity index 100% rename from tests/test_plugins/variadic.c rename to tests/import/variadic.c diff --git a/tests/test_plugins/variadic.gw b/tests/import/variadic.gw similarity index 100% rename from tests/test_plugins/variadic.gw rename to tests/import/variadic.gw diff --git a/tests/sh/plugin.sh b/tests/sh/plugin.sh index 41b54c477..705a73fba 100644 --- a/tests/sh/plugin.sh +++ b/tests/sh/plugin.sh @@ -1,5 +1,5 @@ #!/bin/bash -# [test] #26 +# [test] #27 n=0 [ "$1" ] && n="$1" @@ -30,7 +30,7 @@ rm "empty.so" BASE_DIR="$PWD" -cd tests/test_plugins || exit +cd tests/import || exit for test_file in *.c do test_plugin "${test_file:0:-2}" done diff --git a/tests/error/switch_in.gw b/tests/tree/nested_switch.gw similarity index 72% rename from tests/error/switch_in.gw rename to tests/tree/nested_switch.gw index 098f0ff5c..fabddf099 100644 --- a/tests/error/switch_in.gw +++ b/tests/tree/nested_switch.gw @@ -1,5 +1,3 @@ -// [skip] -// [contains] swith inside an other switch switch(maybe) { case 1: <<<1>>>;break; case 0: diff --git a/util b/util index 03a9cf22e..fa9f700bb 160000 --- a/util +++ b/util @@ -1 +1 @@ -Subproject commit 03a9cf22e9a5388cf396503ff722a84d137f48f8 +Subproject commit fa9f700bb617e6368150c9a29ffac4c6d5256d2d