Normalize all the arguments to functions
[fur] / normalization.py
1 import collections
2
3 import parsing
4
5 NormalVariableExpression = collections.namedtuple(
6     'NormalVariableExpression',
7     [
8         'variable',
9     ],
10 )
11
12 NormalVariableAssignmentStatement = collections.namedtuple(
13     'NormalVariableAssignmentStatement',
14     [
15         'variable',
16         'expression',
17     ],
18 )
19
20 NormalFunctionCallExpression = collections.namedtuple(
21     'NormalFunctionCallExpression',
22     [
23         'function',
24         'arguments',
25     ],
26 )
27
28 NormalExpressionStatement = collections.namedtuple(
29     'NormalExpressionStatement',
30     [
31         'expression',
32     ],
33 )
34
35 NormalProgram = collections.namedtuple(
36     'NormalProgram',
37     [
38         'statement_list',
39     ],
40 )
41
42 def fake_normalization(counter, thing):
43     return (counter, (), thing)
44
45 def normalize_function_call_expression(counter, expression):
46     assert isinstance(expression, parsing.FurFunctionCallExpression)
47
48     prestatements = []
49     arguments = []
50
51     for argument in expression.arguments:
52         counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
53
54         for s in argument_prestatements:
55             prestatements.append(s)
56
57         variable = '${}'.format(counter)
58         prestatements.append(NormalVariableAssignmentStatement(
59             variable=variable,
60             expression=normalized_argument,
61         ))
62         arguments.append(NormalVariableExpression(
63             variable=variable,
64         ))
65         counter += 1
66
67     return (
68         counter,
69         tuple(prestatements),
70         NormalFunctionCallExpression(
71             expression.function, # TODO Normalize the function
72             arguments=tuple(arguments),
73         ),
74     )
75
76 def normalize_expression(counter, expression):
77     return {
78         parsing.FurFunctionCallExpression: normalize_function_call_expression,
79         parsing.FurInfixExpression: fake_normalization, # TODO This should not be faked
80         parsing.FurIntegerLiteralExpression: fake_normalization,
81         parsing.FurNegationExpression: fake_normalization,
82         parsing.FurStringLiteralExpression: fake_normalization,
83         parsing.FurSymbolExpression: fake_normalization,
84     }[type(expression)](counter, expression)
85
86 def normalize_expression_statement(counter, statement):
87     counter, prestatements, normalized = {
88         parsing.FurFunctionCallExpression: normalize_function_call_expression,
89     }[type(statement.expression)](counter, statement.expression)
90
91     return (
92         counter,
93         prestatements,
94         NormalExpressionStatement(expression=normalized),
95     )
96
97 def normalize_statement(counter, statement):
98     return {
99         parsing.FurExpressionStatement: normalize_expression_statement,
100         parsing.FurAssignmentStatement: fake_normalization,
101     }[type(statement)](counter, statement)
102
103 def normalize(program):
104     counter = 0
105     statement_list = []
106
107     for statement in program.statement_list:
108         counter, prestatements, normalized = normalize_statement(counter, statement)
109         for s in prestatements:
110             statement_list.append(s)
111         statement_list.append(normalized)
112
113     return NormalProgram(
114         statement_list=statement_list,
115     )