Add a CExpressionStatement to wrap expressions instead of passing them into statement...
[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 normalize_function_call_expression(counter, expression):
43     prestatements = []
44     arguments = []
45
46     for argument in expression.arguments:
47         variable = '${}'.format(counter)
48         prestatements.append(NormalVariableAssignmentStatement(
49             variable=variable,
50             expression=argument, # TODO Normalize each argument
51         ))
52         arguments.append(NormalVariableExpression(
53             variable=variable,
54         ))
55         counter += 1
56
57     return (
58         counter,
59         tuple(prestatements),
60         NormalFunctionCallExpression(
61             expression.function, # TODO Normalize the function
62             arguments=tuple(arguments),
63         ),
64     )
65
66 def normalize_statement(counter, statement):
67     if isinstance(statement, parsing.FurExpressionStatement):
68         counter, prestatements, normalized = {
69             parsing.FurFunctionCallExpression: normalize_function_call_expression,
70         }[type(statement.expression)](counter, statement.expression)
71
72         return (
73             counter,
74             prestatements,
75             NormalExpressionStatement(expression=normalized),
76         )
77
78     return (counter, (), statement)
79
80 def normalize(program):
81     counter = 0
82     statement_list = []
83
84     for statement in program.statement_list:
85         counter, prestatements, normalized = normalize_statement(counter, statement)
86         for s in prestatements:
87             statement_list.append(s)
88         statement_list.append(normalized)
89
90     return NormalProgram(
91         statement_list=statement_list,
92     )