Desugar function definitions to assignments to lambda
[fur] / desugaring.py
1 import collections
2
3 import parsing
4
5 DesugaredFunctionCallExpression = collections.namedtuple(
6     'DesugaredFunctionCallExpression',
7     (
8         'metadata',
9         'function',
10         'argument_list',
11     ),
12 )
13
14 DesugaredIfExpression = collections.namedtuple(
15     'DesugaredIfExpression',
16     (
17         'condition_expression',
18         'if_statement_list',
19         'else_statement_list',
20     ),
21 )
22
23 DesugaredIntegerLiteralExpression = collections.namedtuple(
24     'DesugaredIntegerLiteralExpression',
25     (
26         'integer',
27     ),
28 )
29
30 _DesugaredLambdaExpression = collections.namedtuple(
31     'DesugaredLambdaExpression',
32     (
33         'name',
34         'argument_name_list',
35         'statement_list',
36     ),
37 )
38
39 class DesugaredLambdaExpression(_DesugaredLambdaExpression):
40     def __new__(cls, *args, **kwargs):
41         if 'name' not in kwargs:
42             kwargs['name'] = None
43
44         return super(DesugaredLambdaExpression, cls).__new__(cls, *args, **kwargs)
45
46 DesugaredListLiteralExpression = collections.namedtuple(
47     'DesugaredListLiteralExpression',
48     (
49         'item_expression_list',
50     ),
51 )
52
53 DesugaredStringLiteralExpression = collections.namedtuple(
54     'DesugaredStringLiteralExpression',
55     (
56         'string',
57     ),
58 )
59
60 DesugaredSymbolExpressionPair = collections.namedtuple(
61     'DesugaredSymbolExpressionPair',
62     (
63         'symbol',
64         'expression',
65     ),
66 )
67
68 DesugaredStructureLiteralExpression = collections.namedtuple(
69     'DesugaredStructureLiteralExpression',
70     (
71         'fields',
72     ),
73 )
74
75 DesugaredSymbolExpression = collections.namedtuple(
76     'DesugaredSymbolExpression',
77     (
78         'metadata',
79         'symbol',
80     ),
81 )
82
83 DesugaredAssignmentStatement = collections.namedtuple(
84     'DesugaredAssignmentStatement',
85     (
86         'target',
87         'expression',
88     ),
89 )
90
91 DesugaredExpressionStatement = collections.namedtuple(
92     'DesugaredExpressionStatement',
93     (
94         'expression',
95     ),
96 )
97
98 DesugaredProgram = collections.namedtuple(
99     'DesugaredProgram',
100     (
101         'statement_list',
102     ),
103 )
104
105 def desugar_function_call_expression(expression):
106     return DesugaredFunctionCallExpression(
107         metadata=expression.metadata,
108         function=desugar_expression(expression.function),
109         argument_list=tuple(desugar_expression(e) for e in expression.arguments),
110     )
111
112 def desugar_if_expression(expression):
113     return DesugaredIfExpression(
114         condition_expression=desugar_expression(expression.condition_expression),
115         if_statement_list=tuple(desugar_statement(s) for s in expression.if_statement_list),
116         else_statement_list=tuple(desugar_statement(s) for s in expression.else_statement_list),
117     )
118
119 def desugar_infix_expression(expression):
120     if expression.operator == 'and':
121         return DesugaredIfExpression(
122             condition_expression=desugar_expression(expression.left),
123             if_statement_list=(
124                 DesugaredExpressionStatement(expression=desugar_expression(expression.right)),
125             ),
126             else_statement_list=(
127                 DesugaredExpressionStatement(
128                     expression=DesugaredSymbolExpression(
129                         metadata=expression.metadata,
130                         symbol='false',
131                     ),
132                 ),
133             ),
134         )
135
136     if expression.operator == 'or':
137         return DesugaredIfExpression(
138             condition_expression=desugar_expression(expression.left),
139             if_statement_list=(
140                 DesugaredExpressionStatement(
141                     expression=DesugaredSymbolExpression(
142                         metadata=expression.metadata,
143                         symbol='true',
144                     ),
145                 ),
146             ),
147             else_statement_list=(
148                 DesugaredExpressionStatement(expression=desugar_expression(expression.right)),
149             ),
150         )
151
152     if expression.operator == '.':
153         return DesugaredFunctionCallExpression(
154             metadata=expression.metadata,
155             function=DesugaredSymbolExpression(
156                 metadata=expression.metadata,
157                 symbol='__field__',
158             ),
159             argument_list=(
160                 desugar_expression(expression.left),
161                 DesugaredStringLiteralExpression(string=expression.right.symbol),
162             ),
163         )
164
165     function = {
166         '++': '__concat__',
167         '+': '__add__',
168         '-': '__subtract__',
169         '*': '__multiply__',
170         '//': '__integer_divide__',
171         '%': '__modular_divide__',
172         '<': '__lt__',
173         '>': '__gt__',
174         '<=': '__lte__',
175         '>=': '__gte__',
176         '==': '__eq__',
177         '!=': '__neq__',
178     }[expression.operator]
179
180     return DesugaredFunctionCallExpression(
181         metadata=expression.metadata,
182         function=DesugaredSymbolExpression(
183             metadata=expression.metadata,
184             symbol=function,
185         ),
186         argument_list=(
187             desugar_expression(expression.left),
188             desugar_expression(expression.right),
189         ),
190     )
191
192 def desugar_integer_literal_expression(expression):
193     return DesugaredIntegerLiteralExpression(
194         integer=expression.integer,
195     )
196
197 def desugar_lambda_expression(expression):
198     return DesugaredLambdaExpression(
199         argument_name_list=expression.argument_name_list,
200         statement_list=tuple(desugar_statement(s) for s in expression.statement_list),
201     )
202
203 def desugar_list_item_expression(expression):
204     return DesugaredFunctionCallExpression(
205         metadata=expression.metadata,
206         function=DesugaredSymbolExpression(
207             metadata=expression.metadata,
208             symbol='__get__',
209         ),
210         argument_list=(
211             desugar_expression(expression.list_expression),
212             desugar_expression(expression.index_expression),
213         ),
214     )
215
216 def desugar_list_literal_expression(expression):
217     return DesugaredListLiteralExpression(
218         item_expression_list=tuple(desugar_expression(i) for i in expression.item_expression_list),
219     )
220
221 def desugar_negation_expression(expression):
222     return DesugaredFunctionCallExpression(
223         metadata=expression.metadata,
224         function=DesugaredSymbolExpression(
225             metadata=expression.metadata,
226             symbol='__negate__',
227         ),
228         argument_list=(
229             desugar_expression(expression.value),
230         ),
231     )
232
233 def desugar_string_literal_expression(expression):
234     return DesugaredStringLiteralExpression(
235         string=expression.string,
236     )
237
238 def desugar_structure_literal_expression(expression):
239     return DesugaredStructureLiteralExpression(
240         fields=tuple(
241             DesugaredSymbolExpressionPair(
242                 symbol=p.symbol,
243                 expression=desugar_expression(p.expression),
244             ) for p in expression.fields
245         ),
246     )
247
248 def desugar_symbol_expression(expression):
249     return DesugaredSymbolExpression(
250         metadata=expression.metadata,
251         symbol=expression.symbol,
252     )
253
254 def desugar_expression(expression):
255     return {
256         parsing.FurFunctionCallExpression: desugar_function_call_expression,
257         parsing.FurIfExpression: desugar_if_expression,
258         parsing.FurInfixExpression: desugar_infix_expression,
259         parsing.FurIntegerLiteralExpression: desugar_integer_literal_expression,
260         parsing.FurLambdaExpression: desugar_lambda_expression,
261         parsing.FurListItemExpression: desugar_list_item_expression,
262         parsing.FurListLiteralExpression: desugar_list_literal_expression,
263         parsing.FurNegationExpression: desugar_negation_expression,
264         parsing.FurStringLiteralExpression: desugar_string_literal_expression,
265         parsing.FurStructureLiteralExpression: desugar_structure_literal_expression,
266         parsing.FurSymbolExpression: desugar_symbol_expression,
267     }[type(expression)](expression)
268
269 def desugar_assignment_statement(statement):
270     return DesugaredAssignmentStatement(
271         target=statement.target,
272         expression=desugar_expression(statement.expression),
273     )
274
275 def desugar_expression_statement(statement):
276     return DesugaredExpressionStatement(
277         expression=desugar_expression(statement.expression),
278     )
279
280 def desugar_function_definition_statement(statement):
281     return DesugaredAssignmentStatement(
282         target=statement.name,
283         expression=DesugaredLambdaExpression(
284             name=statement.name,
285             argument_name_list=statement.argument_name_list,
286             statement_list=tuple(desugar_statement(s) for s in statement.statement_list),
287         ),
288     )
289
290 def desugar_statement(statement):
291     return {
292         parsing.FurAssignmentStatement: desugar_assignment_statement,
293         parsing.FurExpressionStatement: desugar_expression_statement,
294         parsing.FurFunctionDefinitionStatement: desugar_function_definition_statement,
295     }[type(statement)](statement)
296
297 def desugar(program):
298     return DesugaredProgram(
299         statement_list=[desugar_statement(s) for s in program.statement_list],
300     )