# 控制流程图

> 原文： [https://www.fuzzingbook.org/html/ControlFlow.html](https://www.fuzzingbook.org/html/ControlFlow.html)

本笔记本中的代码有助于获取python函数的控制流程图。

**前提条件**

*   该笔记本需要对Python的高级概念有一些了解，特别是
    *   类

## 控制流程图

`PyCFG`类允许获得控制流程图。

```py
from [ControlFlow](ControlFlow.html) import gen_cfg, to_graph
from [graphviz](https://docs.python.org/3/library/graphviz.html) import Source
cfg = gen_cfg(inspect.getsource(my_function))
graph = to_graph(cfg)
Source(graph)

```

```py
import [fuzzingbook_utils](https://github.com/uds-se/fuzzingbook/tree/master/notebooks/fuzzingbook_utils)

```

```py
import [ast](https://docs.python.org/3/library/ast.html)
import [re](https://docs.python.org/3/library/re.html)
import [astor](https://docs.python.org/3/library/astor.html)
from [graphviz](https://docs.python.org/3/library/graphviz.html) import Source, Graph, Digraph

```

### 注册表

```py
REGISTRY_IDX = 0

```

```py
REGISTRY = {}

```

```py
def get_registry_idx():
    global REGISTRY_IDX
    v = REGISTRY_IDX
    REGISTRY_IDX += 1
    return v

```

```py
def reset_registry():
    global REGISTRY_IDX
    global REGISTRY
    REGISTRY_IDX = 0
    REGISTRY = {}

```

```py
def register_node(node):
    node.rid = get_registry_idx()
    REGISTRY[node.rid] = node

```

```py
def get_registry():
    return dict(REGISTRY)

```

### CFGNode

我们从代表控制流程图中每个节点的`CFGNode`开始。 \ todo {扩展和注释的分配（`a += 1`），（`a:int = 1`）}。

```py
class CFGNode(dict):
    def __init__(self, parents=[], ast=None):
        assert type(parents) is list
        register_node(self)
        self.parents = parents
        self.ast_node = ast
        self.update_children(parents)  # requires self.rid
        self.children = []
        self.calls = []

    def i(self):
        return str(self.rid)

    def update_children(self, parents):
        for p in parents:
            p.add_child(self)

    def add_child(self, c):
        if c not in self.children:
            self.children.append(c)

    def lineno(self):
        return self.ast_node.lineno if hasattr(self.ast_node, 'lineno') else 0

    def __str__(self):
        return "id:%d line[%d] parents: %s : %s" % (
            self.rid, self.lineno(), str([p.rid for p in self.parents]),
            self.source())

    def __repr__(self):
        return str(self)

    def __eq__(self, other):
        return self.rid == other.rid

    def __neq__(self, other):
        return self.rid != other.rid

    def set_parents(self, p):
        self.parents = p

    def add_parent(self, p):
        if p not in self.parents:
            self.parents.append(p)

    def add_parents(self, ps):
        for p in ps:
            self.add_parent(p)

    def add_calls(self, func):
        self.calls.append(func)

    def source(self):
        return astor.to_source(self.ast_node).strip()

    def to_json(self):
        return {
            'id': self.rid,
            'parents': [p.rid for p in self.parents],
            'children': [c.rid for c in self.children],
            'calls': self.calls,
            'at': self.lineno(),
            'ast': self.source()
        }

```

```py
REGISTRY_IDX = 0

```

```py
REGISTRY = {}

```

```py
def get_registry_idx():
    global REGISTRY_IDX
    v = REGISTRY_IDX
    REGISTRY_IDX += 1
    return v

```

```py
def reset_registry():
    global REGISTRY_IDX
    global REGISTRY
    REGISTRY_IDX = 0
    REGISTRY = {}

```

```py
def register_node(node):
    node.rid = get_registry_idx()
    REGISTRY[node.rid] = node

```

### PyCFG

接下来，负责分析并保存图形的`PyCFG`类。

```py
class PyCFG:
    def __init__(self):
        self.founder = CFGNode(
            parents=[], ast=ast.parse('start').body[0])  # sentinel
        self.founder.ast_node.lineno = 0
        self.functions = {}
        self.functions_node = {}

```

```py
class PyCFG(PyCFG):
    def parse(self, src):
        return ast.parse(src)

```

```py
class PyCFG(PyCFG):
    def walk(self, node, myparents):
        fname = "on_%s" % node.__class__.__name__.lower()
        if hasattr(self, fname):
            fn = getattr(self, fname)
            v = fn(node, myparents)
            return v
        else:
            return myparents

```

```py
class PyCFG(PyCFG):
    def on_module(self, node, myparents):
        """
 Module(stmt* body)
 """
        # each time a statement is executed unconditionally, make a link from
        # the result to next statement
        p = myparents
        for n in node.body:
            p = self.walk(n, p)
        return p

```

```py
class PyCFG(PyCFG):
    def on_augassign(self, node, myparents):
        """
 AugAssign(expr target, operator op, expr value)
 """
        p = [CFGNode(parents=myparents, ast=node)]
        p = self.walk(node.value, p)

        return p

```

```py
class PyCFG(PyCFG):
    def on_annassign(self, node, myparents):
        """
 AnnAssign(expr target, expr annotation, expr? value, int simple)
 """
        p = [CFGNode(parents=myparents, ast=node)]
        p = self.walk(node.value, p)

        return p

```

```py
class PyCFG(PyCFG):
    def on_assign(self, node, myparents):
        """
 Assign(expr* targets, expr value)
 """
        if len(node.targets) > 1:
            raise NotImplemented('Parallel assignments')

        p = [CFGNode(parents=myparents, ast=node)]
        p = self.walk(node.value, p)

        return p

```

```py
class PyCFG(PyCFG):
    def on_pass(self, node, myparents):
        return [CFGNode(parents=myparents, ast=node)]

```

```py
class PyCFG(PyCFG):
    def on_break(self, node, myparents):
        parent = myparents[0]
        while not hasattr(parent, 'exit_nodes'):
            # we have ordered parents
            parent = parent.parents[0]

        assert hasattr(parent, 'exit_nodes')
        p = CFGNode(parents=myparents, ast=node)

        # make the break one of the parents of label node.
        parent.exit_nodes.append(p)

        # break doesn't have immediate children
        return []

```

```py
class PyCFG(PyCFG):
    def on_continue(self, node, myparents):
        parent = myparents[0]
        while not hasattr(parent, 'exit_nodes'):
            # we have ordered parents
            parent = parent.parents[0]
        assert hasattr(parent, 'exit_nodes')
        p = CFGNode(parents=myparents, ast=node)

        # make continue one of the parents of the original test node.
        parent.add_parent(p)

        # return the parent because a continue is not the parent
        # for the just next node
        return []

```

```py
class PyCFG(PyCFG):
    def on_for(self, node, myparents):
        # node.target in node.iter: node.body
        # The For loop in python (no else) can be translated
        # as follows:
        # 
        # for a in iterator:
        #      mystatements
        #
        # __iv = iter(iterator)
        # while __iv.__length_hint() > 0:
        #     a = next(__iv)
        #     mystatements

        init_node = CFGNode(parents=myparents,
            ast=ast.parse('__iv = iter(%s)' % astor.to_source(node.iter).strip()).body[0])
        ast.copy_location(init_node.ast_node, node.iter)

        _test_node = CFGNode(
            parents=[init_node],
            ast=ast.parse('_for: __iv.__length__hint__() > 0').body[0])
        ast.copy_location(_test_node.ast_node, node)

        # we attach the label node here so that break can find it.
        _test_node.exit_nodes = []
        test_node = self.walk(node.iter, [_test_node])

        extract_node = CFGNode(parents=test_node,
            ast=ast.parse('%s = next(__iv)' % astor.to_source(node.target).strip()).body[0])
        ast.copy_location(extract_node.ast_node, node.iter)

        # now we evaluate the body, one at a time.
        p1 = [extract_node]
        for n in node.body:
            p1 = self.walk(n, p1)

        # the test node is looped back at the end of processing.
        _test_node.add_parents(p1)

        return _test_node.exit_nodes + test_node

```

```py
class PyCFG(PyCFG):
    def on_while(self, node, myparents):
        # For a while, the earliest parent is the node.test
        _test_node = CFGNode(
            parents=myparents,
            ast=ast.parse(
                '_while: %s' % astor.to_source(node.test).strip()).body[0])
        ast.copy_location(_test_node.ast_node, node.test)
        _test_node.exit_nodes = []
        test_node = self.walk(node.test, [_test_node])

        # we attach the label node here so that break can find it.

        # now we evaluate the body, one at a time.
        assert len(test_node) == 1
        p1 = test_node
        for n in node.body:
            p1 = self.walk(n, p1)

        # the test node is looped back at the end of processing.
        _test_node.add_parents(p1)

        # link label node back to the condition.
        return _test_node.exit_nodes + test_node

```

```py
class PyCFG(PyCFG):
    def on_if(self, node, myparents):
        _test_node = CFGNode(
            parents=myparents,
            ast=ast.parse(
                '_if: %s' % astor.to_source(node.test).strip()).body[0])
        ast.copy_location(_test_node.ast_node, node.test)
        test_node = self.walk(node.test, [ _test_node])
        assert len(test_node) == 1
        g1 = test_node
        for n in node.body:
            g1 = self.walk(n, g1)
        g2 = test_node
        for n in node.orelse:
            g2 = self.walk(n, g2)
        return g1 + g2

```

```py
class PyCFG(PyCFG):
    def on_binop(self, node, myparents):
        left = self.walk(node.left, myparents)
        right = self.walk(node.right, left)
        return right

```

```py
class PyCFG(PyCFG):
    def on_compare(self, node, myparents):
        left = self.walk(node.left, myparents)
        right = self.walk(node.comparators[0], left)
        return right

```

```py
class PyCFG(PyCFG):
    def on_unaryop(self, node, myparents):
        return self.walk(node.operand, myparents)

```

```py
class PyCFG(PyCFG):
    def on_call(self, node, myparents):
        def get_func(node):
            if type(node.func) is ast.Name:
                mid = node.func.id
            elif type(node.func) is ast.Attribute:
                mid = node.func.attr
            elif type(node.func) is ast.Call:
                mid = get_func(node.func)
            else:
                raise Exception(str(type(node.func)))
            return mid
            #mid = node.func.value.id

        p = myparents
        for a in node.args:
            p = self.walk(a, p)
        mid = get_func(node)
        myparents[0].add_calls(mid)

        # these need to be unlinked later if our module actually defines these
        # functions. Otherwsise we may leave them around.
        # during a call, the direct child is not the next
        # statement in text.
        for c in p:
            c.calllink = 0
        return p

```

```py
class PyCFG(PyCFG):
    def on_expr(self, node, myparents):
        p = [CFGNode(parents=myparents, ast=node)]
        return self.walk(node.value, p)

```

```py
class PyCFG(PyCFG):
    def on_return(self, node, myparents):
        if type(myparents) is tuple:
            parent = myparents[0][0]
        else:
            parent = myparents[0]

        val_node = self.walk(node.value, myparents)
        # on return look back to the function definition.
        while not hasattr(parent, 'return_nodes'):
            parent = parent.parents[0]
        assert hasattr(parent, 'return_nodes')

        p = CFGNode(parents=val_node, ast=node)

        # make the break one of the parents of label node.
        parent.return_nodes.append(p)

        # return doesnt have immediate children
        return []

```

```py
class PyCFG(PyCFG):
    def on_functiondef(self, node, myparents):
        # a function definition does not actually continue the thread of
        # control flow
        # name, args, body, decorator_list, returns
        fname = node.name
        args = node.args
        returns = node.returns

        enter_node = CFGNode(
            parents=[],
            ast=ast.parse('enter: %s(%s)' % (node.name, ', '.join(
                [a.arg for a in node.args.args]))).body[0])  # sentinel
        enter_node.calleelink = True
        ast.copy_location(enter_node.ast_node, node)
        exit_node = CFGNode(
            parents=[],
            ast=ast.parse('exit: %s(%s)' % (node.name, ', '.join(
                [a.arg for a in node.args.args]))).body[0])  # sentinel
        exit_node.fn_exit_node = True
        ast.copy_location(exit_node.ast_node, node)
        enter_node.return_nodes = []  # sentinel

        p = [enter_node]
        for n in node.body:
            p = self.walk(n, p)

        for n in p:
            if n not in enter_node.return_nodes:
                enter_node.return_nodes.append(n)

        for n in enter_node.return_nodes:
            exit_node.add_parent(n)

        self.functions[fname] = [enter_node, exit_node]
        self.functions_node[enter_node.lineno()] = fname

        return myparents

```

```py
class PyCFG(PyCFG):
    def get_defining_function(self, node):
        if node.lineno() in self.functions_node:
            return self.functions_node[node.lineno()]
        if not node.parents:
            self.functions_node[node.lineno()] = ''
            return ''
        val = self.get_defining_function(node.parents[0])
        self.functions_node[node.lineno()] = val
        return val

```

```py
class PyCFG(PyCFG):
    def link_functions(self):
        for nid, node in REGISTRY.items():
            if node.calls:
                for calls in node.calls:
                    if calls in self.functions:
                        enter, exit = self.functions[calls]
                        enter.add_parent(node)
                        if node.children:
                            # # until we link the functions up, the node
                            # # should only have succeeding node in text as
                            # # children.
                            # assert(len(node.children) == 1)
                            # passn = node.children[0]
                            # # We require a single pass statement after every
                            # # call (which means no complex expressions)
                            # assert(type(passn.ast_node) == ast.Pass)

                            # # unlink the call statement
                            assert node.calllink > -1
                            node.calllink += 1
                            for i in node.children:
                                i.add_parent(exit)
                            # passn.set_parents([exit])
                            # ast.copy_location(exit.ast_node, passn.ast_node)

                            # #for c in passn.children: c.add_parent(exit)
                            # #passn.ast_node = exit.ast_node

```

```py
class PyCFG(PyCFG):
    def update_functions(self):
        for nid, node in REGISTRY.items():
            _n = self.get_defining_function(node)

```

```py
class PyCFG(PyCFG):
    def update_children(self):
        for nid, node in REGISTRY.items():
            for p in node.parents:
                p.add_child(node)

```

```py
class PyCFG(PyCFG):
    def gen_cfg(self, src):
        """
 >>> i = PyCFG()
 >>> i.walk("100")
 5
 """
        node = self.parse(src)
        nodes = self.walk(node, [self.founder])
        self.last_node = CFGNode(parents=nodes, ast=ast.parse('stop').body[0])
        ast.copy_location(self.last_node.ast_node, self.founder.ast_node)
        self.update_children()
        self.update_functions()
        self.link_functions()

```

### 支持功能

```py
def compute_dominator(cfg, start=0, key='parents'):
    dominator = {}
    dominator[start] = {start}
    all_nodes = set(cfg.keys())
    rem_nodes = all_nodes - {start}
    for n in rem_nodes:
        dominator[n] = all_nodes

    c = True
    while c:
        c = False
        for n in rem_nodes:
            pred_n = cfg[n][key]
            doms = [dominator[p] for p in pred_n]
            i = set.intersection(*doms) if doms else set()
            v = {n} | i
            if dominator[n] != v:
                c = True
            dominator[n] = v
    return dominator

```

```py
def compute_flow(pythonfile):
    cfg, first, last = get_cfg(pythonfile)
    return cfg, compute_dominator(
        cfg, start=first), compute_dominator(
            cfg, start=last, key='children')

```

```py
def gen_cfg(fnsrc, remove_start_stop=True):
    reset_registry()
    cfg = PyCFG()
    cfg.gen_cfg(fnsrc)
    cache = dict(REGISTRY)
    if remove_start_stop:
        return {
            k: cache[k]
            for k in cache if cache[k].source() not in {'start', 'stop'}
        }
    else:
        return cache

```

```py
def get_cfg(src):
    reset_registry()
    cfg = PyCFG()
    cfg.gen_cfg(src)
    cache = dict(REGISTRY)
    g = {}
    for k, v in cache.items():
        j = v.to_json()
        at = j['at']
        parents_at = [cache[p].to_json()['at'] for p in j['parents']]
        children_at = [cache[c].to_json()['at'] for c in j['children']]
        if at not in g:
            g[at] = {'parents': set(), 'children': set()}
        # remove dummy nodes
        ps = set([p for p in parents_at if p != at])
        cs = set([c for c in children_at if c != at])
        g[at]['parents'] |= ps
        g[at]['children'] |= cs
        if v.calls:
            g[at]['calls'] = v.calls
        g[at]['function'] = cfg.functions_node[v.lineno()]
    return (g, cfg.founder.ast_node.lineno, cfg.last_node.ast_node.lineno)

```

```py
def to_graph(cache, arcs=[]):
    graph = Digraph(comment='Control Flow Graph')
    colors = {0: 'blue', 1: 'red'}
    kind = {0: 'T', 1: 'F'}
    cov_lines = set(i for i, j in arcs)
    for nid, cnode in cache.items():
        lineno = cnode.lineno()
        shape, peripheries = 'oval', '1'
        if isinstance(cnode.ast_node, ast.AnnAssign):
            if cnode.ast_node.target.id in {'_if', '_for', '_while'}:
                shape = 'diamond'
            elif cnode.ast_node.target.id in {'enter', 'exit'}:
                shape, peripheries = 'oval', '2'
        else:
            shape = 'rectangle'
        graph.node(cnode.i(), "%d: %s" % (lineno, unhack(cnode.source())), shape=shape, peripheries=peripheries)
        for pn in cnode.parents:
            plineno = pn.lineno()
            if hasattr(pn, 'calllink') and pn.calllink > 0 and not hasattr(
                    cnode, 'calleelink'):
                graph.edge(pn.i(), cnode.i(), style='dotted', weight=100)
                continue

            if arcs:
                if (plineno, lineno) in arcs:
                    graph.edge(pn.i(), cnode.i(), color='green')
                elif plineno == lineno and lineno in cov_lines:
                    graph.edge(pn.i(), cnode.i(), color='green')
                # child is exit and parent is covered
                elif hasattr(cnode, 'fn_exit_node') and plineno in cov_lines:
                    graph.edge(pn.i(), cnode.i(), color='green')
                # parent is exit and one of its parents is covered.
                elif hasattr(pn, 'fn_exit_node') and len(
                        set(n.lineno() for n in pn.parents) | cov_lines) > 0:
                    graph.edge(pn.i(), cnode.i(), color='green')
                # child is a callee (has calleelink) and one of the parents is covered.
                elif plineno in cov_lines and hasattr(cnode, 'calleelink'):
                    graph.edge(pn.i(), cnode.i(), color='green')
                else:
                    graph.edge(pn.i(), cnode.i(), color='red')
            else:
                order = {c.i():i for i,c in enumerate(pn.children)}
                if len(order) < 2:
                    graph.edge(pn.i(), cnode.i())
                else:
                    o = order[cnode.i()]
                    graph.edge(pn.i(), cnode.i(), color=colors[o], label=kind[o])
    return graph

```

```py
def unhack(v):
    for i in ['if', 'while', 'for', 'elif']:
        v = re.sub(r'^_%s:' % i, '%s:' % i, v)
    return v

```

### 示例

#### check_triangle

```py
def check_triangle(a,b,c):
    if a == b:
        if a == c:
            if b == c:
                return "Equilateral"
            else:
                return "Isosceles"
        else:
            return "Isosceles"
    else:
        if b != c:
            if a == c:
                return "Isosceles"
            else:
                return "Scalene"
        else:
              return "Isosceles"

```

```py
import [inspect](https://docs.python.org/3/library/inspect.html)

```

```py
graph = to_graph(gen_cfg(inspect.getsource(check_triangle)))

```

```py
Source(graph)

```

<svg height="488pt" viewBox="0.00 0.00 693.00 488.00" width="693pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g class="graph" id="graph0" transform="scale(1 1) rotate(0) translate(4 484)"><title>%3</title> <g class="node" id="node1"><title>1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="265.5" y="-454.3">1: enter: check_triangle(a, b, c)</text></g> <g class="node" id="node9"><title>3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="265.5" y="-377.3">2: if: a == b</text></g> <g class="edge" id="edge7"><title>1->3</title></g> <g class="node" id="node2"><title>2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="362.5" y="-18.3">1: exit: check_triangle(a, b, c)</text></g> <g class="node" id="node3"><title>6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="148.5" y="-95.3">5: return 'Equilateral'</text></g> <g class="edge" id="edge1"><title>6->2</title></g> <g class="node" id="node4"><title>7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="295.5" y="-95.3">7: return 'Isosceles'</text></g> <g class="edge" id="edge2"><title>7->2</title></g> <g class="node" id="node5"><title>8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="61.5" y="-149.3">9: return 'Isosceles'</text></g> <g class="edge" id="edge3"><title>8->2</title></g> <g class="node" id="node6"><title>11</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="478.5" y="-95.3">13: return 'Isosceles'</text></g> <g class="edge" id="edge4"><title>11->2</title></g> <g class="node" id="node7"><title>12</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="623.5" y="-95.3">15: return 'Scalene'</text></g> <g class="edge" id="edge5"><title>12->2</title></g> <g class="node" id="node8"><title>13</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="379.5" y="-149.3">17: return 'Isosceles'</text></g> <g class="edge" id="edge6"><title>13->2</title></g> <g class="node" id="node10"><title>4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="179.5" y="-290.3">3: if: a == c</text></g> <g class="edge" id="edge8"><title>3->4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="233" y="-333.8">T</text></g> <g class="node" id="node12"><title>9</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="377.5" y="-290.3">11: if: b != c</text></g> <g class="edge" id="edge13"><title>3->9</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="331.5" y="-333.8">F</text></g> <g class="edge" id="edge12"><title>4->8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="130.5" y="-246.8">F</text></g> <g class="node" id="node11"><title>5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="179.5" y="-203.3">4: if: b == c</text></g> <g class="edge" id="edge9"><title>4->5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="184" y="-246.8">T</text></g> <g class="edge" id="edge10"><title>5->6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="174" y="-149.3">T</text></g> <g class="edge" id="edge11"><title>5->7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="259.5" y="-149.3">F</text></g> <g class="edge" id="edge17"><title>9->13</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="381.5" y="-246.8">F</text></g> <g class="node" id="node13"><title>10</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="487.5" y="-203.3">12: if: a == c</text></g> <g class="edge" id="edge14"><title>9->10</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="443" y="-246.8">T</text></g> <g class="edge" id="edge15"><title>10->11</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="488" y="-149.3">T</text></g> <g class="edge" id="edge16"><title>10->12</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="579.5" y="-149.3">F</text></g></g></svg>

#### cgi_decode

请注意，我们尚不支持*扩展分配*：即`+=`之类的分配

```py
def cgi_decode(s):
    hex_values = {
        '0': 0, '1': 1, '2': 2, '3': 3, '4': 4,
        '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
        'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15,
        'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15,
    }

    t = ""
    i = 0
    while i < len(s):
        c = s[i]
        if c == '+':
            t += ' '
        elif c == '%':
            digit_high, digit_low = s[i + 1], s[i + 2]
            i += 2
            if digit_high in hex_values and digit_low in hex_values:
                v = hex_values[digit_high] * 16 + hex_values[digit_low]
                t += chr(v)
            else:
                raise ValueError("Invalid encoding")
        else:
            t += c
        i += 1
    return t

```

```py
graph = to_graph(gen_cfg(inspect.getsource(cgi_decode)))

```

```py
Source(graph)

```

<svg height="1152pt" viewBox="0.00 0.00 812.50 1152.00" width="813pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g class="graph" id="graph0" transform="scale(1 1) rotate(0) translate(4 1148)"><title>%3</title> <g class="node" id="node1"><title>1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-1118.3">1: enter: cgi_decode(s)</text></g> <g class="node" id="node4"><title>3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-1047.8">2: hex_values = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7':</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-1032.8">   7, '8': 8, '9': 9, 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15,</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-1017.8">   'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15}</text></g> <g class="edge" id="edge2"><title>1->3</title></g> <g class="node" id="node2"><title>2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="420" y="-641.3">1: exit: cgi_decode(s)</text></g> <g class="node" id="node3"><title>18</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="472" y="-718.3">26: return t</text></g> <g class="edge" id="edge1"><title>18->2</title></g> <g class="node" id="node5"><title>4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-951.3">9: t = ''</text></g> <g class="edge" id="edge3"><title>3->4</title></g> <g class="node" id="node6"><title>5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-878.3">10: i = 0</text></g> <g class="edge" id="edge4"><title>4->5</title></g> <g class="node" id="node7"><title>6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-805.3">11: while: i < len(s)</text></g> <g class="edge" id="edge5"><title>5->6</title></g> <g class="edge" id="edge21"><title>6->18</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="559" y="-761.8">F</text></g> <g class="node" id="node9"><title>7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-718.3">12: c = s[i]</text></g> <g class="edge" id="edge7"><title>6->7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="624.5" y="-761.8">T</text></g> <g class="node" id="node8"><title>17</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="498" y="-14.3">25: i += 1</text></g> <g class="edge" id="edge6"><title>17->6</title></g> <g class="node" id="node10"><title>8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-641.3">13: if: c == '+'</text></g> <g class="edge" id="edge8"><title>7->8</title></g> <g class="node" id="node11"><title>9</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="479" y="-496.3">14: t += ' '</text></g> <g class="edge" id="edge9"><title>8->9</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="560.5" y="-593.8">T</text></g> <g class="node" id="node12"><title>10</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="620" y="-550.3">15: if: c == '%'</text></g> <g class="edge" id="edge10"><title>8->10</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="624" y="-593.8">F</text></g> <g class="edge" id="edge17"><title>9->17</title></g> <g class="node" id="node13"><title>11</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="405" y="-442.3">16: digit_high, digit_low = s[i + 1], s[i + 2]</text></g> <g class="edge" id="edge11"><title>10->11</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="583.5" y="-496.3">T</text></g> <g class="node" id="node18"><title>16</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="657" y="-388.3">24: t += c</text></g> <g class="edge" id="edge16"><title>10->16</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="640" y="-496.3">F</text></g> <g class="node" id="node14"><title>12</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="374" y="-334.3">17: i += 2</text></g> <g class="edge" id="edge12"><title>11->12</title></g> <g class="node" id="node15"><title>13</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="353" y="-261.3">18: if: digit_high in hex_values and digit_low in hex_values</text></g> <g class="edge" id="edge13"><title>12->13</title></g> <g class="edge" id="edge19"><title>13->17</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="335" y="-130.8">F</text></g> <g class="node" id="node16"><title>14</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="498" y="-174.3">19: v = hex_values[digit_high] * 16 + hex_values[digit_low]</text></g> <g class="edge" id="edge14"><title>13->14</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="439.5" y="-217.8">T</text></g> <g class="node" id="node17"><title>15</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="498" y="-87.3">20: t += chr(v)</text></g> <g class="edge" id="edge15"><title>14->15</title></g> <g class="edge" id="edge18"><title>15->17</title></g> <g class="edge" id="edge20"><title>16->17</title></g></g></svg>

#### gcd

```py
def gcd(a, b):
    if a<b:
        c: int = a
        a: int = b
        b: int = c

    while b != 0 :
        c: int = a
        a: int = b
        b: int = c % b
    return a

```

```py
graph = to_graph(gen_cfg(inspect.getsource(gcd)))

```

```py
Source(graph)

```

<svg height="672pt" viewBox="0.00 0.00 341.94 672.00" width="342pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g class="graph" id="graph0" transform="scale(1 1) rotate(0) translate(4 668)"><title>%3</title> <g class="node" id="node1"><title>1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="221.8437" y="-638.3">1: enter: gcd(a, b)</text></g> <g class="node" id="node4"><title>3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="221.8437" y="-561.3">2: if: a < b</text></g> <g class="edge" id="edge2"><title>1->3</title></g> <g class="node" id="node2"><title>2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="74.8437" y="-91.3">1: exit: gcd(a, b)</text></g> <g class="node" id="node3"><title>11</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="92.8437" y="-168.3">11: return a</text></g> <g class="edge" id="edge1"><title>11->2</title></g> <g class="node" id="node5"><title>4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="179.8437" y="-474.3">3: c: int = a</text></g> <g class="edge" id="edge3"><title>3->4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="208.3437" y="-517.8">T</text></g> <g class="node" id="node8"><title>7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="219.8437" y="-255.3">7: while: b != 0</text></g> <g class="edge" id="edge7"><title>3->7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="265.8437" y="-401.3">F</text></g> <g class="node" id="node6"><title>5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="172.8437" y="-401.3">4: a: int = b</text></g> <g class="edge" id="edge4"><title>4->5</title></g> <g class="node" id="node7"><title>6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="178.8437" y="-328.3">5: b: int = c</text></g> <g class="edge" id="edge5"><title>5->6</title></g> <g class="edge" id="edge6"><title>6->7</title></g> <g class="edge" id="edge12"><title>7->11</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="168.8437" y="-211.8">F</text></g> <g class="node" id="node10"><title>8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="219.8437" y="-168.3">8: c: int = a</text></g> <g class="edge" id="edge9"><title>7->8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="224.3437" y="-211.8">T</text></g> <g class="node" id="node9"><title>10</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="259.8437" y="-14.3">10: b: int = c % b</text></g> <g class="edge" id="edge8"><title>10->7</title></g> <g class="node" id="node11"><title>9</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="219.8437" y="-91.3">9: a: int = b</text></g> <g class="edge" id="edge10"><title>8->9</title></g> <g class="edge" id="edge11"><title>9->10</title></g></g></svg>

```py
def compute_gcd(x, y): 
    if x > y: 
        small = y 
    else: 
        small = x 
    for i in range(1, small+1): 
        if((x % i == 0) and (y % i == 0)): 
            gcd = i 

    return gcd 

```

```py
graph = to_graph(gen_cfg(inspect.getsource(compute_gcd)))

```

```py
Source(graph)

```

<svg height="613pt" viewBox="0.00 0.00 640.64 613.00" width="641pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g class="graph" id="graph0" transform="scale(1 1) rotate(0) translate(4 609)"><title>%3</title> <g class="node" id="node1"><title>1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="283.2405" y="-579.3">1: enter: compute_gcd(x, y)</text></g> <g class="node" id="node4"><title>3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="283.2405" y="-502.3">2: if: x > y</text></g> <g class="edge" id="edge2"><title>1->3</title></g> <g class="node" id="node2"><title>2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="111.2405" y="-105.3">1: exit: compute_gcd(x, y)</text></g> <g class="node" id="node3"><title>11</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="143.2405" y="-182.3">10: return gcd</text></g> <g class="edge" id="edge1"><title>11->2</title></g> <g class="node" id="node5"><title>4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="233.2405" y="-415.3">3: small = y</text></g> <g class="edge" id="edge3"><title>3->4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="265.7405" y="-458.8">T</text></g> <g class="node" id="node6"><title>5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="334.2405" y="-415.3">5: small = x</text></g> <g class="edge" id="edge4"><title>3->5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="315.2405" y="-458.8">F</text></g> <g class="node" id="node7"><title>6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="283.2405" y="-342.3">6: __iv = iter(range(1, small + 1))</text></g> <g class="edge" id="edge5"><title>4->6</title></g> <g class="edge" id="edge6"><title>5->6</title></g> <g class="node" id="node8"><title>7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="283.2405" y="-269.3">6: for: __iv.__length__hint__() > 0</text></g> <g class="edge" id="edge7"><title>6->7</title></g> <g class="edge" id="edge13"><title>7->11</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="226.2405" y="-225.8">F</text></g> <g class="node" id="node11"><title>8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="348.2405" y="-182.3">6: i = next(__iv)</text></g> <g class="edge" id="edge10"><title>7->8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="323.7405" y="-225.8">T</text></g> <g class="node" id="node9"><title>10</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="266.2405" y="-14.3">8: gcd = i</text></g> <g class="edge" id="edge8"><title>10->7</title></g> <g class="node" id="node10"><title>9</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="455.2405" y="-105.3">7: if: x % i == 0 and y % i == 0</text></g> <g class="edge" id="edge9"><title>9->7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="438.2405" y="-182.3">F</text></g> <g class="edge" id="edge12"><title>9->10</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="375.7405" y="-57.8">T</text></g> <g class="edge" id="edge11"><title>8->9</title></g></g></svg>

#### 光纤

注意， *for循环*需要额外的按摩。 在正确显示标签的同时，需要提取*比较节点*。 因此，表示不准确。

```py
def fib(n,):
    l = [0, 1]
    for i in range(n-2):
        l.append(l[-1]+l[-2])
    return l

```

```py
graph = to_graph(gen_cfg(inspect.getsource(fib)))

```

```py
Source(graph)

```

<svg height="439pt" viewBox="0.00 0.00 399.56 439.00" width="400pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g class="graph" id="graph0" transform="scale(1 1) rotate(0) translate(4 435)"><title>%3</title> <g class="node" id="node1"><title>1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="195.7805" y="-405.3">1: enter: fib(n)</text></g> <g class="node" id="node4"><title>3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="195.7805" y="-328.3">2: l = [0, 1]</text></g> <g class="edge" id="edge2"><title>1->3</title></g> <g class="node" id="node2"><title>2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="87.7805" y="-18.3">1: exit: fib(n)</text></g> <g class="node" id="node3"><title>8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="87.7805" y="-95.3">5: return l</text></g> <g class="edge" id="edge1"><title>8->2</title></g> <g class="node" id="node5"><title>4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="195.7805" y="-255.3">3: __iv = iter(range(n - 2))</text></g> <g class="edge" id="edge3"><title>3->4</title></g> <g class="node" id="node6"><title>5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="195.7805" y="-182.3">3: for: __iv.__length__hint__() > 0</text></g> <g class="edge" id="edge4"><title>4->5</title></g> <g class="edge" id="edge8"><title>5->8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="152.7805" y="-138.8">F</text></g> <g class="node" id="node8"><title>6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="195.7805" y="-95.3">3: i = next(__iv)</text></g> <g class="edge" id="edge6"><title>5->6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="200.2805" y="-138.8">T</text></g> <g class="node" id="node7"><title>7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="261.7805" y="-18.3">4: l.append(l[-1] + l[-2])</text></g> <g class="edge" id="edge5"><title>7->5</title></g> <g class="edge" id="edge7"><title>6->7</title></g></g></svg>

#### quad_solver

```py
def quad_solver(a, b, c):
    discriminant = b^2 - 4*a*c
    r1, r2 = 0, 0
    i1, i2 = 0, 0
    if discriminant >= 0:
        droot = math.sqrt(discriminant)
        r1 = (-b + droot) / (2*a)
        r2 = (-b - droot) / (2*a)
    else:
        droot = math.sqrt(-1 * discriminant)
        droot_ = droot/(2*a)
        r1, i1 = -b/(2*a), droot_
        r2, i2 = -b/(2*a), -droot_
    if i1 == 0 and i2 == 0:
        return (r1, r2)
    return ((r1,i1), (r2,i2))

```

```py
graph = to_graph(gen_cfg(inspect.getsource(quad_solver)))

```

```py
Source(graph)

```

<svg height="926pt" viewBox="0.00 0.00 473.50 926.00" width="474pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g class="graph" id="graph0" transform="scale(1 1) rotate(0) translate(4 922)"><title>%3</title> <g class="node" id="node1"><title>1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="224.5" y="-892.3">1: enter: quad_solver(a, b, c)</text></g> <g class="node" id="node5"><title>3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="224.5" y="-815.3">2: discriminant = b ^ 2 - 4 * a * c</text></g> <g class="edge" id="edge3"><title>1->3</title></g> <g class="node" id="node2"><title>2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="212.5" y="-18.3">1: exit: quad_solver(a, b, c)</text></g> <g class="node" id="node3"><title>15</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="137.5" y="-95.3">15: return r1, r2</text></g> <g class="edge" id="edge1"><title>15->2</title></g> <g class="node" id="node4"><title>16</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="288.5" y="-95.3">16: return (r1, i1), (r2, i2)</text></g> <g class="edge" id="edge2"><title>16->2</title></g> <g class="node" id="node6"><title>4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="224.5" y="-742.3">3: r1, r2 = 0, 0</text></g> <g class="edge" id="edge4"><title>3->4</title></g> <g class="node" id="node7"><title>5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="224.5" y="-669.3">4: i1, i2 = 0, 0</text></g> <g class="edge" id="edge5"><title>4->5</title></g> <g class="node" id="node8"><title>6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="224.5" y="-596.3">5: if: discriminant >= 0</text></g> <g class="edge" id="edge6"><title>5->6</title></g> <g class="node" id="node9"><title>7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="103.5" y="-509.3">6: droot = math.sqrt(discriminant)</text></g> <g class="edge" id="edge7"><title>6->7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="176" y="-552.8">T</text></g> <g class="node" id="node12"><title>10</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="345.5" y="-509.3">10: droot = math.sqrt(-1 * discriminant)</text></g> <g class="edge" id="edge10"><title>6->10</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="295.5" y="-552.8">F</text></g> <g class="node" id="node10"><title>8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="145.5" y="-436.3">7: r1 = (-b + droot) / (2 * a)</text></g> <g class="edge" id="edge8"><title>7->8</title></g> <g class="node" id="node11"><title>9</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="169.5" y="-309.3">8: r2 = (-b - droot) / (2 * a)</text></g> <g class="edge" id="edge9"><title>8->9</title></g> <g class="node" id="node16"><title>14</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="212.5" y="-182.3">14: if: i1 == 0 and i2 == 0</text></g> <g class="edge" id="edge14"><title>9->14</title></g> <g class="node" id="node13"><title>11</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="338.5" y="-436.3">11: droot_ = droot / (2 * a)</text></g> <g class="edge" id="edge11"><title>10->11</title></g> <g class="node" id="node14"><title>12</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="335.5" y="-363.3">12: r1, i1 = -b / (2 * a), droot_</text></g> <g class="edge" id="edge12"><title>11->12</title></g> <g class="node" id="node15"><title>13</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="327.5" y="-255.3">13: r2, i2 = -b / (2 * a), -droot_</text></g> <g class="edge" id="edge13"><title>12->13</title></g> <g class="edge" id="edge15"><title>13->14</title></g> <g class="edge" id="edge16"><title>14->15</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="184" y="-138.8">T</text></g> <g class="edge" id="edge17"><title>14->16</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="259.5" y="-138.8">F</text></g></g></svg>

## 调用图

### 安装：Pyan静态调用图提升程序

```py
import [os](https://docs.python.org/3/library/os.html)
import [networkx](https://docs.python.org/3/library/networkx.html) as [nx](https://docs.python.org/3/library/nx.html)
from [graphviz](https://docs.python.org/3/library/graphviz.html) import Source

```

### 调用图助手

```py
def construct_callgraph(code, name="callgraph"):
    file_name = name + ".py"
    with open(file_name, 'w') as f:
        f.write(code)
    cg_file = name + '.dot'
    os.system(f'pyan {file_name} --uses --defines --colored --grouped --annotated --dot > {cg_file}')

def callgraph(code, name="callgraph"):
    if not os.path.isfile(name + '.dot'):
        construct_callgraph(code, name)
    return Source.from_file(name + '.dot')

def get_callgraph(code, name="callgraph"):
    if not os.path.isfile(name + '.dot'):
        construct_callgraph(code, name)
    return nx.drawing.nx_pydot.read_dot(name + '.dot')

```

### 例如：迷宫

为了提供一个有意义的示例，您可以在其中轻松更改代码的复杂性和目标位置，我们从作为字符串提供的迷宫中生成了迷宫源代码。 本示例大致基于Felipe Andres Manzano的旧版[博客文章](https://feliam.wordpress.com/2010/10/07/the-symbolic-maze/)，有关符号执行（快速大喊大叫！）。

您只需将迷宫指定​​为字符串即可。 像这样

```py
maze_string = """
+-+-----+
|X|     |
| | --+ |
| |   | |
| +-- | |
|     |#|
+-----+-+
"""

```

`maze_string`中的每个字符代表一个图块。 对于每个图块，生成图块功能。

*   如果当前图块为“良性”（），则调用与下一个输入字符（D，U，L，R）相对应的图块功能。 意外的输入字符将被忽略。 如果没有剩余的输入字符，它将返回“ VALID”和当前的迷宫状态。
*   如果当前图块是“陷阱”（`+`，`|`和`-`），则返回“ INVALID”和当前迷宫状态。
*   如果当前图块是“目标”（`#`），则它返回“已解决”和当前迷宫状态。

使用功能`generate_maze_code`生成代码。

```py
def generate_print_maze(maze_string):
    return """
def print_maze(out, row, col):
 output  = out +"\\n"
 c_row = 0
 c_col = 0
 for c in list(\"\"\"%s\"\"\"):
 if c == '\\n':
 c_row += 1
 c_col = 0
 output += "\\n"
 else:
 if c_row == row and c_col == col: output += "X"
 elif c == "X": output += " "
 else: output += c
 c_col += 1
 return output
""" % maze_string

```

```py
def generate_trap_tile(row, col):
    return """
def tile_%d_%d(input, index):
 try: HTMLParser().feed(input)
 except: pass
 return print_maze("INVALID", %d, %d)
""" % (row, col, row, col)

```

```py
def generate_good_tile(c, row, col):
    code = """
def tile_%d_%d(input, index):
 if (index == len(input)): return print_maze("VALID", %d, %d)
 elif input[index] == 'L': return tile_%d_%d(input, index + 1)
 elif input[index] == 'R': return tile_%d_%d(input, index + 1)
 elif input[index] == 'U': return tile_%d_%d(input, index + 1)
 elif input[index] == 'D': return tile_%d_%d(input, index + 1)
 else : return tile_%d_%d(input, index + 1)
""" % (row, col, row, col,
       row, col - 1, 
       row, col + 1, 
       row - 1, col, 
       row + 1, col,
       row, col)

    if c == "X":
        code += """
def maze(input):
 return tile_%d_%d(list(input), 0)
""" % (row, col)

    return code

```

```py
def generate_target_tile(row, col):
    return """
def tile_%d_%d(input, index):
 return print_maze("SOLVED", %d, %d)

def target_tile():
 return "tile_%d_%d"
""" % (row, col, row, col, row, col)

```

```py
def generate_maze_code(maze, name="maze"):
    row = 0
    col = 0
    code = generate_print_maze(maze)

    for c in list(maze):
        if c == '\n':
            row += 1
            col = 0
        else: 
            if c == "-" or c == "+" or c == "|":
                code += generate_trap_tile(row, col)
            elif c == " " or c == "X":
                code += generate_good_tile(c, row, col)
            elif c == "#":
                code += generate_target_tile(row, col)
            else: 
                print("Invalid maze! Try another one.")
            col += 1

    return code

```

现在，您可以为任意迷宫生成迷宫代码。

```py
maze_code = generate_maze_code(maze_string)
exec(maze_code)

```

```py
print(maze("DDDDRRRRUULLUURRRRDDD")) # Appending one more 'D', you have reached the target.

```

```py
VALID

+-+-----+
| |     |
| | --+ |
| |   | |
| +-- |X|
|     |#|
+-----+-+

```

这是相应的调用图。

```py
callgraph(maze_code)

```

<svg height="2287pt" viewBox="0.00 0.00 3826.00 2286.50" width="3826pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g class="graph" id="graph0" transform="scale(1 1) rotate(0) translate(4 2282.5029)"><title>G</title> <g class="cluster" id="clust1"><title>cluster_G</title></g> <g class="cluster" id="clust2"><title>cluster_callgraphX</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1866" y="-2247.3029">callgraph</text></g> <g class="node" id="node1"><title>callgraphX</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3757" y="-1931.7125">callgraph</text></g> <g class="node" id="node2"><title>callgraphX__maze</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1970" y="-2208.4328">maze</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1970" y="-2193.4328">(callgraph.py:84)</text></g> <g class="edge" id="edge2"><title>callgraphX->callgraphX__maze</title></g> <g class="node" id="node3"><title>callgraphX__print_maze</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1267" y="-54.6701">print_maze</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1267" y="-39.6701">(callgraph.py:2)</text></g> <g class="edge" id="edge17"><title>callgraphX->callgraphX__print_maze</title></g> <g class="node" id="node4"><title>callgraphX__target_tile</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3611" y="-2208.4328">target_tile</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3611" y="-2193.4328">(callgraph.py:358)</text></g> <g class="edge" id="edge33"><title>callgraphX->callgraphX__target_tile</title></g> <g class="node" id="node5"><title>callgraphX__tile_1_0</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3616" y="-144.4102">tile_1_0</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3616" y="-129.4102">(callgraph.py:26)</text></g> <g class="edge" id="edge22"><title>callgraphX->callgraphX__tile_1_0</title></g> <g class="node" id="node6"><title>callgraphX__tile_1_1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1858" y="-1221.2916">tile_1_1</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1858" y="-1206.2916">(callgraph.py:31)</text></g> <g class="edge" id="edge27"><title>callgraphX->callgraphX__tile_1_1</title></g> <g class="node" id="node7"><title>callgraphX__tile_1_2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2498" y="-144.4102">tile_1_2</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2498" y="-129.4102">(callgraph.py:36)</text></g> <g class="edge" id="edge34"><title>callgraphX->callgraphX__tile_1_2</title></g> <g class="node" id="node8"><title>callgraphX__tile_1_3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="404" y="-503.3706">tile_1_3</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="404" y="-488.3706">(callgraph.py:41)</text></g> <g class="edge" id="edge35"><title>callgraphX->callgraphX__tile_1_3</title></g> <g class="node" id="node9"><title>callgraphX__tile_1_4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1386" y="-682.8509">tile_1_4</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1386" y="-667.8509">(callgraph.py:46)</text></g> <g class="edge" id="edge42"><title>callgraphX->callgraphX__tile_1_4</title></g> <g class="node" id="node10"><title>callgraphX__tile_1_5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1744" y="-593.1107">tile_1_5</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1744" y="-578.1107">(callgraph.py:51)</text></g> <g class="edge" id="edge47"><title>callgraphX->callgraphX__tile_1_5</title></g> <g class="node" id="node11"><title>callgraphX__tile_1_6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1035" y="-503.3706">tile_1_6</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1035" y="-488.3706">(callgraph.py:56)</text></g> <g class="edge" id="edge49"><title>callgraphX->callgraphX__tile_1_6</title></g> <g class="node" id="node12"><title>callgraphX__tile_1_7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="818" y="-413.6305">tile_1_7</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="818" y="-398.6305">(callgraph.py:61)</text></g> <g class="edge" id="edge53"><title>callgraphX->callgraphX__tile_1_7</title></g> <g class="node" id="node13"><title>callgraphX__tile_1_8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2320" y="-144.4102">tile_1_8</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2320" y="-129.4102">(callgraph.py:66)</text></g> <g class="edge" id="edge58"><title>callgraphX->callgraphX__tile_1_8</title></g> <g class="node" id="node14"><title>callgraphX__tile_2_0</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="593" y="-1939.2125">tile_2_0</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="593" y="-1924.2125">(callgraph.py:71)</text></g> <g class="edge" id="edge62"><title>callgraphX->callgraphX__tile_2_0</title></g> <g class="node" id="node15"><title>callgraphX__tile_2_1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="888" y="-2118.6927">tile_2_1</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="888" y="-2103.6927">(callgraph.py:76)</text></g> <g class="edge" id="edge65"><title>callgraphX->callgraphX__tile_2_1</title></g> <g class="node" id="node16"><title>callgraphX__tile_2_2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="484" y="-772.591">tile_2_2</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="484" y="-757.591">(callgraph.py:87)</text></g> <g class="edge" id="edge6"><title>callgraphX->callgraphX__tile_2_2</title></g> <g class="node" id="node17"><title>callgraphX__tile_2_3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="752" y="-862.3311">tile_2_3</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="752" y="-847.3311">(callgraph.py:92)</text></g> <g class="edge" id="edge11"><title>callgraphX->callgraphX__tile_2_3</title></g> <g class="node" id="node18"><title>callgraphX__tile_2_4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="787" y="-772.591">tile_2_4</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="787" y="-757.591">(callgraph.py:100)</text></g> <g class="edge" id="edge16"><title>callgraphX->callgraphX__tile_2_4</title></g> <g class="node" id="node19"><title>callgraphX__tile_2_5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1055" y="-682.8509">tile_2_5</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1055" y="-667.8509">(callgraph.py:108)</text></g> <g class="edge" id="edge23"><title>callgraphX->callgraphX__tile_2_5</title></g> <g class="node" id="node20"><title>callgraphX__tile_2_6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1035" y="-593.1107">tile_2_6</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1035" y="-578.1107">(callgraph.py:116)</text></g> <g class="edge" id="edge26"><title>callgraphX->callgraphX__tile_2_6</title></g> <g class="node" id="node21"><title>callgraphX__tile_2_7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="650" y="-503.3706">tile_2_7</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="650" y="-488.3706">(callgraph.py:124)</text></g> <g class="edge" id="edge30"><title>callgraphX->callgraphX__tile_2_7</title></g> <g class="node" id="node22"><title>callgraphX__tile_2_8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="635" y="-413.6305">tile_2_8</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="635" y="-398.6305">(callgraph.py:132)</text></g> <g class="edge" id="edge37"><title>callgraphX->callgraphX__tile_2_8</title></g> <g class="node" id="node23"><title>callgraphX__tile_3_0</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="549" y="-1131.5514">tile_3_0</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="549" y="-1116.5514">(callgraph.py:137)</text></g> <g class="edge" id="edge41"><title>callgraphX->callgraphX__tile_3_0</title></g> <g class="node" id="node24"><title>callgraphX__tile_3_1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="888" y="-2028.9526">tile_3_1</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="888" y="-2013.9526">(callgraph.py:142)</text></g> <g class="edge" id="edge48"><title>callgraphX->callgraphX__tile_3_1</title></g> <g class="node" id="node25"><title>callgraphX__tile_3_2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="529" y="-862.3311">tile_3_2</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="529" y="-847.3311">(callgraph.py:150)</text></g> <g class="edge" id="edge57"><title>callgraphX->callgraphX__tile_3_2</title></g> <g class="node" id="node26"><title>callgraphX__tile_3_3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="767" y="-952.0712">tile_3_3</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="767" y="-937.0712">(callgraph.py:155)</text></g> <g class="edge" id="edge64"><title>callgraphX->callgraphX__tile_3_3</title></g> <g class="node" id="node27"><title>callgraphX__tile_3_4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="747" y="-682.8509">tile_3_4</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="747" y="-667.8509">(callgraph.py:163)</text></g> <g class="edge" id="edge1"><title>callgraphX->callgraphX__tile_3_4</title></g> <g class="node" id="node28"><title>callgraphX__tile_3_5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1341" y="-593.1107">tile_3_5</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1341" y="-578.1107">(callgraph.py:168)</text></g> <g class="edge" id="edge8"><title>callgraphX->callgraphX__tile_3_5</title></g> <g class="node" id="node29"><title>callgraphX__tile_3_6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="429" y="-323.8904">tile_3_6</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="429" y="-308.8904">(callgraph.py:173)</text></g> <g class="edge" id="edge12"><title>callgraphX->callgraphX__tile_3_6</title></g> <g class="node" id="node30"><title>callgraphX__tile_3_7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="429" y="-413.6305">tile_3_7</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="429" y="-398.6305">(callgraph.py:178)</text></g> <g class="edge" id="edge18"><title>callgraphX->callgraphX__tile_3_7</title></g> <g class="node" id="node31"><title>callgraphX__tile_3_8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="161" y="-323.8904">tile_3_8</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="161" y="-308.8904">(callgraph.py:186)</text></g> <g class="edge" id="edge24"><title>callgraphX->callgraphX__tile_3_8</title></g> <g class="node" id="node32"><title>callgraphX__tile_4_0</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1084" y="-1849.4724">tile_4_0</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1084" y="-1834.4724">(callgraph.py:191)</text></g> <g class="edge" id="edge28"><title>callgraphX->callgraphX__tile_4_0</title></g> <g class="node" id="node33"><title>callgraphX__tile_4_1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1032" y="-1939.2125">tile_4_1</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1032" y="-1924.2125">(callgraph.py:196)</text></g> <g class="edge" id="edge31"><title>callgraphX->callgraphX__tile_4_1</title></g> <g class="node" id="node34"><title>callgraphX__tile_4_2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1053" y="-952.0712">tile_4_2</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1053" y="-937.0712">(callgraph.py:204)</text></g> <g class="edge" id="edge36"><title>callgraphX->callgraphX__tile_4_2</title></g> <g class="node" id="node35"><title>callgraphX__tile_4_3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="767" y="-1041.8113">tile_4_3</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="767" y="-1026.8113">(callgraph.py:209)</text></g> <g class="edge" id="edge40"><title>callgraphX->callgraphX__tile_4_3</title></g> <g class="node" id="node36"><title>callgraphX__tile_4_4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="817" y="-1131.5514">tile_4_4</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="817" y="-1116.5514">(callgraph.py:217)</text></g> <g class="edge" id="edge44"><title>callgraphX->callgraphX__tile_4_4</title></g> <g class="node" id="node37"><title>callgraphX__tile_4_5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1312" y="-1221.2916">tile_4_5</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1312" y="-1206.2916">(callgraph.py:225)</text></g> <g class="edge" id="edge50"><title>callgraphX->callgraphX__tile_4_5</title></g> <g class="node" id="node38"><title>callgraphX__tile_4_6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1301" y="-234.1503">tile_4_6</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1301" y="-219.1503">(callgraph.py:233)</text></g> <g class="edge" id="edge55"><title>callgraphX->callgraphX__tile_4_6</title></g> <g class="node" id="node39"><title>callgraphX__tile_4_7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="679" y="-323.8904">tile_4_7</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="679" y="-308.8904">(callgraph.py:238)</text></g> <g class="edge" id="edge59"><title>callgraphX->callgraphX__tile_4_7</title></g> <g class="node" id="node40"><title>callgraphX__tile_4_8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="161" y="-234.1503">tile_4_8</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="161" y="-219.1503">(callgraph.py:246)</text></g> <g class="edge" id="edge66"><title>callgraphX->callgraphX__tile_4_8</title></g> <g class="node" id="node41"><title>callgraphX__tile_5_0</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1376" y="-1759.7322">tile_5_0</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1376" y="-1744.7322">(callgraph.py:251)</text></g> <g class="edge" id="edge7"><title>callgraphX->callgraphX__tile_5_0</title></g> <g class="node" id="node42"><title>callgraphX__tile_5_1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1272" y="-1849.4724">tile_5_1</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1272" y="-1834.4724">(callgraph.py:256)</text></g> <g class="edge" id="edge14"><title>callgraphX->callgraphX__tile_5_1</title></g> <g class="node" id="node43"><title>callgraphX__tile_5_2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1607" y="-1580.252">tile_5_2</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1607" y="-1565.252">(callgraph.py:264)</text></g> <g class="edge" id="edge21"><title>callgraphX->callgraphX__tile_5_2</title></g> <g class="node" id="node44"><title>callgraphX__tile_5_3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1689" y="-952.0712">tile_5_3</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1689" y="-937.0712">(callgraph.py:269)</text></g> <g class="edge" id="edge29"><title>callgraphX->callgraphX__tile_5_3</title></g> <g class="node" id="node45"><title>callgraphX__tile_5_4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1441" y="-1041.8113">tile_5_4</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1441" y="-1026.8113">(callgraph.py:274)</text></g> <g class="edge" id="edge32"><title>callgraphX->callgraphX__tile_5_4</title></g> <g class="node" id="node46"><title>callgraphX__tile_5_5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2081" y="-1311.0317">tile_5_5</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2081" y="-1296.0317">(callgraph.py:279)</text></g> <g class="edge" id="edge38"><title>callgraphX->callgraphX__tile_5_5</title></g> <g class="node" id="node47"><title>callgraphX__tile_5_6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2097" y="-144.4102">tile_5_6</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2097" y="-129.4102">(callgraph.py:287)</text></g> <g class="edge" id="edge43"><title>callgraphX->callgraphX__tile_5_6</title></g> <g class="node" id="node48"><title>callgraphX__tile_5_7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1869" y="-234.1503">tile_5_7</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1869" y="-219.1503">(callgraph.py:292)</text></g> <g class="edge" id="edge46"><title>callgraphX->callgraphX__tile_5_7</title></g> <g class="node" id="node49"><title>callgraphX__tile_5_8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1721" y="-144.4102">tile_5_8</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1721" y="-129.4102">(callgraph.py:300)</text></g> <g class="edge" id="edge51"><title>callgraphX->callgraphX__tile_5_8</title></g> <g class="node" id="node50"><title>callgraphX__tile_6_0</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1627" y="-1490.5119">tile_6_0</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1627" y="-1475.5119">(callgraph.py:305)</text></g> <g class="edge" id="edge54"><title>callgraphX->callgraphX__tile_6_0</title></g> <g class="node" id="node51"><title>callgraphX__tile_6_1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1564" y="-1759.7322">tile_6_1</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1564" y="-1744.7322">(callgraph.py:310)</text></g> <g class="edge" id="edge61"><title>callgraphX->callgraphX__tile_6_1</title></g> <g class="node" id="node52"><title>callgraphX__tile_6_2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1651" y="-1669.9921">tile_6_2</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1651" y="-1654.9921">(callgraph.py:318)</text></g> <g class="edge" id="edge3"><title>callgraphX->callgraphX__tile_6_2</title></g> <g class="node" id="node53"><title>callgraphX__tile_6_3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1815" y="-1580.252">tile_6_3</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1815" y="-1565.252">(callgraph.py:326)</text></g> <g class="edge" id="edge4"><title>callgraphX->callgraphX__tile_6_3</title></g> <g class="node" id="node54"><title>callgraphX__tile_6_4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2066" y="-1490.5119">tile_6_4</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2066" y="-1475.5119">(callgraph.py:334)</text></g> <g class="edge" id="edge9"><title>callgraphX->callgraphX__tile_6_4</title></g> <g class="node" id="node55"><title>callgraphX__tile_6_5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2249" y="-1400.7718">tile_6_5</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2249" y="-1385.7718">(callgraph.py:342)</text></g> <g class="edge" id="edge13"><title>callgraphX->callgraphX__tile_6_5</title></g> <g class="node" id="node56"><title>callgraphX__tile_6_6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1124" y="-1221.2916">tile_6_6</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1124" y="-1206.2916">(callgraph.py:350)</text></g> <g class="edge" id="edge20"><title>callgraphX->callgraphX__tile_6_6</title></g> <g class="node" id="node57"><title>callgraphX__tile_6_7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1909" y="-144.4102">tile_6_7</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1909" y="-129.4102">(callgraph.py:355)</text></g> <g class="edge" id="edge25"><title>callgraphX->callgraphX__tile_6_7</title></g> <g class="node" id="node58"><title>callgraphX__tile_6_8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2681" y="-144.4102">tile_6_8</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2681" y="-129.4102">(callgraph.py:361)</text></g> <g class="edge" id="edge39"><title>callgraphX->callgraphX__tile_6_8</title></g> <g class="node" id="node59"><title>callgraphX__tile_7_0</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2869" y="-144.4102">tile_7_0</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2869" y="-129.4102">(callgraph.py:366)</text></g> <g class="edge" id="edge45"><title>callgraphX->callgraphX__tile_7_0</title></g> <g class="node" id="node60"><title>callgraphX__tile_7_1</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="856" y="-1669.9921">tile_7_1</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="856" y="-1654.9921">(callgraph.py:371)</text></g> <g class="edge" id="edge52"><title>callgraphX->callgraphX__tile_7_1</title></g> <g class="node" id="node61"><title>callgraphX__tile_7_2</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1833" y="-1400.7718">tile_7_2</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="1833" y="-1385.7718">(callgraph.py:376)</text></g> <g class="edge" id="edge56"><title>callgraphX->callgraphX__tile_7_2</title></g> <g class="node" id="node62"><title>callgraphX__tile_7_3</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2061" y="-1400.7718">tile_7_3</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2061" y="-1385.7718">(callgraph.py:381)</text></g> <g class="edge" id="edge60"><title>callgraphX->callgraphX__tile_7_3</title></g> <g class="node" id="node63"><title>callgraphX__tile_7_4</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2312" y="-1311.0317">tile_7_4</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2312" y="-1296.0317">(callgraph.py:386)</text></g> <g class="edge" id="edge63"><title>callgraphX->callgraphX__tile_7_4</title></g> <g class="node" id="node64"><title>callgraphX__tile_7_5</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2500" y="-1311.0317">tile_7_5</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="2500" y="-1296.0317">(callgraph.py:391)</text></g> <g class="edge" id="edge19"><title>callgraphX->callgraphX__tile_7_5</title></g> <g class="node" id="node65"><title>callgraphX__tile_7_6</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3057" y="-144.4102">tile_7_6</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3057" y="-129.4102">(callgraph.py:396)</text></g> <g class="edge" id="edge5"><title>callgraphX->callgraphX__tile_7_6</title></g> <g class="node" id="node66"><title>callgraphX__tile_7_7</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3245" y="-144.4102">tile_7_7</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3245" y="-129.4102">(callgraph.py:401)</text></g> <g class="edge" id="edge10"><title>callgraphX->callgraphX__tile_7_7</title></g> <g class="node" id="node67"><title>callgraphX__tile_7_8</title> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3433" y="-144.4102">tile_7_8</text> <text fill="#000000" font-family="Times,serif" font-size="14.00" text-anchor="middle" x="3433" y="-129.4102">(callgraph.py:406)</text></g> <g class="edge" id="edge15"><title>callgraphX->callgraphX__tile_7_8</title></g> <g class="edge" id="edge83"><title>callgraphX__maze->callgraphX__tile_2_1</title></g> <g class="edge" id="edge67"><title>callgraphX__tile_1_0->callgraphX__print_maze</title></g> <g class="edge" id="edge68"><title>callgraphX__tile_1_1->callgraphX__print_maze</title></g> <g class="edge" id="edge69"><title>callgraphX__tile_1_2->callgraphX__print_maze</title></g> <g class="edge" id="edge70"><title>callgraphX__tile_1_3->callgraphX__print_maze</title></g> <g class="edge" id="edge71"><title>callgraphX__tile_1_4->callgraphX__print_maze</title></g> <g class="edge" id="edge72"><title>callgraphX__tile_1_5->callgraphX__print_maze</title></g> <g class="edge" id="edge73"><title>callgraphX__tile_1_6->callgraphX__print_maze</title></g> <g class="edge" id="edge74"><title>callgraphX__tile_1_7->callgraphX__print_maze</title></g> <g class="edge" id="edge75"><title>callgraphX__tile_1_8->callgraphX__print_maze</title></g> <g class="edge" id="edge76"><title>callgraphX__tile_2_0->callgraphX__print_maze</title></g> <g class="edge" id="edge82"><title>callgraphX__tile_2_1->callgraphX__print_maze</title></g> <g class="edge" id="edge78"><title>callgraphX__tile_2_1->callgraphX__tile_1_1</title></g> <g class="edge" id="edge79"><title>callgraphX__tile_2_1->callgraphX__tile_2_0</title></g> <g class="edge" id="edge80"><title>callgraphX__tile_2_1->callgraphX__tile_2_1</title></g> <g class="edge" id="edge77"><title>callgraphX__tile_2_1->callgraphX__tile_2_2</title></g> <g class="edge" id="edge81"><title>callgraphX__tile_2_1->callgraphX__tile_3_1</title></g> <g class="edge" id="edge84"><title>callgraphX__tile_2_2->callgraphX__print_maze</title></g> <g class="edge" id="edge90"><title>callgraphX__tile_2_3->callgraphX__print_maze</title></g> <g class="edge" id="edge85"><title>callgraphX__tile_2_3->callgraphX__tile_1_3</title></g> <g class="edge" id="edge86"><title>callgraphX__tile_2_3->callgraphX__tile_2_2</title></g> <g class="edge" id="edge87"><title>callgraphX__tile_2_3->callgraphX__tile_2_3</title></g> <g class="edge" id="edge89"><title>callgraphX__tile_2_3->callgraphX__tile_2_4</title></g> <g class="edge" id="edge88"><title>callgraphX__tile_2_3->callgraphX__tile_3_3</title></g> <g class="edge" id="edge96"><title>callgraphX__tile_2_4->callgraphX__print_maze</title></g> <g class="edge" id="edge93"><title>callgraphX__tile_2_4->callgraphX__tile_1_4</title></g> <g class="edge" id="edge94"><title>callgraphX__tile_2_4->callgraphX__tile_2_3</title></g> <g class="edge" id="edge95"><title>callgraphX__tile_2_4->callgraphX__tile_2_4</title></g> <g class="edge" id="edge92"><title>callgraphX__tile_2_4->callgraphX__tile_2_5</title></g> <g class="edge" id="edge91"><title>callgraphX__tile_2_4->callgraphX__tile_3_4</title></g> <g class="edge" id="edge102"><title>callgraphX__tile_2_5->callgraphX__print_maze</title></g> <g class="edge" id="edge100"><title>callgraphX__tile_2_5->callgraphX__tile_1_5</title></g> <g class="edge" id="edge101"><title>callgraphX__tile_2_5->callgraphX__tile_2_4</title></g> <g class="edge" id="edge97"><title>callgraphX__tile_2_5->callgraphX__tile_2_5</title></g> <g class="edge" id="edge98"><title>callgraphX__tile_2_5->callgraphX__tile_2_6</title></g> <g class="edge" id="edge99"><title>callgraphX__tile_2_5->callgraphX__tile_3_5</title></g> <g class="edge" id="edge108"><title>callgraphX__tile_2_6->callgraphX__print_maze</title></g> <g class="edge" id="edge107"><title>callgraphX__tile_2_6->callgraphX__tile_1_6</title></g> <g class="edge" id="edge103"><title>callgraphX__tile_2_6->callgraphX__tile_2_5</title></g> <g class="edge" id="edge104"><title>callgraphX__tile_2_6->callgraphX__tile_2_6</title></g> <g class="edge" id="edge106"><title>callgraphX__tile_2_6->callgraphX__tile_2_7</title></g> <g class="edge" id="edge105"><title>callgraphX__tile_2_6->callgraphX__tile_3_6</title></g> <g class="edge" id="edge114"><title>callgraphX__tile_2_7->callgraphX__print_maze</title></g> <g class="edge" id="edge110"><title>callgraphX__tile_2_7->callgraphX__tile_1_7</title></g> <g class="edge" id="edge112"><title>callgraphX__tile_2_7->callgraphX__tile_2_6</title></g> <g class="edge" id="edge113"><title>callgraphX__tile_2_7->callgraphX__tile_2_7</title></g> <g class="edge" id="edge109"><title>callgraphX__tile_2_7->callgraphX__tile_2_8</title></g> <g class="edge" id="edge111"><title>callgraphX__tile_2_7->callgraphX__tile_3_7</title></g> <g class="edge" id="edge115"><title>callgraphX__tile_2_8->callgraphX__print_maze</title></g> <g class="edge" id="edge116"><title>callgraphX__tile_3_0->callgraphX__print_maze</title></g> <g class="edge" id="edge122"><title>callgraphX__tile_3_1->callgraphX__print_maze</title></g> <g class="edge" id="edge119"><title>callgraphX__tile_3_1->callgraphX__tile_2_1</title></g> <g class="edge" id="edge118"><title>callgraphX__tile_3_1->callgraphX__tile_3_0</title></g> <g class="edge" id="edge121"><title>callgraphX__tile_3_1->callgraphX__tile_3_1</title></g> <g class="edge" id="edge117"><title>callgraphX__tile_3_1->callgraphX__tile_3_2</title></g> <g class="edge" id="edge120"><title>callgraphX__tile_3_1->callgraphX__tile_4_1</title></g> <g class="edge" id="edge123"><title>callgraphX__tile_3_2->callgraphX__print_maze</title></g> <g class="edge" id="edge129"><title>callgraphX__tile_3_3->callgraphX__print_maze</title></g> <g class="edge" id="edge127"><title>callgraphX__tile_3_3->callgraphX__tile_2_3</title></g> <g class="edge" id="edge125"><title>callgraphX__tile_3_3->callgraphX__tile_3_2</title></g> <g class="edge" id="edge128"><title>callgraphX__tile_3_3->callgraphX__tile_3_3</title></g> <g class="edge" id="edge124"><title>callgraphX__tile_3_3->callgraphX__tile_3_4</title></g> <g class="edge" id="edge126"><title>callgraphX__tile_3_3->callgraphX__tile_4_3</title></g> <g class="edge" id="edge130"><title>callgraphX__tile_3_4->callgraphX__print_maze</title></g> <g class="edge" id="edge131"><title>callgraphX__tile_3_5->callgraphX__print_maze</title></g> <g class="edge" id="edge132"><title>callgraphX__tile_3_6->callgraphX__print_maze</title></g> <g class="edge" id="edge138"><title>callgraphX__tile_3_7->callgraphX__print_maze</title></g> <g class="edge" id="edge137"><title>callgraphX__tile_3_7->callgraphX__tile_2_7</title></g> <g class="edge" id="edge136"><title>callgraphX__tile_3_7->callgraphX__tile_3_6</title></g> <g class="edge" id="edge133"><title>callgraphX__tile_3_7->callgraphX__tile_3_7</title></g> <g class="edge" id="edge134"><title>callgraphX__tile_3_7->callgraphX__tile_3_8</title></g> <g class="edge" id="edge135"><title>callgraphX__tile_3_7->callgraphX__tile_4_7</title></g> <g class="edge" id="edge139"><title>callgraphX__tile_3_8->callgraphX__print_maze</title></g> <g class="edge" id="edge140"><title>callgraphX__tile_4_0->callgraphX__print_maze</title></g> <g class="edge" id="edge146"><title>callgraphX__tile_4_1->callgraphX__print_maze</title></g> <g class="edge" id="edge145"><title>callgraphX__tile_4_1->callgraphX__tile_3_1</title></g> <g class="edge" id="edge142"><title>callgraphX__tile_4_1->callgraphX__tile_4_0</title></g> <g class="edge" id="edge144"><title>callgraphX__tile_4_1->callgraphX__tile_4_1</title></g> <g class="edge" id="edge141"><title>callgraphX__tile_4_1->callgraphX__tile_4_2</title></g> <g class="edge" id="edge143"><title>callgraphX__tile_4_1->callgraphX__tile_5_1</title></g> <g class="edge" id="edge147"><title>callgraphX__tile_4_2->callgraphX__print_maze</title></g> <g class="edge" id="edge153"><title>callgraphX__tile_4_3->callgraphX__print_maze</title></g> <g class="edge" id="edge152"><title>callgraphX__tile_4_3->callgraphX__tile_3_3</title></g> <g class="edge" id="edge148"><title>callgraphX__tile_4_3->callgraphX__tile_4_2</title></g> <g class="edge" id="edge149"><title>callgraphX__tile_4_3->callgraphX__tile_4_3</title></g> <g class="edge" id="edge150"><title>callgraphX__tile_4_3->callgraphX__tile_4_4</title></g> <g class="edge" id="edge151"><title>callgraphX__tile_4_3->callgraphX__tile_5_3</title></g> <g class="edge" id="edge159"><title>callgraphX__tile_4_4->callgraphX__print_maze</title></g> <g class="edge" id="edge155"><title>callgraphX__tile_4_4->callgraphX__tile_3_4</title></g> <g class="edge" id="edge156"><title>callgraphX__tile_4_4->callgraphX__tile_4_3</title></g> <g class="edge" id="edge157"><title>callgraphX__tile_4_4->callgraphX__tile_4_4</title></g> <g class="edge" id="edge154"><title>callgraphX__tile_4_4->callgraphX__tile_4_5</title></g> <g class="edge" id="edge158"><title>callgraphX__tile_4_4->callgraphX__tile_5_4</title></g> <g class="edge" id="edge165"><title>callgraphX__tile_4_5->callgraphX__print_maze</title></g> <g class="edge" id="edge162"><title>callgraphX__tile_4_5->callgraphX__tile_3_5</title></g> <g class="edge" id="edge163"><title>callgraphX__tile_4_5->callgraphX__tile_4_4</title></g> <g class="edge" id="edge164"><title>callgraphX__tile_4_5->callgraphX__tile_4_5</title></g> <g class="edge" id="edge161"><title>callgraphX__tile_4_5->callgraphX__tile_4_6</title></g> <g class="edge" id="edge160"><title>callgraphX__tile_4_5->callgraphX__tile_5_5</title></g> <g class="edge" id="edge166"><title>callgraphX__tile_4_6->callgraphX__print_maze</title></g> <g class="edge" id="edge172"><title>callgraphX__tile_4_7->callgraphX__print_maze</title></g> <g class="edge" id="edge167"><title>callgraphX__tile_4_7->callgraphX__tile_3_7</title></g> <g class="edge" id="edge168"><title>callgraphX__tile_4_7->callgraphX__tile_4_6</title></g> <g class="edge" id="edge169"><title>callgraphX__tile_4_7->callgraphX__tile_4_7</title></g> <g class="edge" id="edge171"><title>callgraphX__tile_4_7->callgraphX__tile_4_8</title></g> <g class="edge" id="edge170"><title>callgraphX__tile_4_7->callgraphX__tile_5_7</title></g> <g class="edge" id="edge173"><title>callgraphX__tile_4_8->callgraphX__print_maze</title></g> <g class="edge" id="edge174"><title>callgraphX__tile_5_0->callgraphX__print_maze</title></g> <g class="edge" id="edge180"><title>callgraphX__tile_5_1->callgraphX__print_maze</title></g> <g class="edge" id="edge179"><title>callgraphX__tile_5_1->callgraphX__tile_4_1</title></g> <g class="edge" id="edge176"><title>callgraphX__tile_5_1->callgraphX__tile_5_0</title></g> <g class="edge" id="edge178"><title>callgraphX__tile_5_1->callgraphX__tile_5_1</title></g> <g class="edge" id="edge175"><title>callgraphX__tile_5_1->callgraphX__tile_5_2</title></g> <g class="edge" id="edge177"><title>callgraphX__tile_5_1->callgraphX__tile_6_1</title></g> <g class="edge" id="edge181"><title>callgraphX__tile_5_2->callgraphX__print_maze</title></g> <g class="edge" id="edge182"><title>callgraphX__tile_5_3->callgraphX__print_maze</title></g> <g class="edge" id="edge183"><title>callgraphX__tile_5_4->callgraphX__print_maze</title></g> <g class="edge" id="edge189"><title>callgraphX__tile_5_5->callgraphX__print_maze</title></g> <g class="edge" id="edge188"><title>callgraphX__tile_5_5->callgraphX__tile_4_5</title></g> <g class="edge" id="edge187"><title>callgraphX__tile_5_5->callgraphX__tile_5_4</title></g> <g class="edge" id="edge184"><title>callgraphX__tile_5_5->callgraphX__tile_5_5</title></g> <g class="edge" id="edge185"><title>callgraphX__tile_5_5->callgraphX__tile_5_6</title></g> <g class="edge" id="edge186"><title>callgraphX__tile_5_5->callgraphX__tile_6_5</title></g> <g class="edge" id="edge190"><title>callgraphX__tile_5_6->callgraphX__print_maze</title></g> <g class="edge" id="edge195"><title>callgraphX__tile_5_7->callgraphX__print_maze</title></g> <g class="edge" id="edge193"><title>callgraphX__tile_5_7->callgraphX__tile_4_7</title></g> <g class="edge" id="edge192"><title>callgraphX__tile_5_7->callgraphX__tile_5_6</title></g> <g class="edge" id="edge194"><title>callgraphX__tile_5_7->callgraphX__tile_5_7</title></g> <g class="edge" id="edge196"><title>callgraphX__tile_5_7->callgraphX__tile_5_8</title></g> <g class="edge" id="edge191"><title>callgraphX__tile_5_7->callgraphX__tile_6_7</title></g> <g class="edge" id="edge197"><title>callgraphX__tile_5_8->callgraphX__print_maze</title></g> <g class="edge" id="edge198"><title>callgraphX__tile_6_0->callgraphX__print_maze</title></g> <g class="edge" id="edge203"><title>callgraphX__tile_6_1->callgraphX__print_maze</title></g> <g class="edge" id="edge202"><title>callgraphX__tile_6_1->callgraphX__tile_5_1</title></g> <g class="edge" id="edge199"><title>callgraphX__tile_6_1->callgraphX__tile_6_0</title></g> <g class="edge" id="edge200"><title>callgraphX__tile_6_1->callgraphX__tile_6_1</title></g> <g class="edge" id="edge201"><title>callgraphX__tile_6_1->callgraphX__tile_6_2</title></g> <g class="edge" id="edge204"><title>callgraphX__tile_6_1->callgraphX__tile_7_1</title></g> <g class="edge" id="edge210"><title>callgraphX__tile_6_2->callgraphX__print_maze</title></g> <g class="edge" id="edge205"><title>callgraphX__tile_6_2->callgraphX__tile_5_2</title></g> <g class="edge" id="edge208"><title>callgraphX__tile_6_2->callgraphX__tile_6_1</title></g> <g class="edge" id="edge209"><title>callgraphX__tile_6_2->callgraphX__tile_6_2</title></g> <g class="edge" id="edge206"><title>callgraphX__tile_6_2->callgraphX__tile_6_3</title></g> <g class="edge" id="edge207"><title>callgraphX__tile_6_2->callgraphX__tile_7_2</title></g> <g class="edge" id="edge216"><title>callgraphX__tile_6_3->callgraphX__print_maze</title></g> <g class="edge" id="edge214"><title>callgraphX__tile_6_3->callgraphX__tile_5_3</title></g> <g class="edge" id="edge215"><title>callgraphX__tile_6_3->callgraphX__tile_6_2</title></g> <g class="edge" id="edge211"><title>callgraphX__tile_6_3->callgraphX__tile_6_3</title></g> <g class="edge" id="edge212"><title>callgraphX__tile_6_3->callgraphX__tile_6_4</title></g> <g class="edge" id="edge213"><title>callgraphX__tile_6_3->callgraphX__tile_7_3</title></g> <g class="edge" id="edge222"><title>callgraphX__tile_6_4->callgraphX__print_maze</title></g> <g class="edge" id="edge221"><title>callgraphX__tile_6_4->callgraphX__tile_5_4</title></g> <g class="edge" id="edge217"><title>callgraphX__tile_6_4->callgraphX__tile_6_3</title></g> <g class="edge" id="edge218"><title>callgraphX__tile_6_4->callgraphX__tile_6_4</title></g> <g class="edge" id="edge219"><title>callgraphX__tile_6_4->callgraphX__tile_6_5</title></g> <g class="edge" id="edge220"><title>callgraphX__tile_6_4->callgraphX__tile_7_4</title></g> <g class="edge" id="edge228"><title>callgraphX__tile_6_5->callgraphX__print_maze</title></g> <g class="edge" id="edge224"><title>callgraphX__tile_6_5->callgraphX__tile_5_5</title></g> <g class="edge" id="edge225"><title>callgraphX__tile_6_5->callgraphX__tile_6_4</title></g> <g class="edge" id="edge226"><title>callgraphX__tile_6_5->callgraphX__tile_6_5</title></g> <g class="edge" id="edge223"><title>callgraphX__tile_6_5->callgraphX__tile_6_6</title></g> <g class="edge" id="edge227"><title>callgraphX__tile_6_5->callgraphX__tile_7_5</title></g> <g class="edge" id="edge229"><title>callgraphX__tile_6_6->callgraphX__print_maze</title></g> <g class="edge" id="edge230"><title>callgraphX__tile_6_7->callgraphX__print_maze</title></g> <g class="edge" id="edge231"><title>callgraphX__tile_6_8->callgraphX__print_maze</title></g> <g class="edge" id="edge232"><title>callgraphX__tile_7_0->callgraphX__print_maze</title></g> <g class="edge" id="edge233"><title>callgraphX__tile_7_1->callgraphX__print_maze</title></g> <g class="edge" id="edge234"><title>callgraphX__tile_7_2->callgraphX__print_maze</title></g> <g class="edge" id="edge235"><title>callgraphX__tile_7_3->callgraphX__print_maze</title></g> <g class="edge" id="edge236"><title>callgraphX__tile_7_4->callgraphX__print_maze</title></g> <g class="edge" id="edge237"><title>callgraphX__tile_7_5->callgraphX__print_maze</title></g> <g class="edge" id="edge238"><title>callgraphX__tile_7_6->callgraphX__print_maze</title></g> <g class="edge" id="edge239"><title>callgraphX__tile_7_7->callgraphX__print_maze</title></g> <g class="edge" id="edge240"><title>callgraphX__tile_7_8->callgraphX__print_maze</title></g></g></svg>

## 清理

我们完成了，所以我们清理一下：

```py
import [shutil](https://docs.python.org/3/library/shutil.html)

```

```py
if os.path.exists('callgraph.dot'):
    os.remove('callgraph.dot')

if os.path.exists('callgraph.py'):
    os.remove('callgraph.py')

```