From 48c6498d1fae34f12bbd0891d742a4044f542436 Mon Sep 17 00:00:00 2001 From: David Mak Date: Thu, 21 Sep 2023 16:17:29 +0800 Subject: [PATCH] core: Fix restoration of loop target in try statement old_loop_target is only assigned if ctx.loop_target is overwritten, meaning that if ctx.loop_target is never overwritten, ctx.loop_target will always be overwritten to None. We fix this by only restoring from old_loop_target if we previously assigned to old_loop_target. --- nac3core/src/codegen/stmt.rs | 5 ++-- nac3standalone/demo/demo.rs | 3 +++ nac3standalone/demo/src/loop_try_break.py | 33 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 nac3standalone/demo/src/loop_try_break.py diff --git a/nac3core/src/codegen/stmt.rs b/nac3core/src/codegen/stmt.rs index da9545682..450df8205 100644 --- a/nac3core/src/codegen/stmt.rs +++ b/nac3core/src/codegen/stmt.rs @@ -808,8 +808,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>( ctx.outer_catch_clauses = old_clauses; ctx.unwind_target = old_unwind; ctx.return_target = old_return; - ctx.loop_target = old_loop_target; - old_loop_target = None; + ctx.loop_target = old_loop_target.or(ctx.loop_target).take(); let old_unwind = if !finalbody.is_empty() { let final_landingpad = ctx.ctx.append_basic_block(current_fun, "try.catch.final"); @@ -930,7 +929,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>( } ctx.unwind_target = old_unwind; - ctx.loop_target = old_loop_target; + ctx.loop_target = old_loop_target.or(ctx.loop_target).take(); ctx.return_target = old_return; ctx.builder.position_at_end(landingpad); diff --git a/nac3standalone/demo/demo.rs b/nac3standalone/demo/demo.rs index 06b1b51ae..154236dcd 100644 --- a/nac3standalone/demo/demo.rs +++ b/nac3standalone/demo/demo.rs @@ -97,6 +97,9 @@ pub extern "C" fn __nac3_raise(state: u32, exception_object: u32, context: u32) exit(101); } +#[no_mangle] +pub extern "C" fn __nac3_end_catch() {} + extern "C" { fn run() -> i32; } diff --git a/nac3standalone/demo/src/loop_try_break.py b/nac3standalone/demo/src/loop_try_break.py new file mode 100644 index 000000000..eb7d6482b --- /dev/null +++ b/nac3standalone/demo/src/loop_try_break.py @@ -0,0 +1,33 @@ +# Break within try statement within a loop +# Taken from https://book.pythontips.com/en/latest/for_-_else.html + +@extern +def output_int32(x: int32): + ... + +@extern +def output_float64(x: float): + ... + +@extern +def output_str(x: str): + ... + +def run() -> int32: + for n in range(2, 10): + for x in range(2, n): + try: + if n % x == 0: + output_int32(n) + output_str(" equals ") + output_int32(x) + output_str(" * ") + output_float64(n / x) + except: # Assume this is intended to catch x == 0 + break + else: + # loop fell through without finding a factor + output_int32(n) + output_str(" is a prime number") + + return 0 \ No newline at end of file