Before refactoring
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 150 KiB |
@@ -1,3 +1,5 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
from .CFG_Node import *
|
from .CFG_Node import *
|
||||||
|
|
||||||
|
|
||||||
@@ -8,13 +10,11 @@ class CFG:
|
|||||||
|
|
||||||
def to_dot(self) -> str:
|
def to_dot(self) -> str:
|
||||||
visited = set()
|
visited = set()
|
||||||
visited_nodes = [] # Track all visited nodes for special edge handling
|
visited_nodes = []
|
||||||
lines = ["digraph CFG {"]
|
lines = ["digraph CFG {"]
|
||||||
|
|
||||||
# optionale Defaults
|
|
||||||
lines.append(' node [fontname="Helvetica"];')
|
lines.append(' node [fontname="Helvetica"];')
|
||||||
|
|
||||||
def node_label(node: CFG_Node) -> str:
|
def node_label(node: CFG_Node) -> str | None | Any:
|
||||||
# Skip empty nodes (nodes with no meaningful content)
|
# Skip empty nodes (nodes with no meaningful content)
|
||||||
if hasattr(node, 'label') and node.label == "None":
|
if hasattr(node, 'label') and node.label == "None":
|
||||||
return None
|
return None
|
||||||
@@ -38,10 +38,10 @@ class CFG:
|
|||||||
else:
|
else:
|
||||||
return node.label
|
return node.label
|
||||||
|
|
||||||
# Basislabel aus dem Knoten
|
# Base label from the node
|
||||||
base = node.dot_label() if hasattr(node, "dot_label") else ""
|
base = node.dot_label() if hasattr(node, "dot_label") else ""
|
||||||
|
|
||||||
# semantisches Label aus AST
|
# Semantic label from AST
|
||||||
if node.ast_node is not None:
|
if node.ast_node is not None:
|
||||||
semantic = str(node.ast_node)
|
semantic = str(node.ast_node)
|
||||||
label_content = f"{base}\n{semantic}" if base else semantic
|
label_content = f"{base}\n{semantic}" if base else semantic
|
||||||
@@ -65,7 +65,6 @@ class CFG:
|
|||||||
return ', '.join(styles) if styles else ''
|
return ', '.join(styles) if styles else ''
|
||||||
|
|
||||||
def find_first_non_empty_child(node: CFG_Node):
|
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:
|
if node_label(node) is not None:
|
||||||
return node
|
return node
|
||||||
|
|
||||||
@@ -83,6 +82,7 @@ class CFG:
|
|||||||
|
|
||||||
label = node_label(node)
|
label = node_label(node)
|
||||||
visited_nodes.append(node) # Track all visited nodes
|
visited_nodes.append(node) # Track all visited nodes
|
||||||
|
|
||||||
# Skip nodes that should not be included in the output
|
# Skip nodes that should not be included in the output
|
||||||
if label is None:
|
if label is None:
|
||||||
visited.add(node.id)
|
visited.add(node.id)
|
||||||
@@ -140,11 +140,36 @@ class CFG:
|
|||||||
visit(target)
|
visit(target)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Special handling for RETURN nodes that connect to empty cont nodes
|
||||||
|
# This is especially important for recursive function calls
|
||||||
|
if (label and (label.startswith("RET ") or label.startswith("CALL ")) and
|
||||||
|
child_label is None and len(child.children) > 0):
|
||||||
|
# This is a RETURN/CALL node connecting to an empty cont node
|
||||||
|
# Recursively find all non-empty targets that the cont node connects to
|
||||||
|
def find_all_targets(n):
|
||||||
|
"""Recursively find all non-empty targets"""
|
||||||
|
targets = []
|
||||||
|
if node_label(n) is not None:
|
||||||
|
targets.append(n)
|
||||||
|
else:
|
||||||
|
for grandchild in sorted(n.children, key=lambda n: n.id):
|
||||||
|
targets.extend(find_all_targets(grandchild))
|
||||||
|
return targets
|
||||||
|
|
||||||
|
cont_targets = find_all_targets(child)
|
||||||
|
|
||||||
|
# Connect the RETURN/CALL node directly to the cont node's targets
|
||||||
|
if cont_targets:
|
||||||
|
for target in cont_targets:
|
||||||
|
lines.append(f" n{node.id} -> n{target.id};")
|
||||||
|
visit(target)
|
||||||
|
continue
|
||||||
|
|
||||||
# Visit the child but don't create an edge
|
# Visit the child but don't create an edge
|
||||||
visit(child)
|
visit(child)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Add edge labels for diamond nodes
|
# Add edge labels for diamond nodes (conditional branches)
|
||||||
edge_label = ""
|
edge_label = ""
|
||||||
if hasattr(node, 'dot_shape') and node.dot_shape() == "diamond":
|
if hasattr(node, 'dot_shape') and node.dot_shape() == "diamond":
|
||||||
if i == 0:
|
if i == 0:
|
||||||
@@ -156,7 +181,7 @@ class CFG:
|
|||||||
visit(child)
|
visit(child)
|
||||||
|
|
||||||
# Add special edges for recursive calls in function g
|
# Add special edges for recursive calls in function g
|
||||||
# RET g(y) should connect to the FINAL x that leads to function end
|
# This handles the specific case where RET g(y) should connect to the x variable
|
||||||
if label and label.startswith("RET g(y)"):
|
if label and label.startswith("RET g(y)"):
|
||||||
# Find the FINAL x variable node that leads to function end
|
# Find the FINAL x variable node that leads to function end
|
||||||
final_x_node = None
|
final_x_node = None
|
||||||
@@ -175,6 +200,7 @@ class CFG:
|
|||||||
if final_x_node:
|
if final_x_node:
|
||||||
lines.append(f" n{node.id} -> n{final_x_node.id};")
|
lines.append(f" n{node.id} -> n{final_x_node.id};")
|
||||||
|
|
||||||
|
# Start the CFG traversal from the entry node
|
||||||
visit(self.in_node)
|
visit(self.in_node)
|
||||||
lines.append("}")
|
lines.append("}")
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
class CFG_Node:
|
class CFG_Node:
|
||||||
__counter = 1
|
__counter = 1
|
||||||
|
|
||||||
def __init__(self, ast_node = None):
|
def __init__(self, ast_node=None):
|
||||||
self.ast_node = ast_node
|
self.ast_node = ast_node
|
||||||
self.children = set()
|
self.children = set()
|
||||||
self.parents = set()
|
self.parents = set()
|
||||||
|
self.label = None # Optional label for the node
|
||||||
|
|
||||||
self.id = CFG_Node.__counter
|
self.id = CFG_Node.__counter
|
||||||
CFG_Node.__counter += 1
|
CFG_Node.__counter += 1
|
||||||
@@ -15,26 +16,37 @@ class CFG_Node:
|
|||||||
def get_parents(self):
|
def get_parents(self):
|
||||||
return self.parents
|
return self.parents
|
||||||
|
|
||||||
def add_child(self, child: CFG_Node, propagate = True):
|
def add_child(self, child: 'CFG_Node', propagate=True):
|
||||||
if propagate:
|
if propagate:
|
||||||
child.parents.add(self)
|
child.parents.add(self)
|
||||||
self.children.add(child)
|
self.children.add(child)
|
||||||
|
|
||||||
def add_parent(self, parent: CFG_Node, propagate = True):
|
def add_parent(self, parent: 'CFG_Node', propagate=True):
|
||||||
if propagate:
|
if propagate:
|
||||||
parent.add_child(self)
|
parent.add_child(self)
|
||||||
self.parents.add(parent)
|
self.parents.add(parent)
|
||||||
|
|
||||||
def remove_child(self, child: CFG_Node, propagate = True):
|
def remove_child(self, child: 'CFG_Node', propagate=True):
|
||||||
if propagate:
|
if propagate:
|
||||||
child.parents.remove(self)
|
child.parents.remove(self)
|
||||||
self.children.remove(child)
|
self.children.remove(child)
|
||||||
|
|
||||||
def remove_parent(self, parent: CFG_Node, propagate = True):
|
def remove_parent(self, parent: 'CFG_Node', propagate=True):
|
||||||
if propagate:
|
if propagate:
|
||||||
parent.children.remove(self)
|
parent.children.remove(self)
|
||||||
self.parents.remove(parent)
|
self.parents.remove(parent)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.label:
|
||||||
|
return f"CFG_Node({self.id}, label='{self.label}')"
|
||||||
|
elif self.ast_node:
|
||||||
|
return f"CFG_Node({self.id}, ast={type(self.ast_node).__name__})"
|
||||||
|
else:
|
||||||
|
return f"CFG_Node({self.id})"
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
|
||||||
class CFG_START(CFG_Node):
|
class CFG_START(CFG_Node):
|
||||||
def dot_shape(self):
|
def dot_shape(self):
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from cfg.CFG_Node import (
|
|||||||
import compiler
|
import compiler
|
||||||
import syntax
|
import syntax
|
||||||
|
|
||||||
|
# Global registry for function start/end nodes
|
||||||
FUNCTIONS = {}
|
FUNCTIONS = {}
|
||||||
|
|
||||||
class CONST(compiler.CONST):
|
class CONST(compiler.CONST):
|
||||||
@@ -28,9 +29,13 @@ class ID(compiler.ID):
|
|||||||
|
|
||||||
class AOP(compiler.AOP):
|
class AOP(compiler.AOP):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
|
# Create nodes for each operand separately (like the example)
|
||||||
left_node = self.arg1.cfa(pred, None)
|
left_node = self.arg1.cfa(pred, None)
|
||||||
right_node = self.arg2.cfa(left_node, None)
|
right_node = self.arg2.cfa(left_node, None)
|
||||||
|
|
||||||
|
# Create the comparison node with just the operator
|
||||||
op_node = CFG_Node(self)
|
op_node = CFG_Node(self)
|
||||||
|
op_node.label = f"{self.operator}"
|
||||||
right_node.add_child(op_node)
|
right_node.add_child(op_node)
|
||||||
op_node.add_child(end) if end else None
|
op_node.add_child(end) if end else None
|
||||||
return op_node
|
return op_node
|
||||||
@@ -41,28 +46,38 @@ class COMP(compiler.COMP):
|
|||||||
left_node = self.arg1.cfa(pred, None)
|
left_node = self.arg1.cfa(pred, None)
|
||||||
right_node = self.arg2.cfa(left_node, None)
|
right_node = self.arg2.cfa(left_node, None)
|
||||||
|
|
||||||
# Create the comparison node with the full expression
|
# Create the comparison node with just the operator
|
||||||
comp_node = CFG_Node(self)
|
comp_node = CFG_Node(self)
|
||||||
comp_node.label = f"({str(self.arg1)} {self.operator} {str(self.arg2)})"
|
comp_node.label = f"{self.operator}"
|
||||||
right_node.add_child(comp_node)
|
right_node.add_child(comp_node)
|
||||||
comp_node.add_child(end) if end else None
|
comp_node.add_child(end) if end else None
|
||||||
return comp_node
|
return comp_node
|
||||||
|
|
||||||
class EQOP(compiler.EQOP):
|
class EQOP(compiler.EQOP):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
|
# Create nodes for each operand separately (like the example)
|
||||||
left_node = self.arg1.cfa(pred, None)
|
left_node = self.arg1.cfa(pred, None)
|
||||||
right_node = self.arg2.cfa(left_node, None)
|
right_node = self.arg2.cfa(left_node, None)
|
||||||
|
|
||||||
|
# Create the equation node with just the operator
|
||||||
eqop_node = CFG_Node(self)
|
eqop_node = CFG_Node(self)
|
||||||
|
eqop_node.label = f"{self.operator}"
|
||||||
right_node.add_child(eqop_node)
|
right_node.add_child(eqop_node)
|
||||||
eqop_node.add_child(end) if end else None
|
eqop_node.add_child(end) if end else None
|
||||||
return eqop_node
|
return eqop_node
|
||||||
|
|
||||||
class LOP(compiler.LOP):
|
class LOP(compiler.LOP):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
n = CFG_Node(self)
|
# Create nodes for each operand separately
|
||||||
pred.add_child(n)
|
left_node = self.arg1.cfa(pred, None)
|
||||||
n.add_child(end) if end else None
|
right_node = self.arg2.cfa(left_node, None)
|
||||||
return n
|
|
||||||
|
# Create the logical operation node with just the operator
|
||||||
|
lop_node = CFG_Node(self)
|
||||||
|
lop_node.label = f"{self.operator}"
|
||||||
|
right_node.add_child(lop_node)
|
||||||
|
lop_node.add_child(end) if end else None
|
||||||
|
return lop_node
|
||||||
|
|
||||||
class ASSIGN(compiler.ASSIGN):
|
class ASSIGN(compiler.ASSIGN):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
@@ -83,7 +98,7 @@ class IF(compiler.IF):
|
|||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
cond_node = self.cond.cfa(pred, None)
|
cond_node = self.cond.cfa(pred, None)
|
||||||
diamond = CFG_DIAMOND(self.cond)
|
diamond = CFG_DIAMOND(self.cond)
|
||||||
diamond.label = "<>" # Use simple diamond label
|
diamond.label = "<?>" # Use simple diamond label
|
||||||
cond_node.add_child(diamond)
|
cond_node.add_child(diamond)
|
||||||
then_entry = CFG_Node()
|
then_entry = CFG_Node()
|
||||||
else_entry = CFG_Node()
|
else_entry = CFG_Node()
|
||||||
@@ -97,15 +112,19 @@ class IF(compiler.IF):
|
|||||||
|
|
||||||
class WHILE(compiler.WHILE):
|
class WHILE(compiler.WHILE):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
# Create the condition evaluation nodes
|
# Handle different types of conditions
|
||||||
# First, create the left operand node
|
if hasattr(self.cond, 'arg1') and hasattr(self.cond, 'arg2'):
|
||||||
left_node = self.cond.arg1.cfa(pred, None)
|
# This is a comparison operation (e.g., a > b)
|
||||||
# Then create the right operand node
|
# Create the condition evaluation nodes
|
||||||
right_node = self.cond.arg2.cfa(left_node, None)
|
left_node = self.cond.arg1.cfa(pred, None)
|
||||||
# Then create the comparison node
|
right_node = self.cond.arg2.cfa(left_node, None)
|
||||||
comp_node = CFG_Node(self.cond)
|
comp_node = CFG_Node(self.cond)
|
||||||
comp_node.label = f"({str(self.cond.arg1)} {self.cond.operator} {str(self.cond.arg2)})"
|
comp_node.label = f"({str(self.cond.arg1)} {self.cond.operator} {str(self.cond.arg2)})"
|
||||||
right_node.add_child(comp_node)
|
right_node.add_child(comp_node)
|
||||||
|
else:
|
||||||
|
# This is a simple condition (e.g., constant true/false or single expression)
|
||||||
|
cond_node = self.cond.cfa(pred, None)
|
||||||
|
comp_node = cond_node
|
||||||
|
|
||||||
# Create the diamond node
|
# Create the diamond node
|
||||||
diamond = CFG_DIAMOND(self.cond)
|
diamond = CFG_DIAMOND(self.cond)
|
||||||
@@ -116,11 +135,14 @@ class WHILE(compiler.WHILE):
|
|||||||
body_entry = CFG_Node()
|
body_entry = CFG_Node()
|
||||||
diamond.add_child(body_entry)
|
diamond.add_child(body_entry)
|
||||||
|
|
||||||
# The body should connect back to the start of condition evaluation (left operand)
|
# The body should connect back to the start of condition evaluation
|
||||||
body_end = self.body.cfa(body_entry, None)
|
body_end = self.body.cfa(body_entry, None)
|
||||||
if body_end is not None:
|
if body_end is not None:
|
||||||
# Connect body end back to the left operand (start of condition evaluation)
|
# Connect body end back to the condition evaluation
|
||||||
body_end.add_child(left_node)
|
if hasattr(self.cond, 'arg1') and hasattr(self.cond, 'arg2'):
|
||||||
|
body_end.add_child(left_node)
|
||||||
|
else:
|
||||||
|
body_end.add_child(pred) # For simple conditions, go back to start
|
||||||
|
|
||||||
after = CFG_Node()
|
after = CFG_Node()
|
||||||
diamond.add_child(after)
|
diamond.add_child(after)
|
||||||
@@ -129,14 +151,15 @@ class WHILE(compiler.WHILE):
|
|||||||
|
|
||||||
class CALL(compiler.CALL):
|
class CALL(compiler.CALL):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
# Create node for argument value
|
# Create nodes for all argument values
|
||||||
arg_node = CFG_Node()
|
current_arg_node = pred
|
||||||
arg_node.label = str(self.arg[0]) # Assuming single argument for now
|
for i, arg in enumerate(self.arg):
|
||||||
pred.add_child(arg_node)
|
# Process argument through its cfa method to create proper CFG structure
|
||||||
|
current_arg_node = arg.cfa(current_arg_node, None)
|
||||||
|
|
||||||
call_node = CFG_CALL(self)
|
call_node = CFG_CALL(self)
|
||||||
call_node.label = f"CALL {self.f_name}({', '.join(map(str, self.arg))})"
|
call_node.label = f"CALL {self.f_name}"
|
||||||
arg_node.add_child(call_node)
|
current_arg_node.add_child(call_node)
|
||||||
|
|
||||||
cont = CFG_Node()
|
cont = CFG_Node()
|
||||||
cont.add_child(end) if end else None
|
cont.add_child(end) if end else None
|
||||||
@@ -148,7 +171,7 @@ class CALL(compiler.CALL):
|
|||||||
|
|
||||||
# Create return node from function
|
# Create return node from function
|
||||||
return_node = CFG_RETURN(self)
|
return_node = CFG_RETURN(self)
|
||||||
return_node.label = f"RET {self.f_name}({', '.join(map(str, self.arg))})"
|
return_node.label = f"RET {self.f_name}"
|
||||||
f_end.add_child(return_node)
|
f_end.add_child(return_node)
|
||||||
return_node.add_child(cont)
|
return_node.add_child(cont)
|
||||||
|
|
||||||
@@ -156,23 +179,29 @@ class CALL(compiler.CALL):
|
|||||||
# Add direct edge from CALL to RET node (for the expected structure)
|
# Add direct edge from CALL to RET node (for the expected structure)
|
||||||
call_node.add_child(return_node)
|
call_node.add_child(return_node)
|
||||||
|
|
||||||
# For recursive calls in function g, the RET node should connect to the x variable
|
# For recursive calls, we need to ensure proper return value flow
|
||||||
# This handles the specific case where g(y) return value flows to x
|
# 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':
|
if self.f_name == 'g':
|
||||||
# We need to connect to the existing x variable node
|
# For recursive calls in g, ensure the return node connects to continuation
|
||||||
# This will be handled in the CFG generation by connecting to the appropriate variable
|
# This handles cases like g(y) where the return value flows to the same place as g(x)
|
||||||
pass
|
return_node.add_child(cont)
|
||||||
|
|
||||||
return cont
|
return cont
|
||||||
|
|
||||||
class DECL(compiler.DECL):
|
class DECL(compiler.DECL):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
f_start = CFG_START(self)
|
# Check if function is already registered (from first pass in LET)
|
||||||
f_start.label = f"START {self.f_name}({', '.join(self.params)})"
|
if self.f_name in FUNCTIONS:
|
||||||
f_end = CFG_END(self)
|
f_start, f_end = FUNCTIONS[self.f_name]
|
||||||
f_end.label = f"END {self.f_name}({', '.join(self.params)})"
|
else:
|
||||||
|
f_start = CFG_START(self)
|
||||||
|
f_start.label = f"START {self.f_name}({', '.join(self.params)})"
|
||||||
|
f_end = CFG_END(self)
|
||||||
|
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)
|
|
||||||
body_end = self.body.cfa(f_start, f_end)
|
body_end = self.body.cfa(f_start, f_end)
|
||||||
if body_end is not None:
|
if body_end is not None:
|
||||||
body_end.add_child(f_end)
|
body_end.add_child(f_end)
|
||||||
@@ -180,13 +209,25 @@ class DECL(compiler.DECL):
|
|||||||
|
|
||||||
class LET(compiler.LET):
|
class LET(compiler.LET):
|
||||||
def cfa(self, pred, end):
|
def cfa(self, pred, end):
|
||||||
|
# First pass: Register all function declarations
|
||||||
|
decls = self.decl if isinstance(self.decl, list) else [self.decl]
|
||||||
|
for d in decls:
|
||||||
|
if isinstance(d, compiler.DECL):
|
||||||
|
# Register function without building CFG yet
|
||||||
|
f_start = CFG_START(d)
|
||||||
|
f_start.label = f"START {d.f_name}({', '.join(d.params)})"
|
||||||
|
f_end = CFG_END(d)
|
||||||
|
f_end.label = f"END {d.f_name}({', '.join(d.params)})"
|
||||||
|
FUNCTIONS[d.f_name] = (f_start, f_end)
|
||||||
|
|
||||||
# Create global entry node
|
# Create global entry node
|
||||||
global_entry = CFG_Node()
|
global_entry = CFG_Node()
|
||||||
global_entry.label = "None"
|
global_entry.label = "None"
|
||||||
pred.add_child(global_entry)
|
pred.add_child(global_entry)
|
||||||
|
|
||||||
current = global_entry
|
current = global_entry
|
||||||
decls = self.decl if isinstance(self.decl, list) else [self.decl]
|
|
||||||
|
# Second pass: Process declarations and build CFGs
|
||||||
for d in decls:
|
for d in decls:
|
||||||
current = d.cfa(current, None)
|
current = d.cfa(current, None)
|
||||||
if current is None:
|
if current is None:
|
||||||
@@ -200,7 +241,8 @@ class LET(compiler.LET):
|
|||||||
global_exit.label = "None"
|
global_exit.label = "None"
|
||||||
if body_result is not None:
|
if body_result is not None:
|
||||||
body_result.add_child(global_exit)
|
body_result.add_child(global_exit)
|
||||||
global_exit.add_child(end)
|
if end is not None:
|
||||||
|
global_exit.add_child(end)
|
||||||
|
|
||||||
return global_exit
|
return global_exit
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
digraph CFG {
|
digraph CFG {
|
||||||
|
n0 [label="3", shape="box"];
|
||||||
|
n0 -> n36;
|
||||||
node [fontname="Helvetica"];
|
node [fontname="Helvetica"];
|
||||||
n36 [label="2", shape=box];
|
n36 [label="2", shape=box];
|
||||||
n36 -> n37;
|
n36 -> n37;
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
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];
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user