X-Git-Url: https://code.kerkeslager.com/?a=blobdiff_plain;f=generation.py;h=3ad3c0d81ba753829fffbb570ab7714538585a04;hb=8b306504c3a04a4334d3e8de6abed6c3ce182585;hp=fcfaee1e1c2d89fcc3360388be985e07c1bb7a1a;hpb=e0873511cc1425343bb70545571406b25b9cf5d9;p=fur diff --git a/generation.py b/generation.py index fcfaee1..3ad3c0d 100644 --- a/generation.py +++ b/generation.py @@ -12,17 +12,7 @@ def generate_integer_literal(c_integer_literal): return 'integerLiteral({})'.format(c_integer_literal.value) def generate_string_literal(c_string_literal): - def c_escape(ch): - return { - '\n': r'\n', - '"': r'\"', - '\\': r'\\', - }.get(ch, ch) - - return 'stringLiteral(runtime, "{}")'.format( - ''.join(c_escape(ch for ch in c_string_literal.value)), - ) - + return 'stringLiteral(STRING_LITERAL_LIST[{}])'.format(c_string_literal.index) CONSTANT_EXPRESSION_MAPPING = { 'true': 'TRUE', @@ -38,12 +28,15 @@ 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_variable_expression(expression): + return expression.variable + +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, @@ -52,53 +45,127 @@ 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): - return 'builtin${}({}, {})'.format( - c_argument.name, - generate_expression(c_argument.left), - generate_expression(c_argument.right), + if isinstance(expression, transformation.CFunctionCallForFurInfixOperator): + return 'operator${}({}, {})'.format( + expression.name, + generate_expression(expression.left), + generate_expression(expression.right), ) - raise Exception('Could not handle expresssion "{}"'.format(c_argument)) + return { + transformation.CVariableExpression: generate_variable_expression, + }[type(expression)](expression) def generate_negation_expression(c_negation_expression): - return 'builtin$negate({})'.format( + return 'operator$negate({})'.format( generate_expression(c_negation_expression.value) ) -def generate_function_call(c_function_call): - return '{}({})'.format( - c_function_call.name, - ', '.join(generate_expression(argument) for argument in c_function_call.arguments), +def generate_function_call(function_call): + return 'Environment_get(environment, "{}").instance.closure(environment, {}, {})'.format( + function_call.name, + function_call.argument_count, + # TODO This is just a single item containing a reference to the items list--make that clearer + generate_expression(function_call.argument_items), ) -def generate_expression_statement(c_function_call_statement): +def generate_expression_statement(statement): + # TODO Do this at an earlier pass + if isinstance(statement.expression, transformation.CVariableExpression): + return ''; + # TODO Do we need to garbage collect the results of arbitrary statements? - return '{};'.format(generate_expression(c_function_call_statement)) + return '{};'.format(generate_expression(statement.expression)) -def generate_assignment_statement(c_assignment_statement): +def generate_symbol_assignment_statement(c_assignment_statement): return 'Environment_set(environment, SYMBOL_LIST[{}] /* symbol: {} */, {});'.format( c_assignment_statement.target_symbol_list_index, c_assignment_statement.target, generate_expression(c_assignment_statement.expression), ) -def generate_statement(statement): - if isinstance(statement, transformation.CAssignmentStatement): - return generate_assignment_statement(statement) +def generate_array_variable_initialization_statement(statement): + return 'Object {}[] = {{ {} }};'.format( + statement.variable, + ', '.join(generate_expression(i) for i in statement.items), + ) + +def generate_variable_initialization_statement(statement): + return 'Object {} = {};'.format( + statement.variable, + generate_expression(statement.expression), + ) + +def generate_variable_reassignment_statement(statement): + return '{} = {};'.format( + statement.variable, + generate_expression(statement.expression), + ) - return generate_expression_statement(statement) -def generate(c_program): +def indent(s): + return '\n'.join(' ' * 2 + l for l in s.split('\n')) + +def generate_if_else_statement(statement): + # TODO Check that the argument is boolean + condition_expression = '{}.instance.boolean'.format( + generate_expression(statement.condition_expression), + ) + + if len(statement.if_statements) == 0: + condition_expression = '!({})'.format(condition_expression) + if_statements = statement.else_statements + else_statements = () + else: + if_statements = statement.if_statements + else_statements = statement.else_statements + + generated_if_clause = 'if({})'.format(condition_expression) + + if len(if_statements) == 0: + generated_if_statements = ';' + else: + generated_if_statements = indent('\n{{\n{}\n}}'.format( + indent('\n'.join(generate_statement(s) for s in if_statements)), + )) + + if len(else_statements) == 0: + generated_else_statements = '' + else: + generated_else_statements = indent('\nelse\n{{\n{}\n}}'.format( + indent('\n'.join(generate_statement(s) for s in else_statements)), + )) + + return generated_if_clause + generated_if_statements + generated_else_statements + +def generate_function_declaration(statement): + return 'Environment_set(environment, "{}", user${});'.format(statement.name, statement.name) + +def generate_statement(statement): + return { + transformation.CExpressionStatement: generate_expression_statement, + transformation.CFunctionDeclaration: generate_function_declaration, + transformation.CIfElseStatement: generate_if_else_statement, + transformation.CSymbolAssignmentStatement: generate_symbol_assignment_statement, + transformation.CArrayVariableInitializationStatement: generate_array_variable_initialization_statement, + transformation.CVariableInitializationStatement: generate_variable_initialization_statement, + transformation.CVariableReassignmentStatement: generate_variable_reassignment_statement, + }[type(statement)](statement) + +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)), - symbol_list=c_program.symbol_list, + builtins=tuple(sorted(program.builtin_set)), + function_definition_list=program.function_definition_list, + generate_statement=generate_statement, + infix_declarations=program.operator_declarations, + statements=program.statements, + standard_libraries=list(sorted(program.standard_libraries)), + string_literal_list=program.string_literal_list, + symbol_list=program.symbol_list, ) if __name__ == '__main__':