From 0977b80d0e0e81a8215441dbd89faf98fdc47a2c Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sun, 8 Mar 2020 23:57:37 +0100 Subject: [PATCH] :art: Make Vararg a better type --- src/emit/emit.c | 1 + src/env/tupleform.c | 50 ++++++++++++++++++++++++++ src/lib/object.c | 34 +++++++++++++++++- src/lib/vararg.c | 86 +++++++++++++++++++++------------------------ src/parse/check.c | 45 +++--------------------- src/vm/vm.c | 8 ++--- 6 files changed, 133 insertions(+), 91 deletions(-) create mode 100644 src/env/tupleform.c diff --git a/src/emit/emit.c b/src/emit/emit.c index 67e22cee..f528699c 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1649,6 +1649,7 @@ ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) { if(!GET_FLAG(fdef->base->func, empty)) ERR_B(fdef->pos, _("invalid variadic use")) } + vector_pop(&emit->info->variadic); return GW_OK; } diff --git a/src/env/tupleform.c b/src/env/tupleform.c new file mode 100644 index 00000000..f14fec28 --- /dev/null +++ b/src/env/tupleform.c @@ -0,0 +1,50 @@ +#include "gwion_util.h" +#include "gwion_ast.h" +#include "gwion_env.h" +#include "vm.h" +#include "instr.h" +#include "object.h" +#include "emit.h" +#include "vm.h" +#include "gwion.h" +#include "operator.h" +#include "import.h" +#include "gwi.h" +#include "traverse.h" +#include "object.h" +#include "parse.h" +#include "tuple.h" +#include "array.h" + +ANN void tuple_info(const Env env, Type_Decl *base, const Var_Decl var) { + const Value v = var->value; + const m_uint offset = vector_back(&env->class_def->e->tuple->offset); + vector_add(&env->class_def->e->tuple->types, (vtype)v->type); + vector_add(&env->class_def->e->tuple->offset, offset + v->type->size); + Type_Decl *td = cpy_type_decl(env->gwion->mp, base); + if(var->array) + td->array = cpy_array_sub(env->gwion->mp, var->array); + if(env->class_def->e->tuple->list) { + Type_List tl = env->class_def->e->tuple->list; + while(tl->next) + tl = tl->next; + tl->next = new_type_list(env->gwion->mp, td, NULL); + } else + env->class_def->e->tuple->list = new_type_list(env->gwion->mp, td, NULL); +} + +ANN TupleForm new_tupleform(MemPool p) { + TupleForm tuple = mp_malloc(p, TupleForm); + vector_init(&tuple->types); + vector_init(&tuple->offset); + vector_add(&tuple->offset, 0); + tuple->list = NULL; + return tuple; +} + +ANN void free_tupleform(MemPool p, const TupleForm tuple) { + vector_release(&tuple->types); + vector_release(&tuple->offset); + if(tuple->list) + free_type_list(p, tuple->list); +} diff --git a/src/lib/object.c b/src/lib/object.c index ffd8539b..116b2407 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -277,9 +277,41 @@ ANN static inline void emit_member(const Emitter emit, const Value v, const uint 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 Value value = find_value(actual_type(env->gwion, member->t_base), member->xid); + 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; } diff --git a/src/lib/vararg.c b/src/lib/vararg.c index e8b76e47..046ed324 100644 --- a/src/lib/vararg.c +++ b/src/lib/vararg.c @@ -17,20 +17,10 @@ void free_vararg(MemPool p, struct Vararg_* arg) { xfree(arg->d); - xfree(arg->k); xfree(arg->t); mp_free(p, Vararg, arg); } -INSTR(VarargTop) { - struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val); - if(arg) { - assert(arg->d); - PUSH_REG(shred, SZ_INT) - } else - shred->pc = instr->m_val2 + 1; -} - INSTR(VarargIni) { struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg); POP_REG(shred, instr->m_val - SZ_INT) @@ -39,22 +29,19 @@ INSTR(VarargIni) { *(m_uint*)(arg->d + i) = *(m_uint*)(shred->reg - SZ_INT + i); const Vector kinds = (Vector)instr->m_val2; arg->s = vector_size(kinds); - arg->k = (m_uint*)xmalloc(arg->s * SZ_INT); 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; } -INSTR(VarargEnd) { - struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val); - PUSH_REG(shred, SZ_INT); - arg->o += arg->k[arg->i]; +static INSTR(VarargEnd) { + struct Vararg_* arg = *(struct Vararg_**)REG(0); + arg->o += arg->t[arg->i]->size; if(++arg->i < arg->s) - shred->pc = instr->m_val2; + shred->pc = instr->m_val; else free_vararg(shred->info->mp, arg); } @@ -65,15 +52,14 @@ static OP_CHECK(opck_vararg_cast) { } static INSTR(VarargCast) { - struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val); + 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); Except(shred, "InvalidVariadicAccess"); } 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); + *(m_uint*)REG(i - SZ_INT*2) = *(m_uint*)(arg->d + arg->o + i); } ANN static inline Instr get_variadic(const Emitter emit) { @@ -92,9 +78,12 @@ ANN m_bool variadic_check(const Emitter emit, const loc_t pos) { 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; return instr; } @@ -109,47 +98,56 @@ static ID_CHECK(idck_vararg) { ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function")) } +static ID_EMIT(idem_vararg) { + const Instr instr = emit_add_instr(emit, RegPushMem); + instr->m_val = emit->code->stack_depth - SZ_INT; + return instr; +} + static GACK(gack_vararg) { - INTERP_PRINTF("%p\n", *(M_Object*)VALUE); + 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, VarargTop); - instr->m_val = offset; - instr->m_val2 = emit_code_size(emit); + 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) { + 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 = offset; - instr->m_val2 = variadic->m_val2; - variadic->m_val2 = emit_code_size(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; - m_uint offset = emit->env->class_def ? SZ_INT : 0; - Arg_List l = emit->env->func->def->base->args; const m_str str = s_name(member->xid); - while(l) { - offset += l->type->size; - l = l->next; - } - if(!strcmp(str, "start")) { + 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; } - assert(!strcmp(str, "end")); if(!get_variadic(emit)) ERR_O(exp_self(member)->pos, _("vararg.start not used before vararg.end")) emit_vararg_end(emit, offset); @@ -158,25 +156,21 @@ static OP_EMIT(opem_vararg_dot) { OP_CHECK(opck_object_dot); GWION_IMPORT(vararg) { - const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", SZ_INT, NULL); + 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_class_spe(gwi, "@Vararg", 0); + const Type t_vararg = gwi_mk_type(gwi, "@Vararg", SZ_INT, NULL); gwi_gack(gwi, t_vararg, gack_vararg); - 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_OB(gwi_union_end(gwi, ae_flag_const)) - GWI_BB(gwi_class_end(gwi)) +// 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_object_dot)) + 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)) - 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_BB(gwi_oper_end(gwi, "$", NULL)) gwi_register_freearg(gwi, VarargIni, freearg_vararg); - struct SpecialId_ spid = { .type=t_vararg, .exec=RegPushImm, .is_const=1, .ck=idck_vararg}; + struct SpecialId_ spid = { .type=t_vararg, .is_const=1, .ck=idck_vararg, .em=idem_vararg}; gwi_specialid(gwi, "vararg", &spid); return GW_OK; } diff --git a/src/parse/check.c b/src/parse/check.c index 73819a0a..133f8364 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -232,7 +232,7 @@ ANN static Type check_prim_range(const Env env, Range **data) { return op_check(env, &opi); } -ANN static inline m_bool not_from_owner_class(const Env env, const Type t, +ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos) { if(!v->from->owner_class || isa(t, v->from->owner_class) < 0) { ERR_B(pos, @@ -265,9 +265,8 @@ ANN static Value check_non_res_value(const Env env, const Symbol *data) { ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data); -ANN static Type check_dot(const Env env, const Value v, const Exp_Dot *member) { - struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, - .rhs=v->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos }; +ANN static Type check_dot(const Env env, const Exp_Dot *member) { + struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, .data=(uintptr_t)member, .pos=exp_self(member)->pos }; return op_check(env, &opi); } @@ -288,7 +287,7 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) { prim_exp(data)->meta = ae_meta_value; if(v->from->owner_class) { const Exp exp = symbol_owned_exp(env->gwion, data); - const Type ret = check_dot(env, v, &exp->d.exp_dot); + const Type ret = check_dot(env, &exp->d.exp_dot); prim_exp(data)->nspc = exp->nspc; free_exp(env->gwion->mp, exp); CHECK_OO(ret); @@ -850,42 +849,8 @@ ANN static Type check_exp_if(const Env env, const Exp_If* exp_if) { } ANN static Type check_exp_dot(const Env env, Exp_Dot* member) { - const m_str str = s_name(member->xid); CHECK_OO((member->t_base = check_exp(env, member->base))) - 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("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; -// prim_self(member)->value = value; - CHECK_OO(check_dot(env, value, member)) - return value->type; + return check_dot(env, member); } ANN m_bool check_type_def(const Env env, const Type_Def tdef) { diff --git a/src/vm/vm.c b/src/vm/vm.c index 1c8af73e..deef382d 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -382,20 +382,20 @@ regpushaddr: reg += SZ_INT; DISPATCH() regpushmem: - *(m_uint*)reg = *(m_uint*)(mem + VAL); + *(m_uint*)reg = *(m_uint*)(mem + (m_int)VAL); reg += SZ_INT; DISPATCH(); regpushmemfloat: - *(m_float*)reg = *(m_float*)(mem + VAL); + *(m_float*)reg = *(m_float*)(mem + (m_int)VAL); reg += SZ_FLOAT; DISPATCH(); regpushmemother: for(m_uint i = 0; i <= VAL2; i+= SZ_INT) - *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + VAL) + i); + *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + (m_int)VAL) + i); reg += VAL2; DISPATCH(); regpushmemaddr: - *(m_bit**)reg = &*(m_bit*)(mem + VAL); + *(m_bit**)reg = &*(m_bit*)(mem + (m_int)VAL); reg += SZ_INT; DISPATCH() pushnow: -- 2.43.0