Begin adding some C code
[fur] / crossplatform_ir_generation.py
index d753103..54b296e 100644 (file)
@@ -2,6 +2,9 @@ import collections
 
 import conversion
 
+def flatten(xses):
+    return tuple(x for xs in xses for x in xs)
+
 CIRProgram = collections.namedtuple(
     'CIRProgram',
     (
@@ -9,11 +12,10 @@ CIRProgram = collections.namedtuple(
     ),
 )
 
-CIREntry = collections.namedtuple(
-    'CIREntry',
+CIRLabel = collections.namedtuple(
+    'CIRLabel',
     (
-        'name',
-        'instruction_list',
+        'label',
     ),
 )
 
@@ -34,137 +36,239 @@ def generate_string_literal(string):
 def generate_symbol_literal(symbol):
     return 'sym({})'.format(symbol)
 
-def generate_function_call_expression(expression):
-    return generate_expression(expression.function_expression) + (
+def generate_function_call_expression(counters, expression):
+    referenced_entry_list, instruction_list = generate_expression(
+        counters,
+        expression.function_expression,
+    )
+
+    instruction_list += (
         CIRInstruction(
             instruction='call',
             argument=expression.argument_count,
         ),
     )
 
-def generate_integer_literal_expression(expression):
-    return (CIRInstruction(
+    return referenced_entry_list, instruction_list
+
+def generate_integer_literal_expression(counters, expression):
+    referenced_entry_list = ()
+    instruction_list = (CIRInstruction(
         instruction='push_value',
         argument=generate_integer_literal(expression.integer),
     ),)
 
-def generate_string_literal_expression(expression):
-    return (CIRInstruction(
+    return referenced_entry_list, instruction_list
+
+def generate_lambda_expression(counters, expression):
+    if expression.name is None or 'lambda' in expression.name.lower():
+        import ipdb; ipdb.set_trace()
+
+    name_counter = counters.get(expression.name, 0)
+    counters[expression.name] = name_counter + 1
+    label = '{}${}'.format(expression.name, name_counter)
+
+    for argument_name in expression.argument_name_list:
+        import ipdb; ipdb.set_trace()
+
+    referenced_entry_list_list = []
+    instruction_list_list = []
+
+    for statement in expression.statement_list:
+        referenced_entry_list, instruction_list = generate_statement(counters, statement)
+        referenced_entry_list_list.append(referenced_entry_list)
+        instruction_list_list.append(instruction_list)
+
+    referenced_entry_list_list.append(
+        (CIRLabel(label=label),) + flatten(instruction_list_list),
+    )
+
+    instruction_list = (
+        CIRInstruction(instruction='close', argument=label),
+    )
+
+    return flatten(referenced_entry_list_list), instruction_list
+
+def generate_string_literal_expression(counters, expression):
+    referenced_entry_list = ()
+    instruction_list = (CIRInstruction(
         instruction='push_value',
         argument=generate_string_literal(expression.string),
     ),)
 
-def generate_symbol_expression(expression):
-    return (CIRInstruction(
+    return referenced_entry_list, instruction_list
+
+def generate_symbol_expression(counters, expression):
+    referenced_entry_list = ()
+    instruction_list = (CIRInstruction(
         instruction='push',
         argument=generate_symbol_literal(expression.symbol),
     ),)
 
-def generate_variable_expression(expression):
-    return (CIRInstruction(
+    return referenced_entry_list, instruction_list
+
+def generate_variable_expression(counters, expression):
+    referenced_entry_list = ()
+    instruction_list = (CIRInstruction(
         instruction='push',
         argument=generate_symbol_literal(expression.variable),
     ),)
 
-def generate_expression(expression):
+    return referenced_entry_list, instruction_list
+
+def generate_expression(counters, expression):
     return {
         conversion.CPSFunctionCallExpression: generate_function_call_expression,
         conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression,
+        conversion.CPSLambdaExpression: generate_lambda_expression,
         conversion.CPSStringLiteralExpression: generate_string_literal_expression,
         conversion.CPSSymbolExpression: generate_symbol_expression,
         conversion.CPSVariableExpression: generate_variable_expression,
-    }[type(expression)](expression)
+    }[type(expression)](counters, expression)
 
-def generate_expression_statement(statement):
-    return (
-        (),
-        generate_expression(statement.expression) + (
-            CIRInstruction(
-                instruction='drop',
-                argument=None,
-            ),
+def generate_expression_statement(counters, statement):
+    referenced_entry_list, instruction_list = generate_expression(
+        counters,
+        statement.expression,
+    )
+
+    instruction_list += (
+        CIRInstruction(
+            instruction='drop',
+            argument=None,
         ),
     )
 
-def generate_if_else_statement(statement):
-    import ipdb; ipdb.set_trace()
+    return referenced_entry_list, instruction_list
+
+def generate_if_else_statement(counters, statement):
+    if_counter = counters['if']
+    counters['if'] += 1
+
+    referenced_entry_list_list = []
+
+    if_instruction_list_list = []
+    for if_statement in statement.if_statement_list:
+        referenced_entry_list, instruction_list = generate_statement(counters, if_statement)
+        referenced_entry_list_list.append(referenced_entry_list)
+        if_instruction_list_list.append(instruction_list)
+
+    else_instruction_list_list = []
+
+    for else_statement in statement.else_statement_list:
+        referenced_entry_list, instruction_list = generate_statement(counters, else_statement)
+        referenced_entry_list_list.append(referenced_entry_list)
+        else_instruction_list_list.append(instruction_list)
+
+    if_label = '__if${}__'.format(if_counter)
+    else_label = '__else${}__'.format(if_counter)
+    endif_label = '__endif${}__'.format(if_counter)
 
-def generate_assignment_statement(statement):
-    return (
-        (),
-        generate_expression(statement.expression) + (
+    instruction_list = (
+        referenced_entry_list_list,
+        generate_expression(counters, statement.condition_expression) + (
+            CIRInstruction(
+                instruction='jump_if_false',
+                argument=else_label,
+            ),
+            CIRLabel(label=if_label),
+        ) + flatten(if_instruction_list_list) + (
             CIRInstruction(
-                instruction='pop',
-                argument=generate_symbol_literal(statement.target),
+                instruction='jump',
+                argument=endif_label,
             ),
+            CIRLabel(label=else_label),
+        ) + flatten(else_instruction_list_list) + (
+            CIRLabel(label=endif_label),
         ),
     )
 
-def generate_push_statement(statement):
-    return (
-        (),
-        generate_expression(statement.expression),
+    return flatten(referenced_entry_list_list), instruction_list
+
+def generate_assignment_statement(counters, statement):
+    referenced_entry_list, instruction_list = generate_expression(
+        counters,
+        statement.expression,
     )
 
-def generate_variable_initialization_statement(statement):
-    return (
-        (),
-        generate_expression(statement.expression) + (
-            CIRInstruction(
-                instruction='pop',
-                argument=generate_symbol_literal(statement.variable),
-            ),
+    instruction_list += (
+        CIRInstruction(
+            instruction='pop',
+            argument=generate_symbol_literal(statement.target),
+        ),
+    )
+
+    return referenced_entry_list, instruction_list
+
+def generate_push_statement(counters, statement):
+    return generate_expression(counters, statement.expression)
+
+def generate_variable_initialization_statement(counters, statement):
+    referenced_entry_list, instruction_list = generate_expression(
+        counters,
+        statement.expression,
+    )
+
+    instruction_list += (
+        CIRInstruction(
+            instruction='pop',
+            argument=generate_symbol_literal(statement.variable),
         ),
     )
 
-def generate_statement(statement):
+    return referenced_entry_list, instruction_list
+
+def generate_variable_reassignment_statement(counters, statement):
+    referenced_entry_list, instruction_list = generate_expression(
+        counters,
+        statement.expression,
+    )
+
+    instruction_list += (
+        CIRInstruction(
+            instruction='pop',
+            argument=generate_symbol_literal(statement.variable),
+        ),
+    )
+
+    return referenced_entry_list, instruction_list
+
+def generate_statement(counters, statement):
     return {
         conversion.CPSAssignmentStatement: generate_assignment_statement,
         conversion.CPSExpressionStatement: generate_expression_statement,
         conversion.CPSIfElseStatement: generate_if_else_statement,
         conversion.CPSPushStatement: generate_push_statement,
         conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement,
-    }[type(statement)](statement)
+        conversion.CPSVariableReassignmentStatement: generate_variable_reassignment_statement,
+    }[type(statement)](counters, statement)
 
 def generate(converted):
     referenced_entry_list_list = []
     instruction_list_list = []
+    counters = {
+        'if': 0,
+    }
 
     for statement in converted.statement_list:
-        referenced_entry_list, instruction_list = generate_statement(statement)
+        referenced_entry_list, instruction_list = generate_statement(counters, statement)
         referenced_entry_list_list.append(referenced_entry_list)
         instruction_list_list.append(instruction_list)
 
     return CIRProgram(
-        entry_list=tuple(
-            entry
-            for referenced_entry_list in referenced_entry_list_list
-            for entry in referenced_entry_list
-        ) + (CIREntry(
-            name='__main__',
-            instruction_list=tuple(
-                instruction
-                for instruction_list in instruction_list_list
-                for instruction in instruction_list
-            ),
-        ),),
+        entry_list=(
+            CIRLabel(label='__main__'),
+        ) + flatten(referenced_entry_list_list) + flatten(instruction_list_list),
     )
 
 def output(program):
-    entry_outputs = []
+    lines = []
 
     for entry in program.entry_list:
-        statement_outputs = []
-
-        for instruction in entry.instruction_list:
-            statement_outputs.append('    {} {}'.format(
-                instruction.instruction,
-                instruction.argument,
-            ))
+        if isinstance(entry, CIRInstruction):
+            lines.append('    {} {}'.format(entry.instruction, entry.argument))
 
-        entry_outputs.append('{}:\n{}'.format(
-            entry.name,
-            '\n'.join(statement_outputs),
-        ))
+        if isinstance(entry, CIRLabel):
+            lines.append('\n{}:'.format(entry.label))
 
-    return '\n\n'.join(entry_outputs)
+    return '\n'.join(lines).lstrip()