Make it easier to run without memory leak tests
[fur] / transformation.py
index 56b61f3..a9cad95 100644 (file)
@@ -1,7 +1,6 @@
 import collections
 
 import conversion
-import normalization
 
 CIntegerLiteral = collections.namedtuple(
     'CIntegerLiteral',
@@ -117,19 +116,13 @@ CIfElseStatement = collections.namedtuple(
     ],
 )
 
-CFunctionDeclaration = collections.namedtuple(
-    'CFunctionDeclaration',
-    [
-        'name',
-    ],
-)
-
 # TODO If a function definition doesn't end with an expression, we have issues currently because we try to return statement.
 # TODO Closures currently wrap entire defining environment, even symbols that are not used, which makes garbage collection ineffective.
 CFunctionDefinition = collections.namedtuple(
     'CFunctionDefinition',
     [
         'name',
+        'index',
         'argument_name_list',
         'statement_list',
     ],
@@ -191,25 +184,25 @@ def transform_integer_literal_expression(accumulators, expression):
 
 CListConstructExpression = collections.namedtuple(
     'CListConstructExpression',
-    [
+    (
         'allocate',
-    ],
+    ),
+)
+
+CLambdaExpression = collections.namedtuple(
+    'CLambdaExpression',
+    (
+        'name',
+        'index',
+    ),
 )
 
 CListAppendStatement = collections.namedtuple(
     'CListAppendStatement',
-    [
+    (
         'list_expression',
         'item_expression',
-    ],
-)
-
-CListGetExpression = collections.namedtuple(
-    'CListGetExpression',
-    [
-        'list_expression',
-        'index_expression',
-    ],
+    ),
 )
 
 def transform_structure_literal_expression(accumulators, expression):
@@ -219,15 +212,31 @@ def transform_structure_literal_expression(accumulators, expression):
         value_list_variable=expression.value_list_variable,
     )
 
-def transform_list_construct_expression(accumulators, expression):
-    return CListConstructExpression(allocate=expression.allocate)
+def transform_lambda_expression(accumulators, expression):
+    if expression.name is None:
+        name = '__lambda'
+    else:
+        name = expression.name
 
-def transform_list_get_expression(accumulators, expression):
-    return CListGetExpression(
-        list_expression=transform_expression(accumulators, expression.list_expression),
-        index_expression=transform_expression(accumulators, expression.index_expression),
+    index = accumulators.function_name_iterators.get(name, 0)
+    accumulators.function_name_iterators[name] = index + 1
+
+    accumulators.function_definition_list.append(CFunctionDefinition(
+        name=name,
+        index=index,
+        argument_name_list=expression.argument_name_list,
+        statement_list=tuple(transform_statement(accumulators, s) for s in expression.statement_list),
+    ))
+
+    return CLambdaExpression(
+        name=name,
+        index=index,
     )
 
+
+def transform_list_construct_expression(accumulators, expression):
+    return CListConstructExpression(allocate=expression.allocate)
+
 def transform_list_append_statement(accumulators, expression):
     return CListAppendStatement(
         list_expression=transform_expression(accumulators, expression.list_expression),
@@ -238,8 +247,8 @@ def transform_expression(accumulators, expression):
     return {
         conversion.CPSFunctionCallExpression: transform_function_call_expression,
         conversion.CPSIntegerLiteralExpression: transform_integer_literal_expression,
+        conversion.CPSLambdaExpression: transform_lambda_expression,
         conversion.CPSListConstructExpression: transform_list_construct_expression,
-        normalization.NormalListGetExpression: transform_list_get_expression,
         conversion.CPSStructureLiteralExpression: transform_structure_literal_expression,
         conversion.CPSStringLiteralExpression: transform_string_literal_expression,
         conversion.CPSSymbolExpression: transform_symbol_expression,
@@ -319,20 +328,6 @@ def transform_variable_reassignment_statement(accumulators, statement):
         expression=transform_expression(accumulators, statement.expression),
     )
 
-def transform_function_definition_statement(accumulators, statement):
-    # TODO Allow defining the same function in different contexts
-    if any(fd.name == statement.name for fd in accumulators.function_definition_list):
-        raise Exception('A function with name "{}" already exists'.format(statement.name))
-
-    # TODO Add argument names to the symbol table
-    accumulators.function_definition_list.append(CFunctionDefinition(
-        name=statement.name,
-        argument_name_list=statement.argument_name_list,
-        statement_list=tuple(transform_statement(accumulators, s) for s in statement.statement_list)
-    ))
-
-    return CFunctionDeclaration(name=statement.name)
-
 def transform_push_statement(accumulators, statement):
     return CPushStatement(expression=transform_expression(accumulators, statement.expression))
 
@@ -341,7 +336,6 @@ def transform_statement(accumulators, statement):
         conversion.CPSArrayVariableInitializationStatement: transform_array_variable_initialization_statement,
         conversion.CPSAssignmentStatement: transform_symbol_assignment_statement,
         conversion.CPSExpressionStatement: transform_expression_statement,
-        conversion.CPSFunctionDefinitionStatement: transform_function_definition_statement,
         conversion.CPSIfElseStatement: transform_if_else_statement,
         conversion.CPSListAppendStatement: transform_list_append_statement,
         conversion.CPSPushStatement: transform_push_statement,
@@ -356,6 +350,7 @@ Accumulators = collections.namedtuple(
     [
         'builtin_set',
         'function_definition_list',
+        'function_name_iterators',
         'operator_set',
         'symbol_list',
         'string_literal_list',
@@ -366,6 +361,7 @@ def transform(program):
     accumulators = Accumulators(
         builtin_set=set(),
         function_definition_list=[],
+        function_name_iterators={},
         operator_set=set(),
         symbol_list=[],
         string_literal_list=[],