From 8d6f07b43d8b41473fb7d8779bbc7a5843adcd7b Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Sat, 2 Sep 2017 09:04:02 -0400 Subject: [PATCH] Add a stack, and use that for function call arguments --- generation.py | 8 +++-- normalization.py | 30 ++++++++--------- templates/function_definition.c | 8 ++--- templates/program.c | 60 +++++++++++++++++++++++++++------ transformation.py | 13 +++++-- 5 files changed, 84 insertions(+), 35 deletions(-) diff --git a/generation.py b/generation.py index 9757949..145132f 100644 --- a/generation.py +++ b/generation.py @@ -82,12 +82,10 @@ def generate_function_call(function_call): # TODO Check the type of the things being called function_expression = generate_variable_expression(function_call.function_expression) - return '{}.instance.closure.call(environmentPool, {}.instance.closure.closed, {}, {})'.format( + return '{}.instance.closure.call(environmentPool, {}.instance.closure.closed, {}, stack)'.format( 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): @@ -172,6 +170,9 @@ def generate_list_append_statement(statement): 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, @@ -179,6 +180,7 @@ def generate_statement(statement): transformation.CFunctionDeclaration: generate_function_declaration, transformation.CIfElseStatement: generate_if_else_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, diff --git a/normalization.py b/normalization.py index dcbe9dd..2fa57fc 100644 --- a/normalization.py +++ b/normalization.py @@ -56,12 +56,18 @@ NormalInfixExpression = collections.namedtuple( ], ) +NormalPushStatement = collections.namedtuple( + 'NormalPushStatement', + ( + 'expression', + ), +) + NormalFunctionCallExpression = collections.namedtuple( 'NormalFunctionCallExpression', [ 'function_expression', 'argument_count', - 'argument_items', ], ) @@ -326,7 +332,6 @@ def normalize_function_call_expression(counter, expression): assert isinstance(expression, parsing.FurFunctionCallExpression) prestatements = [] - arguments = [] for argument in expression.arguments: counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument) @@ -341,19 +346,15 @@ def normalize_function_call_expression(counter, expression): expression=normalized_argument, ) ) - arguments.append(NormalVariableExpression( - variable=variable, - )) + prestatements.append( + NormalPushStatement( + expression=NormalVariableExpression( + variable=variable, + ), + ), + ) counter += 1 - arguments_variable = '${}'.format(counter) - counter += 1 - - prestatements.append(NormalArrayVariableInitializationStatement( - variable=arguments_variable, - items=tuple(arguments), - )) - counter, function_prestatements, function_expression = normalize_expression( counter, expression.function, @@ -382,8 +383,7 @@ def normalize_function_call_expression(counter, expression): variable=result_variable, expression=NormalFunctionCallExpression( function_expression=function_expression, - argument_count=len(arguments), - argument_items=NormalVariableExpression(variable=arguments_variable), + argument_count=len(expression.arguments), ), ) ) diff --git a/templates/function_definition.c b/templates/function_definition.c index 0c60f30..24c73f8 100644 --- a/templates/function_definition.c +++ b/templates/function_definition.c @@ -1,14 +1,12 @@ -Object user${{name}}$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Object* args) +Object user${{name}}$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Stack* stack) { - assert(argc == {{ argument_name_list|length }}); - Environment* environment = EnvironmentPool_allocate(environmentPool); Environment_initialize(environment, parent); Object result = builtin$nil; - {% for argument_name in argument_name_list %} - Environment_set(environment, "{{ argument_name }}", args[{{ loop.index0 }}]); + {% for argument_name in argument_name_list|reverse %} + Environment_set(environment, "{{ argument_name }}", Stack_pop(stack)); {% endfor %} {% for statement in statement_list %} diff --git a/templates/program.c b/templates/program.c index d6df732..3602921 100644 --- a/templates/program.c +++ b/templates/program.c @@ -34,6 +34,8 @@ struct Environment; typedef struct Environment Environment; struct EnvironmentPool; typedef struct EnvironmentPool EnvironmentPool; +struct Stack; +typedef struct Stack Stack; const char* const STRING_LITERAL_LIST[] = { {% for string_literal in string_literal_list %} @@ -64,7 +66,7 @@ typedef struct Closure Closure; struct Closure { Environment* closed; - Object (*call)(EnvironmentPool*, Environment*, size_t, Object*); + Object (*call)(EnvironmentPool*, Environment*, size_t, Stack*); }; struct List; @@ -149,6 +151,31 @@ Object List_get(Object* list, Object index) return list->instance.list.items[index.instance.integer]; } +struct Stack +{ + uint16_t length; + Object items[256]; +}; + +void Stack_initialize(Stack* self) +{ + self->length = 0; +} + +void Stack_push(Stack* self, Object item) +{ + assert(self->length < 256); + self->items[self->length] = item; + self->length++; +} + +Object Stack_pop(Stack* self) +{ + assert(self->length > 0); + self->length--; + return self->items[self->length]; +} + Object Object_rereference(Object self) { switch(self.type) @@ -560,12 +587,11 @@ Object operator${{ id.name }}(Object left, Object right) {% endfor %} {% if 'pow' in builtins %} -Object builtin$pow$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Object* args) +Object builtin$pow$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Stack* stack) { - assert(argc == 2); - - Object base = args[0]; - Object exponent = args[1]; + // Must unload items in reverse order + Object exponent = Stack_pop(stack); + Object base = Stack_pop(stack); assert(base.type == INTEGER); assert(exponent.type == INTEGER); @@ -580,11 +606,19 @@ Object builtin$pow = { CLOSURE, (Instance)(Closure){ NULL, builtin$pow$implement {% endif %} {% if 'print' in builtins %} -Object builtin$print$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Object* args) +Object builtin$print$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Stack* stack) { + Stack reverse_stack; + Stack_initialize(&reverse_stack); + for(size_t i = 0; i < argc; i++) { - Object output = args[i]; + Stack_push(&reverse_stack, Stack_pop(stack)); + } + + while(reverse_stack.length > 0) + { + Object output = Stack_pop(&reverse_stack); switch(output.type) { case BOOLEAN: @@ -601,8 +635,10 @@ Object builtin$print$implementation(EnvironmentPool* environmentPool, Environmen break; case STRING_CONCATENATION: - builtin$print$implementation(NULL, NULL, 1, &(output.instance.string_concatenation->left)); - builtin$print$implementation(NULL, NULL, 1, &(output.instance.string_concatenation->right)); + Stack_push(stack, output.instance.string_concatenation->left); + builtin$print$implementation(NULL, NULL, 1, stack); + Stack_push(stack, output.instance.string_concatenation->right); + builtin$print$implementation(NULL, NULL, 1, stack); break; case STRING_LITERAL: @@ -636,6 +672,10 @@ int main(int argc, char** argv) Environment* environment = EnvironmentPool_allocate(environmentPool); Environment_initialize(environment, NULL); + Stack stackMemory; + Stack* stack = &stackMemory; + Stack_initialize(stack); + // TODO Use the symbol from SYMBOL_LIST {% for builtin in builtins %} Environment_set(environment, "{{ builtin }}", builtin${{ builtin }}); diff --git a/transformation.py b/transformation.py index c07f692..82d4b3f 100644 --- a/transformation.py +++ b/transformation.py @@ -67,12 +67,18 @@ CFunctionCallForFurInfixOperator = collections.namedtuple( ], ) +CPushStatement = collections.namedtuple( + 'CPushStatement', + ( + 'expression', + ), +) + CFunctionCallExpression = collections.namedtuple( 'CFunctionCallExpression', [ 'function_expression', 'argument_count', - 'argument_items', ], ) @@ -398,7 +404,6 @@ def transform_function_call_expression(accumulators, function_call): return CFunctionCallExpression( function_expression=transform_expression(accumulators, function_call.function_expression), argument_count=function_call.argument_count, - argument_items=transform_expression(accumulators, function_call.argument_items), ) def transform_expression_statement(accumulators, statement): @@ -463,6 +468,9 @@ def transform_function_definition_statement(accumulators, statement): return CFunctionDeclaration(name=statement.name) +def transform_push_statement(accumulators, statement): + return CPushStatement(expression=transform_expression(accumulators, statement.expression)) + def transform_statement(accumulators, statement): return { parsing.FurExpressionStatement: transform_expression_statement, @@ -472,6 +480,7 @@ def transform_statement(accumulators, statement): normalization.NormalFunctionDefinitionStatement: transform_function_definition_statement, normalization.NormalIfElseStatement: transform_if_else_statement, normalization.NormalListAppendStatement: transform_list_append_statement, + normalization.NormalPushStatement: transform_push_statement, normalization.NormalSymbolArrayVariableInitializationStatement: transform_symbol_array_variable_initialization_statement, normalization.NormalVariableInitializationStatement: transform_variable_initialization_statement, normalization.NormalVariableReassignmentStatement: transform_variable_reassignment_statement, -- 2.20.1