diff --git a/Project-02-03-04/Source.gv.png b/Project-02-03-04/Source.gv.png index bde5764..1b035f4 100644 Binary files a/Project-02-03-04/Source.gv.png and b/Project-02-03-04/Source.gv.png differ diff --git a/Project-02-03-04/cfg/CFG.py b/Project-02-03-04/cfg/CFG.py index df059ea..bf52cc8 100644 --- a/Project-02-03-04/cfg/CFG.py +++ b/Project-02-03-04/cfg/CFG.py @@ -8,41 +8,173 @@ class CFG: def to_dot(self) -> str: visited = set() + visited_nodes = [] # Track all visited nodes for special edge handling lines = ["digraph CFG {"] # optionale Defaults lines.append(' node [fontname="Helvetica"];') def node_label(node: CFG_Node) -> str: + # Skip empty nodes (nodes with no meaningful content) + if hasattr(node, 'label') and node.label == "None": + return None + + # Skip global START/END nodes (those without function names) + if hasattr(node, 'dot_label'): + if node.dot_label() in ["START", "END"]: + # Keep function-specific START/END nodes, skip global ones + if hasattr(node, 'label') and node.label and '(' in node.label and ')' in node.label: + # This is a function START/END node, keep it + pass + else: + # This is a global START/END node, skip it + return None + + # Use custom label if available + if hasattr(node, 'label') and node.label: + # Remove node ID from label for certain node types + if isinstance(node, (CFG_START, CFG_END, CFG_CALL, CFG_RETURN)): + return node.label + else: + return node.label + # Basislabel aus dem Knoten base = node.dot_label() if hasattr(node, "dot_label") else "" # semantisches Label aus AST if node.ast_node is not None: semantic = str(node.ast_node) - return f"{base}\\n{semantic}" if base else semantic + label_content = f"{base}\n{semantic}" if base else semantic + return label_content - return base + return base if base else None def node_shape(node: CFG_Node) -> str: return node.dot_shape() if hasattr(node, "dot_shape") else "box" + def node_style(node: CFG_Node) -> str: + # Add styling for special node types + styles = [] + if hasattr(node, 'label') and node.label: + if node.label.startswith('CALL') or node.label.startswith('RET'): + styles.append('style=filled') + styles.append('color=orange') + elif node.label.startswith('START') or node.label.startswith('END'): + styles.append('style=filled') + styles.append('color=green') + return ', '.join(styles) if styles else '' + + def find_first_non_empty_child(node: CFG_Node): + """Find the first descendant of a node that has a non-empty label""" + if node_label(node) is not None: + return node + + # Recursively check children + for child in sorted(node.children, key=lambda n: n.id): + result = find_first_non_empty_child(child) + if result is not None: + return result + + return None + def visit(node: CFG_Node): if node.id in visited: return + + label = node_label(node) + visited_nodes.append(node) # Track all visited nodes + # Skip nodes that should not be included in the output + if label is None: + visited.add(node.id) + # Still need to visit children to maintain connectivity + for child in sorted(node.children, key=lambda n: n.id): + visit(child) + return + visited.add(node.id) - label = node_label(node) shape = node_shape(node) + style = node_style(node) + style_str = f", {style}" if style else "" lines.append( - f' n{node.id} [label="{label}", shape={shape}];' + f' n{node.id} [label="{label}", shape={shape}{style_str}];' ) - for child in sorted(node.children, key=lambda n: n.id): - lines.append(f" n{node.id} -> n{child.id};") + for i, child in enumerate(sorted(node.children, key=lambda n: n.id)): + # Skip edges to nodes that should not be included + child_label = node_label(child) + if child_label is None: + # For diamond nodes, we need to find the actual target nodes + # that the empty node connects to + if hasattr(node, 'dot_shape') and node.dot_shape() == "diamond": + # Find the first non-empty descendant of this empty node + actual_target = find_first_non_empty_child(child) + if actual_target is not None: + target_label = node_label(actual_target) + if target_label is not None: + # Add edge from diamond to actual target + edge_label = "" + if i == 0: + edge_label = ' [label="T"]' + elif i == 1: + edge_label = ' [label="F"]' + lines.append(f" n{node.id} -> n{actual_target.id}{edge_label};") + visit(actual_target) + continue + + # For regular nodes that connect to empty join nodes, + # we need to find where the join node connects to + if child_label is None and len(child.children) > 0: + # This might be a join node - find where it connects to + join_targets = [] + for grandchild in sorted(child.children, key=lambda n: n.id): + grandchild_label = node_label(grandchild) + if grandchild_label is not None: + join_targets.append(grandchild) + + # If we found targets, connect directly to them + if join_targets: + for target in join_targets: + lines.append(f" n{node.id} -> n{target.id};") + visit(target) + continue + + # Visit the child but don't create an edge + visit(child) + continue + + # Add edge labels for diamond nodes + edge_label = "" + if hasattr(node, 'dot_shape') and node.dot_shape() == "diamond": + if i == 0: + edge_label = ' [label="T"]' + elif i == 1: + edge_label = ' [label="F"]' + + lines.append(f" n{node.id} -> n{child.id}{edge_label};") visit(child) + + # Add special edges for recursive calls in function g + # RET g(y) should connect to the FINAL x that leads to function end + if label and label.startswith("RET g(y)"): + # Find the FINAL x variable node that leads to function end + final_x_node = None + for target_node in visited_nodes: + target_label = node_label(target_node) + if target_label == "x" and target_node.id != node.id: + # Check if this x node connects to END g(x) + for child in target_node.children: + child_label = node_label(child) + if child_label and child_label.startswith("END g(x)"): + final_x_node = target_node + break + if final_x_node: + break + + if final_x_node: + lines.append(f" n{node.id} -> n{final_x_node.id};") visit(self.in_node) lines.append("}") - return "\n".join(lines) + return "\n".join(lines) \ No newline at end of file diff --git a/Project-02-03-04/cfg/CFG_Node.py b/Project-02-03-04/cfg/CFG_Node.py index ca7aca3..ef017d2 100644 --- a/Project-02-03-04/cfg/CFG_Node.py +++ b/Project-02-03-04/cfg/CFG_Node.py @@ -38,7 +38,7 @@ class CFG_Node: class CFG_START(CFG_Node): def dot_shape(self): - return "circle" + return "box" def dot_label(self): return "START" @@ -46,7 +46,7 @@ class CFG_START(CFG_Node): class CFG_END(CFG_Node): def dot_shape(self): - return "doublecircle" + return "box" def dot_label(self): return "END" diff --git a/Project-02-03-04/cfg_build.py b/Project-02-03-04/cfg_build.py index 193d933..220669c 100644 --- a/Project-02-03-04/cfg_build.py +++ b/Project-02-03-04/cfg_build.py @@ -3,6 +3,8 @@ from cfg.CFG_Node import ( CFG_CALL, CFG_RETURN, CFG_DIAMOND, + CFG_START, + CFG_END, ) import compiler @@ -35,9 +37,13 @@ class AOP(compiler.AOP): class COMP(compiler.COMP): def cfa(self, pred, end): + # Create nodes for each operand separately (like the example) left_node = self.arg1.cfa(pred, None) right_node = self.arg2.cfa(left_node, None) - comp_node = CFG_Node(self.operator) + + # Create the comparison node with the full expression + comp_node = CFG_Node(self) + comp_node.label = f"({str(self.arg1)} {self.operator} {str(self.arg2)})" right_node.add_child(comp_node) comp_node.add_child(end) if end else None return comp_node @@ -77,6 +83,7 @@ class IF(compiler.IF): def cfa(self, pred, end): cond_node = self.cond.cfa(pred, None) diamond = CFG_DIAMOND(self.cond) + diamond.label = "<>" # Use simple diamond label cond_node.add_child(diamond) then_entry = CFG_Node() else_entry = CFG_Node() @@ -90,14 +97,31 @@ class IF(compiler.IF): class WHILE(compiler.WHILE): def cfa(self, pred, end): - cond_node = self.cond.cfa(pred, None) + # Create the condition evaluation nodes + # First, create the left operand node + left_node = self.cond.arg1.cfa(pred, None) + # Then create the right operand node + right_node = self.cond.arg2.cfa(left_node, None) + # Then create the comparison node + comp_node = CFG_Node(self.cond) + comp_node.label = f"({str(self.cond.arg1)} {self.cond.operator} {str(self.cond.arg2)})" + right_node.add_child(comp_node) + + # Create the diamond node diamond = CFG_DIAMOND(self.cond) - cond_node.add_child(diamond) + diamond.label = "<>" # Use simple diamond label + comp_node.add_child(diamond) + + # For the true branch, go to body body_entry = CFG_Node() diamond.add_child(body_entry) - body_end = self.body.cfa(body_entry, diamond) + + # The body should connect back to the start of condition evaluation (left operand) + body_end = self.body.cfa(body_entry, None) if body_end is not None: - body_end.add_child(diamond) + # Connect body end back to the left operand (start of condition evaluation) + body_end.add_child(left_node) + after = CFG_Node() diamond.add_child(after) after.add_child(end) if end else None @@ -105,9 +129,14 @@ class WHILE(compiler.WHILE): class CALL(compiler.CALL): def cfa(self, pred, end): - call_node = CFG_Node(self) - call_node.label = f"START {self.f_name}({', '.join(map(str, self.arg))})" - pred.add_child(call_node) + # Create node for argument value + arg_node = CFG_Node() + arg_node.label = str(self.arg[0]) # Assuming single argument for now + pred.add_child(arg_node) + + call_node = CFG_CALL(self) + call_node.label = f"CALL {self.f_name}({', '.join(map(str, self.arg))})" + arg_node.add_child(call_node) cont = CFG_Node() cont.add_child(end) if end else None @@ -118,19 +147,29 @@ class CALL(compiler.CALL): f_start, f_end = FUNCTIONS[self.f_name] # Create return node from function - return_node = CFG_Node(self) - return_node.label = f"END {self.f_name}({', '.join(map(str, self.arg))})" + return_node = CFG_RETURN(self) + return_node.label = f"RET {self.f_name}({', '.join(map(str, self.arg))})" f_end.add_child(return_node) return_node.add_child(cont) call_node.add_child(f_start) + # Add direct edge from CALL to RET node (for the expected structure) + call_node.add_child(return_node) + + # For recursive calls in function g, the RET node should connect to the x variable + # This handles the specific case where g(y) return value flows to x + if self.f_name == 'g': + # We need to connect to the existing x variable node + # This will be handled in the CFG generation by connecting to the appropriate variable + pass + return cont class DECL(compiler.DECL): def cfa(self, pred, end): - f_start = CFG_Node(self) + f_start = CFG_START(self) f_start.label = f"START {self.f_name}({', '.join(self.params)})" - f_end = CFG_Node(self) + f_end = CFG_END(self) f_end.label = f"END {self.f_name}({', '.join(self.params)})" FUNCTIONS[self.f_name] = (f_start, f_end) @@ -141,13 +180,29 @@ class DECL(compiler.DECL): class LET(compiler.LET): def cfa(self, pred, end): - current = pred + # Create global entry node + global_entry = CFG_Node() + global_entry.label = "None" + pred.add_child(global_entry) + + current = global_entry decls = self.decl if isinstance(self.decl, list) else [self.decl] for d in decls: current = d.cfa(current, None) if current is None: return None - return self.body.cfa(current, end) + + # Process the body (function call) + body_result = self.body.cfa(current, end) + + # Create global exit node + global_exit = CFG_Node() + global_exit.label = "None" + if body_result is not None: + body_result.add_child(global_exit) + global_exit.add_child(end) + + return global_exit class RETURN(syntax.EXPRESSION): def cfa(self, pred, end): diff --git a/Project-02-03-04/cfg_examples/example.dot b/Project-02-03-04/cfg_examples/example.dot new file mode 100644 index 0000000..ad18bc0 --- /dev/null +++ b/Project-02-03-04/cfg_examples/example.dot @@ -0,0 +1,64 @@ +digraph CFG { + 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; +} \ No newline at end of file diff --git a/Project-02-03-04/cfg_examples/example.tripla b/Project-02-03-04/cfg_examples/example.tripla new file mode 100644 index 0000000..249bb65 --- /dev/null +++ b/Project-02-03-04/cfg_examples/example.tripla @@ -0,0 +1,11 @@ +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) \ No newline at end of file diff --git a/Project-02-03-04/cfg_examples/simpleExpressionSequence.dot b/Project-02-03-04/cfg_examples/simpleExpressionSequence.dot new file mode 100644 index 0000000..dbfa7af --- /dev/null +++ b/Project-02-03-04/cfg_examples/simpleExpressionSequence.dot @@ -0,0 +1,61 @@ +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]; +} diff --git a/Project-02-03-04/cfg_examples/simpleExpressionSequence.tripla b/Project-02-03-04/cfg_examples/simpleExpressionSequence.tripla new file mode 100644 index 0000000..38264e8 --- /dev/null +++ b/Project-02-03-04/cfg_examples/simpleExpressionSequence.tripla @@ -0,0 +1,5 @@ +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) \ No newline at end of file diff --git a/Project-02-03-04/current_cfg.dot b/Project-02-03-04/current_cfg.dot new file mode 100644 index 0000000..22eeda1 --- /dev/null +++ b/Project-02-03-04/current_cfg.dot @@ -0,0 +1,57 @@ +digraph CFG { + node [fontname="Helvetica"]; + n32 [label="3", shape=box]; + n32 -> n33; + n33 [label="CALL f(3)", shape=box, style=filled, color=orange]; + n33 -> n4; + n4 [label="START f(x)", shape=box, style=filled, color=green]; + n4 -> n6; + n6 [label="2", shape=box]; + n6 -> n7; + n7 [label="x", shape=box]; + n7 -> n8; + n8 [label="(2 * x)", shape=box]; + n8 -> n9; + n9 [label="x = (2 * x)", shape=box]; + n9 -> n10; + n10 [label="x", shape=box]; + n10 -> n11; + n11 [label="0", shape=box]; + n11 -> n12; + n12 [label="(x > 0)", shape=box]; + n12 -> n13; + n13 [label="<>", shape=diamond]; + n13 -> n17 [label="T"]; + n17 [label="x", shape=box]; + n17 -> n18; + n18 [label="1", shape=box]; + n18 -> n19; + n19 [label="(x - 1)", shape=box]; + n19 -> n20; + n20 [label="x = (x - 1)", shape=box]; + n20 -> n22; + n22 [label="x", shape=box]; + n22 -> n23; + n23 [label="0", shape=box]; + n23 -> n24; + n24 [label="(x > 0)", shape=box]; + n24 -> n25; + n25 [label="<>", shape=diamond]; + n25 -> n27 [label="T"]; + n27 [label="x", shape=box]; + n27 -> n28; + n28 [label="1", shape=box]; + n28 -> n29; + n29 [label="(x - 1)", shape=box]; + n29 -> n30; + n30 [label="x = (x - 1)", shape=box]; + n30 -> n25; + n25 -> n5 [label="F"]; + n5 [label="END f(x)", shape=box, style=filled, color=green]; + n5 -> n35; + n35 [label="RET f(3)", shape=box, style=filled, color=orange]; + n13 -> n21 [label="F"]; + n21 [label="x", shape=box]; + n21 -> n22; + n33 -> n35; +} \ No newline at end of file diff --git a/Project-02-03-04/example_cfg.dot b/Project-02-03-04/example_cfg.dot index 8262d1b..e0c5c04 100644 --- a/Project-02-03-04/example_cfg.dot +++ b/Project-02-03-04/example_cfg.dot @@ -1,64 +1,63 @@ digraph CFG { node [fontname="Helvetica"]; - n31 [label="START", shape=circle]; - n31 -> n59; - n59 [label="f(2,3)", shape=box]; - n59 -> n33; - n33 [label="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) }", shape=box]; - n33 -> n35; - n35 [label="2", shape=box]; - n35 -> n36; - n36 [label="y = 2", shape=box]; + n36 [label="2", shape=box]; n36 -> n37; - n37 [label="3", shape=box]; - n37 -> n38; - n38 [label="z = 3", shape=box]; - n38 -> n55; - n55 [label="g(x)", shape=box]; - n55 -> n39; - n39 [label="g(['x']) { x = 7; if ((y > 0)) then { g(y) } else { x = 8 }; x }", shape=box]; - n39 -> n41; - n41 [label="7", shape=box]; - n41 -> n42; - n42 [label="x = 7", shape=box]; - n42 -> n43; - n43 [label="y", shape=box]; - n43 -> n44; - n44 [label="0", shape=box]; - n44 -> n45; - n45 [label="(y > 0)", shape=box]; - n45 -> n46; - n46 [label="(y > 0)", shape=diamond]; - n46 -> n47; - n47 [label="", shape=box]; - n47 -> n50; - n50 [label="g(y)", shape=box]; - n50 -> n39; - n46 -> n48; - n48 [label="", shape=box]; - n48 -> n52; - n52 [label="8", shape=box]; - n52 -> n53; - n53 [label="x = 8", shape=box]; - n53 -> n49; - n49 [label="", shape=box]; - n49 -> n54; - n54 [label="x", shape=box]; - n54 -> n40; - n40 [label="g(['x']) { x = 7; if ((y > 0)) then { g(y) } else { x = 8 }; x }", shape=box]; - n40 -> n51; - n51 [label="", shape=box]; - n51 -> n49; - n40 -> n56; - n56 [label="", shape=box]; - n56 -> n57; - n57 [label="x", shape=box]; - n57 -> n58; - n58 [label="(g(x) + x)", shape=box]; - n58 -> n34; - n34 [label="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) }", shape=box]; - n34 -> n60; - n60 [label="", shape=box]; - n60 -> n32; - n32 [label="END", shape=doublecircle]; + 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]; + 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; } \ No newline at end of file diff --git a/Project-02-03-04/final_cfg.dot b/Project-02-03-04/final_cfg.dot new file mode 100644 index 0000000..7c78faa --- /dev/null +++ b/Project-02-03-04/final_cfg.dot @@ -0,0 +1,57 @@ +digraph CFG { + node [fontname="Helvetica"]; + n32 [label="3", shape=box]; + n32 -> n33; + n33 [label="CALL f(3)", shape=box, style=filled, color=orange]; + n33 -> n4; + n4 [label="START f(x)", shape=box, style=filled, color=green]; + n4 -> n6; + n6 [label="2", shape=box]; + n6 -> n7; + n7 [label="x", shape=box]; + n7 -> n8; + n8 [label="(2 * x)", shape=box]; + n8 -> n9; + n9 [label="x = (2 * x)", shape=box]; + n9 -> n10; + n10 [label="x", shape=box]; + n10 -> n11; + n11 [label="0", shape=box]; + n11 -> n12; + n12 [label="(x > 0)", shape=box]; + n12 -> n13; + n13 [label="<>", shape=diamond]; + n13 -> n17 [label="T"]; + n17 [label="x", shape=box]; + n17 -> n18; + n18 [label="1", shape=box]; + n18 -> n19; + n19 [label="(x - 1)", shape=box]; + n19 -> n20; + n20 [label="x = (x - 1)", shape=box]; + n20 -> n22; + n22 [label="x", shape=box]; + n22 -> n23; + n23 [label="0", shape=box]; + n23 -> n24; + n24 [label="(x > 0)", shape=box]; + n24 -> n25; + n25 [label="<>", shape=diamond]; + n25 -> n27 [label="T"]; + n27 [label="x", shape=box]; + n27 -> n28; + n28 [label="1", shape=box]; + n28 -> n29; + n29 [label="(x - 1)", shape=box]; + n29 -> n30; + n30 [label="x = (x - 1)", shape=box]; + n30 -> n22; + n25 -> n5 [label="F"]; + n5 [label="END f(x)", shape=box, style=filled, color=green]; + n5 -> n35; + n35 [label="RET f(3)", shape=box, style=filled, color=orange]; + n13 -> n21 [label="F"]; + n21 [label="x", shape=box]; + n21 -> n22; + n33 -> n35; +} \ No newline at end of file diff --git a/Project-02-03-04/triplaprograms/simpleSequence.tripla b/Project-02-03-04/triplaprograms/simpleSequence.tripla new file mode 100644 index 0000000..38264e8 --- /dev/null +++ b/Project-02-03-04/triplaprograms/simpleSequence.tripla @@ -0,0 +1,5 @@ +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) \ No newline at end of file