X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=generation.py;h=1694e1fee2839824cef3de2b627481ed6eae0ead;hp=86abe96e79409ad5650cf0345fc4b107a3c2e038;hb=3da330f045ed7fcb66ee9d9447de320680263699;hpb=dee52f20ded67843ceac0e92ee2038f8aaf21cc4 diff --git a/generation.py b/generation.py index 86abe96..1694e1f 100644 --- a/generation.py +++ b/generation.py @@ -14,18 +14,10 @@ def generate_integer_literal(c_integer_literal): def generate_string_literal(c_string_literal): return 'stringLiteral(STRING_LITERAL_LIST[{}])'.format(c_string_literal.index) -CONSTANT_EXPRESSION_MAPPING = { - 'true': 'TRUE', - 'false': 'FALSE', -} - -def generate_constant_expression(c_constant_expression): - return CONSTANT_EXPRESSION_MAPPING[c_constant_expression.value] - -def generate_symbol_expression(c_symbol_expression): +def generate_symbol_expression(symbol_expression): return 'Environment_get(environment, SYMBOL_LIST[{}] /* symbol: {} */)'.format( - c_symbol_expression.symbol_list_index, - c_symbol_expression.symbol, + symbol_expression.symbol_list_index, + symbol_expression.symbol, ) def generate_variable_expression(expression): @@ -41,7 +33,6 @@ def generate_expression(expression): LITERAL_TYPE_MAPPING = { transformation.CIntegerLiteral: generate_integer_literal, transformation.CStringLiteral: generate_string_literal, - transformation.CConstantExpression: generate_constant_expression, transformation.CSymbolExpression: generate_symbol_expression, } @@ -65,8 +56,13 @@ def generate_negation_expression(c_negation_expression): ) def generate_function_call(function_call): - return '{}({}, {})'.format( - function_call.name, + # TODO This gets called twice, which is really inefficient--normalization would also allow other clauses besides a variable reference + # TODO This should no longer be called "name", as it can be an expression of a few types + # TODO Check the type of the things being called + get_closure_clause = generate_expression(function_call.name) + return '{}.instance.closure.call(environmentPool, {}.instance.closure.closed, {}, {})'.format( + get_closure_clause, + get_closure_clause, 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), @@ -76,11 +72,11 @@ def generate_expression_statement(statement): # TODO Do we need to garbage collect the results of arbitrary statements? return '{};'.format(generate_expression(statement.expression)) -def generate_symbol_assignment_statement(c_assignment_statement): +def generate_symbol_assignment_statement(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), + statement.target_symbol_list_index, + statement.target, + generate_expression(statement.expression), ) def generate_array_variable_initialization_statement(statement): @@ -107,15 +103,43 @@ def indent(s): def generate_if_else_statement(statement): # TODO Check that the argument is boolean - return 'if({}.instance.boolean)\n{{\n{}\n}}\nelse\n{{\n{}\n}}'.format( + condition_expression = '{}.instance.boolean'.format( generate_expression(statement.condition_expression), - indent('\n'.join(generate_statement(s) for s in statement.if_statements)), - indent('\n'.join(generate_statement(s) for s in statement.else_statements)), ) + 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, "{}", (Object){{ CLOSURE, (Instance)(Closure){{ environment, user${}$implementation }} }});'.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, @@ -123,11 +147,22 @@ def generate_statement(statement): transformation.CVariableReassignmentStatement: generate_variable_reassignment_statement, }[type(statement)](statement) +def generate_function_definition(definition): + template = ENV.get_template('function_definition.c') + return template.render( + name=definition.name, + argument_name_list=definition.argument_name_list, + statement_list=list(generate_statement(s) for s in definition.statement_list), + ) + return definition + def generate(program): template = ENV.get_template('program.c') return template.render( - builtins=list(sorted(program.builtin_set)), - statements=[generate_statement(statement) for statement in program.statements], + 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=program.string_literal_list, symbol_list=program.symbol_list,