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