A pretty featureful commit:
[fur] / transformation.py
1 import collections
2
3 import parsing
4
5 CIntegerLiteral = collections.namedtuple(
6     'CIntegerLiteral',
7     [
8         'value',
9     ],
10 )
11
12 CStringLiteral = collections.namedtuple(
13     'CStringLiteral',
14     [
15         'value',
16     ],
17 )
18
19 CAdditionExpression = collections.namedtuple(
20     'CAdditionExpression',
21     [
22         'left',
23         'right',
24     ],
25 )
26
27 CSubtractionExpression = collections.namedtuple(
28     'CSubtractionExpression',
29     [
30         'left',
31         'right',
32     ],
33 )
34
35 CMultiplicationExpression = collections.namedtuple(
36     'CMultiplicationExpression',
37     [
38         'left',
39         'right',
40     ],
41 )
42
43 CIntegerDivisionExpression = collections.namedtuple(
44     'CIntegerDivisionExpression',
45     [
46         'left',
47         'right',
48     ],
49 )
50
51 CModularDivisionExpression = collections.namedtuple(
52     'CModularDivisionExpression',
53     [
54         'left',
55         'right',
56     ],
57 )
58
59 CFunctionCallExpression = collections.namedtuple(
60     'CFunctionCallExpression',
61     [
62         'name',
63         'arguments',
64     ],
65 )
66
67 CProgram = collections.namedtuple(
68     'CProgram',
69     [
70         'builtins',
71         'statements',
72         'standard_libraries',
73     ],
74 )
75
76 BUILTINS = {
77     'pow':      ['math.h'],
78     'print':    ['stdio.h'],
79 }
80
81 def transform_expression(builtin_dependencies, expression):
82     if isinstance(expression, parsing.FurFunctionCallExpression):
83         return transform_function_call_expression(builtin_dependencies, expression)
84
85     LITERAL_TYPE_MAPPING = {
86         parsing.FurIntegerLiteralExpression: CIntegerLiteral,
87         parsing.FurStringLiteralExpression: CStringLiteral,
88     }
89
90     if type(expression) in LITERAL_TYPE_MAPPING:
91         return LITERAL_TYPE_MAPPING[type(expression)](value=expression.value)
92
93     INFIX_TYPE_MAPPING = {
94         parsing.FurAdditionExpression: CAdditionExpression,
95         parsing.FurSubtractionExpression: CSubtractionExpression,
96         parsing.FurMultiplicationExpression: CMultiplicationExpression,
97         parsing.FurIntegerDivisionExpression: CIntegerDivisionExpression,
98         parsing.FurModularDivisionExpression: CModularDivisionExpression,
99     }
100
101     return INFIX_TYPE_MAPPING[type(expression)](
102         left=transform_expression(builtin_dependencies, expression.left),
103         right=transform_expression(builtin_dependencies, expression.right),
104     )
105
106 def transform_function_call_expression(builtin_dependencies, function_call):
107     if function_call.name in BUILTINS.keys():
108         builtin_dependencies.add(function_call.name)
109
110         return CFunctionCallExpression(
111             name='builtin$' + function_call.name,
112             arguments=tuple(transform_expression(builtin_dependencies, arg) for arg in function_call.arguments),
113         )
114
115     raise Exception()
116
117 def transform(program):
118     builtins = set()
119
120     c_statements = [
121         transform_function_call_expression(builtins, statement) for statement in program.statement_list
122     ]
123
124     standard_libraries = set()
125     for builtin in builtins:
126         for standard_library in BUILTINS[builtin]:
127             standard_libraries.add(standard_library)
128
129     return CProgram(
130         builtins=builtins,
131         statements=c_statements,
132         standard_libraries=standard_libraries,
133     )
134
135
136 if __name__ == '__main__':
137     import unittest
138
139     unittest.main()