@@ -3232,6 +3232,30 @@ static ExecResult exec_stmt(Interpreter* interp, Stmt* stmt, Env* env, LabelMap*
32323232 bool prev_initialized = false;
32333233 env_get (env , stmt -> as .for_stmt .counter , & prev_val , & prev_type , & prev_initialized );
32343234
3235+ /* Track whether the counter name exists in any parent env.
3236+ Loop-local binding must shadow the global symbol and restore it
3237+ after the loop, regardless of where it was originally defined.
3238+ We cannot rely on `env_get` alone because it doesn't distinguish
3239+ between current-env and parent-env bindings. */
3240+ bool had_global = false;
3241+ Value global_prev_val = value_null ();
3242+ DeclType global_prev_type = TYPE_UNKNOWN ;
3243+ bool global_prev_initialized = false;
3244+ for (Env * cursor = env ; cursor && cursor -> parent ; cursor = cursor -> parent ) {
3245+ Env * parent = cursor -> parent ;
3246+ if (!parent ) break ;
3247+ Value tmp_val = value_null ();
3248+ DeclType tmp_type = TYPE_UNKNOWN ;
3249+ bool tmp_initialized = false;
3250+ if (env_get (parent , stmt -> as .for_stmt .counter , & tmp_val , & tmp_type , & tmp_initialized )) {
3251+ had_global = true;
3252+ global_prev_val = tmp_val ;
3253+ global_prev_type = tmp_type ;
3254+ global_prev_initialized = tmp_initialized ;
3255+ break ;
3256+ }
3257+ }
3258+
32353259 /* Detect whether a local binding already exists (trial define) */
32363260 bool local_existed = true;
32373261 if (env_define (env , stmt -> as .for_stmt .counter , TYPE_INT )) {
@@ -3275,8 +3299,7 @@ static ExecResult exec_stmt(Interpreter* interp, Stmt* stmt, Env* env, LabelMap*
32753299 env_delete (env , stmt -> as .for_stmt .counter );
32763300 env_delete (env , temp_name );
32773301 if (local_existed ) {
3278- env_define (env , stmt -> as .for_stmt .counter , prev_type );
3279- if (prev_initialized ) env_assign (env , stmt -> as .for_stmt .counter , prev_val , prev_type , false);
3302+ env_restore_local (env , stmt -> as .for_stmt .counter , prev_val , prev_type , prev_initialized );
32803303 }
32813304 value_free (prev_val );
32823305 interp -> loop_depth -- ;
@@ -3291,8 +3314,7 @@ static ExecResult exec_stmt(Interpreter* interp, Stmt* stmt, Env* env, LabelMap*
32913314 env_delete (env , stmt -> as .for_stmt .counter );
32923315 env_delete (env , temp_name );
32933316 if (local_existed ) {
3294- env_define (env , stmt -> as .for_stmt .counter , prev_type );
3295- if (prev_initialized ) env_assign (env , stmt -> as .for_stmt .counter , prev_val , prev_type , false);
3317+ env_restore_local (env , stmt -> as .for_stmt .counter , prev_val , prev_type , prev_initialized );
32963318 }
32973319 value_free (prev_val );
32983320 interp -> loop_depth -- ;
@@ -3306,8 +3328,7 @@ static ExecResult exec_stmt(Interpreter* interp, Stmt* stmt, Env* env, LabelMap*
33063328 env_delete (env , stmt -> as .for_stmt .counter );
33073329 env_delete (env , temp_name );
33083330 if (local_existed ) {
3309- env_define (env , stmt -> as .for_stmt .counter , prev_type );
3310- if (prev_initialized ) env_assign (env , stmt -> as .for_stmt .counter , prev_val , prev_type , false);
3331+ env_restore_local (env , stmt -> as .for_stmt .counter , prev_val , prev_type , prev_initialized );
33113332 }
33123333 value_free (prev_val );
33133334 interp -> loop_depth -- ;
@@ -3321,8 +3342,7 @@ static ExecResult exec_stmt(Interpreter* interp, Stmt* stmt, Env* env, LabelMap*
33213342 env_delete (env , stmt -> as .for_stmt .counter );
33223343 env_delete (env , temp_name );
33233344 if (local_existed ) {
3324- env_define (env , stmt -> as .for_stmt .counter , prev_type );
3325- if (prev_initialized ) env_assign (env , stmt -> as .for_stmt .counter , prev_val , prev_type , false);
3345+ env_restore_local (env , stmt -> as .for_stmt .counter , prev_val , prev_type , prev_initialized );
33263346 }
33273347 value_free (prev_val );
33283348 interp -> loop_depth -- ;
@@ -3338,8 +3358,14 @@ static ExecResult exec_stmt(Interpreter* interp, Stmt* stmt, Env* env, LabelMap*
33383358 env_delete (env , stmt -> as .for_stmt .counter );
33393359 env_delete (env , temp_name );
33403360 if (local_existed ) {
3341- env_define (env , stmt -> as .for_stmt .counter , prev_type );
3342- if (prev_initialized ) env_assign (env , stmt -> as .for_stmt .counter , prev_val , prev_type , false);
3361+ env_restore_local (env , stmt -> as .for_stmt .counter , prev_val , prev_type , prev_initialized );
3362+ }
3363+
3364+ /* Restore global binding if the aliasing process shadowed a
3365+ non-local (global/parent) symbol with a non-INT type. */
3366+ if (had_global ) {
3367+ env_assign (env , stmt -> as .for_stmt .counter , global_prev_val , global_prev_type , false);
3368+ value_free (global_prev_val );
33433369 }
33443370 value_free (prev_val );
33453371
0 commit comments