Remove dead namedtuple
[fur] / normalization.py
1 import collections
2
3 import desugaring
4 import util
5
6 NormalVariableExpression = collections.namedtuple(
7     'NormalVariableExpression',
8     [
9         'variable',
10     ],
11 )
12
13 NormalIntegerLiteralExpression = collections.namedtuple(
14     'NormalIntegerLiteralExpression',
15     [
16         'integer',
17     ],
18 )
19
20 NormalLambdaExpression = collections.namedtuple(
21     'NormalLambdaExpression',
22     (
23         'name',
24         'argument_name_list',
25         'statement_list',
26     ),
27 )
28
29 NormalStringLiteralExpression = collections.namedtuple(
30     'NormalStringLiteralExpression',
31     [
32         'string',
33     ],
34 )
35
36 NormalSymbolExpression = collections.namedtuple(
37     'NormalSymbolExpression',
38     (
39         'symbol',
40     ),
41 )
42
43 NormalSymbolLiteralExpression = collections.namedtuple(
44     'NormalSymbolLiteralExpression',
45     (
46         'symbol',
47     ),
48 )
49
50 NormalPushStatement = collections.namedtuple(
51     'NormalPushStatement',
52     (
53         'expression',
54     ),
55 )
56
57 NormalFunctionCallExpression = collections.namedtuple(
58     'NormalFunctionCallExpression',
59     [
60         'metadata',
61         'function_expression',
62         'argument_count',
63     ],
64 )
65
66 NormalVariableInitializationStatement = collections.namedtuple(
67     'NormalVariableInitializationStatement',
68     [
69         'variable',
70         'expression',
71     ],
72 )
73
74 NormalExpressionStatement = collections.namedtuple(
75     'NormalExpressionStatement',
76     [
77         'expression',
78     ],
79 )
80
81 NormalAssignmentStatement = collections.namedtuple(
82     'NormalAssignmentStatement',
83     [
84         'target',
85         'expression',
86     ],
87 )
88
89 NormalIfElseExpression = collections.namedtuple(
90     'NormalIfElseExpression',
91     [
92         'condition_expression',
93         'if_statement_list',
94         'else_statement_list',
95     ],
96 )
97
98 NormalProgram = collections.namedtuple(
99     'NormalProgram',
100     [
101         'statement_list',
102     ],
103 )
104
105 def normalize_integer_literal_expression(counter, expression):
106     return (
107         counter,
108         (),
109         NormalIntegerLiteralExpression(integer=expression.integer),
110     )
111
112 def normalize_lambda_expression(counter, expression):
113     variable = '${}'.format(counter)
114
115     _, statement_list = normalize_statement_list(
116         0,
117         expression.statement_list,
118     )
119
120     return (
121         counter + 1,
122         (
123             NormalVariableInitializationStatement(
124                 variable=variable,
125                 expression=NormalLambdaExpression(
126                     name=expression.name,
127                     argument_name_list=expression.argument_name_list,
128                     statement_list=statement_list,
129                 ),
130             ),
131         ),
132         NormalVariableExpression(variable=variable),
133     )
134
135 NormalListConstructExpression = collections.namedtuple(
136     'NormalListConstructExpression',
137     [
138         'allocate',
139     ],
140 )
141
142 def normalize_list_literal_expression(counter, expression):
143     list_variable = '${}'.format(counter)
144     counter += 1
145
146     prestatements = []
147
148     for item_expression in expression.item_expression_list:
149         counter, item_expression_prestatements, normalized = normalize_expression(
150             counter,
151             item_expression,
152         )
153
154         for p in item_expression_prestatements:
155             prestatements.append(p)
156
157         prestatements.append(
158             NormalPushStatement(
159                 expression=normalized,
160             )
161         )
162
163     return (
164         counter,
165         tuple(prestatements),
166         NormalListConstructExpression(allocate=len(expression.item_expression_list)),
167     )
168
169 def normalize_string_literal_expression(counter, expression):
170     return (
171         counter,
172         (),
173         NormalStringLiteralExpression(string=expression.string),
174     )
175
176 NormalStructureLiteralExpression = collections.namedtuple(
177     'NormalStructureLiteralExpression',
178     (
179         'field_count',
180     ),
181 )
182
183 def normalize_structure_literal_expression(counter, expression):
184     prestatements = []
185
186     for field in expression.fields:
187         counter, field_expression_prestatements, field_expression = normalize_expression(
188             counter,
189             field.expression,
190         )
191
192         for p in field_expression_prestatements:
193             prestatements.append(p)
194
195         prestatements.append(NormalPushStatement(
196             expression=field_expression,
197         ))
198
199         prestatements.append(NormalPushStatement(
200             expression=NormalSymbolLiteralExpression(
201                 symbol=field.symbol,
202             ),
203         ))
204
205     return (
206         counter,
207         tuple(prestatements),
208         NormalStructureLiteralExpression(
209             field_count=len(expression.fields),
210         ),
211     )
212
213 def normalize_symbol_expression(counter, expression):
214     return (
215         counter,
216         (),
217         NormalSymbolExpression(symbol=expression.symbol),
218     )
219
220 def normalize_function_call_expression(counter, expression):
221     prestatements = []
222
223     for argument in expression.argument_list:
224         counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
225
226         for s in argument_prestatements:
227             prestatements.append(s)
228
229         prestatements.append(
230             NormalPushStatement(
231                 expression=normalized_argument,
232             ),
233         )
234
235     counter, function_prestatements, function_expression = normalize_expression(
236         counter,
237         expression.function,
238     )
239
240     for ps in function_prestatements:
241         prestatements.append(ps)
242
243     result_variable = '${}'.format(counter)
244
245     prestatements.append(
246         NormalVariableInitializationStatement(
247             variable=result_variable,
248             expression=NormalFunctionCallExpression(
249                 metadata=expression.metadata,
250                 function_expression=function_expression,
251                 argument_count=len(expression.argument_list),
252             ),
253         )
254     )
255
256     return (
257         counter + 1,
258         tuple(prestatements),
259         NormalVariableExpression(variable=result_variable),
260     )
261
262 def normalize_if_expression(counter, expression):
263     counter, condition_prestatements, condition_expression = normalize_expression(
264         counter,
265         expression.condition_expression,
266     )
267
268     counter, if_statement_list = normalize_statement_list(
269         counter,
270         expression.if_statement_list,
271     )
272     counter, else_statement_list = normalize_statement_list(
273         counter,
274         expression.else_statement_list,
275     )
276
277     return (
278         counter,
279         condition_prestatements,
280         NormalIfElseExpression(
281             condition_expression=condition_expression,
282             if_statement_list=if_statement_list,
283             else_statement_list=else_statement_list,
284         ),
285     )
286
287 def normalize_expression(counter, expression):
288     return {
289         desugaring.DesugaredFunctionCallExpression: normalize_function_call_expression,
290         desugaring.DesugaredIfExpression: normalize_if_expression,
291         desugaring.DesugaredIntegerLiteralExpression: normalize_integer_literal_expression,
292         desugaring.DesugaredLambdaExpression: normalize_lambda_expression,
293         desugaring.DesugaredListLiteralExpression: normalize_list_literal_expression,
294         desugaring.DesugaredStringLiteralExpression: normalize_string_literal_expression,
295         desugaring.DesugaredStructureLiteralExpression: normalize_structure_literal_expression,
296         desugaring.DesugaredSymbolExpression: normalize_symbol_expression,
297     }[type(expression)](counter, expression)
298
299 def normalize_expression_statement(counter, statement):
300     # TODO Normalized will be a NormalVariableExpression, which will go unused
301     # for expression statements in every case except when it's a return
302     # statement. This cases warnings on C compilation. We should only generate
303     # this variable when it will be used on return.
304     counter, prestatements, normalized = normalize_expression(counter, statement.expression)
305
306     return (
307         counter,
308         prestatements,
309         NormalExpressionStatement(expression=normalized),
310     )
311
312 def normalize_assignment_statement(counter, statement):
313     counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
314     return (
315         counter,
316         prestatements,
317         NormalAssignmentStatement(
318             target=statement.target,
319             expression=normalized_expression,
320         ),
321     )
322
323 def normalize_statement(counter, statement):
324     return {
325         desugaring.DesugaredAssignmentStatement: normalize_assignment_statement,
326         desugaring.DesugaredExpressionStatement: normalize_expression_statement,
327     }[type(statement)](counter, statement)
328
329 @util.force_generator(tuple)
330 def normalize_statement_list(counter, statement_list):
331     result_statement_list = []
332
333     for statement in statement_list:
334         counter, prestatements, normalized = normalize_statement(counter, statement)
335         for s in prestatements:
336             result_statement_list.append(s)
337         result_statement_list.append(normalized)
338
339     return (
340         counter,
341         result_statement_list,
342     )
343
344 def normalize(program):
345     _, statement_list = normalize_statement_list(0, program.statement_list)
346
347     return NormalProgram(
348         statement_list=statement_list,
349     )