Some minor refactoring and added a (currently trivial) normalization step
authorDavid Kerkeslager <kerkeslager@gmail.com>
Tue, 8 Aug 2017 05:29:14 +0000 (01:29 -0400)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Tue, 8 Aug 2017 05:29:14 +0000 (01:29 -0400)
generation.py
main.py
normalization.py [new file with mode: 0644]
parsing.py
transformation.py

index 26945a2..816ebc9 100644 (file)
@@ -28,12 +28,12 @@ def generate_symbol_expression(c_symbol_expression):
         c_symbol_expression.symbol,
     )
 
-def generate_expression(c_argument):
-    if isinstance(c_argument, transformation.CNegationExpression):
-        return generate_negation_expression(c_argument)
+def generate_expression(expression):
+    if isinstance(expression, transformation.CNegationExpression):
+        return generate_negation_expression(expression)
 
-    if isinstance(c_argument, transformation.CFunctionCallExpression):
-        return generate_function_call(c_argument)
+    if isinstance(expression, transformation.CFunctionCallExpression):
+        return generate_function_call(expression)
 
     LITERAL_TYPE_MAPPING = {
         transformation.CIntegerLiteral: generate_integer_literal,
@@ -42,17 +42,17 @@ def generate_expression(c_argument):
         transformation.CSymbolExpression: generate_symbol_expression,
     }
 
-    if type(c_argument) in LITERAL_TYPE_MAPPING:
-        return LITERAL_TYPE_MAPPING[type(c_argument)](c_argument)
+    if type(expression) in LITERAL_TYPE_MAPPING:
+        return LITERAL_TYPE_MAPPING[type(expression)](expression)
 
-    if isinstance(c_argument, transformation.CFunctionCallForFurInfixOperator):
+    if isinstance(expression, transformation.CFunctionCallForFurInfixOperator):
         return 'builtin${}({}, {})'.format(
-            c_argument.name,
-            generate_expression(c_argument.left),
-            generate_expression(c_argument.right),
+            expression.name,
+            generate_expression(expression.left),
+            generate_expression(expression.right),
         )
 
-    raise Exception('Could not handle expresssion "{}"'.format(c_argument))
+    raise Exception('Could not handle expresssion "{}"'.format(expression))
 
 def generate_negation_expression(c_negation_expression):
     return 'builtin$negate({})'.format(
@@ -82,14 +82,14 @@ def generate_statement(statement):
 
     return generate_expression_statement(statement)
 
-def generate(c_program):
+def generate(program):
     template = ENV.get_template('program.c')
     return template.render(
-        builtins=list(sorted(c_program.builtin_set)),
-        statements=[generate_statement(statement) for statement in c_program.statements],
-        standard_libraries=list(sorted(c_program.standard_libraries)),
-        string_literal_list=c_program.string_literal_list,
-        symbol_list=c_program.symbol_list,
+        builtins=list(sorted(program.builtin_set)),
+        statements=[generate_statement(statement) for statement in program.statements],
+        standard_libraries=list(sorted(program.standard_libraries)),
+        string_literal_list=program.string_literal_list,
+        symbol_list=program.symbol_list,
     )
 
 if __name__ == '__main__':
diff --git a/main.py b/main.py
index c2592c6..be48e78 100644 (file)
--- a/main.py
+++ b/main.py
@@ -1,6 +1,7 @@
 import sys
 
 import generation
+import normalization
 import parsing
 import tokenization
 import transformation
@@ -12,7 +13,8 @@ with open(source_path, 'r') as f:
 
 tokens = tokenization.tokenize(source)
 parsed = parsing.parse(tokens)
-transformed = transformation.transform(parsed)
+normalized = normalization.normalize(parsed)
+transformed = transformation.transform(normalized)
 generated = generation.generate(transformed)
 
 assert source_path.endswith('.fur')
diff --git a/normalization.py b/normalization.py
new file mode 100644 (file)
index 0000000..1cddaed
--- /dev/null
@@ -0,0 +1,19 @@
+import collections
+
+NormalProgram = collections.namedtuple(
+    'NormalProgram',
+    [
+        'statement_list',
+    ],
+)
+
+def flatten(iterable):
+    return tuple(item for internal in iterable for item in internal)
+
+def normalize_statement(statement):
+    return (statement,)
+
+def normalize(program):
+    return NormalProgram(
+        statement_list=flatten(normalize_statement(s) for s in program.statement_list),
+    )
index a7dd838..aa4f427 100644 (file)
@@ -244,6 +244,13 @@ FurFunctionCallExpression = collections.namedtuple(
     ],
 )
 
+FurExpressionStatement = collections.namedtuple(
+    'FurExpressionStatement',
+    [
+        'expression',
+    ],
+)
+
 FurAssignmentStatement = collections.namedtuple(
     'FurAssignmentStatement',
     [
@@ -288,6 +295,16 @@ def _function_call_expression_parser(index, tokens):
 
 _expression_parser = _or_level_expression_parser
 
+def _expression_statement_parser(index, tokens):
+    failure = (False, index, None)
+
+    success, index, expression = _expression_parser(index, tokens)
+
+    if not success:
+        return failure
+
+    return (True, index, FurExpressionStatement(expression=expression))
+
 def _assignment_statement_parser(index, tokens):
     # TODO Use a FurSymbolExpression for the target? Maybe this is actually not a good idea
     failure = (False, index, None)
@@ -320,7 +337,7 @@ def _statement_parser(index, tokens):
 
     return _or_parser(
         _assignment_statement_parser,
-        _expression_parser,
+        _expression_statement_parser,
     )(index, tokens)
 
 def _program_formatter(statement_list):
index b75b3a0..98398f8 100644 (file)
@@ -221,10 +221,15 @@ def transform_function_call_expression(accumulators, function_call):
 
     raise Exception()
 
+def transform_expression_statement(accumulators, statement):
+    return {
+        parsing.FurFunctionCallExpression: transform_function_call_expression,
+    }[type(statement.expression)](accumulators, statement.expression)
+
 def transform_statement(accumulators, statement):
     return {
         parsing.FurAssignmentStatement: transform_assignment_statement,
-        parsing.FurFunctionCallExpression: transform_function_call_expression,
+        parsing.FurExpressionStatement: transform_expression_statement,
     }[type(statement)](accumulators, statement)
 
 
@@ -244,19 +249,19 @@ def transform(program):
         string_literal_list=[],
     )
 
-    c_statements = [
+    statement_list = [
         transform_statement(accumulators, statement) for statement in program.statement_list
     ]
 
-    standard_libraries = set()
+    standard_library_set = set()
     for builtin in accumulators.builtin_set:
         for standard_library in BUILTINS[builtin]:
-            standard_libraries.add(standard_library)
+            standard_library_set.add(standard_library)
 
     return CProgram(
         builtin_set=accumulators.builtin_set,
-        statements=c_statements,
-        standard_libraries=standard_libraries,
+        statements=statement_list,
+        standard_libraries=standard_library_set,
         string_literal_list=accumulators.string_literal_list,
         symbol_list=accumulators.symbol_list,
     )