From 760e5bf89ec48d6c1207650d3ae12503017f39f8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sat, 7 Mar 2020 17:03:40 +0100 Subject: [PATCH] :art: Vararg uses cast --- examples/template_vararg.gw | 2 +- examples/vararg.gw | 14 ++--- include/emit.h | 5 ++ include/instr.h | 1 - include/vararg.h | 1 + src/emit/emit.c | 35 ++++------- src/lib/array.c | 1 + src/lib/engine.c | 2 - src/lib/object.c | 11 +++- src/lib/tuple.c | 1 + src/lib/vararg.c | 77 ++++++++++++++++++------ src/parse/check.c | 1 - src/parse/operator.c | 2 + tests/error/vararg_after.gw | 2 +- tests/error/vararg_before.gw | 2 +- tests/error/vararg_invalid_acces.gw | 2 +- tests/new/typedef_func_class_variadic.gw | 2 +- tests/tree/empty_vararg.gw | 4 +- tests/tree/varobject_assign.gw | 2 +- 19 files changed, 104 insertions(+), 63 deletions(-) diff --git a/examples/template_vararg.gw b/examples/template_vararg.gw index 83dd8a76..564d0b80 100644 --- a/examples/template_vararg.gw +++ b/examples/template_vararg.gw @@ -1,6 +1,6 @@ fun void test<~A~>(...) { vararg.start; - <<< vararg.i >>>; + <<< vararg $ int >>>; vararg.end; } test<~int~>(1, 2); diff --git a/examples/vararg.gw b/examples/vararg.gw index a5b017e7..0270e4f9 100644 --- a/examples/vararg.gw +++ b/examples/vararg.gw @@ -3,19 +3,19 @@ fun void test(...) { vararg.start; if(i == 0) - <<< vararg.i >>>; + <<< vararg $ int >>>; else if(i == 1) - <<< vararg.f >>>; + <<< vararg $ float >>>; else if(i == 2) - <<< vararg.c >>>; + <<< vararg $ complex >>>; else if(i == 3) - <<< vararg.p >>>; + <<< vararg $ polar >>>; else if(i == 4) - <<< vararg.v3 >>>; + <<< vararg $ Vec3 >>>; else if(i == 5) - <<< vararg.v4 >>>; + <<< vararg $ Vec4 >>>; else if(i == 6) - <<< vararg.o >>>; + <<< vararg $ Object >>>; i++; vararg.end; } diff --git a/include/emit.h b/include/emit.h index 8c701214..8a8cb71e 100644 --- a/include/emit.h +++ b/include/emit.h @@ -47,4 +47,9 @@ ANN2(1,2) m_bool emit_instantiate_object(const Emitter, const Type, const Array_ ANN m_uint emit_code_offset(const Emitter emit); ANN m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj); ANN Instr emit_exp_spork(const Emitter, const Exp_Unary*); +ANN m_bool emit_exp(const Emitter, const Exp, const m_bool add_ref); +ANN static inline void emit_except(const Emitter emit, const Type t) { + emit_add_instr(emit, !GET_FLAG(t, nonnull) ? GWOP_EXCEPT : SetObj); +} + #endif diff --git a/include/instr.h b/include/instr.h index 9a545cbe..2565644b 100644 --- a/include/instr.h +++ b/include/instr.h @@ -50,7 +50,6 @@ INSTR(ArrayAlloc); INSTR(VarargIni); INSTR(VarargTop); INSTR(VarargEnd); -INSTR(VarargMember); INSTR(VecCpy); INSTR(VecMember); diff --git a/include/vararg.h b/include/vararg.h index ed207e29..f94f649f 100644 --- a/include/vararg.h +++ b/include/vararg.h @@ -2,6 +2,7 @@ #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) }; diff --git a/src/emit/emit.c b/src/emit/emit.c index 66018ecc..97312a7d 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -85,7 +85,7 @@ ANN static m_int frame_pop(Frame* frame) { return l->is_obj ? (m_int)l->offset : frame_pop(frame); } -ANN static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool add_ref); +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); @@ -750,7 +750,7 @@ ANN static m_uint vararg_size(const Exp_Call* exp_call, const Vector kinds) { while(e) { if(!l) { size += e->type->size; - vector_add(kinds, e->type->size); + vector_add(kinds, (vtype)e->type); // ->size } else l = l->next; e = e->next; @@ -854,12 +854,10 @@ ANN static m_bool emit_exp_post(const Emitter emit, const Exp_Postfix* post) { return op_emit_bool(emit, &opi); } -ANN static m_bool is_special(const Emitter emit, const Type t) { - if(isa(t, emit->gwion->type[et_complex]) > 0 || isa(t, emit->gwion->type[et_polar]) > 0 || - isa(t, emit->gwion->type[et_vec3]) > 0 || isa(t, emit->gwion->type[et_vec4]) > 0 || - isa(t, emit->gwion->type[et_vararg]) > 0) - return GW_OK; - return GW_ERROR; +ANN static inline m_bool is_special(const Emitter emit, const Type t) { + return isa(t, emit->gwion->type[et_object]) < 0 && + isa(t, emit->gwion->type[et_class]) < 0 ? + GW_OK : GW_ERROR; } ANN static inline m_bool traverse_emit_func_def(const Emitter emit, const Func_Def fdef) { @@ -1242,7 +1240,7 @@ ANN static m_bool emit_exp_interp(const Emitter emit, const Exp_Interp *exp) { DECL_EXP_FUNC(emit, m_bool, Emitter) -ANN2(1) static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) { +ANN2(1) /*static */m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) { do { CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d)) if(ref && isa(exp->type, emit->gwion->type[et_object]) > 0) { @@ -1716,6 +1714,7 @@ ANN static m_bool emit_vararg_start(const Emitter emit, const m_uint offset) { vector_set(&emit->info->variadic, vector_size(&emit->info->variadic) -1, (vtype)instr); return GW_OK; } + ANN static inline Instr get_variadic(const Emitter emit) { return (Instr)vector_back(&emit->info->variadic); } @@ -1749,14 +1748,8 @@ ANN static m_bool emit_vararg(const Emitter emit, const Exp_Dot* member) { emit_vararg_end(emit, offset); return GW_OK; } - if(!get_variadic(emit)) - ERR_B(exp_self(member)->pos, _("vararg.%s used before vararg.start"), s_name(member->xid)) - if(GET_FLAG(emit->env->func, empty)) - ERR_B(exp_self(member)->pos, _("vararg.%s used after vararg.end"), s_name(member->xid)) - const Instr instr = emit_add_instr(emit, VarargMember); - instr->m_val = offset; - instr->m_val2 = exp_self(member)->type->size; - return GW_OK; +// should not be reached now + return GW_ERROR; } ANN static m_bool emit_exp_dot_special(const Emitter emit, const Exp_Dot* member) { @@ -1805,12 +1798,10 @@ ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) { return emit_exp_dot_special(emit, member); 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))) -) { + (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && + !is_fptr(emit->gwion, exp_self(member)->type)))) { CHECK_BB(emit_exp(emit, member->base, 0)) - emit_add_instr(emit, GWOP_EXCEPT); - -// emit_except(emit, member->t_base); + 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)) return emit_member_func(emit, member); diff --git a/src/lib/array.c b/src/lib/array.c index 11b751ef..5f9a9157 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -14,6 +14,7 @@ #include "traverse.h" #include "parse.h" #include "gwi.h" +#include "emit.h" struct M_Vector_ { m_bit* ptr; diff --git a/src/lib/engine.c b/src/lib/engine.c index bcd5ca0a..5cef63a1 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -76,8 +76,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_null = gwi_mk_type(gwi, "@null", SZ_INT, NULL); - GWI_BB(gwi_set_global_type(gwi, t_null, et_null)) 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)) diff --git a/src/lib/object.c b/src/lib/object.c index 5c3cebf8..b94a6536 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -236,13 +236,15 @@ static OP_CHECK(opck_object_scan) { } GWION_IMPORT(object) { -const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL); -gwi_add_type(gwi, t_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)) -//assert(GET_FLAG(t_object, checked)); 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, "@null", "Object", "Object")) GWI_BB(gwi_oper_add(gwi, at_object)) @@ -269,6 +271,9 @@ gwi_add_type(gwi, t_object); GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj)) GWI_BB(gwi_oper_end(gwi, "@implicit", NULL)) GWI_BB(gwi_oper_ini(gwi, "Object", "@null", "int")) +// 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_end(gwi, "==", EqObject)) GWI_BB(gwi_oper_end(gwi, "!=", NeqObject)) GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool")) diff --git a/src/lib/tuple.c b/src/lib/tuple.c index ca97a433..8dd269ae 100644 --- a/src/lib/tuple.c +++ b/src/lib/tuple.c @@ -14,6 +14,7 @@ #include "object.h" #include "parse.h" #include "tuple.h" +#include "array.h" struct TupleEmit { Exp e; diff --git a/src/lib/vararg.c b/src/lib/vararg.c index 69621f9b..129fa43b 100644 --- a/src/lib/vararg.c +++ b/src/lib/vararg.c @@ -13,10 +13,12 @@ #include "specialid.h" #include "traverse.h" #include "parse.h" +#include "gack.h" void free_vararg(MemPool p, struct Vararg_* arg) { xfree(arg->d); xfree(arg->k); + xfree(arg->t); mp_free(p, Vararg, arg); } @@ -38,8 +40,12 @@ INSTR(VarargIni) { const Vector kinds = (Vector)instr->m_val2; arg->s = vector_size(kinds); arg->k = (m_uint*)xmalloc(arg->s * SZ_INT); - for(m_uint i = 0; i < arg->s; ++i) - *(m_uint*)(arg->k + i) = vector_at(kinds, i); + 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; + *(m_uint*)(arg->k + i) = t->size; + } *(struct Vararg_**)REG(-SZ_INT) = arg; } @@ -53,15 +59,48 @@ INSTR(VarargEnd) { free_vararg(shred->info->mp, arg); } -INSTR(VarargMember) { +static OP_CHECK(opck_vararg_cast) { + const Exp_Cast* cast = (Exp_Cast*)data; + const Type t = known_type(env, cast->td); +//puts(t->name); + return t; +} + +static INSTR(VarargCast) { struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val); - if(instr->m_val2 != arg->k[arg->i]) { // TODO: differnciate object and primitives - free_vararg(shred->info->mp, arg); - Except(shred, "InvalidVariadicAccess"); + const Type t = (Type)instr->m_val2; + if(isa(arg->t[arg->i], t) < 0){ + free_vararg(shred->info->mp, arg); + Except(shred, "InvalidVariadicAccess"); } - for(m_uint i = 0; i < instr->m_val2; i += SZ_INT) - *(m_uint*)REG(i) = *(m_uint*)(arg->d + arg->o + i); - PUSH_REG(shred, instr->m_val2); +// POP_REG(shred, SZ_INT); + for(m_uint i = 0; i < t->size; i += SZ_INT) + *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + arg->o + i); + PUSH_REG(shred, t->size - SZ_INT); +} + +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; +} + +static OP_EMIT(opem_vararg_cast) { + const Exp_Cast* cast = (Exp_Cast*)data; + CHECK_BO(variadic_check(emit, cast->exp->pos)) + const Instr instr = emit_add_instr(emit, VarargCast); + const Instr variadic = (Instr)vector_back(&emit->info->variadic); + instr->m_val = variadic->m_val; + const Type t = known_type(emit->env, cast->td); + instr->m_val2 = (m_uint)t; + return instr; } static OP_CHECK(at_varobj) { @@ -85,26 +124,22 @@ static ID_CHECK(idck_vararg) { ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function")) } +static GACK(gack_vararg) { + INTERP_PRINTF("%p\n", *(M_Object*)VALUE); +} + GWION_IMPORT(vararg) { const Type t_varobj = gwi_mk_type(gwi, "VarObject", SZ_INT, "Object"); SET_FLAG(t_varobj, abstract); const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", SZ_INT, NULL); GWI_BB(gwi_add_type(gwi, t_varobj)) GWI_BB(gwi_set_global_type(gwi, t_varloop, et_varloop)) - const Type t_vararg = gwi_class_ini(gwi, "@Vararg", NULL); + const Type t_vararg = gwi_class_spe(gwi, "@Vararg", 0); + gwi_gack(gwi, t_vararg, gack_vararg); gwi->gwion->type[et_vararg] = t_vararg; // use func GWI_BB(gwi_union_ini(gwi, NULL, NULL)) GWI_BB(gwi_union_add(gwi, "@VarLoop", "start")) GWI_BB(gwi_union_add(gwi, "@VarLoop", "end")) - GWI_BB(gwi_union_add(gwi, "int", "i")) - GWI_BB(gwi_union_add(gwi, "float", "f")) - GWI_BB(gwi_union_add(gwi, "time", "t")) - GWI_BB(gwi_union_add(gwi, "dur", "d")) - GWI_BB(gwi_union_add(gwi, "complex", "c")) - GWI_BB(gwi_union_add(gwi, "polar", "p")) - GWI_BB(gwi_union_add(gwi, "Vec3", "v3")) - GWI_BB(gwi_union_add(gwi, "Vec4", "v4")) - GWI_BB(gwi_union_add(gwi, "VarObject", "o")) GWI_OB(gwi_union_end(gwi, ae_flag_const)) GWI_BB(gwi_class_end(gwi)) GWI_BB(gwi_oper_ini(gwi, "VarObject", "Object", NULL)) @@ -113,6 +148,10 @@ GWION_IMPORT(vararg) { GWI_BB(gwi_oper_ini(gwi, "Object", "VarObject", NULL)) GWI_BB(gwi_oper_add(gwi, at_varobj)) GWI_BB(gwi_oper_end(gwi, "@=>", VarargAssign)) + GWI_BB(gwi_oper_ini(gwi, "@Vararg", (m_str)OP_ANY_TYPE, NULL)) + GWI_BB(gwi_oper_add(gwi, opck_vararg_cast)) + GWI_BB(gwi_oper_emi(gwi, opem_vararg_cast)) + GWI_BB(gwi_oper_end(gwi, "$", VarargCast)) gwi_register_freearg(gwi, VarargIni, freearg_vararg); struct SpecialId_ spid = { .type=t_vararg, .exec=RegPushImm, .is_const=1, .ck=idck_vararg}; gwi_specialid(gwi, "vararg", &spid); diff --git a/src/parse/check.c b/src/parse/check.c index 5f67e708..567a98b6 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -33,7 +33,6 @@ ANN /*static inline */m_bool check_implicit(const Env env, const Exp e, const Ty return check_internal(env, sym, e, t); } - ANN m_bool check_subscripts(Env env, const Array_Sub array) { CHECK_OB(check_exp(env, array->exp)) m_uint depth = 0; diff --git a/src/parse/operator.c b/src/parse/operator.c index e8395899..0f8e3240 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -8,6 +8,8 @@ #include "instr.h" #include "emit.h" #include "operator.h" +#include "object.h" +#include "array.h" typedef Type (*f_type)(const Env env, const Exp exp); diff --git a/tests/error/vararg_after.gw b/tests/error/vararg_after.gw index c9dec0cc..93375f6d 100644 --- a/tests/error/vararg_after.gw +++ b/tests/error/vararg_after.gw @@ -2,5 +2,5 @@ fun void test(...) { vararg.start; vararg.end; - vararg.i; + vararg $ int; } diff --git a/tests/error/vararg_before.gw b/tests/error/vararg_before.gw index ee2680b7..9159d480 100644 --- a/tests/error/vararg_before.gw +++ b/tests/error/vararg_before.gw @@ -1,4 +1,4 @@ #! [contains] used before fun void test(...) { - vararg.i; + vararg $ int; } diff --git a/tests/error/vararg_invalid_acces.gw b/tests/error/vararg_invalid_acces.gw index 4467d961..ad3a91b0 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; } Vec3(1.3) => test; diff --git a/tests/new/typedef_func_class_variadic.gw b/tests/new/typedef_func_class_variadic.gw index 914c46d2..e8400730 100644 --- a/tests/new/typedef_func_class_variadic.gw +++ b/tests/new/typedef_func_class_variadic.gw @@ -6,7 +6,7 @@ class C { fun void test(...) { <<< this, " ", __func__ >>>; vararg.start; - <<< vararg.i >>>; + <<< vararg $ int >>>; vararg.end; } diff --git a/tests/tree/empty_vararg.gw b/tests/tree/empty_vararg.gw index fa873c54..bc944a4d 100644 --- a/tests/tree/empty_vararg.gw +++ b/tests/tree/empty_vararg.gw @@ -1,7 +1,7 @@ fun int test(...){ vararg.start; - <<< "test" >>>; - <<< vararg.i >>>; + <<< "test" >>>; + <<< vararg $ int >>>; vararg.end; return 1; } diff --git a/tests/tree/varobject_assign.gw b/tests/tree/varobject_assign.gw index 87a2f858..23a891ca 100644 --- a/tests/tree/varobject_assign.gw +++ b/tests/tree/varobject_assign.gw @@ -1,6 +1,6 @@ fun void test(...) { Object o; vararg.start; - vararg.o @=> o; + vararg $ Object @=> o; vararg.end; } -- 2.43.0