]> Nishi Git Mirror - gwion.git/commitdiff
:art: shadowing and tests
authorJérémie Astor <fennecdjay@gmail.com>
Mon, 17 May 2021 11:17:13 +0000 (13:17 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Mon, 17 May 2021 11:17:13 +0000 (13:17 +0200)
ast
src/clean.c
src/emit/emit.c
src/parse/check.c
src/parse/scan1.c
tests/tree/repeat_idx.gw [new file with mode: 0644]
tests/tree/repeat_idx_shadow.gw [new file with mode: 0644]

diff --git a/ast b/ast
index ec83de3d86f1288cf88d3dc095fd77e35a48126f..5c6ff39a52550be2956e927091e58470d3cc6dc6 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit ec83de3d86f1288cf88d3dc095fd77e35a48126f
+Subproject commit 5c6ff39a52550be2956e927091e58470d3cc6dc6
index c4069804ace965bd68f6a8055a511da7ee40b2ba..da790e5c43271c4293007a574cc389f655cfb186 100644 (file)
@@ -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;
 }
 
index 73fdc95c32d8ebd59c416610a00a28fdefb96a8c..80f2dc7cde39d3f9625175f8a6bf1c88b2d27e7b 100644 (file)
@@ -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;
index 14ede8f49bdb7ae608af185b292d538c63b77851..42a3713da7e0dcb271d9bd58a9da17a88df7e59b 100644 (file)
@@ -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) {
index 2b5cfbe52aff8a0a6c8cf8c337dc8bc5febf1cfc..adfc62721b808ae8f4d3657ade41dcdcf7ad7b56 100644 (file)
@@ -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 (file)
index 0000000..61f7351
--- /dev/null
@@ -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 (file)
index 0000000..2b5d7e9
--- /dev/null
@@ -0,0 +1,4 @@
+#! [contains] shadows a previously defined variable
+var int i;
+
+repeat(i, 12);