summaryrefslogtreecommitdiff
path: root/chapter23
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-09-17 15:34:28 -0700
committerCliff Click <cliffc@acm.org>2026-09-17 15:34:28 -0700
commit42681f41318796afc58bc14ce04620b7c5c7eb18 (patch)
tree6c8a90f441a4a0edd2b4e5f3a8293d45b9c55834 /chapter23
parent5eb00d3306e6e8738b8033c5ba8401770f9d7ffd (diff)
downloadSimple-42681f41318796afc58bc14ce04620b7c5c7eb18.tar.gz
Simple-42681f41318796afc58bc14ce04620b7c5c7eb18.zip
Parser fix OR temps
Diffstat (limited to 'chapter23')
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/Parser.java2
-rw-r--r--chapter23/src/test/java/com/seaofnodes/simple/Chapter23Test.java42
2 files changed, 43 insertions, 1 deletions
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/Parser.java b/chapter23/src/main/java/com/seaofnodes/simple/Parser.java
index 8a6b1967..76898bea 100644
--- a/chapter23/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter23/src/main/java/com/seaofnodes/simple/Parser.java
@@ -590,7 +590,7 @@ public class Parser {
};
rhs.keep();
_scope.removeGuards(ifF);
- if( doRHS )
+ if( doRHS || fside.equals("||") )
fScope = _scope;
pred.unkeep();
diff --git a/chapter23/src/test/java/com/seaofnodes/simple/Chapter23Test.java b/chapter23/src/test/java/com/seaofnodes/simple/Chapter23Test.java
index 9d500266..435b675c 100644
--- a/chapter23/src/test/java/com/seaofnodes/simple/Chapter23Test.java
+++ b/chapter23/src/test/java/com/seaofnodes/simple/Chapter23Test.java
@@ -13,6 +13,48 @@ import static org.junit.Assert.*;
public class Chapter23Test {
@Test
+ public void testOrRhsLoopLocal() throws IOException {
+ checkOrRhsLoop("""
+ struct S { int f; };
+ int x = 0;
+ int result = (arg & 1) || (new S {
+ while (x < 3) x++;
+ f = ++x;
+ }).f;
+ return x * 10 + result;
+ """);
+ }
+
+ @Test
+ public void testOrRhsLoopMemory() throws IOException {
+ checkOrRhsLoop("""
+ struct S { int f; };
+ S !s = new S;
+ int result = (arg & 1) || (new S {
+ while (s.f < 3) s.f++;
+ s.f++;
+ f = s.f;
+ }).f;
+ return s.f * 10 + result;
+ """);
+ }
+
+ private static void checkOrRhsLoop(String src) throws IOException {
+ CodeGen code = new CodeGen(src).driver("riscv", "SystemV", null);
+ for (int arg : new int[]{0, 1, 2, 3}) {
+ byte[] image = new byte[1 << 20];
+ System.arraycopy(code._encoding.bits(), 0, image, 0, code._encoding._bits.size());
+ EvalRisc5 r5 = new EvalRisc5(image, 1 << 16);
+ r5.regs[riscv.A0] = arg;
+ assertEquals("Execution must finish", 0, r5.step(1000));
+ // False LHS runs the loop and final increment, returning 4.
+ // True LHS skips all RHS effects and returns the LHS value, 1.
+ assertEquals("OR result and side effects for arg=" + arg,
+ (arg & 1) == 0 ? 44 : 1, r5.regs[riscv.A0]);
+ }
+ }
+
+ @Test
public void testJig() throws IOException {
String src =
"""