From 437f7cdd411ae43352c0f386729c5aa41762aebb Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Sat, 17 Aug 2019 12:32:20 +0200 Subject: [PATCH] :art: Improve ArrayAccess --- src/emit/emit.c | 102 ++++++++++++++++++++++++++++++++-------------- src/parse/check.c | 73 +++++++++++++++++---------------- 2 files changed, 108 insertions(+), 67 deletions(-) diff --git a/src/emit/emit.c b/src/emit/emit.c index 9a7bc160..f3a14efd 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -398,6 +398,21 @@ ANN static m_bool prim_array(const Emitter emit, const Exp_Primary * primary) { return GW_OK; } +//! emit only one index at the time +ANN static inline m_bool emit_index(const Emitter emit, const Exp e) { + const Exp next = e->next; + e->next = NULL; + const m_bool ret = emit_exp(emit, e, 0); + e->next = next; + return ret; +} + +static inline Exp take_exp(Exp e, m_uint n) { + for(m_uint i = 1; i < n; ++i) + CHECK_OO((e = e->next)) + return e; +} + ANN static void array_loop(const Emitter emit, const m_uint depth) { regpop(emit, depth * SZ_INT); emit_add_instr(emit, GWOP_EXCEPT); @@ -422,10 +437,12 @@ ANN static void array_finish(const Emitter emit, const m_uint depth, push->m_val = is_var ? SZ_INT : size; } -ANN static inline void array_do(const Emitter emit, const m_uint depth, - const m_uint size, const m_bool is_var) { - array_loop(emit, depth); - array_finish(emit, depth, size, is_var); +ANN static inline m_bool array_do(const Emitter emit, const Array_Sub array, const m_bool is_var) { + emit_add_instr(emit, GcAdd); + CHECK_BB(emit_exp(emit, array->exp, 0)) + array_loop(emit, array->depth); + array_finish(emit, array->depth, array->type->size, is_var); + return GW_OK; } ANN static inline void tuple_access(const Emitter emit, const m_uint idx, @@ -437,38 +454,61 @@ ANN static inline void tuple_access(const Emitter emit, const m_uint idx, emit_add_instr(emit, DotMember); // just a place holder. } -ANN static inline Exp exp_antepenultimate(Exp e) { - while(e->next && e->next->next) - e = e->next; - return e; -} +struct ArrayAccessInfo { + struct Array_Sub_ array; + const Type type; + const m_bool is_var; +}; -ANN static m_bool emit_array_indexes(const Emitter emit, const Exp exp, - const m_bool is_tuple) { - const Exp e = exp_antepenultimate(exp), next = e->next; - emit_add_instr(emit, GcAdd); - if(is_tuple) - e->next = NULL; - CHECK_BB(emit_exp(emit, exp, 0)) - if(is_tuple) - e->next = next; - return GW_OK; +ANN static inline m_bool _emit_indexes(const Emitter emit, struct ArrayAccessInfo *const info); + +ANN static inline m_bool tuple_index(const Emitter emit, struct ArrayAccessInfo *const info) { + assert(isa(info->array.type, t_tuple) > 0); + const m_uint idx = info->array.exp->d.exp_primary.d.num; + tuple_access(emit, info->array.exp->d.exp_primary.d.num, info->array.depth ? 0 : info->is_var); + if(!info->array.exp->next) + return GW_OK; + const Type type = (Type)vector_at(&info->array.type->e->tuple->types, idx); + struct Array_Sub_ next = { info->array.exp->next, type, info->array.depth - 1 }; + info->array = next; + return _emit_indexes(emit, info); +} + +ANN static inline Exp emit_n_exp(const Emitter emit, struct ArrayAccessInfo *const info) { + const Exp e = take_exp(info->array.exp, info->array.depth); + const Exp next = e->next; + e->next = NULL; + struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.depth }; + const m_bool ret = array_do(emit, &partial, 0); + e->next = next; + return ret > 0 ? next : NULL; +} + +ANN static inline m_bool _emit_indexes(const Emitter emit, struct ArrayAccessInfo *const info) { + if(GET_FLAG(info->array.type, typedef)) { + info->array.type = info->array.type->e->parent; + return _emit_indexes(emit, info); + } + if(!info->array.type->array_depth) + return tuple_index(emit, info); + if(info->array.type->array_depth >= info->array.depth) { + struct Array_Sub_ next = { info->array.exp, info->type, info->array.depth }; + return array_do(emit, &next, info->is_var); + } + struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.depth - info->array.type->array_depth }; + struct Array_Sub_ next = { info->array.exp, array_base(info->array.type), info->array.depth - info->array.type->array_depth }; + info->array = partial; + DECL_OB(const Exp, exp, = emit_n_exp(emit, info)) + next.exp = exp; + info->array = next; + return _emit_indexes(emit, info); } ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) { CHECK_BB(emit_exp(emit, array->base, 0)) - const Type array_type = exp_self(array)->type, t_base = array->base->type, - type = array_base(t_base) ?: t_base; - const m_uint depth = get_depth(t_base) - get_depth(array_type); - const m_bool is_tuple = isa(type, t_tuple) > 0 && isa(array_type, t_tuple) < 0; - const m_uint is_var = exp_self(array)->emit_var; - if(depth) { - CHECK_BB(emit_array_indexes(emit, array->array->exp, is_tuple)) - array_do(emit, depth, array_type->size, is_var); - } - if(is_tuple) - tuple_access(emit, array->array->exp->d.exp_primary.d.num, is_var); - return GW_OK; + const Exp e = exp_self(array); + struct ArrayAccessInfo info = { *array->array, e->type, e->emit_var }; + return _emit_indexes(emit, &info); } ANN static m_bool prim_vec(const Emitter emit, const Exp_Primary * primary) { diff --git a/src/parse/check.c b/src/parse/check.c index 9c2ef81d..4ba79152 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -358,13 +358,42 @@ ANN static Type check_exp_primary(const Env env, const Exp_Primary* primary) { return exp_self(primary)->type = prim_func[primary->primary_type](env, primary); } -ANN Type at_depth(const Env env, const Type t, const m_uint depth) { +static inline Exp take_exp(Exp e, m_uint n) { + for(m_uint i = 1; i < n; ++i) + CHECK_OO((e = e->next)) + return e; +} + +ANN static Type at_depth(const Env env, const Array_Sub array) { + const Type t = array->type; + const m_uint depth = array->depth; + const Exp e = array->exp; if(!depth) return t; - if(GET_FLAG(t, typedef)) - return at_depth(env, t->e->parent, depth); - if(depth > t->array_depth) - return at_depth(env, t->e->d.base_type, depth - t->array_depth); + if(GET_FLAG(t, typedef)) { + struct Array_Sub_ next = { e, t->e->parent, depth }; + return at_depth(env, &next); + } + if(depth > t->array_depth) { + const Exp curr = take_exp(e, t->array_depth); + const Type t_base = array_base(t) ?: t; + if(isa(t_base, t_tuple) > 0) { + if(curr->exp_type != ae_exp_primary || + curr->d.exp_primary.primary_type != ae_primary_num) + ERR_O(e->pos, _("tuple subscripts must be litteral")) + const m_uint idx = curr->d.exp_primary.d.num; + const Type type = (Type)vector_at(&t_base->e->tuple->types, idx); + if(type == t_undefined) + ERR_O(e->pos, _("tuple subscripts is undefined")) + struct Array_Sub_ next = { curr->next, type, depth - t->array_depth - 1 }; + return at_depth(env, &next); + } + if(!curr->next) + ERR_O(e->pos, _("array subscripts (%i) exceeds defined dimension (%i)"), + depth, get_depth(t)) + struct Array_Sub_ next = { curr->next, t_base, depth - t->array_depth }; + return at_depth(env, &next); + } return array_type(env, array_base(t), t->array_depth - depth); } @@ -381,42 +410,14 @@ static m_bool array_access_valid(const Env env, const Exp_Array* array) { CHECK_BB(index_is_int(env, array->array->exp, &depth)) if(depth != array->array->depth) ERR_B(exp_self(array)->pos, _("invalid array acces expression.")) - DECL_OB(const Type, t_base, = check_exp(env, array->base)) - if(depth > get_depth(t_base)) { - const Type type = array_base(t_base) ?: t_base; - if(isa(type, t_tuple) > 0 && depth - get_depth(t_base) == 1) { - Exp e = array->array->exp; - while(e->next) - e = e->next; - if(e->exp_type != ae_exp_primary || - e->d.exp_primary.primary_type != ae_primary_num) - ERR_B(exp_self(array)->pos, _("tuple subscripts must be litteral")) - if((Type)vector_at(&type->e->tuple->types, e->d.exp_primary.d.num) == t_undefined) - ERR_B(exp_self(array)->pos, _("tuple subscripts is undefined")) - return 0; - } - ERR_B(exp_self(array)->pos, - _("array subscripts (%i) exceeds defined dimension (%i)"), - array->array->depth, get_depth(t_base)) - } return GW_OK; } static ANN Type check_exp_array(const Env env, const Exp_Array* array) { + CHECK_OO((array->array->type = check_exp(env, array->base))) CHECK_OO(check_exp(env, array->array->exp)) - const m_bool ret = array_access_valid(env, array); - CHECK_BO(ret); - if(!ret) { - Exp e = array->array->exp; - while(e->next) - e = e->next; - // if we implement tuple with no type, err_msg - const Type type = array_base(array->base->type) ?: array->base->type; - if(e->d.exp_primary.d.num >= vector_size(&type->e->tuple->types)) - ERR_O(exp_self(array)->pos, "Invalid tuple subscript") - return (Type)vector_at(&type->e->tuple->types, e->d.exp_primary.d.num); - } - return at_depth(env, array->base->type, array->array->depth); + CHECK_BO(array_access_valid(env, array)) + return at_depth(env, array->array); } ANN static Type_List mk_type_list(const Env env, const Type type) { -- 2.43.0