From: David Kerkeslager Date: Wed, 28 Aug 2019 03:37:41 +0000 (-0400) Subject: Add support for lists to IR, clean up X-Git-Url: https://code.kerkeslager.com/?a=commitdiff_plain;h=7b12616d21169685753b6e530569e431d45427b3;p=fur Add support for lists to IR, clean up --- diff --git a/crossplatform_ir_generation.py b/crossplatform_ir_generation.py index c6adb95..9d3ab4b 100644 --- a/crossplatform_ir_generation.py +++ b/crossplatform_ir_generation.py @@ -97,6 +97,14 @@ def generate_lambda_expression(counters, expression): return flatten(referenced_entry_list_list), instruction_list +def generate_list_construct_expression(counters, expression): + referenced_entry_list = () + instruction_list = (CIRInstruction( + instruction='list', + argument=2, + ),) + return referenced_entry_list, instruction_list + def generate_string_literal_expression(counters, expression): referenced_entry_list = () instruction_list = (CIRInstruction( @@ -130,6 +138,7 @@ def generate_expression(counters, expression): conversion.CPSIfElseExpression: generate_if_else_expression, conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression, conversion.CPSLambdaExpression: generate_lambda_expression, + conversion.CPSListConstructExpression: generate_list_construct_expression, conversion.CPSStringLiteralExpression: generate_string_literal_expression, conversion.CPSSymbolExpression: generate_symbol_expression, conversion.CPSVariableExpression: generate_variable_expression, diff --git a/generation.py b/generation.py deleted file mode 100644 index 645441f..0000000 --- a/generation.py +++ /dev/null @@ -1,192 +0,0 @@ -import jinja2 - -import transformation - -ENV = jinja2.Environment( - autoescape=jinja2.select_autoescape([]), - loader=jinja2.FileSystemLoader('templates'), - trim_blocks=True, -) - -def generate_integer_literal(c_integer_literal): - return 'integerLiteral({})'.format(c_integer_literal.value) - -def generate_string_literal(c_string_literal): - return 'stringLiteral(STRING_LITERAL_LIST[{}] /* string: {} */)'.format( - c_string_literal.index, - repr(c_string_literal.value), - ) - -def generate_symbol_expression(symbol_expression): - return 'Environment_get(environment, SYMBOL_LIST[{}] /* symbol: {} */)'.format( - symbol_expression.symbol_list_index, - symbol_expression.symbol, - ) - -def generate_variable_expression(expression): - return expression.variable - -def generate_structure_literal_expression(expression): - return 'Structure_construct({}, {}, {})'.format( - expression.field_count, - expression.symbol_list_variable, - expression.value_list_variable, - ) - -def generate_lambda_expression(expression): - return '(Object){{ CLOSURE, (Instance)(Closure){{ environment, user${}${}$implementation }} }}'.format( - expression.name, - expression.index, - ) - -def generate_list_construct_expression(expression): - return 'List_construct({})'.format(expression.allocate) - -def generate_expression(expression): - return { - transformation.CFunctionCallExpression: generate_function_call, - transformation.CIfElseExpression: generate_if_else_expression, - transformation.CIntegerLiteral: generate_integer_literal, - transformation.CLambdaExpression: generate_lambda_expression, - transformation.CListConstructExpression: generate_list_construct_expression, - transformation.CStringLiteral: generate_string_literal, - transformation.CStructureLiteralExpression: generate_structure_literal_expression, - transformation.CSymbolExpression: generate_symbol_expression, - transformation.CVariableExpression: generate_variable_expression, - }[type(expression)](expression) - -def generate_function_call(function_call): - # This gets called twice, so we want to be sure it is efficient and without side effects - assert isinstance(function_call.function_expression, transformation.CSymbolExpression) - - # TODO Check the type of the things being called - function_expression = generate_expression(function_call.function_expression) - return '{}.instance.closure.call(environmentPool, {}.instance.closure.closed, {}, stack, {}, jump)'.format( - function_expression, - function_expression, - function_call.argument_count, - function_call.metadata.line, - ) - -def generate_expression_statement(statement): - return 'Object_deinitialize(&({}));'.format(generate_expression(statement.expression)) - -def generate_symbol_assignment_statement(statement): - return 'Environment_set(environment, SYMBOL_LIST[{}] /* symbol: {} */, {});'.format( - statement.target_symbol_list_index, - statement.target, - generate_expression(statement.expression), - ) - -def generate_array_variable_initialization_statement(statement): - return 'Object {}[] = {{ {} }};'.format( - statement.variable, - ', '.join(generate_expression(i) for i in statement.items), - ) - -def generate_symbol_array_variable_initialization_statement(statement): - return 'const char* {}[] = {{ {} }};'.format( - statement.variable, - ', '.join('SYMBOL_LIST[{}] /* symbol: "{}" */'.format( - statement.symbol_list_indices[i], - statement.symbol_list[i], - ) for i in range(len(statement.symbol_list))), - ) - -def generate_variable_initialization_statement(statement): - return 'Object {} = {};'.format( - statement.variable, - generate_expression(statement.expression), - ) - -def indent(s): - return '\n'.join(' ' * 2 + l for l in s.split('\n')) - -def generate_if_else_expression(statement): - # TODO Check that the argument is boolean - condition_expression = '{}.instance.boolean'.format( - generate_expression(statement.condition_expression), - ) - - if len(statement.if_statement_list) == 0: - condition_expression = '!({})'.format(condition_expression) - if_statement_list = statement.else_statement_list - else_statement_list = () - else: - if_statement_list = statement.if_statement_list - else_statement_list = statement.else_statement_list - - generated_if_clause = 'if({})'.format(condition_expression) - - if len(if_statement_list) == 0: - generated_if_statement_list = ';' - else: - generated_if_statement_list = indent('\n{{\n{}\n}}'.format( - indent('\n'.join(generate_statement(s) for s in if_statement_list)), - )) - - if len(else_statement_list) == 0: - generated_else_statement_list = '' - else: - generated_else_statement_list = indent('\nelse\n{{\n{}\n}}'.format( - indent('\n'.join(generate_statement(s) for s in else_statement_list)), - )) - - return generated_if_clause + generated_if_statement_list + generated_else_statement_list - -def generate_list_append_statement(statement): - return 'List_append(&{}, {});'.format( - generate_expression(statement.list_expression), - generate_expression(statement.item_expression), - ) - -def generate_push_statement(statement): - return 'Stack_push(stack, {});'.format(generate_expression(statement.expression)) - -def generate_statement(statement): - return { - transformation.CArrayVariableInitializationStatement: generate_array_variable_initialization_statement, - transformation.CExpressionStatement: generate_expression_statement, - transformation.CListAppendStatement: generate_list_append_statement, - transformation.CPushStatement: generate_push_statement, - transformation.CSymbolAssignmentStatement: generate_symbol_assignment_statement, - transformation.CSymbolArrayVariableInitializationStatement: generate_symbol_array_variable_initialization_statement, - transformation.CVariableInitializationStatement: generate_variable_initialization_statement, - }[type(statement)](statement) - -def generate_function_definition(definition): - template = ENV.get_template('function_definition.c') - return template.render( - name=definition.name, - index=definition.index, - argument_name_list=definition.argument_name_list, - statement_list=list(generate_statement(s) for s in definition.statement_list), - ) - return definition - -C_ESCAPES = { - '"': r'\"', -} - -def escape_character(ch): - return C_ESCAPES.get(ch, ch) - -def escape_string_literal(string_literal): - return ''.join(escape_character(ch) for ch in string_literal) - -def generate(program): - template = ENV.get_template('program.c') - return template.render( - builtins=tuple(sorted(program.builtin_set)), - function_definition_list=list(generate_function_definition(fd) for fd in program.function_definition_list), - infix_declarations=program.operator_declarations, - statements=list(generate_statement(s) for s in program.statements), - standard_libraries=list(sorted(program.standard_libraries)), - string_literal_list=list(escape_string_literal(s) for s in program.string_literal_list), - symbol_list=program.symbol_list, - ) - -if __name__ == '__main__': - import unittest - - unittest.main() diff --git a/main.py b/main.py index 198072e..7deafb8 100644 --- a/main.py +++ b/main.py @@ -3,12 +3,10 @@ import sys import conversion import crossplatform_ir_generation import desugaring -import generation import normalization import optimization import parsing import tokenization -import transformation source_path = sys.argv[1] @@ -21,15 +19,12 @@ desugared = desugaring.desugar(parsed) normalized = normalization.normalize(desugared) converted = conversion.convert(normalized) -# This is the C generation path -transformed = transformation.transform(converted) -generated = generation.generate(transformed) - assert source_path.endswith('.fur') destination_path = source_path + '.c' with open(destination_path, 'w') as f: - f.write(generated) + pass + #f.write(generated) # This is the crossplatform IR generation path crossplatform_ir = crossplatform_ir_generation.generate(converted) diff --git a/normalization.py b/normalization.py index 7ce7488..76c5395 100644 --- a/normalization.py +++ b/normalization.py @@ -160,12 +160,7 @@ def normalize_list_literal_expression(counter, expression): list_variable = '${}'.format(counter) counter += 1 - prestatements = [ - NormalVariableInitializationStatement( - variable=list_variable, - expression=NormalListConstructExpression(allocate=len(expression.item_expression_list)), - ), - ] + prestatements = [] list_expression = NormalVariableExpression(variable=list_variable) @@ -179,12 +174,16 @@ def normalize_list_literal_expression(counter, expression): prestatements.append(p) prestatements.append( - NormalListAppendStatement( - list_expression=list_expression, - item_expression=normalized, + NormalPushStatement( + expression=normalized, ) ) + prestatements.append(NormalVariableInitializationStatement( + variable=list_variable, + expression=NormalListConstructExpression(allocate=len(expression.item_expression_list)), + )) + return ( counter, tuple(prestatements), diff --git a/transformation.py b/transformation.py deleted file mode 100644 index 6aa7080..0000000 --- a/transformation.py +++ /dev/null @@ -1,378 +0,0 @@ -import collections - -import conversion - -CIntegerLiteral = collections.namedtuple( - 'CIntegerLiteral', - [ - 'value', - ], -) - -CStringLiteral = collections.namedtuple( - 'CStringLiteral', - [ - 'index', - 'value', - ], -) - -CVariableExpression = collections.namedtuple( - 'CVariableExpression', - [ - 'variable', - ], -) - -CSymbolExpression = collections.namedtuple( - 'CSymbolExpression', - [ - 'symbol', - 'symbol_list_index', - ], -) - -CStructureLiteralExpression = collections.namedtuple( - 'CStructureLiteralExpression', - [ - 'field_count', - 'symbol_list_variable', - 'value_list_variable', - ], -) - -CPushStatement = collections.namedtuple( - 'CPushStatement', - ( - 'expression', - ), -) - -CFunctionCallExpression = collections.namedtuple( - 'CFunctionCallExpression', - ( - 'metadata', - 'function_expression', - 'argument_count', - ), -) - -# TODO We are currently not changing variables, just preventing them from being accessed. -CSymbolAssignmentStatement = collections.namedtuple( - 'CSymbolAssignmentStatement', - [ - 'target', - 'target_symbol_list_index', - 'expression', - ], -) - -CArrayVariableInitializationStatement = collections.namedtuple( - 'CArrayVariableInitializationStatement', - [ - 'variable', - 'items', - ], -) - -CSymbolArrayVariableInitializationStatement = collections.namedtuple( - 'CSymbolArrayVariableInitializationStatement', - [ - 'variable', - 'symbol_list', - 'symbol_list_indices', - ], -) - -CVariableInitializationStatement = collections.namedtuple( - 'CVariableInitializationStatement', - [ - 'variable', - 'expression', - ], -) - -CExpressionStatement = collections.namedtuple( - 'CExpressionStatement', - [ - 'expression', - ], -) - -CIfElseExpression = collections.namedtuple( - 'CIfElseExpression', - [ - 'condition_expression', - 'if_statement_list', - 'else_statement_list', - ], -) - -# 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', - ], -) - -CProgram = collections.namedtuple( - 'CProgram', - [ - 'builtin_set', - 'function_definition_list', - 'operator_declarations', - 'statements', - 'standard_libraries', - 'string_literal_list', - 'symbol_list', - ], -) - -BUILTINS = { - 'concatenate': [], - 'false': [], - 'pow': ['math.h'], - 'print': ['stdio.h'], - 'true': [], -} - -def transform_variable_expression(accumulators, expression): - assert isinstance(expression, conversion.CPSVariableExpression) - return CVariableExpression(variable=expression.variable) - -def transform_string_literal_expression(accumulators, expression): - value = expression.string - - try: - index = accumulators.string_literal_list.index(value) - except ValueError: - index = len(accumulators.string_literal_list) - accumulators.string_literal_list.append(value) - - return CStringLiteral(index=index, value=value) - -def transform_symbol_expression(accumulators, expression): - if expression.symbol in BUILTINS: - accumulators.builtin_set.add(expression.symbol) - - try: - symbol_list_index = accumulators.symbol_list.index(expression.symbol) - except ValueError: - symbol_list_index = len(accumulators.symbol_list) - accumulators.symbol_list.append(expression.symbol) - - return CSymbolExpression( - symbol=expression.symbol, - symbol_list_index=symbol_list_index, - ) - -def transform_integer_literal_expression(accumulators, expression): - return CIntegerLiteral(value=expression.integer) - -CListConstructExpression = collections.namedtuple( - 'CListConstructExpression', - ( - 'allocate', - ), -) - -CLambdaExpression = collections.namedtuple( - 'CLambdaExpression', - ( - 'name', - 'index', - ), -) - -CListAppendStatement = collections.namedtuple( - 'CListAppendStatement', - ( - 'list_expression', - 'item_expression', - ), -) - -def transform_structure_literal_expression(accumulators, expression): - return CStructureLiteralExpression( - field_count=expression.field_count, - symbol_list_variable=expression.symbol_list_variable, - value_list_variable=expression.value_list_variable, - ) - -def transform_lambda_expression(accumulators, expression): - if expression.name is None: - name = '__lambda' - else: - name = expression.name - - 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), - item_expression=transform_expression(accumulators, expression.item_expression), - ) - -def transform_expression(accumulators, expression): - return { - conversion.CPSFunctionCallExpression: transform_function_call_expression, - conversion.CPSIfElseExpression: transform_if_else_expression, - conversion.CPSIntegerLiteralExpression: transform_integer_literal_expression, - conversion.CPSLambdaExpression: transform_lambda_expression, - conversion.CPSListConstructExpression: transform_list_construct_expression, - conversion.CPSStructureLiteralExpression: transform_structure_literal_expression, - conversion.CPSStringLiteralExpression: transform_string_literal_expression, - conversion.CPSSymbolExpression: transform_symbol_expression, - conversion.CPSVariableExpression: transform_variable_expression, - }[type(expression)](accumulators, expression) - -def transform_symbol_assignment_statement(accumulators, assignment_statement): - # TODO Check that target is not a builtin - try: - symbol_list_index = accumulators.symbol_list.index(assignment_statement.target) - except ValueError: - symbol_list_index = len(accumulators.symbol_list) - accumulators.symbol_list.append(assignment_statement.target) - - return CSymbolAssignmentStatement( - target=assignment_statement.target, - target_symbol_list_index=symbol_list_index, - expression=transform_expression( - accumulators, - assignment_statement.expression, - ), - ) - -def transform_function_call_expression(accumulators, function_call): - # TODO Use the symbol from SYMBOL LIST - return CFunctionCallExpression( - metadata=function_call.metadata, - function_expression=transform_expression(accumulators, function_call.function_expression), - argument_count=function_call.argument_count, - ) - -def transform_expression_statement(accumulators, statement): - return CExpressionStatement( - expression=transform_expression(accumulators, statement.expression), - ) - -def transform_if_else_expression(accumulators, statement): - return CIfElseExpression( - condition_expression=transform_expression(accumulators, statement.condition_expression), - if_statement_list=tuple(transform_statement(accumulators, s) for s in statement.if_statement_list), - else_statement_list=tuple(transform_statement(accumulators, s) for s in statement.else_statement_list), - ) - -def transform_array_variable_initialization_statement(accumulators, statement): - return CArrayVariableInitializationStatement( - variable=statement.variable, - items=tuple(transform_expression(accumulators, i) for i in statement.items), - ) - -def transform_symbol_array_variable_initialization_statement(accumulators, statement): - symbol_list_indices = [] - - for symbol in statement.symbol_list: - try: - symbol_list_index = accumulators.symbol_list.index(symbol) - except ValueError: - symbol_list_index = len(accumulators.symbol_list) - accumulators.symbol_list.append(symbol) - - symbol_list_indices.append(symbol_list_index) - - return CSymbolArrayVariableInitializationStatement( - variable=statement.variable, - symbol_list=statement.symbol_list, - symbol_list_indices=tuple(symbol_list_indices), - ) - -def transform_variable_initialization_statement(accumulators, statement): - return CVariableInitializationStatement( - variable=statement.variable, - expression=transform_expression(accumulators, statement.expression), - ) - -def transform_push_statement(accumulators, statement): - return CPushStatement(expression=transform_expression(accumulators, statement.expression)) - -def transform_statement(accumulators, statement): - return { - conversion.CPSArrayVariableInitializationStatement: transform_array_variable_initialization_statement, - conversion.CPSAssignmentStatement: transform_symbol_assignment_statement, - conversion.CPSExpressionStatement: transform_expression_statement, - conversion.CPSListAppendStatement: transform_list_append_statement, - conversion.CPSPushStatement: transform_push_statement, - conversion.CPSSymbolArrayVariableInitializationStatement: transform_symbol_array_variable_initialization_statement, - conversion.CPSVariableInitializationStatement: transform_variable_initialization_statement, - }[type(statement)](accumulators, statement) - - -Accumulators = collections.namedtuple( - 'Accumulators', - [ - 'builtin_set', - 'function_definition_list', - 'function_name_iterators', - 'operator_set', - 'symbol_list', - 'string_literal_list', - ], -) - -def transform(program): - accumulators = Accumulators( - builtin_set=set(), - function_definition_list=[], - function_name_iterators={}, - operator_set=set(), - symbol_list=[], - string_literal_list=[], - ) - - statement_list = [ - transform_statement(accumulators, statement) for statement in program.statement_list - ] - - standard_library_set = set() - for builtin in accumulators.builtin_set: - for standard_library in BUILTINS[builtin]: - standard_library_set.add(standard_library) - - return CProgram( - builtin_set=accumulators.builtin_set, - function_definition_list=accumulators.function_definition_list, - operator_declarations=tuple(sorted(accumulators.operator_set)), - statements=statement_list, - standard_libraries=standard_library_set, - string_literal_list=accumulators.string_literal_list, - symbol_list=accumulators.symbol_list, - ) - - -if __name__ == '__main__': - import unittest - - unittest.main()