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
|
from parsimonious import NodeVisitor # type: ignore
from parsimonious.nodes import Node # type: ignore
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 == ';'
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)
|