From 9b987caf73a932327fe24f135693973fcdd46e9a Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Mon, 17 May 2021 13:17:13 +0200 Subject: [PATCH] :art: shadowing and tests --- ast | 2 +- src/clean.c | 7 +++++++ src/emit/emit.c | 20 ++++++++++++++++---- src/parse/check.c | 25 +++++++++++++++++-------- src/parse/scan1.c | 31 +++++++++++++++++++++++-------- tests/tree/repeat_idx.gw | 4 ++++ tests/tree/repeat_idx_shadow.gw | 4 ++++ 7 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 tests/tree/repeat_idx.gw create mode 100644 tests/tree/repeat_idx_shadow.gw diff --git a/ast b/ast index ec83de3d..5c6ff39a 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit ec83de3d86f1288cf88d3dc095fd77e35a48126f +Subproject commit 5c6ff39a52550be2956e927091e58470d3cc6dc6 diff --git a/src/clean.c b/src/clean.c index c4069804..da790e5c 100644 --- a/src/clean.c +++ b/src/clean.c @@ -171,12 +171,19 @@ ANN static void clean_stmt_for(Clean *a, Stmt_For b) { --a->scope; } +ANN static void clean_idx(Clean *a, struct EachIdx_ *b) { + if(b->v) + value_remref(b->v, a->gwion); +} + ANN static void clean_stmt_each(Clean *a, Stmt_Each b) { ++a->scope; clean_exp(a, b->exp); clean_stmt(a, b->body); if(b->v) value_remref(b->v, a->gwion); + if(b->idx) + clean_idx(a, b->idx); --a->scope; } diff --git a/src/emit/emit.c b/src/emit/emit.c index 73fdc95c..80f2dc7c 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1861,23 +1861,35 @@ ANN static m_bool emit_stmt_each(const Emitter emit, const Stmt_Each stmt) { } ANN static void stmt_loop_roll(const Emitter emit, const struct Looper *loop) { - const Instr cpy = emit_add_instr(emit, RegPushMem4); - cpy->m_val = loop->offset; + const Instr counter = emit_add_instr(emit, RegPushMem4); + counter->m_val = loop->offset; emit_add_instr(emit, int_post_dec); } +ANN static void stmt_loop_roll_idx(const Emitter emit, const struct Looper *loop) { + const Instr target = emit_add_instr(emit, RegPushMem); + target->m_val = loop->offset + SZ_INT; + const Instr counter = emit_add_instr(emit, RegPushMem4); + counter->m_val = loop->offset; + emit_add_instr(emit, int_post_inc); + emit_add_instr(emit, int_minus); +} + ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt, m_uint *index) { const uint n = emit->info->unroll; if(n) unroll_init(emit, n); const m_uint offset = emit_local(emit, emit->gwion->type[et_int]); + if(stmt->idx) + emit_local(emit, emit->gwion->type[et_int]); CHECK_BB(emit_exp_pop_next(emit, stmt->cond)); regpop(emit, SZ_INT); +// set mem const Instr tomem = emit_add_instr(emit, Reg2Mem); - tomem->m_val = offset; + tomem->m_val = offset + !stmt->idx ? 0 : SZ_INT; *index = emit_code_size(emit); struct Looper loop = { .stmt=stmt->body, .offset=offset, .n=n, - .roll=stmt_loop_roll }; + .roll= !stmt->idx ? stmt_loop_roll : stmt_loop_roll_idx}; CHECK_BB(looper_run(emit, &loop)); const Instr _goto = emit_add_instr(emit, Goto); _goto->m_val = *index; diff --git a/src/parse/check.c b/src/parse/check.c index 14ede8f4..42a3713d 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -1068,6 +1068,13 @@ ANN static inline Type foreach_type(const Env env, const Exp exp) { return depth ? array_type(env, t, depth) : t; } +ANN static void check_idx(const Env env, struct EachIdx_ *const idx) { + idx->v = new_value(env->gwion->mp, env->gwion->type[et_int], s_name(idx->sym)); + valuefrom(env, idx->v->from, idx->pos); + set_vflag(idx->v, vflag_valid); + nspc_add_value(env->curr, idx->sym, idx->v); +} + ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) { DECL_OB(const Type, base, = foreach_type(env, stmt->exp)); CHECK_BB(ensure_traverse(env, base)); @@ -1080,12 +1087,14 @@ ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) { stmt->v = new_value(env->gwion->mp, ret, s_name(stmt->sym)); set_vflag(stmt->v, vflag_valid); nspc_add_value(env->curr, stmt->sym, stmt->v); - if(stmt->idx) { - stmt->idx->v = new_value(env->gwion->mp, env->gwion->type[et_int], s_name(stmt->idx->sym)); - valuefrom(env, stmt->idx->v->from, stmt->idx->pos); - set_vflag(stmt->idx->v, vflag_valid); - nspc_add_value(env->curr, stmt->idx->sym, stmt->idx->v); - } + if(stmt->idx) + check_idx(env, stmt->idx); + return check_conts(env, stmt_self(stmt), stmt->body); +} + +ANN static m_bool do_stmt_repeat(const Env env, const Stmt_Loop stmt) { + if(stmt->idx) + check_idx(env, stmt->idx); return check_conts(env, stmt_self(stmt), stmt->body); } @@ -1118,9 +1127,9 @@ stmt_func_xxx(for, Stmt_For,, !( !check_flow(env, stmt->c2->d.stmt_exp.val) || (stmt->c3 && !check_exp(env, stmt->c3)) || check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1) -stmt_func_xxx(loop, Stmt_Loop,, !(!check_exp(env, stmt->cond) || +stmt_func_xxx(loop, Stmt_Loop, check_idx(env, stmt->idx), !(!check_exp(env, stmt->cond) || cond_type(env, stmt->cond) < 0 || - check_conts(env, stmt_self(stmt), stmt->body) < 0) ? 1 : -1) + do_stmt_repeat(env, stmt) < 0) ? 1 : -1) stmt_func_xxx(each, Stmt_Each,, do_stmt_each(env, stmt)) ANN static m_bool check_stmt_return(const Env env, const Stmt_Exp stmt) { diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 2b5cfbe5..adfc6272 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -303,6 +303,25 @@ ANN static inline m_bool stmt_each_defined(const restrict Env env, const Stmt_Ea return GW_OK; } +ANN static inline m_bool shadow_err(const Env env, const Symbol sym, const loc_t loc) { + ERR_B(loc, _("argument '%s' shadows a previously defined variable"), + s_name(sym)) +} + +ANN static inline m_bool shadow_arg(const Env env, const Symbol sym, const loc_t loc) { + Nspc nspc = env->curr; + do if(nspc_lookup_value0(nspc, sym)) + return shadow_err(env, sym, loc); + while((nspc = nspc->parent)); + return GW_OK; +} + +ANN static inline m_bool shadow_var(const Env env, const Symbol sym, const loc_t loc) { + if(nspc_lookup_value1(env->curr, sym)) + return shadow_err(env, sym, loc); + return GW_OK; +} + #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) @@ -314,7 +333,8 @@ describe_ret_nspc(for, Stmt_For,, !(scan1_stmt(env, stmt->c1) < 0 || scan1_stmt(env, stmt->body) < 0) ? 1 : -1) describe_ret_nspc(each, Stmt_Each,, !(stmt_each_defined(env, stmt) < 0 || scan1_exp(env, stmt->exp) < 0 || scan1_stmt(env, stmt->body) < 0) ? 1 : -1) -describe_ret_nspc(loop, Stmt_Loop,, !(scan1_exp(env, stmt->cond) < 0 || +describe_ret_nspc(loop, Stmt_Loop,, !( (!stmt->idx ? GW_OK : shadow_var(env, stmt->idx->sym, stmt->idx->pos)) < 0 || + scan1_exp(env, stmt->cond) < 0 || scan1_stmt(env, stmt->body) < 0) ? 1 : -1) describe_ret_nspc(if, Stmt_If,, !(scan1_exp(env, stmt->cond) < 0 || scan1_stmt(env, stmt->if_body) < 0 || @@ -553,13 +573,8 @@ ANN static m_bool scan_internal(const Env env, const Func_Base *base) { } ANN static m_bool scan1_fdef_args(const Env env, Arg_List list) { - do { - Nspc nspc = env->curr; - do if(nspc_lookup_value0(nspc, list->var_decl->xid)) - ERR_B(list->var_decl->pos, _("argument '%s' shadows a previously defined variable"), - s_name(list->var_decl->xid)) - while((nspc = nspc->parent)); - } while((list = list->next)); + do CHECK_BB(shadow_arg(env, list->var_decl->xid, list->var_decl->pos)); + while((list = list->next)); return GW_OK; } diff --git a/tests/tree/repeat_idx.gw b/tests/tree/repeat_idx.gw new file mode 100644 index 00000000..61f7351b --- /dev/null +++ b/tests/tree/repeat_idx.gw @@ -0,0 +1,4 @@ +repeat(i, 100000) + <<< "${i} test" >>>; +repeat(100000) + <<< "test" >>>; diff --git a/tests/tree/repeat_idx_shadow.gw b/tests/tree/repeat_idx_shadow.gw new file mode 100644 index 00000000..2b5d7e95 --- /dev/null +++ b/tests/tree/repeat_idx_shadow.gw @@ -0,0 +1,4 @@ +#! [contains] shadows a previously defined variable +var int i; + +repeat(i, 12); -- 2.43.0