Skip to content

Commit

Permalink
Merge pull request #182 from KennyOliver/issue-181
Browse files Browse the repository at this point in the history
Issue 181: Function Return Handling Prevents Variable Assignment
  • Loading branch information
KennyOliver authored Jan 5, 2025
2 parents e580456 + 054f38e commit ea5027e
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 40 deletions.
70 changes: 48 additions & 22 deletions src/interpreter/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,36 @@ InterpretResult interpret_node(ASTNode *node, Environment *env) {
}

case AST_FUNCTION_RETURN: {
// After assignment
debug_print_int("===Value stored in 'a': %lld\n",
get_variable(env, "a"));

// Interpret the return expression
InterpretResult return_res =
interpret_node(node->function_return.return_data, env);

// Before serve call
debug_print_int("===About to execute serve(a)\n");
// Log the return value for debugging
switch (return_res.value.type) {
case TYPE_INTEGER:
debug_print_int("Function returning integer: %lld\n",
return_res.value.data.integer);
break;
case TYPE_FLOAT:
debug_print_int("Function returning float: %Lf\n",
return_res.value.data.floating_point);
break;
case TYPE_STRING:
debug_print_int("Function returning string: %s\n",
return_res.value.data.string);
break;
// Handle other types as needed
default:
debug_print_int("Function returning type: %d\n",
return_res.value.type);
}

// Propagate errors if any
if (return_res.is_error) {
return return_res;
}

// Indicate that a return has occurred
return_res.did_return = true;
return return_res;
}
Expand All @@ -90,16 +108,15 @@ InterpretResult interpret_node(ASTNode *node, Environment *env) {
break;
}

case AST_VARIABLE: {
debug_print_int("\tMatched: `AST_VARIABLE`\n");
case AST_VAR_DECLARATION: {
debug_print_int("\tMatched: `AST_VAR_DECLARATION`\n");
// Replace LiteralValue with InterpretResult
InterpretResult var_res = interpret_variable(node, env);
result = var_res;
result = interpret_variable(node, env);
break;
}

case AST_CONSTANT: {
debug_print_int("\tMatched: `AST_CONSTANT`\n");
case AST_CONST_DECLARATION: {
debug_print_int("\tMatched: `AST_CONST_DECLARATION`\n");
result = interpret_constant(node, env);
break;
}
Expand Down Expand Up @@ -141,10 +158,6 @@ void interpret_program(ASTNode *program, Environment *env) {
fprintf(stderr, "Unhandled error: %s\n", res.value.data.string);
break; // (or handle as needed in future)
}
if (res.did_return) {
// Handle unexpected return at top-level, if applicable
break;
}
current = current->next;
}
}
Expand Down Expand Up @@ -198,7 +211,7 @@ InterpretResult interpret_variable(ASTNode *node, Environment *env) {
}

InterpretResult interpret_constant(ASTNode *node, Environment *env) {
if (node->type != AST_CONSTANT) {
if (node->type != AST_CONST_DECLARATION) {
return raise_error("Invalid node type for constant declaration.\n");
}

Expand Down Expand Up @@ -235,8 +248,9 @@ InterpretResult interpret_assignment(ASTNode *node, Environment *env) {

// Evaluate the right-hand side
InterpretResult assign_r = interpret_node(node->assignment.value, env);
// If the RHS triggered a return or break, propagate it
if (assign_r.did_return || assign_r.did_break) {

// If the RHS triggered an error or break, propagate it
if (assign_r.is_error || assign_r.did_break) {
return assign_r;
}

Expand All @@ -259,15 +273,27 @@ InterpretResult interpret_assignment(ASTNode *node, Environment *env) {
target_env = target_env->parent;
}

// If variable doesn't exist anywhere, add to current scope
// If it exists, update in the scope where it was found
// Determine the scope to modify
Environment *scope_to_modify = existing_var ? target_env : env;

// Create a new variable instance
Variable new_var = {.variable_name = strdup(node->assignment.variable_name),
.value = new_value,
.is_constant = false};

return add_variable(scope_to_modify, new_var);
// Assign the variable
InterpretResult add_res = add_variable(scope_to_modify, new_var);
if (add_res.is_error) {
return add_res;
}

// Now, if a return was triggered during assignment, propagate it
if (assign_r.did_return) {
return assign_r;
}

// Otherwise, return the assigned value
return make_result(new_value, false, false);
}

InterpretResult handle_string_concatenation(InterpretResult left,
Expand Down
4 changes: 2 additions & 2 deletions src/interpreter/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,8 @@ ASTNode *copy_ast_node(ASTNode *node) {
new_node->switch_case.cases = new_case_head;
break;

case AST_VARIABLE:
case AST_CONSTANT:
case AST_VAR_DECLARATION:
case AST_CONST_DECLARATION:
if (node->variable_name) {
new_node->variable_name = strdup(node->variable_name);
if (!new_node->variable_name) {
Expand Down
2 changes: 1 addition & 1 deletion src/parser/operator_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ ASTNode *create_variable_node(char *name) {
if (!node) {
parser_error("Memory allocation failed for variable node", NULL);
}
node->type = AST_VARIABLE;
node->type = AST_VAR_DECLARATION;
node->variable_name = strdup(name);
node->next = NULL;
return node;
Expand Down
17 changes: 9 additions & 8 deletions src/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ ASTNode *parse_expression_statement(ParserState *state) {
}

ASTNode *parse_declaration(ParserState *state, ASTNodeType type) {
if (type == AST_CONSTANT) {
if (type == AST_CONST_DECLARATION) {
debug_print_par("Starting constant declaration parse\n");
expect_token(state, TOKEN_KEYWORD, "Expected `const` keyword");
} else {
Expand All @@ -99,7 +99,7 @@ ASTNode *parse_declaration(ParserState *state, ASTNodeType type) {

// Parse variable/constant name
Token *name = get_current_token(state);
if (type == AST_CONSTANT) {
if (type == AST_CONST_DECLARATION) {
expect_token(state, TOKEN_IDENTIFIER, "Expected constant name");
expect_token(state, TOKEN_OPERATOR, "Expected `=` after constant name");
} else {
Expand All @@ -118,23 +118,24 @@ ASTNode *parse_declaration(ParserState *state, ASTNodeType type) {
if (name && name->lexeme) {
node->assignment.variable_name = strdup(name->lexeme);
if (!node->assignment.variable_name) {
parser_error(AST_CONSTANT
parser_error(AST_CONST_DECLARATION
? "Memory allocation failed for constant name"
: "Memory allocation failed for variable name",
name);
}
} else {
parser_error(AST_CONSTANT ? "Invalid constant name token"
: "Invalid variable name token",
parser_error(AST_CONST_DECLARATION ? "Invalid constant name token"
: "Invalid variable name token",
name);
}

node->assignment.value = parse_expression(state);
node->next = NULL;

expect_token(state, TOKEN_DELIMITER,
AST_CONSTANT ? "Expected `;` after constant declaration"
: "Expected `;` after variable declaration");
AST_CONST_DECLARATION
? "Expected `;` after constant declaration"
: "Expected `;` after variable declaration");

return node;
}
Expand All @@ -144,7 +145,7 @@ ASTNode *parse_variable_declaration(ParserState *state) {
}

ASTNode *parse_constant_declaration(ParserState *state) {
return parse_declaration(state, AST_CONSTANT);
return parse_declaration(state, AST_CONST_DECLARATION);
}

ASTNode *parse_variable_assignment(ParserState *state) {
Expand Down
8 changes: 4 additions & 4 deletions src/parser/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ void free_ast(ASTNode *node) {
free_ast(node->for_loop.body);
break;

case AST_CONSTANT:
case AST_VARIABLE:
case AST_CONST_DECLARATION:
case AST_VAR_DECLARATION:
free(node->variable_name);
break;

Expand Down Expand Up @@ -370,11 +370,11 @@ void print_ast(ASTNode *node, int depth) {
print_ast(node->ternary.false_expr, depth + 2);
break;

case AST_VARIABLE:
case AST_VAR_DECLARATION:
printf("Variable: `%s`\n", node->variable_name);
break;

case AST_CONSTANT:
case AST_CONST_DECLARATION:
printf("Constant: `%s`\n", node->variable_name);
break;

Expand Down
4 changes: 2 additions & 2 deletions src/shared/ast_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ typedef enum {
AST_SWITCH,
AST_BREAK,
AST_TERNARY,
AST_VARIABLE,
AST_CONSTANT,
AST_VAR_DECLARATION,
AST_CONST_DECLARATION,
AST_TRY,
AST_CATCH,
AST_FINALLY
Expand Down
2 changes: 1 addition & 1 deletion src/tests/17_nested_function_application.flv
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ create test(num, func_a, func_b) {
deliver func_b(func_a(func_b(num)));
}

const a = test(10, times_2, times_3); # 180
let a = test(10, times_2, times_3); # 180
serve(a);

0 comments on commit ea5027e

Please sign in to comment.