Skip to content

Commit

Permalink
Merge pull request #120 from Brainrotlang/feat/func_scope
Browse files Browse the repository at this point in the history
Fix function scope
  • Loading branch information
SIGMazer authored Feb 7, 2025
2 parents f172e33 + 0505aa1 commit 3f312e7
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 71 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ LDFLAGS := -lfl -lm

# Source files and directories
SRC_DIR := lib
DEBUG_FLAGS := -g
SRCS := $(SRC_DIR)/hm.c $(SRC_DIR)/mem.c $(SRC_DIR)/input.c ast.c
GENERATED_SRCS := lang.tab.c lex.yy.c
ALL_SRCS := $(SRCS) $(GENERATED_SRCS)
Expand All @@ -23,6 +24,13 @@ FLEX_OUTPUT := lex.yy.c
.PHONY: all
all: $(TARGET)

# Debug target
.PHONY: debug
debug: CFLAGS += $(DEBUG_FLAGS)
debug: clean $(TARGET)
@echo "Debug build compiled with -g. Time to sigma grind with GDB."


# Main executable build
$(TARGET): $(ALL_SRCS)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
Expand Down
198 changes: 133 additions & 65 deletions ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,18 @@ int get_expression_type(ASTNode *node)
{
return VAR_INT; // Sizeof always returns an integer
}
case NODE_FUNC_CALL:
{
// Look up the function in the symbol table
const char *func_name = node->data.func_call.function_name;
Function *func = get_function(func_name);
if (func != NULL)
{
return func->return_type;
}
yyerror("Undefined function in get_expression_type");
return NONE;
}
default:
yyerror("Unknown node type in get_expression_type");
return NONE;
Expand Down Expand Up @@ -643,6 +655,7 @@ void *handle_binary_operation(ASTNode *node)
return NULL;
}


// Perform the operation and allocate the result.
void *result;
if (promoted_type == VAR_DOUBLE)
Expand Down Expand Up @@ -2308,6 +2321,7 @@ void execute_statement(ASTNode *node)
evaluate_expression(node);
break;
case NODE_FUNC_CALL:
// TODO: clearn up built-in functions
if (strcmp(node->data.func_call.function_name, "yapping") == 0)
{
execute_yapping_call(node->data.func_call.arguments);
Expand All @@ -2332,6 +2346,12 @@ void execute_statement(ASTNode *node)
{
execute_slorp_call(node->data.func_call.arguments);
}
else
{
execute_function_call(
node->data.func_call.function_name,
node->data.func_call.arguments);
}
break;
case NODE_FOR_STATEMENT:
execute_for_statement(node);
Expand Down Expand Up @@ -3459,6 +3479,10 @@ Variable *get_variable(const char *name)
{
return var;
}
if (scope->is_function_scope)
{
return NULL;
}
scope = scope->parent;
}
return NULL;
Expand Down Expand Up @@ -3561,70 +3585,9 @@ void execute_function_call(const char *name, ArgumentList *args)
if (strcmp(func->name, name) == 0)
{
// Create new scope for function
enter_scope();

// Process arguments and parameters
ArgumentList *curr_arg = args;
Parameter *curr_param = func->parameters;
enter_function_scope(func, args);
current_return_value.type = func->return_type;

// reverse the order of parameters
Parameter *prev = NULL;
Parameter *next = NULL;
while (curr_param)
{
next = curr_param->next;
curr_param->next = prev;
prev = curr_param;
curr_param = next;
}
curr_param = prev;

while (curr_arg && curr_param)
{
// Create variable for parameter
Variable *var = variable_new(curr_param->name);
var->var_type = curr_param->type;
add_variable_to_scope(curr_param->name, var);

switch (curr_param->type)
{
case VAR_INT:
set_int_variable(curr_param->name, evaluate_expression_int(curr_arg->expr), get_current_modifiers());
break;
case VAR_FLOAT:
set_float_variable(curr_param->name, evaluate_expression_float(curr_arg->expr), get_current_modifiers());
break;
case VAR_DOUBLE:
set_double_variable(curr_param->name, evaluate_expression_double(curr_arg->expr), get_current_modifiers());
break;
case VAR_BOOL:
set_bool_variable(curr_param->name, evaluate_expression_bool(curr_arg->expr), get_current_modifiers());
break;
case VAR_SHORT:
set_short_variable(curr_param->name, evaluate_expression_short(curr_arg->expr), get_current_modifiers());
break;
case VAR_CHAR:
set_int_variable(curr_param->name, evaluate_expression_int(curr_arg->expr), get_current_modifiers());
break;
case NONE:
break;
}

Parameter *tmp = curr_param;
curr_arg = curr_arg->next;
curr_param = curr_param->next;
SAFE_FREE(var);
SAFE_FREE(tmp->name);
SAFE_FREE(tmp);
}

if (curr_arg || curr_param)
{
yyerror("Mismatched number of arguments and parameters");
exit_scope();
return;
}

// Set up return handling
current_return_value.has_value = false;
Expand All @@ -3635,8 +3598,6 @@ void execute_function_call(const char *name, ArgumentList *args)
}

POP_JUMP_BUFFER();
// Clean up scope
exit_scope();
return;
}
func = func->next;
Expand Down Expand Up @@ -3672,9 +3633,17 @@ void handle_return_statement(ASTNode *expr)
exit(1);
}
}
// Clean up all scopes until we reach the function scope
while (current_scope && !current_scope->is_function_scope)
{
exit_scope();
}

// skibidi main function do not have jump buffer
if (CURRENT_JUMP_BUFFER())
if (CURRENT_JUMP_BUFFER()){
exit_scope(); // exit current function scope
LONGJMP();
}
}

Parameter *create_parameter(char *name, VarType type, Parameter *next)
Expand Down Expand Up @@ -3744,3 +3713,102 @@ void free_function_table(void)
}
function_table = NULL;
}

void reverse_parameter_list(Parameter **head)
{
Parameter *prev = NULL, *current = *head, *next = NULL;
while (current)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head = prev;
}

void enter_function_scope(Function *func, ArgumentList *args)
{
ArgumentList *curr_arg = args;
Value arg_values[MAX_ARGUMENTS];
int arg_count = 0;

// Reverse the parameter list
reverse_parameter_list(&func->parameters);
Parameter *curr_param = func->parameters;

// Evaluate argument values before creating the scope
while (curr_arg && curr_param)
{
switch (curr_param->type)
{
case VAR_INT:
case VAR_CHAR:
arg_values[arg_count].ivalue = evaluate_expression_int(curr_arg->expr);
break;
case VAR_FLOAT:
arg_values[arg_count].fvalue = evaluate_expression_float(curr_arg->expr);
break;
case VAR_DOUBLE:
arg_values[arg_count].dvalue = evaluate_expression_double(curr_arg->expr);
break;
case VAR_BOOL:
arg_values[arg_count].bvalue = evaluate_expression_bool(curr_arg->expr);
break;
case VAR_SHORT:
arg_values[arg_count].svalue = evaluate_expression_short(curr_arg->expr);
break;
case NONE:
break;
}

curr_arg = curr_arg->next;
curr_param = curr_param->next;
arg_count++;
}

if (curr_arg || curr_param)
{
yyerror("Mismatched number of arguments and parameters");
return;
}

// Create function scope after evaluating arguments
Scope *scope = create_scope(current_scope);
current_scope = scope;
current_scope->is_function_scope = true;

curr_param = func->parameters; // Reset parameter list after reversing

// Assign evaluated values to function parameters
for (int i = 0; i < arg_count; i++)
{
Variable *var = variable_new(curr_param->name);
var->var_type = curr_param->type;
add_variable_to_scope(curr_param->name, var);

switch (curr_param->type)
{
case VAR_INT:
case VAR_CHAR:
set_int_variable(curr_param->name, arg_values[i].ivalue, get_current_modifiers());
break;
case VAR_FLOAT:
set_float_variable(curr_param->name, arg_values[i].fvalue, get_current_modifiers());
break;
case VAR_DOUBLE:
set_double_variable(curr_param->name, arg_values[i].dvalue, get_current_modifiers());
break;
case VAR_BOOL:
set_bool_variable(curr_param->name, arg_values[i].bvalue, get_current_modifiers());
break;
case VAR_SHORT:
set_short_variable(curr_param->name, arg_values[i].svalue, get_current_modifiers());
break;
case NONE:
break;
}
curr_param = curr_param->next;
}
}

17 changes: 12 additions & 5 deletions ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <setjmp.h>

#define MAX_VARS 100
#define MAX_ARGUMENTS 100

/* Forward declarations */
typedef struct ASTNode ASTNode;
Expand Down Expand Up @@ -104,11 +105,15 @@ typedef struct

typedef union
{
int ivalue;
short svalue;
bool bvalue;
float fvalue;
double dvalue;
VarType type;
union
{
int ivalue;
short svalue;
bool bvalue;
float fvalue;
double dvalue;
};
} Value;

/* Operator types */
Expand Down Expand Up @@ -272,6 +277,7 @@ typedef struct Scope
{
HashMap *variables;
struct Scope *parent;
bool is_function_scope;
} Scope;

/* Global variable declarations */
Expand All @@ -291,6 +297,7 @@ void reset_modifiers(void);
TypeModifiers get_current_modifiers(void);
Variable *get_variable(const char *name);
Scope *create_scope(Scope *parent);
void enter_function_scope(Function *func, ArgumentList *args);
void exit_scope();
void enter_scope();
void free_scope(Scope *scope);
Expand Down
12 changes: 12 additions & 0 deletions test_cases/fib.brainrot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
rizz fib(rizz n) {
edgy (n <= 1) {
bussin n;
}
bussin fib(n -1) + fib(n -2);
}

skibidi main {
rizz result = fib(10);
yapping("%d",result);
bussin 0;
}
18 changes: 18 additions & 0 deletions test_cases/func_scope.brainrot
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
rizz inner()
{
rizz x = 10;
yapping("from inner %d",x);
bussin 0;
}

rizz outer(rizz n) {
rizz x = 4;
inner();
yapping("from outer %d",x);
bussin x;
}

skibidi main {
outer(10);
bussin 0;
}
4 changes: 3 additions & 1 deletion tests/expected_results.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,7 @@
"slorp_float": "You typed: 3.140000",
"slorp_double": "You typed: 3.141592",
"slorp_char": "You typed: c",
"slorp_string": "You typed: skibidi bop bop yes yes"
"slorp_string": "You typed: skibidi bop bop yes yes",
"fib": "55",
"func_scope": "from inner 10\nfrom outer 4\n"
}

0 comments on commit 3f312e7

Please sign in to comment.