Fix recursion for each function name

This commit is contained in:
Jan-Niclas Loosen
2026-01-23 12:55:49 +01:00
parent 188cba7fa6
commit add07249dc
7 changed files with 21 additions and 158 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -13,6 +13,9 @@ import syntax
# Global registry for function start/end nodes # Global registry for function start/end nodes
FUNCTIONS = {} FUNCTIONS = {}
# Global variable to track the current function being processed
CURRENT_FUNCTION = None
class CONST(compiler.CONST): class CONST(compiler.CONST):
def cfa(self, pred, end = None): def cfa(self, pred, end = None):
node = CFG_Node(self) node = CFG_Node(self)
@@ -220,16 +223,9 @@ class CALL(compiler.CALL):
call_node.add_child(f_start) call_node.add_child(f_start)
call_node.add_child(return_node) call_node.add_child(return_node)
# TODO: Why only g? Also f can be recursive. # Return value flow for recursive calls
# For recursive calls, we need to ensure proper return value flow if CURRENT_FUNCTION is not None and self.f_name == CURRENT_FUNCTION:
# In expressions like g(x)+x, the return value from g(x) flows to the continuation
# This is especially important for recursive functions where multiple calls return values
# that need to flow to the same continuation point
if self.f_name == 'g':
# For recursive calls in g, ensure the return node connects to continuation
# This handles cases like g(y) where the return value flows to the same place as g(x)
return_node.add_child(cont) return_node.add_child(cont)
return cont return cont
class DECL(compiler.DECL): class DECL(compiler.DECL):
@@ -245,12 +241,22 @@ class DECL(compiler.DECL):
f_end.label = f"END {self.f_name}({', '.join(self.params)})" f_end.label = f"END {self.f_name}({', '.join(self.params)})"
FUNCTIONS[self.f_name] = (f_start, f_end) FUNCTIONS[self.f_name] = (f_start, f_end)
# Unwrap the method body # Set the current function context for recursion detection
body_end = self.body.cfa(f_start, f_end) global CURRENT_FUNCTION
previous_function = CURRENT_FUNCTION
CURRENT_FUNCTION = self.f_name
try:
# Unwrap the method body
body_end = self.body.cfa(f_start, f_end)
# Attach the end node if it is provided
if body_end is not None:
body_end.add_child(f_end)
finally:
# Restore the previous function context
CURRENT_FUNCTION = previous_function
# Attach the end node if it is provided
if body_end is not None:
body_end.add_child(f_end)
return pred return pred
class LET(compiler.LET): class LET(compiler.LET):

View File

@@ -1,66 +0,0 @@
digraph CFG {
n0 [label="3", shape="box"];
n0 -> n36;
node [fontname="Helvetica"];
n36 [label="2", shape=box];
n36 -> n37;
n37 [label="CALL f(2, 3)", shape=box, style=filled, color=orange];
n37 -> n4;
n4 [label="START f(x, y, z)", shape=box, style=filled, color=green];
n4 -> n6;
n6 [label="2", shape=box];
n6 -> n7;
n7 [label="y = 2", shape=box];
n7 -> n8;
n8 [label="3", shape=box];
n8 -> n9;
n9 [label="z = 3", shape=box];
n9 -> n29;
n29 [label="x", shape=box];
n29 -> n30;
n30 [label="CALL g(x)", shape=box, style=filled, color=orange];
n30 -> n11;
n11 [label="START g(x)", shape=box, style=filled, color=green];
n11 -> n13;
n13 [label="7", shape=box];
n13 -> n14;
n14 [label="x = 7", shape=box];
n14 -> n15;
n15 [label="y", shape=box];
n15 -> n16;
n16 [label="0", shape=box];
n16 -> n17;
n17 [label="(y > 0)", shape=box];
n17 -> n18;
n18 [label="<>", shape=diamond];
n18 -> n22 [label="T"];
n22 [label="y", shape=box];
n22 -> n23;
n23 [label="CALL g(y)", shape=box, style=filled, color=orange];
n23 -> n11;
n23 -> n25;
n25 [label="RET g(y)", shape=box, style=filled, color=orange];
n25 -> n28;
n28 [label="x", shape=box];
n28 -> n12;
n12 [label="END g(x)", shape=box, style=filled, color=green];
n12 -> n25;
n12 -> n32;
n32 [label="RET g(x)", shape=box, style=filled, color=orange];
n32 -> n33;
n33 [label="x", shape=box];
n33 -> n34;
n34 [label="(g(x) + x)", shape=box];
n34 -> n5;
n5 [label="END f(x, y, z)", shape=box, style=filled, color=green];
n5 -> n39;
n39 [label="RET f(2, 3)", shape=box, style=filled, color=orange];
n34 -> n5;
n18 -> n26 [label="F"];
n26 [label="8", shape=box];
n26 -> n27;
n27 [label="x = 8", shape=box];
n27 -> n28;
n30 -> n32;
n37 -> n39;
}

View File

@@ -1,11 +0,0 @@
let f(x,y,z) {
y=2;
z=3;
let g(x) {
x=7;
if (y>0)
then g(y)
else x=8;
x
} in g(x)+x
} in f(2,3)

View File

@@ -1,61 +0,0 @@
digraph G {
58 -> 57;
57 -> 61;
61 -> 1;
1 -> 4;
4 -> 7;
7 -> 10;
10 -> 12;
12 -> 14;
14 -> 17;
17 -> 20;
20 -> 34;
34 -> 22 [label="T"];
34 -> 32 [label="F"];
22 -> 25;
25 -> 28;
28 -> 30;
30 -> 37;
37 -> 40;
40 -> 43;
43 -> 55;
55 -> 45 [label="T"];
55 -> 2 [label="F"];
45 -> 48;
2 -> 60;
48 -> 51;
51 -> 53;
53 -> 37;
60 -> 59;
32 -> 37;
61 -> 60;
58 [label="58: None"];
57 [label="57: 3"];
61 [label="61: CALL f(3)", shape=box, style=filled, color=orange];
1 [label="1: START f(x)", shape=box, style=filled, color=green];
4 [label="4: 2"];
7 [label="7: x"];
10 [label="10: (2*x)"];
12 [label="12: x=(2*x)"];
14 [label="14: x"];
17 [label="17: 0"];
20 [label="20: (x>0)"];
34 [label="34: <>", shape=diamond];
22 [label="22: x"];
32 [label="32: x"];
25 [label="25: 1"];
28 [label="28: (x-1)"];
30 [label="30: x=(x-1)"];
37 [label="37: x"];
40 [label="40: 0"];
43 [label="43: (x>0)"];
55 [label="55: <>", shape=diamond];
45 [label="45: x"];
60 [label="60: RET f(3)", shape=box, style=filled, color=orange];
59 [label="59: None"];
48 [label="48: 1"];
51 [label="51: (x-1)"];
53 [label="53: x=(x-1)"];
2 [label="2: END f(x)", shape=box, style=filled, color=green];
}

View File

@@ -1,5 +0,0 @@
let f(x) { x=2*x;
if (x>0) then x=x-1 else x;
while (x>0) do { x=x-1 }
}
in f(3)

View File

@@ -5,4 +5,4 @@ let ggT(a, b) {
ggT(a-b, b) ggT(a-b, b)
else else
ggT(b-a, a) ggT(b-a, a)
} in ggT(3528, 3780) // result should be 252 } in ggT(2, 8)