From 27da3787164219da4a6c97ff2e3dbef16c1093c3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Thu, 12 Mar 2020 19:08:59 +0100 Subject: [PATCH] :art: Stop using cryptic symbols and other stuff :fire: --- ast | 2 +- examples/vararg.gw | 19 +- include/emit.h | 1 - include/env/nspc.h | 1 - include/env/type.h | 2 +- include/import/cdef.h | 1 + include/import/checker.h | 1 + include/import/oper.h | 3 + include/instr.h | 4 - include/lang_private.h | 2 + include/operator.h | 9 +- include/vararg.h | 9 +- src/emit/emit.c | 44 +-- src/emit/emitter.c | 2 - src/env/nspc.c | 12 +- src/import/cdef.c | 26 +- src/import/checker.c | 5 +- src/import/oper.c | 26 +- src/lib/array.c | 10 +- src/lib/engine.c | 26 +- src/lib/event.c | 5 +- src/lib/object.c | 390 ------------------------ src/lib/object_op.c | 415 ++++++++++++++++++++++++++ src/lib/prim.c | 36 +-- src/lib/prim_values.c | 49 +++ src/lib/ptr.c | 56 ++-- src/lib/string.c | 22 +- src/lib/ugen.c | 27 +- src/lib/vararg.c | 181 ++++++----- src/parse/check.c | 27 +- src/parse/operator.c | 21 +- src/parse/scan0.c | 6 +- src/parse/scan1.c | 33 +- src/parse/scan2.c | 16 +- src/parse/type_decl.c | 1 + src/vm/vm.c | 2 + tests/error/connect_except.gw | 2 +- tests/error/ev.gw | 2 +- tests/error/vararg_after.gw | 6 - tests/error/vararg_before.gw | 4 - tests/error/vararg_invalid_acces.gw | 6 +- tests/error/vararg_outside_varloop.gw | 5 + tests/error/variadic_end_no_start.gw | 7 - tests/error/variadic_start_twice.gw | 2 - tests/error/variadic_test.gw | 7 - tests/error/varloop_not_vararg.gw | 4 + tests/error/varloop_only.gw | 5 - tests/import/gwi_oper_emit_var.c | 42 +++ tests/import/gwi_oper_emit_var.gw | 5 + tests/sh/import.sh | 2 +- 50 files changed, 855 insertions(+), 736 deletions(-) create mode 100644 src/lib/object_op.c create mode 100644 src/lib/prim_values.c delete mode 100644 tests/error/vararg_after.gw delete mode 100644 tests/error/vararg_before.gw create mode 100644 tests/error/vararg_outside_varloop.gw delete mode 100644 tests/error/variadic_end_no_start.gw delete mode 100644 tests/error/variadic_start_twice.gw delete mode 100644 tests/error/variadic_test.gw create mode 100644 tests/error/varloop_not_vararg.gw delete mode 100644 tests/error/varloop_only.gw create mode 100644 tests/import/gwi_oper_emit_var.c create mode 100644 tests/import/gwi_oper_emit_var.gw diff --git a/ast b/ast index e3939cd9..318792cd 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit e3939cd9cdb1f8aeab49df8db855fea945938ba9 +Subproject commit 318792cdc12f6b9632f89052c2d6cc258031b99c diff --git a/examples/vararg.gw b/examples/vararg.gw index 8d1df413..7daaa2b2 100644 --- a/examples/vararg.gw +++ b/examples/vararg.gw @@ -1,15 +1,14 @@ fun void test(...) { int i; - vararg.start; - - if(i == 0) - <<< vararg $ int >>>; - else if(i == 1) - <<< vararg $ float >>>; - else if(i == 2) - <<< vararg $ Object >>>; - i++; - vararg.end; + varloop vararg { + if(i == 0) + <<< vararg $ int >>>; + else if(i == 1) + <<< vararg $ float >>>; + else if(i == 2) + <<< vararg $ Object >>>; + i++; + } } test(1); test(1, 2.3, null); diff --git a/include/emit.h b/include/emit.h index 2c2c7569..ff00f7f8 100644 --- a/include/emit.h +++ b/include/emit.h @@ -17,7 +17,6 @@ typedef struct Code_ { struct EmitterInfo_ { struct Vector_ pure; - struct Vector_ variadic; char *escape; f_instr finalyzer; VM_Code (*emit_code)(const Emitter); diff --git a/include/env/nspc.h b/include/env/nspc.h index c0e3546a..efb75b81 100644 --- a/include/env/nspc.h +++ b/include/env/nspc.h @@ -18,7 +18,6 @@ struct Nspc_ { struct VM_Code_* dtor; struct NspcInfo_* info; HAS_OBJ - uint is_union; }; extern ANEW ANN Nspc new_nspc(MemPool p, const m_str name); diff --git a/include/env/type.h b/include/env/type.h index deaa596b..874bdf7f 100644 --- a/include/env/type.h +++ b/include/env/type.h @@ -49,7 +49,7 @@ ANN m_uint get_depth(const Type type); typedef enum { et_void, et_int, et_bool, et_char, et_float, et_null, et_object, et_shred, et_fork, et_event, et_ugen, et_string, et_ptr, et_array, et_gack, - et_function, et_fptr, et_varloop, et_lambda, et_class, et_union, et_undefined, et_auto, + et_function, et_fptr, et_vararg, et_lambda, et_class, et_union, et_undefined, et_auto, MAX_TYPE } type_enum; #endif diff --git a/include/import/cdef.h b/include/import/cdef.h index 03285493..f44f1855 100644 --- a/include/import/cdef.h +++ b/include/import/cdef.h @@ -4,4 +4,5 @@ ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str, const m_str parent); ANN2(1,2) Type gwi_class_spe(const Gwi gwi, const m_str, const m_uint size); ANN2(1) void gwi_class_xtor(const Gwi gwi, const f_xtor ctor, const f_xtor dtor); ANN m_int gwi_class_end(const Gwi gwi); +ANN void inherit(const Type); #endif diff --git a/include/import/checker.h b/include/import/checker.h index 52e8b7a3..510943c6 100644 --- a/include/import/checker.h +++ b/include/import/checker.h @@ -41,6 +41,7 @@ typedef struct OperCK { // name_checker ? Instr (*em)(Emitter, void*); // oper m_str lhs;// oper m_str rhs;// oper + m_uint emit_var; } OperCK; struct array_checker { diff --git a/include/import/oper.h b/include/import/oper.h index cf5bedcf..1bb02818 100644 --- a/include/import/oper.h +++ b/include/import/oper.h @@ -7,6 +7,9 @@ ANN m_int gwi_oper_emi(const Gwi gwi, const opem); ANN2(1) m_int gwi_oper_end(const Gwi gwi, const m_str op, const f_instr f); ANN m_int gwi_oper_cond(const Gwi, const m_str, const f_instr, const f_instr); +//! use this with one if the right side operator's to emit_var is set +ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset); + #define _EQUALITY_OPER(sz, sign) \ POP_REG(shred, sz*2 - SZ_INT); \ *(m_uint*)REG(-SZ_INT) = sign \ diff --git a/include/instr.h b/include/instr.h index 2565644b..4e75bf5b 100644 --- a/include/instr.h +++ b/include/instr.h @@ -48,11 +48,7 @@ INSTR(ArrayAlloc); /* vararg */ INSTR(VarargIni); -INSTR(VarargTop); -INSTR(VarargEnd); -INSTR(VecCpy); -INSTR(VecMember); INSTR(PopArrayClass); INSTR(DotTmpl); diff --git a/include/lang_private.h b/include/lang_private.h index 96479a37..f3351265 100644 --- a/include/lang_private.h +++ b/include/lang_private.h @@ -11,4 +11,6 @@ ANN m_bool import_array(const Gwi gwi); ANN m_bool import_ptr(const Gwi gwi); ANN m_bool import_func(const Gwi gwi); ANN m_bool import_modules(const Gwi gwi); +ANN m_bool import_object_op(const Gwi gwi); +ANN m_bool import_values(const Gwi gwi); #endif diff --git a/include/operator.h b/include/operator.h index eae103e5..c7453f11 100644 --- a/include/operator.h +++ b/include/operator.h @@ -13,13 +13,18 @@ typedef Type (*opck)(const Env, void*, m_bool*); typedef struct Instr_* (*opem)(const Emitter, void*); -struct Op_Import { - Type lhs, rhs, ret; +struct Op_Func { opck ck; opem em; +}; + +struct Op_Import { + Type lhs, rhs, ret; + const struct Op_Func *func; uintptr_t data; loc_t pos; Symbol op; + m_uint emit_var; }; struct Implicit { diff --git a/include/vararg.h b/include/vararg.h index f94f649f..76feea9f 100644 --- a/include/vararg.h +++ b/include/vararg.h @@ -1,10 +1,11 @@ #ifndef __VARARG #define __VARARG struct Vararg_ { - m_uint* k; // sizes - Type* t; // types - m_bit* d; // d(ata) - m_uint o, i, s; // o(ffset), i(ndex), s(ize) + struct Vector_ t; // types + m_bit *d; // d(ata) + m_uint o, i, s, l; // o(ffset), i(ndex), s(ize), l(en) + m_uint pc; }; +ANN void emit_vararg_end(const Emitter emit, const m_uint pc); void free_vararg(MemPool p, struct Vararg_* arg); #endif diff --git a/src/emit/emit.c b/src/emit/emit.c index f528699c..00a36785 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -18,6 +18,7 @@ #include "parser.h" #include "tuple.h" #include "specialid.h" +#include "vararg.h" #undef insert_symbol #define insert_symbol(a) insert_symbol(emit->gwion->st, (a)) @@ -1225,6 +1226,30 @@ ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) { return GW_OK; } +ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, const m_uint status) { + regpushi(emit, status); + CHECK_BB(emit_exp(emit, stmt->exp, 0)) + emit_add_instr(emit, SetObj); + const Instr member = emit_add_instr(emit, DotMember4); + member->m_val = SZ_INT; + emit_add_instr(emit, int_r_assign); + regpop(emit, SZ_INT); + return GW_OK; +} + +ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt) { + CHECK_BB(variadic_state(emit, stmt, 1)) + CHECK_BB(emit_exp(emit, stmt->exp, 0)) + const Instr instr = emit_add_instr(emit, BranchEqInt); + const m_uint pc = emit_code_size(emit); + emit_stmt(emit, stmt->body, 1); + CHECK_BB(emit_exp(emit, stmt->exp, 0)) + emit_vararg_end(emit, pc); + instr->m_val = emit_code_size(emit); + CHECK_BB(variadic_state(emit, stmt, 0)) + return GW_OK; +} + // scope push problem ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) { emit_push_stack(emit); @@ -1545,10 +1570,6 @@ ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List l) { return GW_OK; } -ANN static inline Instr get_variadic(const Emitter emit) { - return (Instr)vector_back(&emit->info->variadic); -} - ANN static inline m_bool ensure_emit(const Emitter emit, const Type type) { const Type t = actual_type(emit->gwion, type) ?: type; if(!GET_FLAG(t, emit) && t->e->def) @@ -1629,7 +1650,7 @@ ANN static VM_Code emit_func_def_code(const Emitter emit, const Func func) { return finalyze(emit, FuncReturn); } -ANN static m_bool _fdef_body(const Emitter emit, const Func_Def fdef) { +ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) { if(fdef->base->args) emit_func_def_args(emit, fdef->base->args); if(GET_FLAG(fdef, variadic)) @@ -1640,19 +1661,6 @@ ANN static m_bool _fdef_body(const Emitter emit, const Func_Def fdef) { return GW_OK; } -ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) { - vector_add(&emit->info->variadic, 0); - CHECK_BB(_fdef_body(emit, fdef)) - if(GET_FLAG(fdef, variadic)) { - if(!get_variadic(emit)) - ERR_B(fdef->pos, _("invalid variadic use")) - if(!GET_FLAG(fdef->base->func, empty)) - ERR_B(fdef->pos, _("invalid variadic use")) - } - vector_pop(&emit->info->variadic); - return GW_OK; -} - ANN static Instr me_top(MemoizeEmitter *me) { const Instr idx = emit_add_instr(me->emit, MemSetImm); idx->m_val = me->offset; diff --git a/src/emit/emitter.c b/src/emit/emitter.c index 2527bf4c..6520d9fa 100644 --- a/src/emit/emitter.c +++ b/src/emit/emitter.c @@ -19,7 +19,6 @@ ANEW Emitter new_emitter(MemPool p) { vector_init(&emit->stack); emit->info = (struct EmitterInfo_*)mp_calloc(p, EmitterInfo); vector_init(&emit->info->pure); - vector_init(&emit->info->variadic); emit->info->escape = escape_table(p); emit->info->emit_code = emit_code; emit->info->finalyzer = EOC; @@ -29,7 +28,6 @@ ANEW Emitter new_emitter(MemPool p) { ANN void free_emitter(MemPool p, Emitter a) { vector_release(&a->stack); vector_release(&a->info->pure); - vector_release(&a->info->variadic); mp_free2(p, 256, a->info->escape); mp_free(p, EmitterInfo, a->info); mp_free(p, Emitter, a); diff --git a/src/env/nspc.c b/src/env/nspc.c index 54d0f360..e767d722 100644 --- a/src/env/nspc.c +++ b/src/env/nspc.c @@ -24,14 +24,10 @@ ANN static inline void nspc_release_object(const Nspc a, Value value, Gwion gwio ANN static void free_nspc_value(const Nspc a, Gwion gwion) { struct scope_iter iter = { a->info->value, 0, 0 }; Value v; - if(!a->is_union) { - while(scope_iter(&iter, &v) > 0) { - if(v) { - if(isa(v->type, gwion->type[et_object]) > 0) - nspc_release_object(a, v, gwion); - REM_REF(v, gwion); - } - } + while(scope_iter(&iter, &v) > 0) { + if(isa(v->type, gwion->type[et_object]) > 0) + nspc_release_object(a, v, gwion); + REM_REF(v, gwion); } free_scope(gwion->mp, a->info->value); } diff --git a/src/import/cdef.c b/src/import/cdef.c index eddfa296..1f6cd6c5 100644 --- a/src/import/cdef.c +++ b/src/import/cdef.c @@ -26,14 +26,29 @@ ANN static m_bool mk_xtor(MemPool p, const Type type, const m_uint d, const ae_f return GW_OK; } +ANN2(1,2) static inline m_bool class_parent(const Env env, const Type t) { + Type parent = t->e->parent; + while(parent && !GET_FLAG(parent, checked)) { + if(t->e->def) + CHECK_BB(traverse_class_def(env, t->e->def)) + parent = parent->e->parent; + } + return GW_OK; +} + +ANN void inherit(const Type t) { + const Nspc nspc = t->nspc, parent = t->e->parent->nspc; + if(!nspc || !parent) + return; + nspc->info->offset = parent->info->offset; + if(parent->info->vtable.ptr) + vector_copy2(&parent->info->vtable, &nspc->info->vtable); +} + ANN2(1,2) static void import_class_ini(const Env env, const Type t) { t->nspc = new_nspc(env->gwion->mp, t->name); t->nspc->parent = env->curr; - if(t->e->parent && t->e->parent->nspc) { - t->nspc->info->offset = t->e->parent->nspc->info->offset; - if(t->e->parent->nspc->info->vtable.ptr) - vector_copy2(&t->e->parent->nspc->info->vtable, &t->nspc->info->vtable); - } + inherit(t); t->e->owner = env->curr; SET_FLAG(t, checked); env_push_type(env, t); @@ -53,6 +68,7 @@ ANN static inline void gwi_type_flag(const Type t) { ANN static Type type_finish(const Gwi gwi, const Type t) { gwi_add_type(gwi, t); + CHECK_BO(class_parent(gwi->gwion->env, t)) import_class_ini(gwi->gwion->env, t); return t; } diff --git a/src/import/checker.c b/src/import/checker.c index 62edeaed..8794839c 100644 --- a/src/import/checker.c +++ b/src/import/checker.c @@ -214,7 +214,9 @@ ANN static Type_List str2tl(const Gwi gwi, const m_str s) { } //! convert a string to a Type_Decl -ANN Type_Decl* str2decl(const Gwi gwi, const m_str s) { +ANN Type_Decl* str2decl(const Gwi gwi, const m_str str) { + const ae_flag flag = strncmp(str, "nonnull ", 8) ? ae_flag_none : ae_flag_nonnull; + const m_str s = strncmp(str, "nonnull ", 8) ? str : str + 8; // we can do better DECL_OO(const m_str, type_name, = get_type_name(gwi->gwion->env, s, 0)) struct array_checker ck = { .str=type_name }; @@ -233,6 +235,7 @@ ANN Type_Decl* str2decl(const Gwi gwi, const m_str s) { td->array = new_array_sub(gwi->gwion->mp, ck.exp); td->array->depth = ck.depth; } + td->flag |= flag; return td; } diff --git a/src/import/oper.c b/src/import/oper.c index 7e280453..c810f096 100644 --- a/src/import/oper.c +++ b/src/import/oper.c @@ -16,15 +16,13 @@ #include "mpool.h" #include "specialid.h" -ANN static Type _get_type(const Gwi gwi, const m_str str) { - if(str == (m_str)OP_ANY_TYPE) +ANN static Type _get_type(const Gwi gwi, const m_str s) { + if(s == (m_str)OP_ANY_TYPE) return OP_ANY_TYPE; - struct array_checker ck = { .str=str }; - DECL_OO(const ID_List, list, = ck2list(gwi, &ck)) - const Type t = find_type(gwi->gwion->env, list); - if(list) - free_id_list(gwi->gwion->mp, list); - return t ? (ck.depth ? array_type(gwi->gwion->env, t, ck.depth) : t) : NULL; + Type_Decl *td = str2decl(gwi, s); + const Type t = known_type(gwi->gwion->env, td); + free_type_decl(gwi->gwion->mp, td); + return t; } ANN2(1) static inline Type get_type(const Gwi gwi, const m_str str) { @@ -36,8 +34,9 @@ ANN2(1,2) static int import_op(const Gwi gwi, const struct OperCK* op, const Type lhs = get_type(gwi, op->lhs), rhs = get_type(gwi, op->rhs), ret = get_type(gwi, op->ret); - const struct Op_Import opi = { lhs, rhs, ret, - op->ck, op->em, (uintptr_t)f, gwi->loc, op->sym }; + const struct Op_Func opfunc = { .ck=op->ck, .em=op->em }; + const struct Op_Import opi = { .lhs=lhs, .rhs=rhs, .ret=ret, + .func=&opfunc, .data=(uintptr_t)f, .pos=gwi->loc, .op=op->sym, .emit_var=op->emit_var }; return add_op(gwi->gwion, &opi); } @@ -55,6 +54,11 @@ ANN m_int gwi_oper_add(const Gwi gwi, Type (*ck)(Env, void*, m_bool*)) { return GW_OK; } +ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset) { + gwi->oper->emit_var = offset; + return GW_OK; +} + ANN m_int gwi_oper_emi(const Gwi gwi, const opem em) { gwi->oper->em = em; return GW_OK; @@ -70,7 +74,7 @@ ANN m_int gwi_oper_end(const Gwi gwi, const m_str op, const f_instr f) { ANN m_int gwi_oper_cond(const Gwi gwi, const m_str type, const f_instr f1, const f_instr f2) { - GWI_BB(gwi_oper_ini(gwi, NULL, type, "int")) + GWI_BB(gwi_oper_ini(gwi, NULL, type, "bool")) GWI_BB(gwi_oper_end(gwi, "@conditionnal", f1)) GWI_BB(gwi_oper_end(gwi, "@unconditionnal", f2)) return GW_OK; diff --git a/src/lib/array.c b/src/lib/array.c index b27651e7..fff75f3a 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -165,8 +165,6 @@ static OP_EMIT(opem_array_shift) { const Type type = bin->rhs->type; const Instr pop = emit_add_instr(emit, RegPop); pop->m_val = type->size; - if(!GET_FLAG(bin->lhs->type, nonnull)) - emit_add_instr(emit, GWOP_EXCEPT); return emit_add_instr(emit, ArrayAppend); } @@ -216,9 +214,6 @@ static INSTR(ArraySlice) { } static OP_EMIT(opem_array_slice) { - const Exp exp = (Exp)data; - if(!GET_FLAG(exp->type, nonnull)) - emit_add_instr(emit, GWOP_EXCEPT); emit_add_instr(emit, ArraySlice); return emit_add_instr(emit, GcAdd); } @@ -331,6 +326,7 @@ GWION_IMPORT(array) { GWI_BB(gwi_oper_ini(gwi, "@Array", (m_str)OP_ANY_TYPE, NULL)) GWI_BB(gwi_oper_add(gwi, opck_array_at)) GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign)) + GWI_BB(gwi_oper_ini(gwi, "nonnull @Array", (m_str)OP_ANY_TYPE, NULL)) GWI_BB(gwi_oper_add(gwi, opck_array_shift)) GWI_BB(gwi_oper_emi(gwi, opem_array_shift)) GWI_BB(gwi_oper_end(gwi, "<<", NULL)) @@ -338,11 +334,11 @@ GWION_IMPORT(array) { GWI_BB(gwi_oper_add(gwi, opck_array_cast)) GWI_BB(gwi_oper_emi(gwi, opem_basic_cast)) GWI_BB(gwi_oper_end(gwi, "$", NULL)) - GWI_BB(gwi_oper_ini(gwi, "@Array", "int", "int")) + GWI_BB(gwi_oper_ini(gwi, "nonnull @Array", "int", "int")) GWI_BB(gwi_oper_add(gwi, opck_array_slice)) GWI_BB(gwi_oper_emi(gwi, opem_array_slice)) + GWI_BB(gwi_oper_var(gwi, SZ_INT*2)) GWI_BB(gwi_oper_end(gwi, "@slice", NULL)) - GWI_BB(gwi_oper_add(gwi, opck_array_slice)) GWI_BB(gwi_oper_ini(gwi, "int", (m_str)OP_ANY_TYPE, NULL)) GWI_BB(gwi_oper_add(gwi, opck_not_array)) GWI_BB(gwi_oper_end(gwi, "@array", NULL)) diff --git a/src/lib/engine.c b/src/lib/engine.c index c8519b9f..2bc1d817 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -17,6 +17,7 @@ #include "specialid.h" #include "gack.h" +#undef insert_symbol static GACK(gack_class) { const Type type = actual_type(shred->info->vm->gwion, t) ?: t; INTERP_PRINTF("class(%s)", type->name) @@ -73,7 +74,6 @@ ANN static m_bool import_core_libs(const Gwi gwi) { GWI_BB(gwi_oper_emi(gwi, opem_object_dot)) GWI_BB(gwi_oper_end(gwi, "@dot", NULL)) GWI_BB(gwi_gack(gwi, gwi->gwion->type[et_class], gack_class)) // not working yet - gwi->gwion->type[et_class] = t_class; const Type t_undefined = gwi_mk_type(gwi, "@Undefined", SZ_INT, NULL); GWI_BB(gwi_set_global_type(gwi, t_undefined, et_undefined)) const Type t_auto = gwi_mk_type(gwi, "auto", SZ_INT, NULL); @@ -82,14 +82,6 @@ ANN static m_bool import_core_libs(const Gwi gwi) { const Type t_void = gwi_mk_type(gwi, "void", 0, NULL); GWI_BB(gwi_gack(gwi, t_void, gack_void)) GWI_BB(gwi_set_global_type(gwi, t_void, et_void)) - const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL); - GWI_BB(gwi_gack(gwi, t_function, gack_function)) - GWI_BB(gwi_set_global_type(gwi, t_function, et_function)) - const Type t_fptr = gwi_mk_type(gwi, "@func_ptr", SZ_INT, "@function"); - GWI_BB(gwi_gack(gwi, t_fptr, gack_fptr)) - GWI_BB(gwi_set_global_type(gwi, t_fptr, et_fptr)) - const Type t_lambda = gwi_mk_type(gwi, "@lambda", SZ_INT, "@function"); - GWI_BB(gwi_set_global_type(gwi, t_lambda, et_lambda)) const Type t_gack = gwi_mk_type(gwi, "@Gack", SZ_INT, NULL); GWI_BB(gwi_set_global_type(gwi, t_gack, et_gack)) const Type t_int = gwi_mk_type(gwi, "int", SZ_INT, NULL); @@ -112,10 +104,22 @@ ANN static m_bool import_core_libs(const Gwi gwi) { struct SpecialId_ spid = { .type=t_now, .exec=RegPushNow, .is_const=1 }; gwi_specialid(gwi, "now", &spid); + GWI_BB(import_object(gwi)) + GWI_BB(import_prim(gwi)) + const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL); + GWI_BB(gwi_gack(gwi, t_function, gack_function)) + GWI_BB(gwi_set_global_type(gwi, t_function, et_function)) + const Type t_fptr = gwi_mk_type(gwi, "@func_ptr", SZ_INT, "@function"); + GWI_BB(gwi_gack(gwi, t_fptr, gack_fptr)) + GWI_BB(gwi_set_global_type(gwi, t_fptr, et_fptr)) + const Type t_lambda = gwi_mk_type(gwi, "@lambda", SZ_INT, "@function"); + GWI_BB(gwi_set_global_type(gwi, t_lambda, et_lambda)) GWI_BB(gwi_typedef_ini(gwi, "int", "@internal")) GWI_BB(gwi_typedef_end(gwi, ae_flag_none)) - GWI_BB(import_object(gwi)) + + GWI_BB(import_object_op(gwi)) + GWI_BB(import_values(gwi)) // TODO: check me const Type t_union = gwi_class_ini(gwi, "@Union", NULL); @@ -131,7 +135,7 @@ ANN static m_bool import_core_libs(const Gwi gwi) { GWI_BB(gwi_oper_add(gwi, opck_new)) GWI_BB(gwi_oper_emi(gwi, opem_new)) GWI_BB(gwi_oper_end(gwi, "new", NULL)) - GWI_BB(import_prim(gwi)) +// GWI_BB(import_prim(gwi)) GWI_BB(import_vararg(gwi)) GWI_BB(import_string(gwi)) GWI_BB(import_shred(gwi)) diff --git a/src/lib/event.c b/src/lib/event.c index 1e90b1de..99718565 100644 --- a/src/lib/event.c +++ b/src/lib/event.c @@ -24,8 +24,6 @@ static OP_CHECK(opck_eventwait) { static INSTR(EventWait) { POP_REG(shred, SZ_FLOAT); const M_Object event = *(M_Object*)REG(-SZ_INT); - if(!event) - Except(shred, "NullEventWait"); shreduler_remove(shred->tick->shreduler, shred, 0); const Vector v = EV_SHREDS(event); vector_add(v, (vtype)shred); @@ -66,7 +64,8 @@ GWION_IMPORT(event) { GWI_BB(gwi_func_ini(gwi, "void", "broadcast")) GWI_BB(gwi_func_end(gwi, event_broadcast, ae_flag_none)) GWI_BB(gwi_class_end(gwi)) - GWI_BB(gwi_oper_ini(gwi, "Event", "@now", "int")) + GWI_BB(gwi_oper_ini(gwi, "nonnull Event", "@now", "int")) + GWI_BB(gwi_oper_var(gwi, -SZ_FLOAT)) _CHECK_OP("=>", eventwait, EventWait) return GW_OK; } diff --git a/src/lib/object.c b/src/lib/object.c index 116b2407..c421f141 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -95,123 +95,6 @@ ANN void free_object(MemPool p, const M_Object o) { mp_free(p, M_Object, o); } -#define describe_logical(name, op) \ -static INSTR(name##Object) {\ - POP_REG(shred, SZ_INT); \ - const M_Object lhs = *(M_Object*)REG(-SZ_INT); \ - const M_Object rhs = *(M_Object*)REG(0); \ - *(m_uint*)REG(-SZ_INT) = (lhs op rhs); \ - release(lhs, shred); \ - release(rhs, shred); \ -} - -describe_logical(Eq, ==) -describe_logical(Neq, !=) - -static inline m_bool nonnull_check(const Type l, const Type r) { - return !GET_FLAG(l, nonnull) && GET_FLAG(r, nonnull); -} - -static inline Type check_nonnull(const Env env, const Type l, const Type r, - const m_str action, const loc_t pos) { - if(GET_FLAG(r, nonnull)) { - if(isa(l, env->gwion->type[et_null]) > 0) - ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); - if(isa(l, r) < 0) - ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); - return r->e->parent; - } - if(l != env->gwion->type[et_null] && isa(l, r) < 0) - ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); - return r; -} - -static OP_CHECK(at_object) { - const Exp_Binary* bin = (Exp_Binary*)data; - const Type l = bin->lhs->type; - const Type r = bin->rhs->type; - if(opck_rassign(env, data, mut) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; - if(check_nonnull(env, l, r, "assign", exp_self(bin)->pos) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; - if(bin->rhs->exp_type == ae_exp_decl) { - SET_FLAG(bin->rhs->d.exp_decl.td, ref); - SET_FLAG(bin->rhs->d.exp_decl.list->self->value, ref); - } - bin->rhs->emit_var = 1; - return r; -} - -static OP_EMIT(opem_at_object) { - const Exp_Binary* bin = (Exp_Binary*)data; - const Type l = bin->lhs->type; - const Type r = bin->rhs->type; - if(nonnull_check(l, r)) { - const Instr instr = emit_add_instr(emit, GWOP_EXCEPT); - instr->m_val = SZ_INT; - } - return emit_add_instr(emit, ObjectAssign); -} - -#define STR_FORCE ":force" -#define STRLEN_FORCE strlen(STR_FORCE) - -static inline Type new_force_type(MemPool p, const Type t, const Symbol sym) { - const Type ret = type_copy(p, t); - if(ret->nspc) - ADD_REF(ret->nspc) - ret->name = s_name(sym); - ret->flag = t->flag | ae_flag_force; - nspc_add_type_front(t->e->owner, sym, ret); - return ret; - } - -static Type get_force_type(const Env env, const Type t) { - const size_t len = strlen(t->name); - char name[len + STRLEN_FORCE + 2]; - strcpy(name, t->name); - strcpy(name + len, STR_FORCE); - const Symbol sym = insert_symbol(env->gwion->st, name); - return nspc_lookup_type1(t->e->owner, sym) ?: new_force_type(env->gwion->mp, t, sym); -} - -static OP_CHECK(opck_object_cast) { - const Exp_Cast* cast = (Exp_Cast*)data; - const Type l = cast->exp->type; - const Type r = exp_self(cast)->type; - if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; - return get_force_type(env, r); -} - -static OP_EMIT(opem_object_cast) { - const Exp_Cast* cast = (Exp_Cast*)data; - const Type l = cast->exp->type; - const Type r = exp_self(cast)->type; - if(nonnull_check(l, r)) - emit_add_instr(emit, GWOP_EXCEPT); - return (Instr)GW_OK; -} - -static OP_CHECK(opck_implicit_null2obj) { - const struct Implicit* imp = (struct Implicit*)data; - const Type l = imp->e->type; - const Type r = imp->t; - if(check_nonnull(env, l, r, "implicitly cast", imp->e->pos) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; - imp->e->cast_to = r; - return imp->t; -} - -static OP_EMIT(opem_implicit_null2obj) { - const struct Implicit* imp = (struct Implicit*)data; - const Type l = imp->e->type; - const Type r = imp->t; - if(nonnull_check(l, r)) - emit_add_instr(emit, GWOP_EXCEPT); - return (Instr)GW_OK; -} - static ID_CHECK(check_this) { if(!env->class_def) ERR_O(exp_self(prim)->pos, _("keyword 'this' can be used only inside class definition...")) @@ -224,286 +107,13 @@ static GACK(gack_object) { INTERP_PRINTF("%p", *(M_Object*)VALUE); } -ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td); - -static OP_CHECK(opck_object_scan) { - struct TemplateScan *ts = (struct TemplateScan*)data; - if(ts->td->types) - return scan_class(env, ts->t, ts->td); - ERR_O(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name) -} - -static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm }; -ANN Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]); -ANN static void emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) { - const m_uint size = v->type->size; - const Instr instr = emit_kind(emit, size, emit_var, dotstatic); - instr->m_val = (m_uint)(v->from->owner->info->class_data + v->from->offset); - instr->m_val2 = size; -} - -static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 }; -ANN static void emit_dot_static_import_data(const Emitter emit, const Value v, const uint emit_addr) { - if(v->d.ptr && GET_FLAG(v, builtin) && GET_FLAG(v, const)) { - const m_uint size = v->type->size; - const Instr instr = emit_kind(emit, size, emit_addr, regpushimm); - instr->m_val = (m_uint)v->d.ptr; - instr->m_val2 = size; - } else - emit_dot_static_data(emit, v, emit_addr); -} -static const f_instr dotmember[] = { DotMember, DotMember2, DotMember3, DotMember4 }; - -ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) { - const Func f = exp_self(member)->type->e->d.func; - if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) { - const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode); - func_i->m_val = (m_uint)f->code; - return; - } - if(f->def->base->tmpl) - emit_add_instr(emit, DotTmplVal); - else { - const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc); - instr->m_val = f->vt_index; - } - return; -} - -ANN static inline void emit_member(const Emitter emit, const Value v, const uint emit_addr) { - const m_uint size = v->type->size; - const Instr instr = emit_kind(emit, size, emit_addr, dotmember); - instr->m_val = v->from->offset; - instr->m_val2 = size; -} - -ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos); -OP_CHECK(opck_object_dot) { - const Exp_Dot *member = (Exp_Dot*)data; - const m_str str = s_name(member->xid); - const m_bool base_static = is_class(env->gwion, member->t_base); - const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base; - if(!the_base->nspc) - ERR_O(member->base->pos, - _("type '%s' does not have members - invalid use in dot expression of %s"), - the_base->name, str) - if(member->xid == insert_symbol(env->gwion->st, "this") && base_static) - ERR_O(exp_self(member)->pos, - _("keyword 'this' must be associated with object instance...")) - const Value value = find_value(the_base, member->xid); - if(!value) { - env_err(env, exp_self(member)->pos, - _("class '%s' has no member '%s'"), the_base->name, str); - if(member->t_base->nspc) - did_you_mean_type(the_base, str); - return NULL; - } - CHECK_BO(not_from_owner_class(env, the_base, value, exp_self(member)->pos)) - if(!env->class_def || isa(env->class_def, value->from->owner_class) < 0) { - if(GET_FLAG(value, private)) - ERR_O(exp_self(member)->pos, - _("can't access private '%s' outside of class..."), value->name) - else if(GET_FLAG(value, protect)) - exp_self(member)->meta = ae_meta_protect; - } - if(base_static && GET_FLAG(value, member)) - ERR_O(exp_self(member)->pos, - _("cannot access member '%s.%s' without object instance..."), - the_base->name, str) - if(GET_FLAG(value, const) || GET_FLAG(value, enum)) - exp_self(member)->meta = ae_meta_value; - return value->type; -} - -OP_EMIT(opem_object_dot) { - const Exp_Dot *member = (Exp_Dot*)data; - const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid); - if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) || - (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && - !is_fptr(emit->gwion, exp_self(member)->type)))) { - CHECK_BO(emit_exp(emit, member->base, 0)) - emit_except(emit, member->t_base); - } - if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type)) - emit_member_func(emit, member); - else (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data)(emit, value, exp_self(member)->emit_var); - return (Instr)GW_OK; -} - GWION_IMPORT(object) { const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL); gwi_add_type(gwi, t_object); GWI_BB(gwi_gack(gwi, t_object, gack_object)) SET_FLAG(t_object, checked); // should be set by gwi_add_type gwi->gwion->type[et_object] = t_object; - - const Type t_null = gwi_mk_type(gwi, "@null", SZ_INT, "Object"); - gwi->gwion->type[et_null] = t_null; - GWI_BB(gwi_set_global_type(gwi, t_null, et_null)) - GWI_BB(gwi_oper_cond(gwi, "Object", BranchEqInt, BranchNeqInt)) - GWI_BB(gwi_oper_ini(gwi, "Object", "Object", NULL)) - GWI_BB(gwi_oper_add(gwi, at_object)) - GWI_BB(gwi_oper_emi(gwi, opem_at_object)) - GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign)) - GWI_BB(gwi_oper_ini(gwi, "Object", "Object", "int")) - GWI_BB(gwi_oper_end(gwi, "==", EqObject)) - GWI_BB(gwi_oper_end(gwi, "!=", NeqObject)) - GWI_BB(gwi_oper_add(gwi, opck_object_cast)) - GWI_BB(gwi_oper_emi(gwi, opem_object_cast)) - GWI_BB(gwi_oper_end(gwi, "$", NULL)) - GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj)) - GWI_BB(gwi_oper_emi(gwi, opem_implicit_null2obj)) - GWI_BB(gwi_oper_end(gwi, "@implicit", NULL)) - GWI_BB(gwi_oper_ini(gwi, "@null", "Object", "int")) - GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj)) - GWI_BB(gwi_oper_end(gwi, "@implicit", NULL)) - GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool")) - GWI_BB(gwi_oper_add(gwi, opck_unary_meta2)) - GWI_BB(gwi_oper_end(gwi, "!", IntNot)) - GWI_BB(gwi_oper_ini(gwi, "Object", NULL, NULL)) - GWI_BB(gwi_oper_add(gwi, opck_object_scan)) - GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) - gwi_item_ini(gwi, "@null", "null"); - gwi_item_end(gwi, 0, NULL); struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 }; gwi_specialid(gwi, "this", &spid); return GW_OK; } -struct tmpl_info { - const Class_Def cdef; - Type_List call; - struct Vector_ type; - struct Vector_ size; - uint8_t index; -}; - -ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) { - vector_add(&info->type, (vtype)t); - const size_t len = strlen(t->name); - vector_add(&info->size, len); - return len; -} - -ANN static ssize_t template_size(const Env env, struct tmpl_info* info) { - ID_List base = info->cdef->base.tmpl->list; - Type_List call = info->call; - size_t size = tmpl_set(info, info->cdef->base.type); - do { - DECL_OB(const Type, t, = known_type(env, call->td)) - size += tmpl_set(info, t); - } while((call = call->next) && (base = base->next) && ++size); - return size + 16 + 3; -} - -ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) { - const Type t = (Type)vector_at(&info->type, info->index); - strcpy(str, t->name); - return str += vector_at(&info->size, info->index); -} - -ANN static void template_name(struct tmpl_info* info, m_str s) { - m_str str = s; - str = tmpl_get(info, str); - *str++ = '<'; - *str++ = '~'; - const m_uint size = vector_size(&info->type); - for(info->index = 1; info->index < size; ++info->index) { - str = tmpl_get(info, str); - if(info->index < size - 1) - *str++ = ','; - else { - *str++ = '~'; - *str++ = '>'; - } - } - *str = '\0'; -} - -ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) { - struct tmpl_info info = { .cdef=c, .call=call }; - vector_init(&info.type); - vector_init(&info.size); - ssize_t sz = template_size(env, &info); - char name[sz]; - if(sz > GW_ERROR) - template_name(&info, name); - vector_release(&info.type); - vector_release(&info.size); - return sz > GW_ERROR ? insert_symbol(env->gwion->st, name) : NULL; -} - -ANN m_bool template_match(ID_List base, Type_List call) { - while((call = call->next) && (base = base->next)); - return !call ? GW_OK : GW_ERROR; -} - -ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) { - DECL_OO(const Symbol, name, = template_id(env, def, call)) - if(env->class_def && name == insert_symbol(env->gwion->st, env->class_def->name)) - return env->class_def->e->def; - const Type t = nspc_lookup_type1(env->curr, name); - if(t) - return t->e->def; - const Class_Def c = cpy_class_def(env->gwion->mp, def); - c->base.xid = name; - SET_FLAG(c, template | ae_flag_ref); - return c; - -} - -extern ANN m_bool scan0_class_def(const Env, const Class_Def); -extern ANN m_bool scan1_class_def(const Env, const Class_Def); -extern ANN m_bool traverse_func_def(const Env, const Func_Def); -extern ANN m_bool traverse_class_def(const Env, const Class_Def); - -ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) { - a->union_def = new_union_def(env->gwion->mp, a->list, - loc_cpy(env->gwion->mp, t->e->def->pos)); - a->union_def->type_xid = a->base.xid; - CHECK_BB(scan0_union_def(env, a->union_def)) - SET_FLAG(a, scan0); - a->base.type = a->union_def->type; - a->base.type->e->def = a; - return GW_OK; -} - -ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) { - if(template_match(t->e->def->base.tmpl->list, td->types) < 0) - ERR_O(td->xid->pos, _("invalid template types number")) - DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types)) - if(a->base.type) - return a->base.type; - a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types); - if(t->e->parent != env->gwion->type[et_union]) - CHECK_BO(scan0_class_def(env, a)) - else - CHECK_BO(class2udef(env, a, t)) - SET_FLAG(a->base.type, template); - if(GET_FLAG(t, builtin)) - SET_FLAG(a->base.type, builtin); - CHECK_BO(scan1_cdef(env, a)) - return a->base.type; -} - -ANN static inline Symbol dot_symbol(SymTable *st, const Value v) { - const m_str name = !GET_FLAG(v, static) ? "this" : v->from->owner_class->name; - return insert_symbol(st, name); -} - -ANN static inline Type dot_type(SymTable *st, const Value v) { - const Type t = v->from->owner_class; - if(!GET_FLAG(v, static)) - return t; - const Value val = nspc_lookup_value1(t->nspc->parent, insert_symbol(st, t->name)); - return val->type; -} - -ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data) { - const Value v = prim_self(data)->value; - const Exp base = new_prim_id(gwion->mp, dot_symbol(gwion->st, v), loc_cpy(gwion->mp, prim_pos(data))); - const Exp dot = new_exp_dot(gwion->mp, base, *data); - dot->d.exp_dot.t_base = dot->d.exp_dot.base->type = dot_type(gwion->st, v); - dot->type = prim_exp(data)->type; - dot->emit_var = prim_exp(data)->emit_var; - return dot; -} diff --git a/src/lib/object_op.c b/src/lib/object_op.c new file mode 100644 index 00000000..e0ccb8b0 --- /dev/null +++ b/src/lib/object_op.c @@ -0,0 +1,415 @@ +#include +#include +#include "gwion_util.h" +#include "gwion_ast.h" +#include "gwion_env.h" +#include "vm.h" +#include "gwion.h" +#include "instr.h" +#include "object.h" +#include "operator.h" +#include "import.h" +#include "emit.h" +#include "traverse.h" +#include "template.h" +#include "parse.h" +#include "specialid.h" + +#include "gwi.h" + +#undef insert_symbol + +#define describe_logical(name, op) \ +static INSTR(name##Object) {\ + POP_REG(shred, SZ_INT); \ + const M_Object lhs = *(M_Object*)REG(-SZ_INT); \ + const M_Object rhs = *(M_Object*)REG(0); \ + *(m_uint*)REG(-SZ_INT) = (lhs op rhs); \ + release(lhs, shred); \ + release(rhs, shred); \ +} + +describe_logical(Eq, ==) +describe_logical(Neq, !=) +static inline m_bool nonnull_check(const Type l, const Type r) { + return !GET_FLAG(l, nonnull) && GET_FLAG(r, nonnull); +} + +static inline Type check_nonnull(const Env env, const Type l, const Type r, + const m_str action, const loc_t pos) { + if(GET_FLAG(r, nonnull)) { + if(isa(l, env->gwion->type[et_null]) > 0) + ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); + if(isa(l, r) < 0) + ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); + return r->e->parent; + } + if(l != env->gwion->type[et_null] && isa(l, r) < 0) + ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); + return r; +} + +static OP_CHECK(at_object) { + const Exp_Binary* bin = (Exp_Binary*)data; + const Type l = bin->lhs->type; + const Type r = bin->rhs->type; + if(opck_rassign(env, data, mut) == env->gwion->type[et_null]) + return env->gwion->type[et_null]; + if(check_nonnull(env, l, r, "assign", exp_self(bin)->pos) == env->gwion->type[et_null]) + return env->gwion->type[et_null]; + if(bin->rhs->exp_type == ae_exp_decl) { + SET_FLAG(bin->rhs->d.exp_decl.td, ref); + SET_FLAG(bin->rhs->d.exp_decl.list->self->value, ref); + } + bin->rhs->emit_var = 1; + return r; +} + +static OP_EMIT(opem_at_object) { + const Exp_Binary* bin = (Exp_Binary*)data; + const Type l = bin->lhs->type; + const Type r = bin->rhs->type; + if(nonnull_check(l, r)) { + const Instr instr = emit_add_instr(emit, GWOP_EXCEPT); + instr->m_val = SZ_INT; + } + return emit_add_instr(emit, ObjectAssign); +} + +#define STR_FORCE ":force" +#define STRLEN_FORCE strlen(STR_FORCE) + +static inline Type new_force_type(MemPool p, const Type t, const Symbol sym) { + const Type ret = type_copy(p, t); + if(ret->nspc) + ADD_REF(ret->nspc) + ret->name = s_name(sym); + ret->flag = t->flag | ae_flag_force; + nspc_add_type_front(t->e->owner, sym, ret); + return ret; + } + +static Type get_force_type(const Env env, const Type t) { + const size_t len = strlen(t->name); + char name[len + STRLEN_FORCE + 2]; + strcpy(name, t->name); + strcpy(name + len, STR_FORCE); + const Symbol sym = insert_symbol(env->gwion->st, name); + return nspc_lookup_type1(t->e->owner, sym) ?: new_force_type(env->gwion->mp, t, sym); +} + +static OP_CHECK(opck_object_cast) { + const Exp_Cast* cast = (Exp_Cast*)data; + const Type l = cast->exp->type; + const Type r = exp_self(cast)->type; + if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null]) + return env->gwion->type[et_null]; + return get_force_type(env, r); +} + +static OP_EMIT(opem_object_cast) { + const Exp_Cast* cast = (Exp_Cast*)data; + const Type l = cast->exp->type; + const Type r = exp_self(cast)->type; + if(nonnull_check(l, r)) + emit_add_instr(emit, GWOP_EXCEPT); + return (Instr)GW_OK; +} + +static OP_CHECK(opck_implicit_null2obj) { + const struct Implicit* imp = (struct Implicit*)data; + const Type l = imp->e->type; + const Type r = imp->t; + if(check_nonnull(env, l, r, "implicitly cast", imp->e->pos) == env->gwion->type[et_null]) + return env->gwion->type[et_null]; + imp->e->cast_to = r; + return imp->t; +} + +static OP_EMIT(opem_implicit_null2obj) { + const struct Implicit* imp = (struct Implicit*)data; + const Type l = imp->e->type; + const Type r = imp->t; + if(nonnull_check(l, r)) + emit_add_instr(emit, GWOP_EXCEPT); + return (Instr)GW_OK; +} + +ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td); + +OP_CHECK(opck_object_scan) { + struct TemplateScan *ts = (struct TemplateScan*)data; + if(ts->td->types) + return scan_class(env, ts->t, ts->td); + if(GET_FLAG(ts->t, unary)) + return ts->t; + ERR_O(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name) +} + +static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm }; +ANN Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]); +ANN static void emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) { + const m_uint size = v->type->size; + const Instr instr = emit_kind(emit, size, emit_var, dotstatic); + instr->m_val = (m_uint)(v->from->owner->info->class_data + v->from->offset); + instr->m_val2 = size; +} + +static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 }; +ANN static void emit_dot_static_import_data(const Emitter emit, const Value v, const uint emit_addr) { + if(v->d.ptr && GET_FLAG(v, builtin) && GET_FLAG(v, const)) { + const m_uint size = v->type->size; + const Instr instr = emit_kind(emit, size, emit_addr, regpushimm); + instr->m_val = (m_uint)v->d.ptr; + instr->m_val2 = size; + } else + emit_dot_static_data(emit, v, emit_addr); +} +static const f_instr dotmember[] = { DotMember, DotMember2, DotMember3, DotMember4 }; + +ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) { + const Func f = exp_self(member)->type->e->d.func; + if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) { + const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode); + func_i->m_val = (m_uint)f->code; + return; + } + if(f->def->base->tmpl) + emit_add_instr(emit, DotTmplVal); + else { + const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc); + instr->m_val = f->vt_index; + } + return; +} + +ANN static inline void emit_member(const Emitter emit, const Value v, const uint emit_addr) { + const m_uint size = v->type->size; + const Instr instr = emit_kind(emit, size, emit_addr, dotmember); + instr->m_val = v->from->offset; + instr->m_val2 = size; +} + +ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos); +OP_CHECK(opck_object_dot) { + const Exp_Dot *member = (Exp_Dot*)data; + const m_str str = s_name(member->xid); + const m_bool base_static = is_class(env->gwion, member->t_base); + const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base; + if(!the_base->nspc) + ERR_O(member->base->pos, + _("type '%s' does not have members - invalid use in dot expression of %s"), + the_base->name, str) + if(member->xid == insert_symbol(env->gwion->st, "this") && base_static) + ERR_O(exp_self(member)->pos, + _("keyword 'this' must be associated with object instance...")) + const Value value = find_value(the_base, member->xid); + if(!value) { + env_err(env, exp_self(member)->pos, + _("class '%s' has no member '%s'"), the_base->name, str); + if(member->t_base->nspc) + did_you_mean_type(the_base, str); + return NULL; + } + CHECK_BO(not_from_owner_class(env, the_base, value, exp_self(member)->pos)) + if(!env->class_def || isa(env->class_def, value->from->owner_class) < 0) { + if(GET_FLAG(value, private)) + ERR_O(exp_self(member)->pos, + _("can't access private '%s' outside of class..."), value->name) + else if(GET_FLAG(value, protect)) + exp_self(member)->meta = ae_meta_protect; + } + if(base_static && GET_FLAG(value, member)) + ERR_O(exp_self(member)->pos, + _("cannot access member '%s.%s' without object instance..."), + the_base->name, str) + if(GET_FLAG(value, const) || GET_FLAG(value, enum)) + exp_self(member)->meta = ae_meta_value; + return value->type; +} + +OP_EMIT(opem_object_dot) { + const Exp_Dot *member = (Exp_Dot*)data; + const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid); + if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) || + (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && + !is_fptr(emit->gwion, exp_self(member)->type)))) { + CHECK_BO(emit_exp(emit, member->base, 0)) + emit_except(emit, member->t_base); + } + if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type)) + emit_member_func(emit, member); + else (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data)(emit, value, exp_self(member)->emit_var); + return (Instr)GW_OK; +} + +struct tmpl_info { + const Class_Def cdef; + Type_List call; + struct Vector_ type; + struct Vector_ size; + uint8_t index; +}; + +ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) { + vector_add(&info->type, (vtype)t); + const size_t len = strlen(t->name); + vector_add(&info->size, len); + return len; +} + +ANN static ssize_t template_size(const Env env, struct tmpl_info* info) { + ID_List base = info->cdef->base.tmpl->list; + Type_List call = info->call; + size_t size = tmpl_set(info, info->cdef->base.type); + do { + DECL_OB(const Type, t, = known_type(env, call->td)) + size += tmpl_set(info, t); + } while((call = call->next) && (base = base->next) && ++size); + return size + 16 + 3; +} + +ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) { + const Type t = (Type)vector_at(&info->type, info->index); + strcpy(str, t->name); + return str += vector_at(&info->size, info->index); +} + +ANN static void template_name(struct tmpl_info* info, m_str s) { + m_str str = s; + str = tmpl_get(info, str); + *str++ = '<'; + *str++ = '~'; + const m_uint size = vector_size(&info->type); + for(info->index = 1; info->index < size; ++info->index) { + str = tmpl_get(info, str); + if(info->index < size - 1) + *str++ = ','; + else { + *str++ = '~'; + *str++ = '>'; + } + } + *str = '\0'; +} + +ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) { + struct tmpl_info info = { .cdef=c, .call=call }; + vector_init(&info.type); + vector_init(&info.size); + ssize_t sz = template_size(env, &info); + char name[sz]; + if(sz > GW_ERROR) + template_name(&info, name); + vector_release(&info.type); + vector_release(&info.size); + return sz > GW_ERROR ? insert_symbol(env->gwion->st, name) : NULL; +} + +ANN m_bool template_match(ID_List base, Type_List call) { + while((call = call->next) && (base = base->next)); + return !call ? GW_OK : GW_ERROR; +} + +ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) { + DECL_OO(const Symbol, name, = template_id(env, def, call)) + if(env->class_def && name == insert_symbol(env->gwion->st, env->class_def->name)) + return env->class_def->e->def; + const Type t = nspc_lookup_type1(env->curr, name); + if(t) + return t->e->def; + const Class_Def c = cpy_class_def(env->gwion->mp, def); + c->base.xid = name; + SET_FLAG(c, template | ae_flag_ref); + return c; + +} + +extern ANN m_bool scan0_class_def(const Env, const Class_Def); +extern ANN m_bool scan1_class_def(const Env, const Class_Def); +extern ANN m_bool traverse_func_def(const Env, const Func_Def); +extern ANN m_bool traverse_class_def(const Env, const Class_Def); + +ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) { + a->union_def = new_union_def(env->gwion->mp, a->list, + loc_cpy(env->gwion->mp, t->e->def->pos)); + a->union_def->type_xid = a->base.xid; + CHECK_BB(scan0_union_def(env, a->union_def)) + SET_FLAG(a, scan0); + a->base.type = a->union_def->type; + a->base.type->e->def = a; + return GW_OK; +} + +ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) { + if(template_match(t->e->def->base.tmpl->list, td->types) < 0) + ERR_O(td->xid->pos, _("invalid template types number")) + DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types)) + if(a->base.type) + return a->base.type; + a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types); + if(t->e->parent != env->gwion->type[et_union]) + CHECK_BO(scan0_class_def(env, a)) + else + CHECK_BO(class2udef(env, a, t)) + SET_FLAG(a->base.type, template); + if(GET_FLAG(t, builtin)) + SET_FLAG(a->base.type, builtin); + CHECK_BO(scan1_cdef(env, a)) + return a->base.type; +} + +ANN static inline Symbol dot_symbol(SymTable *st, const Value v) { + const m_str name = !GET_FLAG(v, static) ? "this" : v->from->owner_class->name; + return insert_symbol(st, name); +} + +ANN static inline Type dot_type(SymTable *st, const Value v) { + const Type t = v->from->owner_class; + if(!GET_FLAG(v, static)) + return t; + const Value val = nspc_lookup_value1(t->nspc->parent, insert_symbol(st, t->name)); + return val->type; +} + +ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data) { + const Value v = prim_self(data)->value; + const Exp base = new_prim_id(gwion->mp, dot_symbol(gwion->st, v), loc_cpy(gwion->mp, prim_pos(data))); + const Exp dot = new_exp_dot(gwion->mp, base, *data); + dot->d.exp_dot.t_base = dot->d.exp_dot.base->type = dot_type(gwion->st, v); + dot->type = prim_exp(data)->type; + dot->emit_var = prim_exp(data)->emit_var; + return dot; +} + +GWION_IMPORT(object_op) { + const Type t_null = gwi_mk_type(gwi, "@null", SZ_INT, "Object"); + gwi->gwion->type[et_null] = t_null; + GWI_BB(gwi_set_global_type(gwi, t_null, et_null)) + GWI_BB(gwi_oper_cond(gwi, "Object", BranchEqInt, BranchNeqInt)) + GWI_BB(gwi_oper_ini(gwi, "Object", "Object", NULL)) + GWI_BB(gwi_oper_add(gwi, at_object)) + GWI_BB(gwi_oper_emi(gwi, opem_at_object)) + GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign)) + GWI_BB(gwi_oper_ini(gwi, "Object", "Object", "int")) + GWI_BB(gwi_oper_end(gwi, "==", EqObject)) + GWI_BB(gwi_oper_end(gwi, "!=", NeqObject)) + GWI_BB(gwi_oper_add(gwi, opck_object_cast)) + GWI_BB(gwi_oper_emi(gwi, opem_object_cast)) + GWI_BB(gwi_oper_end(gwi, "$", NULL)) + GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj)) + GWI_BB(gwi_oper_emi(gwi, opem_implicit_null2obj)) + GWI_BB(gwi_oper_end(gwi, "@implicit", NULL)) + GWI_BB(gwi_oper_ini(gwi, "@null", "Object", "int")) + GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj)) + GWI_BB(gwi_oper_end(gwi, "@implicit", NULL)) + GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool")) + GWI_BB(gwi_oper_add(gwi, opck_unary_meta2)) + GWI_BB(gwi_oper_end(gwi, "!", IntNot)) + GWI_BB(gwi_oper_ini(gwi, "Object", NULL, NULL)) + GWI_BB(gwi_oper_add(gwi, opck_object_scan)) + GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) + gwi_item_ini(gwi, "@null", "null"); + gwi_item_end(gwi, 0, NULL); + return GW_OK; +} diff --git a/src/lib/prim.c b/src/lib/prim.c index dcc518c4..5127bc62 100644 --- a/src/lib/prim.c +++ b/src/lib/prim.c @@ -123,44 +123,13 @@ static GWION_IMPORT(int_values) { } static GWION_IMPORT(int) { + GWI_BB(import_int_values(gwi)) GWI_BB(gwi_oper_cond(gwi, "int", BranchEqInt, BranchNeqInt)) GWI_BB(gwi_oper_ini(gwi, "int", "int", "int")) GWI_BB(import_int_op(gwi)) GWI_BB(import_int_logical(gwi)) GWI_BB(import_int_r(gwi)) GWI_BB(import_int_unary(gwi)) - return import_int_values(gwi); -} - -static GWION_IMPORT(values) { - VM* vm = gwi_vm(gwi); - ALLOC_PTR(gwi->gwion->mp, d_zero, m_float, 0.0); - ALLOC_PTR(gwi->gwion->mp, sr, m_float, (m_float)vm->bbq->si->sr); - ALLOC_PTR(gwi->gwion->mp, samp, m_float, 1.0); - ALLOC_PTR(gwi->gwion->mp, ms, m_float, (m_float)(*sr / 1000.)); - ALLOC_PTR(gwi->gwion->mp, second, m_float, (m_float)*sr); - ALLOC_PTR(gwi->gwion->mp, minute, m_float, (m_float)(*sr * 60.0)); - ALLOC_PTR(gwi->gwion->mp, hour, m_float, (m_float)(*minute * 60.0)); - ALLOC_PTR(gwi->gwion->mp, t_zero, m_float, 0.0); - ALLOC_PTR(gwi->gwion->mp, pi, m_float, (m_float)M_PI); - gwi_item_ini(gwi, "float", "samplerate"); - gwi_item_end(gwi, ae_flag_const, sr); - gwi_item_ini(gwi, "float", "pi"); - gwi_item_end(gwi, ae_flag_const, pi); - gwi_item_ini(gwi, "dur", "d_zero"); - gwi_item_end(gwi, ae_flag_const, d_zero); - gwi_item_ini(gwi, "dur", "samp"); - gwi_item_end(gwi, ae_flag_const, samp); - gwi_item_ini(gwi, "dur", "ms"); - gwi_item_end(gwi, ae_flag_const, ms); - gwi_item_ini(gwi, "dur", "second"); - gwi_item_end(gwi, ae_flag_const, second); - gwi_item_ini(gwi, "dur", "minute"); - gwi_item_end(gwi, ae_flag_const, minute); - gwi_item_ini(gwi, "dur", "hour"); - gwi_item_end(gwi, ae_flag_const, hour); - gwi_item_ini(gwi, "time", "t_zero"); - gwi_item_end(gwi, ae_flag_const, t_zero); return GW_OK; } @@ -305,6 +274,5 @@ GWION_IMPORT(prim) { GWI_BB(import_intfloat(gwi)) GWI_BB(import_floatint(gwi)) GWI_BB(import_dur(gwi)) - GWI_BB(import_time(gwi)) - return import_values(gwi); + return import_time(gwi); } diff --git a/src/lib/prim_values.c b/src/lib/prim_values.c new file mode 100644 index 00000000..9a49f76e --- /dev/null +++ b/src/lib/prim_values.c @@ -0,0 +1,49 @@ +#include "gwion_util.h" +#include "gwion_ast.h" +#include "gwion_env.h" +#include "vm.h" +#include "gwion.h" +#include "instr.h" +#include "object.h" +#include "emit.h" +#include "operator.h" +#include "import.h" +#include "gwi.h" +#include "driver.h" +#include "traverse.h" +#include "parse.h" +#include "specialid.h" +#include "array.h" +#include "gack.h" + +GWION_IMPORT(values) { + VM* vm = gwi_vm(gwi); + ALLOC_PTR(gwi->gwion->mp, d_zero, m_float, 0.0); + ALLOC_PTR(gwi->gwion->mp, sr, m_float, (m_float)vm->bbq->si->sr); + ALLOC_PTR(gwi->gwion->mp, samp, m_float, 1.0); + ALLOC_PTR(gwi->gwion->mp, ms, m_float, (m_float)(*sr / 1000.)); + ALLOC_PTR(gwi->gwion->mp, second, m_float, (m_float)*sr); + ALLOC_PTR(gwi->gwion->mp, minute, m_float, (m_float)(*sr * 60.0)); + ALLOC_PTR(gwi->gwion->mp, hour, m_float, (m_float)(*minute * 60.0)); + ALLOC_PTR(gwi->gwion->mp, t_zero, m_float, 0.0); + ALLOC_PTR(gwi->gwion->mp, pi, m_float, (m_float)M_PI); + gwi_item_ini(gwi, "float", "samplerate"); + gwi_item_end(gwi, ae_flag_const, sr); + gwi_item_ini(gwi, "float", "pi"); + gwi_item_end(gwi, ae_flag_const, pi); + gwi_item_ini(gwi, "dur", "d_zero"); + gwi_item_end(gwi, ae_flag_const, d_zero); + gwi_item_ini(gwi, "dur", "samp"); + gwi_item_end(gwi, ae_flag_const, samp); + gwi_item_ini(gwi, "dur", "ms"); + gwi_item_end(gwi, ae_flag_const, ms); + gwi_item_ini(gwi, "dur", "second"); + gwi_item_end(gwi, ae_flag_const, second); + gwi_item_ini(gwi, "dur", "minute"); + gwi_item_end(gwi, ae_flag_const, minute); + gwi_item_ini(gwi, "dur", "hour"); + gwi_item_end(gwi, ae_flag_const, hour); + gwi_item_ini(gwi, "time", "t_zero"); + gwi_item_end(gwi, ae_flag_const, t_zero); + return GW_OK; +} diff --git a/src/lib/ptr.c b/src/lib/ptr.c index 3a82cb25..ab421ef1 100644 --- a/src/lib/ptr.c +++ b/src/lib/ptr.c @@ -20,9 +20,14 @@ static OP_CHECK(opck_ptr_assign) { ERR_N(exp_self(bin)->pos, _("left side operand is constant")); bin->lhs->emit_var = 1; Type t = bin->lhs->type; - do if(!strcmp(t->name, get_type_name(env, bin->rhs->type->name, 1))) - return bin->lhs->type; - while((t = t->e->parent)); + do { + Type u = bin->rhs->type; + do { + const m_str str = get_type_name(env, u->name, 1); + if(str && !strcmp(t->name, str)) + return bin->lhs->type; + } while((u = u->e->parent)); + } while((t = t->e->parent)); return env->gwion->type[et_null]; } @@ -32,32 +37,24 @@ static INSTR(instr_ptr_assign) { *(m_uint**)o->data = *(m_uint**)REG(-SZ_INT); } -static OP_EMIT(opem_ptr_assign) { - const Exp_Binary* bin = (Exp_Binary*)data; - if(!GET_FLAG(bin->rhs->type, nonnull)) - emit_add_instr(emit, GWOP_EXCEPT); - return emit_add_instr(emit, instr_ptr_assign); -} - static OP_CHECK(opck_ptr_deref) { const Exp_Unary* unary = (Exp_Unary*)data; - return exp_self(unary)->type = nspc_lookup_type1(env->curr, insert_symbol(get_type_name(env, unary->exp->type->name, 1))); + DECL_ON(const m_str, str, = get_type_name(env, unary->exp->type->name, 1)) + return exp_self(unary)->type = nspc_lookup_type1(env->curr, insert_symbol(str)); } static OP_CHECK(opck_ptr_cast) { const Exp_Cast* cast = (Exp_Cast*)data; DECL_ON(const Type, t, = type_decl_resolve(env, cast->td)) - if(!GET_FLAG(t, check)) { - assert(t->e->def); + if(!GET_FLAG(t, check)) CHECK_BN(traverse_class_def(env, t->e->def)) - } const Type to = known_type(env, cast->td->types->td); if(isa(cast->exp->type, to) > 0) return t; ERR_N(exp_self(cast)->pos, "invalid pointer cast") } -static OP_CHECK(opck_implicit_ptr) { +static OP_CHECK(opck_ptr_implicit) { const struct Implicit* imp = (struct Implicit*)data; const Exp e = imp->e; if(!strcmp(get_type_name(env, imp->t->name, 1), e->type->name)) { @@ -65,6 +62,8 @@ static OP_CHECK(opck_implicit_ptr) { ERR_N(e->pos, _("can't cast constant to Ptr")); e->cast_to = imp->t; e->emit_var = 1; + if(!GET_FLAG(imp->t, check)) + CHECK_BN(traverse_class_def(env, imp->t->e->def)) return imp->t; } return NULL; @@ -83,18 +82,25 @@ static INSTR(instr_ptr_deref) { } static INSTR(Cast2Ptr) { - const M_Object o = new_object(shred->info->mp, shred, shred->info->vm->gwion->type[et_ptr]); + const M_Object o = new_object(shred->info->mp, shred, (Type)instr->m_val); *(m_uint**)o->data = *(m_uint**)REG(-SZ_INT); *(M_Object*)REG(-SZ_INT) = o; } -/* + static OP_EMIT(opem_ptr_cast) { const Exp_Cast* cast = (Exp_Cast*)data; const Instr instr = emit_add_instr(emit, Cast2Ptr); instr->m_val = (m_uint)exp_self(cast)->type; - return GW_OK; + return instr; } -*/ + +static OP_EMIT(opem_ptr_implicit) { + const struct Implicit* imp = (struct Implicit*)data; + const Instr instr = emit_add_instr(emit, Cast2Ptr); + instr->m_val = (m_uint)imp->t; + return instr; +} + static OP_EMIT(opem_ptr_deref) { const Exp_Unary* unary = (Exp_Unary*)data; const Instr instr = emit_add_instr(emit, instr_ptr_deref); @@ -109,17 +115,17 @@ GWION_IMPORT(ptr) { GWI_BB(gwi_item_ini(gwi, "@internal", "@val")) GWI_BB(gwi_item_end(gwi, 0, NULL)) GWI_BB(gwi_class_end(gwi)) - t_ptr->nspc->info->offset = SZ_INT; - GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "Ptr", NULL)) + SET_FLAG(t_ptr, unary); + GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "nonnull Ptr", NULL)) GWI_BB(gwi_oper_add(gwi, opck_ptr_assign)) - GWI_BB(gwi_oper_emi(gwi, opem_ptr_assign)) GWI_BB(gwi_oper_end(gwi, ":=>", instr_ptr_assign)) - GWI_BB(gwi_oper_add(gwi, opck_implicit_ptr)) + GWI_BB(gwi_oper_add(gwi, opck_ptr_implicit)) + GWI_BB(gwi_oper_emi(gwi, opem_ptr_implicit)) GWI_BB(gwi_oper_end(gwi, "@implicit", Cast2Ptr)) - GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "Ptr", NULL)) GWI_BB(gwi_oper_add(gwi, opck_ptr_cast)) + GWI_BB(gwi_oper_emi(gwi, opem_ptr_cast)) GWI_BB(gwi_oper_end(gwi, "$", Cast2Ptr)) - GWI_BB(gwi_oper_ini(gwi, NULL, "Ptr", NULL)) + GWI_BB(gwi_oper_ini(gwi, NULL, "nonnull Ptr", NULL)) GWI_BB(gwi_oper_add(gwi, opck_ptr_deref)) GWI_BB(gwi_oper_emi(gwi, opem_ptr_deref)) GWI_BB(gwi_oper_end(gwi, "*", instr_ptr_deref)) diff --git a/src/lib/string.c b/src/lib/string.c index 4a3b084a..944d26b4 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -107,17 +107,17 @@ describe_string(Object, M_Object, SZ_INT, "%p%s", (void*)lhs, rhs ? STRING(rhs) : "") -#define describe_string_plus(name, offset, type, opt, len, format, ...) \ -static INSTR(name##String_Plus) {\ - POP_REG(shred, offset); \ - const type lhs = *(type*)REG(-SZ_INT); \ - const M_Object rhs = *(M_Object*)REG(offset - SZ_INT); \ - opt; \ - if(!rhs) \ - Except(shred, "NullPtrException"); \ - char c[strlen(STRING(rhs)) + (len) + 1]; \ - sprintf(c, "%s"format, STRING(rhs), __VA_ARGS__); \ - push_string(shred, rhs, c); \ +#define describe_string_plus(_name, offset, type, opt, len, format, ...) \ +static INSTR(_name##String_Plus) { \ + POP_REG(shred, offset); \ + const type lhs = *(type*)REG(-SZ_INT); \ + const M_Object rhs = *(M_Object*)REG(offset - SZ_INT); \ + opt; \ + if(!rhs) \ + Except(shred, "NullPtrException"); \ + char c[strlen(STRING(rhs)) + (len) + 1]; \ + sprintf(c, "%s"format, STRING(rhs), __VA_ARGS__); \ + push_string(shred, rhs, c); \ } describe_string_plus(,SZ_INT, M_Object, release(lhs, shred), lhs ? strlen(STRING(lhs)) : 0, "%s", lhs ? STRING(lhs) : "") diff --git a/src/lib/ugen.c b/src/lib/ugen.c index 3c44d32b..d4c4dc18 100644 --- a/src/lib/ugen.c +++ b/src/lib/ugen.c @@ -127,23 +127,10 @@ ANN void ugen_ini(const struct Gwion_ *gwion, const UGen u, const uint in, const } } -ANN static m_bool connect_init(const VM_Shred shred, restrict M_Object* lhs, restrict M_Object* rhs) { +ANN void connect_init(const VM_Shred shred, restrict M_Object* lhs, restrict M_Object* rhs) { POP_REG(shred, SZ_INT * 2); *rhs = *(M_Object*)REG(SZ_INT); *lhs = *(M_Object*)REG(0); - if(!*lhs) { - if(*rhs) - _release(*rhs, shred); - goto end; - } - if(!*rhs) { - _release(*lhs, shred); - goto end; - } - return GW_OK; -end: - exception(shred, "UgenConnectException"); - return GW_ERROR; } #define describe_connect(name, func) \ @@ -192,12 +179,12 @@ if(!UGEN(rhs)->module.gen.trig) { \ Except(shred, "NonTriggerException"); \ } #define describe_connect_instr(name, func, opt) \ -static INSTR(name##func) {\ +static INSTR(name##func) { \ M_Object lhs, rhs; \ - if(connect_init(shred, &lhs, &rhs) > 0) { \ - opt \ - _do_(func, UGEN(lhs), UGEN(rhs)); /*}*/ \ - release_connect(shred); } \ + connect_init(shred, &lhs, &rhs); \ + opt \ + _do_(func, UGEN(lhs), UGEN(rhs)); \ + release_connect(shred); \ } describe_connect_instr(Ugen, Connect,) describe_connect_instr(Ugen, Disconnect,) @@ -355,7 +342,7 @@ GWION_IMPORT(ugen) { GWI_BB(gwi_func_end(gwi, ugen_get_last, ae_flag_none)) GWI_BB(gwi_class_end(gwi)) - GWI_BB(gwi_oper_ini(gwi, "UGen", "UGen", "UGen")) + GWI_BB(gwi_oper_ini(gwi, "nonnull UGen", "nonnull UGen", "nonnull UGen")) _CHECK_OP("=>", chuck_ugen, UgenConnect) _CHECK_OP("=<", chuck_ugen, UgenDisconnect) _CHECK_OP(":=>", chuck_ugen, TrigConnect) diff --git a/src/lib/vararg.c b/src/lib/vararg.c index 046ed324..e54b3d0b 100644 --- a/src/lib/vararg.c +++ b/src/lib/vararg.c @@ -17,33 +17,77 @@ void free_vararg(MemPool p, struct Vararg_* arg) { xfree(arg->d); - xfree(arg->t); + vector_release(&arg->t); mp_free(p, Vararg, arg); } +static DTOR(vararg_dtor) { + struct Vararg_ *arg = *(struct Vararg_**)o->data; + m_uint offset = 0; + for(m_uint i = 0; i < vector_size(&arg->t); ++i) { + const Type t = (Type)vector_at(&arg->t, arg->i); + *(m_uint*)(arg->d + offset) = *(m_uint*)(shred->reg - SZ_INT + offset); + if(isa(t, shred->info->vm->gwion->type[et_object]) > 0) + release(*(M_Object*)(arg->d + offset), shred); + offset += t->size; + } + free_vararg(shred->info->vm->gwion->mp, arg); +} + +ANN static M_Object vararg_cpy(VM_Shred shred, struct Vararg_* src) { + const M_Object o = new_object(shred->info->mp, shred, shred->info->vm->gwion->type[et_vararg]); + struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg); + vector_copy2(&src->t, &arg->t); + arg->l = src->l; + arg->d = (m_bit*)xmalloc(round2szint(arg->l)); + m_uint offset = 0; + for(m_uint i = 0; i < vector_size(&arg->t); ++i) { + const Type t = (Type)vector_at(&arg->t, arg->i); + *(m_uint*)(arg->d + offset) = *(m_uint*)(src->d + offset); + if(isa(t, shred->info->vm->gwion->type[et_object]) > 0) + ++(*(M_Object*)(arg->d + offset))->ref; + offset += t->size; + } + arg->s = vector_size(&arg->t); + arg->i = src->i; + arg->o = src->o; + *(struct Vararg_**)o->data = arg; + return o; +} + +static MFUN(mfun_vararg_cpy) { + *(M_Object*)RETURN = vararg_cpy(shred, *(struct Vararg_**)o->data); +} + INSTR(VarargIni) { + const M_Object o = new_object(shred->info->mp, shred, shred->info->vm->gwion->type[et_vararg]); struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg); POP_REG(shred, instr->m_val - SZ_INT) - arg->d = (m_bit*)xmalloc(round2szint(instr->m_val)); - for(m_uint i = 0; i < instr->m_val; i += SZ_INT) - *(m_uint*)(arg->d + i) = *(m_uint*)(shred->reg - SZ_INT + i); + arg->l = instr->m_val; + arg->d = (m_bit*)xmalloc(round2szint(arg->l)); const Vector kinds = (Vector)instr->m_val2; - arg->s = vector_size(kinds); - arg->t = (Type*)xmalloc(arg->s * SZ_INT); - for(m_uint i = 0; i < arg->s; ++i) { - const Type t = (Type)vector_at(kinds, i); - *(Type*)(arg->t + i) = t; + vector_copy2(kinds, &arg->t); + m_uint offset = 0; + for(m_uint i = 0; i < vector_size(&arg->t); ++i) { + const Type t = (Type)vector_at(&arg->t, arg->i); + *(m_uint*)(arg->d + offset) = *(m_uint*)(shred->reg - SZ_INT + offset); + if(isa(t, shred->info->vm->gwion->type[et_object]) > 0) + ++(*(M_Object*)(arg->d + offset))->ref; + offset += t->size; } - *(struct Vararg_**)REG(-SZ_INT) = arg; + arg->s = vector_size(kinds); + *(struct Vararg_**)o->data = arg; + *(M_Object*)REG(-SZ_INT) = o; } static INSTR(VarargEnd) { - struct Vararg_* arg = *(struct Vararg_**)REG(0); - arg->o += arg->t[arg->i]->size; + const M_Object o = *(M_Object*)REG(0); + struct Vararg_* arg = *(struct Vararg_**)o->data; + arg->o += ((Type)vector_at(&arg->t, arg->i))->size; if(++arg->i < arg->s) shred->pc = instr->m_val; else - free_vararg(shred->info->mp, arg); + arg->i = arg->o = 0; } static OP_CHECK(opck_vararg_cast) { @@ -51,39 +95,28 @@ static OP_CHECK(opck_vararg_cast) { return known_type(env, cast->td); } +static OP_CHECK(opck_vararg_at) { + return env->gwion->type[et_null]; +} + static INSTR(VarargCast) { - struct Vararg_* arg = *(struct Vararg_**)REG(-SZ_INT); - const Type t = (Type)instr->m_val2; - if(isa(arg->t[arg->i], t) < 0){ - free_vararg(shred->info->mp, arg); + const M_Object o = *(M_Object*)REG(-SZ_INT); + if(!*(m_uint*)(o->data + SZ_INT)) + Except(shred, "Using Vararg outside varloop"); + struct Vararg_* arg = *(struct Vararg_**)o->data; + const Type t = (Type)instr->m_val; + if(isa((Type)vector_at(&arg->t, arg->i), t) < 0) Except(shred, "InvalidVariadicAccess"); - } for(m_uint i = 0; i < t->size; i += SZ_INT) - *(m_uint*)REG(i - SZ_INT*2) = *(m_uint*)(arg->d + arg->o + i); -} - -ANN static inline Instr get_variadic(const Emitter emit) { - return (Instr)vector_back(&emit->info->variadic); -} - -ANN m_bool variadic_check(const Emitter emit, const loc_t pos) { - const Env env = emit->env; - if(!get_variadic(emit)) - ERR_B(pos, _("vararg.xxx used before vararg.start")) - if(GET_FLAG(emit->env->func, empty)) - ERR_B(pos, _("vararg.xxx used after vararg.end")) - return GW_OK; + *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + arg->o + i); } static OP_EMIT(opem_vararg_cast) { const Exp_Cast* cast = (Exp_Cast*)data; - CHECK_BO(variadic_check(emit, cast->exp->pos)) - CHECK_BO(emit_exp(emit, cast->exp, 0)) const Instr instr = emit_add_instr(emit, VarargCast); - instr->m_val = get_variadic(emit)->m_val; - instr->m_val2 = (m_uint)exp_self(cast)->type; - const Instr pop = emit_add_instr(emit, RegPush); - pop->m_val = exp_self(cast)->type->size - SZ_INT *2; + instr->m_val = (m_uint)exp_self(cast)->type; + const Instr push = emit_add_instr(emit, RegPush); + push->m_val = exp_self(cast)->type->size - SZ_INT; return instr; } @@ -94,7 +127,7 @@ static FREEARG(freearg_vararg) { static ID_CHECK(idck_vararg) { if(env->func && GET_FLAG(env->func->def, variadic)) - return exp_self(prim)->type; + return type_nonnull(env, exp_self(prim)->type); ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function")) } @@ -108,67 +141,33 @@ static GACK(gack_vararg) { INTERP_PRINTF("%p", *(M_Object*)VALUE); } -ANN static inline m_uint emit_code_size(const Emitter emit) { - return vector_size(&emit->code->instr); -} -ANN static m_bool emit_vararg_start(const Emitter emit, const m_uint offset) { - const Instr instr = emit_add_instr(emit, BranchEqInt); - instr->m_val = emit_code_size(emit); - vector_set(&emit->info->variadic, vector_size(&emit->info->variadic) -1, (vtype)instr); - return GW_OK; -} - -ANN static void emit_vararg_end(const Emitter emit, const m_uint offset) { +ANN void emit_vararg_end(const Emitter emit, const m_uint pc) { const Instr pop = emit_add_instr(emit, RegPop); pop->m_val = SZ_INT; - const Instr instr = emit_add_instr(emit, VarargEnd), - variadic = get_variadic(emit); - instr->m_val = variadic->m_val; - variadic->m_val = emit_code_size(emit); - SET_FLAG(emit->env->func, empty);// mark vararg func as complete -} - -static OP_CHECK(opck_vararg_dot) { - const Exp_Dot *member = (Exp_Dot*)data; - const m_str str = s_name(member->xid); - if(!strcmp(str, "start") || !strcmp(str, "end")) - return env->gwion->type[et_varloop]; - ERR_O(exp_self(member)->pos, _("'%s' is not a vararg keyword."), str) -} - -static OP_EMIT(opem_vararg_dot) { - const Env env = emit->env; - const Exp_Dot *member = (Exp_Dot*)data; - const m_str str = s_name(member->xid); - const m_uint offset = emit->code->stack_depth - SZ_INT; - CHECK_BO(emit_exp(emit, member->base, 0)) - if(str[0] == 's') { - if(get_variadic(emit)) - ERR_O(exp_self(member)->pos, _("vararg.start already used")) - emit_vararg_start(emit, offset); - return (Instr)GW_OK; - } - if(!get_variadic(emit)) - ERR_O(exp_self(member)->pos, _("vararg.start not used before vararg.end")) - emit_vararg_end(emit, offset); - return (Instr)GW_OK; + const Instr instr = emit_add_instr(emit, VarargEnd); + instr->m_val = pc; } -OP_CHECK(opck_object_dot); GWION_IMPORT(vararg) { - const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", 0, NULL); - GWI_BB(gwi_set_global_type(gwi, t_varloop, et_varloop)) - const Type t_vararg = gwi_mk_type(gwi, "@Vararg", SZ_INT, NULL); + const Type t_vararg = gwi_class_ini(gwi, "Vararg", "Object"); + gwi_class_xtor(gwi, NULL, vararg_dtor); gwi_gack(gwi, t_vararg, gack_vararg); -// gwi_gack(gwi, t_varloop, gack_vararg);// ???? - GWI_BB(gwi_add_type(gwi, t_vararg)) - GWI_BB(gwi_oper_ini(gwi, "@Vararg", (m_str)OP_ANY_TYPE, NULL)) - GWI_BB(gwi_oper_add(gwi, opck_vararg_dot)) - GWI_BB(gwi_oper_emi(gwi, opem_vararg_dot)) - GWI_BB(gwi_oper_end(gwi, "@dot", NULL)) + CHECK_BB(gwi_item_ini(gwi, "@internal", "@data")) + CHECK_BB(gwi_item_end(gwi, ae_flag_none, NULL)) + CHECK_BB(gwi_item_ini(gwi, "int", "@inLoop")) + CHECK_BB(gwi_item_end(gwi, ae_flag_none, NULL)) + CHECK_BB(gwi_func_ini(gwi, "Vararg", "cpy")) + CHECK_BB(gwi_func_end(gwi, mfun_vararg_cpy, ae_flag_none)) + GWI_BB(gwi_class_end(gwi)) + SET_FLAG(t_vararg, abstract | ae_flag_const); + CHECK_BB(gwi_set_global_type(gwi, t_vararg, et_vararg)) + GWI_BB(gwi_oper_ini(gwi, "nonnull Vararg", (m_str)OP_ANY_TYPE, NULL)) GWI_BB(gwi_oper_add(gwi, opck_vararg_cast)) GWI_BB(gwi_oper_emi(gwi, opem_vararg_cast)) GWI_BB(gwi_oper_end(gwi, "$", NULL)) + GWI_BB(gwi_oper_ini(gwi, "Vararg", (m_str)OP_ANY_TYPE, NULL)) + GWI_BB(gwi_oper_add(gwi, opck_vararg_at)) + GWI_BB(gwi_oper_end(gwi, "@=>", NULL)) gwi_register_freearg(gwi, VarargIni, freearg_vararg); struct SpecialId_ spid = { .type=t_vararg, .is_const=1, .ck=idck_vararg, .em=idem_vararg}; gwi_specialid(gwi, "vararg", &spid); diff --git a/src/parse/check.c b/src/parse/check.c index 133f8364..dd6410d8 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -389,7 +389,7 @@ ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t, const Type owner = nspc_lookup_type1(t->e->owner->parent, insert_symbol(t->e->owner->name)); const m_bool ret = check_lambda(env, owner, &e->d.exp_lambda, t->e->d.func->def); - e->emit_var = 1; +// e->emit_var = 1; return ret; } if(implicit) @@ -873,17 +873,13 @@ ANN static Type check_exp_interp(const Env env, const Exp_Interp* exp) { DECL_EXP_FUNC(check, Type, Env) ANN Type check_exp(const Env env, const Exp exp) { - Exp curr = exp, next = NULL, prev = NULL; + Exp curr = exp; do { - next = curr->next; CHECK_OO((curr->type = check_exp_func[curr->exp_type](env, &curr->d))) - if(env->gwion->type[et_varloop] && isa(curr->type, env->gwion->type[et_varloop]) > 0 && (prev || next)) - ERR_O(exp->pos, _("Varloop must be the only expression")) if(env->func && isa(curr->type, env->gwion->type[et_lambda]) < 0 && isa(curr->type, env->gwion->type[et_function]) > 0 && !GET_FLAG(curr->type->e->d.func, pure)) UNSET_FLAG(env->func, pure); - prev = curr; - } while((curr = next)); + } while((curr = curr->next)); return exp->type; } @@ -901,6 +897,14 @@ ANN static m_bool check_stmt_code(const Env env, const Stmt_Code stmt) { return GW_OK; } +ANN static m_bool check_stmt_varloop(const Env env, const Stmt_VarLoop stmt) { + CHECK_OB(check_exp(env, stmt->exp)) + if(isa(stmt->exp->type, env->gwion->type[et_vararg]) < 0) + ERR_B(stmt->exp->pos, "varloop expression type must be '%s', not '%s'", + env->gwion->type[et_vararg]->name, stmt->exp->type->name) + return check_stmt(env, stmt->body); +} + ANN static inline m_bool _check_breaks(const Env env, const Stmt b) { RET_NSPC(check_stmt(env, b)) } @@ -1314,15 +1318,6 @@ ANN static m_bool check_parent(const Env env, const Class_Def cdef) { return GW_OK; } -ANN static inline void inherit(const Type t) { - const Nspc nspc = t->nspc, parent = t->e->parent->nspc; - if(!parent) - return; - nspc->info->offset = parent->info->offset; - if(parent->info->vtable.ptr) - vector_copy2(&parent->info->vtable, &nspc->info->vtable); -} - ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) { if(cdef->base.tmpl && cdef->base.tmpl->list) CHECK_BB(template_push_types(env, cdef->base.tmpl)) diff --git a/src/parse/operator.c b/src/parse/operator.c index 46bd2b19..723fa8b5 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -19,6 +19,7 @@ typedef struct M_Operator_{ Func func; opck ck; opem em; + m_uint emit_var; } M_Operator; ANN void free_op_map(Map map, struct Gwion_ *gwion) { @@ -52,7 +53,6 @@ static m_bool op_match(const restrict Type t, const restrict Type mo) { return GW_OK; Type type = t; while(SAFE_FLAG(type, template) && type->e->def && type->e->def->base.tmpl && type->e->def->base.tmpl->call) type = type->e->parent; -// if((t && mo && mo->xid == t->xid) || (!t && !mo)) if((type && mo && mo->xid == type->xid) || (!type && !mo)) return GW_OK; return 0; @@ -91,8 +91,11 @@ ANN static M_Operator* new_mo(MemPool p, const struct Op_Import* opi) { mo->rhs = opi->rhs; mo->ret = opi->ret; mo->instr = (f_instr)opi->data; - mo->ck = opi->ck; - mo->em = opi->em; + if(opi->func) { + mo->ck = opi->func->ck; + mo->em = opi->func->em; + } + mo->emit_var = opi->emit_var; return mo; } @@ -257,6 +260,15 @@ ANN static inline Nspc ensure_nspc(SymTable *st, const struct Op_Import* opi) { return nspc; } +ANN void op_emit_nonnull(const Emitter emit, const Type mo, const Type opi, const m_uint offset) { + if(!mo || mo == OP_ANY_TYPE) + return; + if(GET_FLAG(mo, nonnull) && !GET_FLAG(opi, nonnull)) { + const Instr instr = emit_add_instr(emit, GWOP_EXCEPT); + instr->m_val = offset; + } +} + ANN Instr op_emit(const Emitter emit, const struct Op_Import* opi) { DECL_OO(Nspc, nspc, = ensure_nspc(emit->gwion->st, opi)) Type l = opi->lhs; @@ -267,6 +279,9 @@ ANN Instr op_emit(const Emitter emit, const struct Op_Import* opi) { if(!v)continue; const M_Operator* mo = operator_find(v, l, r); if(mo) { + const m_uint sz = opi->rhs ? opi->rhs->size : 0; + op_emit_nonnull(emit, mo->lhs, opi->lhs, mo->emit_var ?: sz); + op_emit_nonnull(emit, mo->rhs, opi->rhs, 0); if(mo->em) return mo->em(emit, (void*)opi->data); return handle_instr(emit, mo); diff --git a/src/parse/scan0.c b/src/parse/scan0.c index c8fe689b..b9fbc242 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -119,12 +119,13 @@ static OP_CHECK(opck_cast_similar) { } ANN static void scan0_implicit_similar(const Env env, const Type lhs, const Type rhs) { - struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .ck=opck_cast_similar }; + struct Op_Func opfunc = { .ck=opck_cast_similar }; + struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .func=&opfunc }; add_op(env->gwion, &opi); opi.lhs=rhs; opi.rhs=lhs; add_op(env->gwion, &opi); - opi.ck = opck_implicit_similar; + opfunc.ck = opck_implicit_similar; opi.op=insert_symbol("@implicit"); add_op(env->gwion, &opi); } @@ -222,7 +223,6 @@ ANN static Type union_type(const Env env, const Symbol s, const m_bool add) { t->name = name; t->nspc = new_nspc(env->gwion->mp, name); t->e->owner = t->nspc->parent = env->curr; - t->nspc->is_union = 1; t->e->parent = env->gwion->type[et_union]; add_type(env, env->curr, t); if(add) { diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 3fa4ebaa..7b4c8ab8 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -105,6 +105,9 @@ ANN m_bool scan1_exp_decl(const Env env, const Exp_Decl* decl) { CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos)) ((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl); CHECK_OB(decl->type) + if(GET_FLAG(decl->type, const)) + exp_self(decl)->meta = ae_meta_value; +// SET_FLAG(decl->td, const); const m_bool global = GET_FLAG(decl->td, global); if(global && decl->type->e->owner != env->global_nspc) ERR_B(exp_self(decl)->pos, _("type '%s' is not global"), decl->type->name) @@ -228,6 +231,8 @@ ANN static inline m_bool scan1_stmt_match(const restrict Env env, const Stmt_Mat #define describe_ret_nspc(name, type, prolog, exp) describe_stmt_func(scan1, name, type, prolog, exp) describe_ret_nspc(flow, Stmt_Flow,, !(scan1_exp(env, stmt->cond) < 0 || scan1_stmt(env, stmt->body) < 0) ? 1 : -1) +describe_ret_nspc(varloop, Stmt_VarLoop,, !(scan1_exp(env, stmt->exp) < 0 || + scan1_stmt(env, stmt->body) < 0) ? 1 : -1) describe_ret_nspc(for, Stmt_For,, !(scan1_stmt(env, stmt->c1) < 0 || scan1_stmt(env, stmt->c2) < 0 || (stmt->c3 && scan1_exp(env, stmt->c3) < 0) || @@ -267,6 +272,13 @@ ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) { return GW_OK; } +ANN static Value arg_value(MemPool p, const Arg_List list) { + const Var_Decl var = list->var_decl; + const Value v = new_value(p, list->type, var->xid ? s_name(var->xid) : (m_str)__func__); + if(list->td) + v->flag = list->td->flag | ae_flag_arg; + return v; +} ANN static m_bool scan1_args(const Env env, Arg_List list) { do { const Var_Decl var = list->var_decl; @@ -274,6 +286,8 @@ ANN static m_bool scan1_args(const Env env, Arg_List list) { CHECK_BB(isres(env, var->xid, var->pos)) if(list->td) CHECK_OB((list->type = void_type(env, list->td))) + var->value = arg_value(env->gwion->mp, list); + nspc_add_value(env->curr, var->xid, var->value); } while((list = list->next)); return GW_OK; } @@ -304,6 +318,12 @@ ANN m_bool scan1_union_def_action(const Env env, const Union_Def udef, else if(GET_FLAG(udef, static)) SET_FLAG(decl.td, static); CHECK_BB(scan1_exp(env, l->self)) + +Var_Decl_List list = decl.list; +do ADD_REF(list->self->value) +while((list = list->next)); + + if(global) SET_FLAG(decl.td, global); return GW_OK; @@ -400,6 +420,14 @@ ANN static m_bool scan_internal(const Env env, const Func_Base *base) { return GW_OK; } +ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) { + if(fdef->base->args) + CHECK_BB(scan1_args(env, fdef->base->args)) + if(!GET_FLAG(fdef, builtin) && fdef->d.code && fdef->d.code->d.stmt_code.stmt_list) + CHECK_BB(scan1_stmt_list(env, fdef->d.code->d.stmt_code.stmt_list)) + return GW_OK; +} + ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) { if(fdef->base->td) CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td))) @@ -407,10 +435,7 @@ ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) { CHECK_BB(scan_internal(env, fdef->base)) else if(GET_FLAG(fdef, op) && env->class_def) SET_FLAG(fdef, static); - if(fdef->base->args) - CHECK_BB(scan1_args(env, fdef->base->args)) - if(!GET_FLAG(fdef, builtin) && fdef->d.code) - CHECK_BB(scan1_stmt_code(env, &fdef->d.code->d.stmt_code)) + RET_NSPC(scan1_fbody(env, fdef)) return GW_OK; } diff --git a/src/parse/scan2.c b/src/parse/scan2.c index f58c2694..ec8b2f5e 100644 --- a/src/parse/scan2.c +++ b/src/parse/scan2.c @@ -38,21 +38,12 @@ ANN m_bool scan2_exp_decl(const Env env, const Exp_Decl* decl) { return ret; } -ANN static Value arg_value(MemPool p, const Arg_List list) { - const Var_Decl var = list->var_decl; - const Value v = new_value(p, list->type, var->xid ? s_name(var->xid) : (m_str)__func__); - if(list->td) - v->flag = list->td->flag | ae_flag_arg; - return v; -} - ANN static m_bool scan2_args(const Env env, const Func_Def f) { Arg_List list = f->base->args; do { const Var_Decl var = list->var_decl; if(var->array) list->type = array_type(env, list->type, var->array->depth); - var->value = arg_value(env->gwion->mp, list); var->value->from->offset = f->stack_depth; f->stack_depth += list->type->size; } while((list = list->next)); @@ -222,6 +213,8 @@ HANDLE_EXP_FUNC(scan2, m_bool, Env) #define scan2_stmt_func(name, type, prolog, exp) describe_stmt_func(scan2, name, type, prolog, exp) scan2_stmt_func(flow, Stmt_Flow,, !(scan2_exp(env, stmt->cond) < 0 || scan2_stmt(env, stmt->body) < 0) ? 1 : -1) +scan2_stmt_func(varloop, Stmt_VarLoop,, !(scan2_exp(env, stmt->exp) < 0 || + scan2_stmt(env, stmt->body) < 0) ? 1 : -1) scan2_stmt_func(for, Stmt_For,, !(scan2_stmt(env, stmt->c1) < 0 || scan2_stmt(env, stmt->c2) < 0 || (stmt->c3 && scan2_exp(env, stmt->c3) < 0) || @@ -427,10 +420,9 @@ ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f) { const Type r = f->base->args ? is_unary ? f->base->args->var_decl->value->type : f->base->args->next ? f->base->args->next->var_decl->value->type : f->base->ret_type : NULL; + struct Op_Func opfunc = { .ck=strcmp(str, "@implicit") ? 0 : opck_usr_implicit }; struct Op_Import opi = { .op=f->base->xid, .lhs=l, .rhs=r, .ret=f->base->ret_type, - .pos=f->pos, .data=(uintptr_t)f->base->func }; - if(!strcmp(str, "@implicit")) - opi.ck = opck_usr_implicit; + .pos=f->pos, .data=(uintptr_t)f->base->func, .func=&opfunc }; CHECK_BB(add_op(env->gwion, &opi)) operator_set_func(&opi); return GW_OK; diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index 42290b6e..c03cc6e1 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -23,6 +23,7 @@ ANN Type type_nonnull(const Env env, const Type base) { t->flag = base->flag; SET_FLAG(t, nonnull); nspc_add_type_front(t->e->owner, sym, t); + mk_class(env, t); return t; } diff --git a/src/vm/vm.c b/src/vm/vm.c index deef382d..599c3dfe 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -356,7 +356,9 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto] M_Object obj; VM_Code code; } a; +PRAGMA_PUSH() register VM_Shred child; +PRAGMA_POP() MUTEX_LOCK(s->mutex); do { SDISPATCH(); diff --git a/tests/error/connect_except.gw b/tests/error/connect_except.gw index a71e9bd8..893c5b6e 100644 --- a/tests/error/connect_except.gw +++ b/tests/error/connect_except.gw @@ -1,3 +1,3 @@ -#! [contains] UgenConnectException +#! [contains] NullPtrException UGen ref u; adc => u; diff --git a/tests/error/ev.gw b/tests/error/ev.gw index 09b83520..974c769d 100644 --- a/tests/error/ev.gw +++ b/tests/error/ev.gw @@ -1,3 +1,3 @@ -#! [contains] NullEventWait +#! [contains] NullPtrException Event ref e; e => now; diff --git a/tests/error/vararg_after.gw b/tests/error/vararg_after.gw deleted file mode 100644 index 93375f6d..00000000 --- a/tests/error/vararg_after.gw +++ /dev/null @@ -1,6 +0,0 @@ -#! [contains] used after -fun void test(...) { - vararg.start; - vararg.end; - vararg $ int; -} diff --git a/tests/error/vararg_before.gw b/tests/error/vararg_before.gw deleted file mode 100644 index 9159d480..00000000 --- a/tests/error/vararg_before.gw +++ /dev/null @@ -1,4 +0,0 @@ -#! [contains] used before -fun void test(...) { - vararg $ int; -} diff --git a/tests/error/vararg_invalid_acces.gw b/tests/error/vararg_invalid_acces.gw index 16fc011c..36ca072b 100644 --- a/tests/error/vararg_invalid_acces.gw +++ b/tests/error/vararg_invalid_acces.gw @@ -1,7 +1,7 @@ #! [contains] InvalidVariadicAccess fun void test(...) { - vararg.start; - <<>>; - vararg.end; + varloop vararg { + <<>>; + } } new Object => test; diff --git a/tests/error/vararg_outside_varloop.gw b/tests/error/vararg_outside_varloop.gw new file mode 100644 index 00000000..1c0abef9 --- /dev/null +++ b/tests/error/vararg_outside_varloop.gw @@ -0,0 +1,5 @@ +#! [contains] outside varloop +fun void test(...) { + <<>>; +} +new Object => test; diff --git a/tests/error/variadic_end_no_start.gw b/tests/error/variadic_end_no_start.gw deleted file mode 100644 index 7dc0c9d2..00000000 --- a/tests/error/variadic_end_no_start.gw +++ /dev/null @@ -1,7 +0,0 @@ -#! [contains] vararg.start not used before vararg.end -fun void test(int i, ...) { - vararg.end; -#! vararg.start; -} - -test(1, 2.3, null); diff --git a/tests/error/variadic_start_twice.gw b/tests/error/variadic_start_twice.gw deleted file mode 100644 index dd192f7a..00000000 --- a/tests/error/variadic_start_twice.gw +++ /dev/null @@ -1,2 +0,0 @@ -#! [contains] vararg.start already used -fun void test(...) { vararg.start; vararg.start;} diff --git a/tests/error/variadic_test.gw b/tests/error/variadic_test.gw deleted file mode 100644 index 7dc0c9d2..00000000 --- a/tests/error/variadic_test.gw +++ /dev/null @@ -1,7 +0,0 @@ -#! [contains] vararg.start not used before vararg.end -fun void test(int i, ...) { - vararg.end; -#! vararg.start; -} - -test(1, 2.3, null); diff --git a/tests/error/varloop_not_vararg.gw b/tests/error/varloop_not_vararg.gw new file mode 100644 index 00000000..75d5a95a --- /dev/null +++ b/tests/error/varloop_not_vararg.gw @@ -0,0 +1,4 @@ +#! varloop expression type must be +varloop 1 { + +} diff --git a/tests/error/varloop_only.gw b/tests/error/varloop_only.gw deleted file mode 100644 index 551f2318..00000000 --- a/tests/error/varloop_only.gw +++ /dev/null @@ -1,5 +0,0 @@ -#! [contains] Varloop must be the only expression -fun void test(...) { - <<<"test">>>, vararg.start; - vararg.end; -} diff --git a/tests/import/gwi_oper_emit_var.c b/tests/import/gwi_oper_emit_var.c new file mode 100644 index 00000000..ea28b4a6 --- /dev/null +++ b/tests/import/gwi_oper_emit_var.c @@ -0,0 +1,42 @@ +#include "gwion_util.h" +#include "gwion_ast.h" +#include "gwion_env.h" +#include "vm.h" +#include "object.h" +#include "instr.h" +#include "gwion.h" +#include "operator.h" +#include "import.h" + +static OP_CHECK(opck_ptrext_assign) { + const Exp_Binary* bin = (Exp_Binary*)data; + if(bin->rhs->meta != ae_meta_var) + ERR_N(exp_self(bin)->pos, _("left side operand is constant")); + bin->rhs->emit_var = 1; + Type t = bin->rhs->type; + do { + Type u = bin->lhs->type; + do { + const m_str str = get_type_name(env, u->name, 1); + if(str && !strcmp(t->name, str)) + return bin->lhs->type; + } while((u = u->e->parent)); + } while((t = t->e->parent)); + return env->gwion->type[et_null]; +} + +static INSTR(instr_ptrext_assign) { + POP_REG(shred, SZ_INT) + const M_Object o = *(M_Object*)REG(-SZ_INT); + *(m_float**)o->data = *(m_float**)REG(0); +} + +GWION_IMPORT(typedef_test) { + GWI_OB(gwi_class_ini(gwi, "PtrExt", "Ptr<~float~>")) + GWI_BB(gwi_class_end(gwi)) + GWI_BB(gwi_oper_ini(gwi, "nonnull PtrExt", "float", NULL)) + GWI_BB(gwi_oper_var(gwi, SZ_INT)) + GWI_BB(gwi_oper_add(gwi, opck_ptrext_assign)) + GWI_BB(gwi_oper_end(gwi, "<=:", instr_ptrext_assign)) + return GW_OK; +} diff --git a/tests/import/gwi_oper_emit_var.gw b/tests/import/gwi_oper_emit_var.gw new file mode 100644 index 00000000..31a9b502 --- /dev/null +++ b/tests/import/gwi_oper_emit_var.gw @@ -0,0 +1,5 @@ +1234.5 => float f; +PtrExt ref ptr; +<<< ptr >>>; +ptr <=: f; +<<< f >>>; diff --git a/tests/sh/import.sh b/tests/sh/import.sh index e4b35b68..c9f2ab76 100644 --- a/tests/sh/import.sh +++ b/tests/sh/import.sh @@ -1,5 +1,5 @@ #!/bin/bash -# [test] #74 +# [test] #75 n=0 [ "$1" ] && n="$1" -- 2.43.0