From b59f51486393b2fae7b0015bc5099c5514c7335a Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Fri, 13 Jun 2025 15:42:08 -0700 Subject: Chapter 24b: SCCP Across Functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tamás Hadházy <85063808+Hels15@users.noreply.github.com> Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: fuhsnn <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: Symious <14933944+symious@users.noreply.github.com> Co-authored-by: Jun Kawasaki Co-authored-by: Hadházy Tamás Co-authored-by: Claude Opus 5 --- src/test/java/com/seaofnodes/simple/Chapter18Test.java | 10 ++++++---- src/test/java/com/seaofnodes/simple/Chapter24Test.java | 14 ++++++++++++++ src/test/java/com/seaofnodes/simple/SccpTest.java | 18 +++++------------- 3 files changed, 25 insertions(+), 17 deletions(-) (limited to 'src/test') diff --git a/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/src/test/java/com/seaofnodes/simple/Chapter18Test.java index e5dd259b..b6a0ab57 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -406,8 +406,7 @@ return g(); } - // Local SCCP cannot infer this recursive return type. The next chapter - // solves across calls and checks the same program's execution results. + // Mutual recursion: check results, independent of how much gets inlined. @Test public void testFcnMutRec() { CodeGen code = new CodeGen( @@ -416,8 +415,11 @@ val is_even = { int x -> x ? is_odd (x-1) : true ; }; val is_odd = { int x -> x ? is_even(x-1) : false; }; return is_even(arg); """); - try { code.driver(CodeGen.Phase.TypeCheck); fail(); } - catch( Parser.ParseException e ) { assertEquals("No defined return type",e.getMessage()); } + code.driver(CodeGen.Phase.FinalizeIR); + assertEquals("1", Eval2.eval(code, 0)); + assertEquals("0", Eval2.eval(code, 1)); + assertEquals("1", Eval2.eval(code, 2)); + assertEquals("0", Eval2.eval(code, 3)); } // Forward ref to 'x' means that diff --git a/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/src/test/java/com/seaofnodes/simple/Chapter24Test.java index 4eb1324d..6e0fd95f 100644 --- a/src/test/java/com/seaofnodes/simple/Chapter24Test.java +++ b/src/test/java/com/seaofnodes/simple/Chapter24Test.java @@ -17,6 +17,20 @@ import org.junit.Test; import static org.junit.Assert.*; public class Chapter24Test { + @Test public void testRecursiveWidening() { + String[] srcs = { + // Parm(x) must widen even though the recursive result is constant. + "val f = { int x, int limit -> x >= limit ? 0 : f(x+1,limit); }; return f(0,arg);", + // The growing result has its own cycle, which never crosses Parm(x). + "val f = { int x -> x <= 0 ? 0 : f(x-1)+1; }; return f(3);" + }; + for( int i=0; i x+1; }; return f(1)+f(2);").parse().iter().opto(); int[] parms = {0}; code._start.walk(n -> { if( n instanceof ParmNode p && "x".equals(p._label) ) { parms[0]++; - assertSame(TypeInteger.BOT,p._type); - assertTrue(p.fun().in(1) instanceof StartNode); + TypeInteger t = (TypeInteger)p._type; + assertEquals(1,t._min); + assertEquals(2,t._max); + assertFalse(p.fun().in(1) instanceof StartNode); } - if( n instanceof CallEndNode cend ) assertEquals(1,cend.nIns()); return null; }); assertEquals(1,parms[0]); -- cgit v1.2.3