aboutsummaryrefslogtreecommitdiff
path: root/crowbar_reference_compiler/ssagen.py
blob: 7cb886141a58c918d2486ecbee8daaea679f8988 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
from parsimonious import NodeVisitor
from parsimonious.nodes import Node


class SsaGenVisitor(NodeVisitor):
    def __init__(self):
        self.data = []

    def visit_ImplementationFile(self, node, visited_children):
        data = '\n'.join(self.data)
        functions = '\n'.join(visited_children)
        return data + '\n' + functions

    def visit_IncludeStatement(self, node, visited_children):
        include, included_header, semicolon = visited_children
        assert include.text[0].type == 'include'
        assert included_header.type == 'string_literal'
        included_header = included_header.data
        assert semicolon.text[0].type == ';'
        print("including", included_header)
        return ''

    def visit_FunctionDefinition(self, node, visited_children):
        signature, body = visited_children
        return_type, name, args = signature
        body = '\n'.join('    ' + instr for instr in body)
        return f"export function w ${name}() {{\n@start\n{body}\n}}"

    def visit_FunctionSignature(self, node, visited_children):
        return_type, name, lparen, args, rparen = visited_children
        assert name.type == 'identifier'
        name = name.data
        assert lparen.text[0].type == '('
        assert rparen.text[0].type == ')'
        return return_type, name, args

    def visit_Block(self, node, visited_children):
        lbrace, statements, rbrace = visited_children
        return statements

    def visit_Statement(self, node, visited_children):
        return visited_children[0]

    def visit_ExpressionStatement(self, node, visited_children):
        expression, semicolon = visited_children
        assert semicolon.text[0].type == ';'
        return expression

    def visit_Expression(self, node, visited_children):
        # TODO handle logical and/or
        return visited_children[0]

    def visit_ComparisonExpression(self, node, visited_children):
        # TODO handle comparisons
        return visited_children[0]

    def visit_BitwiseOpExpression(self, node, visited_children):
        # TODO handle bitwise operations
        return visited_children[0]

    def visit_ArithmeticExpression(self, node, visited_children):
        # TODO handle addition/subtraction
        return visited_children[0]

    def visit_TermExpression(self, node, visited_children):
        # TODO handle multiplication/division/modulus
        return visited_children[0]

    def visit_FactorExpression(self, node, visited_children):
        # TODO handle casts/address-of/pointer-dereference/unary ops/sizeof
        return visited_children[0]

    def visit_ObjectExpression(self, node, visited_children):
        # TODO handle array literals
        # TODO handle struct literals
        base, suffices = visited_children[0]
        if isinstance(suffices, Node):
            suffices = suffices.children
        if len(suffices) == 0:
            return base
        if base.type == 'identifier' and suffices[0].text[0].type == '(':
            arguments = suffices[1]
            if arguments[0].type == 'string_literal':
                data = arguments[0].data
                name = f"$data{len(self.data)}"
                # TODO handle non-variadic functions
                arguments = [f"l {name}", '...']
                self.data.append(f"data {name} = {{ b {data}, b 0 }}")
            return f"call ${base.data}({', '.join(arguments)})"
        print(base)
        print(suffices[0])

    def visit_AtomicExpression(self, node, visited_children):
        # TODO handle parenthesized subexpressions
        return visited_children[0]

    def visit_FlowControlStatement(self, node, visited_children):
        # TODO handle break/continue
        ret, arg, semicolon = visited_children[0]
        assert ret.text[0].type == 'return'
        assert semicolon.text[0].type == ';'
        if arg.type == 'constant':
            return f"ret {arg.data}"

    def visit_constant(self, node, visited_children):
        return node.text[0]

    def visit_string_literal(self, node, visited_children):
        return node.text[0]

    def visit_identifier(self, node, visited_children):
        return node.text[0]

    def generic_visit(self, node, visited_children):
        """ The generic visit method. """
        if not visited_children:
            return node
        if len(visited_children) == 1:
            return visited_children[0]
        return visited_children


def compile_to_ssa(parse_tree):
    ssa_gen = SsaGenVisitor()
    return ssa_gen.visit(parse_tree)