X-Git-Url: https://code.kerkeslager.com/?a=blobdiff_plain;f=generation.py;h=99fd681f459c02687bcf873d8de0c9379da2e401;hb=02d64def49065ad614fe0ee2a85060666552192e;hp=1694e1fee2839824cef3de2b627481ed6eae0ead;hpb=3da330f045ed7fcb66ee9d9447de320680263699;p=fur diff --git a/generation.py b/generation.py index 1694e1f..99fd681 100644 --- a/generation.py +++ b/generation.py @@ -12,7 +12,10 @@ 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[{}])'.format(c_string_literal.index) + 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( @@ -23,30 +26,32 @@ def generate_symbol_expression(symbol_expression): def generate_variable_expression(expression): return expression.variable -def generate_expression(expression): - if isinstance(expression, transformation.CNegationExpression): - return generate_negation_expression(expression) +def generate_function_call_for_fur_infix_operator(expression): + return 'operator${}({}, {})'.format( + expression.name, + generate_expression(expression.left), + generate_expression(expression.right), + ) - if isinstance(expression, transformation.CFunctionCallExpression): - return generate_function_call(expression) +def generate_list_construct_expression(expression): + return 'List_construct({})'.format(expression.allocate) + +def generate_list_get_expression(expression): + return 'List_get(&{}, {})'.format( + generate_expression(expression.list_expression), + generate_expression(expression.index_expression), + ) - LITERAL_TYPE_MAPPING = { +def generate_expression(expression): + return { + transformation.CFunctionCallExpression: generate_function_call, + transformation.CFunctionCallForFurInfixOperator: generate_function_call_for_fur_infix_operator, transformation.CIntegerLiteral: generate_integer_literal, + transformation.CListConstructExpression: generate_list_construct_expression, + transformation.CListGetExpression: generate_list_get_expression, + transformation.CNegationExpression: generate_negation_expression, transformation.CStringLiteral: generate_string_literal, transformation.CSymbolExpression: generate_symbol_expression, - } - - if type(expression) in LITERAL_TYPE_MAPPING: - return LITERAL_TYPE_MAPPING[type(expression)](expression) - - if isinstance(expression, transformation.CFunctionCallForFurInfixOperator): - return 'operator${}({}, {})'.format( - expression.name, - generate_expression(expression.left), - generate_expression(expression.right), - ) - - return { transformation.CVariableExpression: generate_variable_expression, }[type(expression)](expression) @@ -56,21 +61,21 @@ def generate_negation_expression(c_negation_expression): ) def generate_function_call(function_call): - # 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 + # This gets called twice, so we want to be sure it is efficient and without side effects + assert isinstance(function_call.function_expression, transformation.CVariableExpression) + # TODO Check the type of the things being called - get_closure_clause = generate_expression(function_call.name) + function_expression = generate_variable_expression(function_call.function_expression) return '{}.instance.closure.call(environmentPool, {}.instance.closure.closed, {}, {})'.format( - get_closure_clause, - get_closure_clause, + function_expression, + function_expression, 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(statement): - # TODO Do we need to garbage collect the results of arbitrary statements? - return '{};'.format(generate_expression(statement.expression)) + return 'Object_deinitialize(&({}));'.format(generate_expression(statement.expression)) def generate_symbol_assignment_statement(statement): return 'Environment_set(environment, SYMBOL_LIST[{}] /* symbol: {} */, {});'.format( @@ -107,42 +112,49 @@ def generate_if_else_statement(statement): generate_expression(statement.condition_expression), ) - if len(statement.if_statements) == 0: + if len(statement.if_statement_list) == 0: condition_expression = '!({})'.format(condition_expression) - if_statements = statement.else_statements - else_statements = () + if_statement_list = statement.else_statement_list + else_statement_list = () else: - if_statements = statement.if_statements - else_statements = statement.else_statements + if_statement_list = statement.if_statement_list + else_statement_list = statement.else_statement_list generated_if_clause = 'if({})'.format(condition_expression) - if len(if_statements) == 0: - generated_if_statements = ';' + if len(if_statement_list) == 0: + generated_if_statement_list = ';' else: - generated_if_statements = indent('\n{{\n{}\n}}'.format( - indent('\n'.join(generate_statement(s) for s in if_statements)), + generated_if_statement_list = indent('\n{{\n{}\n}}'.format( + indent('\n'.join(generate_statement(s) for s in if_statement_list)), )) - if len(else_statements) == 0: - generated_else_statements = '' + if len(else_statement_list) == 0: + generated_else_statement_list = '' else: - generated_else_statements = indent('\nelse\n{{\n{}\n}}'.format( - indent('\n'.join(generate_statement(s) for s in else_statements)), + 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_statements + generated_else_statements + return generated_if_clause + generated_if_statement_list + generated_else_statement_list def generate_function_declaration(statement): return 'Environment_set(environment, "{}", (Object){{ CLOSURE, (Instance)(Closure){{ environment, user${}$implementation }} }});'.format(statement.name, statement.name) +def generate_list_append_statement(statement): + return 'List_append(&{}, {});'.format( + generate_expression(statement.list_expression), + generate_expression(statement.item_expression), + ) + def generate_statement(statement): return { + transformation.CArrayVariableInitializationStatement: generate_array_variable_initialization_statement, transformation.CExpressionStatement: generate_expression_statement, transformation.CFunctionDeclaration: generate_function_declaration, transformation.CIfElseStatement: generate_if_else_statement, + transformation.CListAppendStatement: generate_list_append_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) @@ -156,6 +168,16 @@ def generate_function_definition(definition): ) 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( @@ -164,7 +186,7 @@ def generate(program): 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, + string_literal_list=list(escape_string_literal(s) for s in program.string_literal_list), symbol_list=program.symbol_list, )