diff --git a/src/interpreter/interpreter.c b/src/interpreter/interpreter.c index 95b2efa..c618c05 100644 --- a/src/interpreter/interpreter.c +++ b/src/interpreter/interpreter.c @@ -216,7 +216,7 @@ InterpretResult interpret_constant(ASTNode *node, Environment *env) { } // Extract the constant name and value - char *const_name = strdup(node->assignment.variable_name); + char *const_name = strdup(node->const_declaration.constant_name); InterpretResult value_res = interpret_node(node->assignment.rhs, env); LiteralValue const_value = value_res.value; @@ -240,7 +240,7 @@ InterpretResult interpret_constant(ASTNode *node, Environment *env) { } InterpretResult interpret_assignment(ASTNode *node, Environment *env) { - if (!node->assignment.variable_name) { + if (!node->var_declaration.variable_name) { debug_print_int("Assignment variable name missing for node type: %d\n", node->type); return make_result((LiteralValue){.type = TYPE_ERROR}, false, false); @@ -262,7 +262,7 @@ InterpretResult interpret_assignment(ASTNode *node, Environment *env) { while (target_env) { for (size_t i = 0; i < target_env->variable_count; i++) { if (strcmp(target_env->variables[i].variable_name, - node->assignment.variable_name) == 0) { + node->var_declaration.variable_name) == 0) { existing_var = &target_env->variables[i]; break; } @@ -277,7 +277,8 @@ InterpretResult interpret_assignment(ASTNode *node, Environment *env) { Environment *scope_to_modify = existing_var ? target_env : env; // Create a new variable instance - Variable new_var = {.variable_name = strdup(node->assignment.variable_name), + Variable new_var = {.variable_name = + strdup(node->var_declaration.variable_name), .value = new_value, .is_constant = false}; diff --git a/src/interpreter/utils.c b/src/interpreter/utils.c index f294175..897a778 100644 --- a/src/interpreter/utils.c +++ b/src/interpreter/utils.c @@ -210,15 +210,15 @@ ASTNode *copy_ast_node(ASTNode *node) { // Deep copy based on node type switch (node->type) { case AST_ASSIGNMENT: - if (node->assignment.variable_name) { - new_node->assignment.variable_name = - strdup(node->assignment.variable_name); - if (!new_node->assignment.variable_name) { + if (node->var_declaration.variable_name) { + new_node->var_declaration.variable_name = + strdup(node->var_declaration.variable_name); + if (!new_node->var_declaration.variable_name) { fatal_error("Memory allocation failed for variable name in " "assignment.\n"); } } else { - new_node->assignment.variable_name = NULL; + new_node->var_declaration.variable_name = NULL; } new_node->assignment.rhs = copy_ast_node(node->assignment.rhs); break; diff --git a/src/parser/parser.c b/src/parser/parser.c index d60dc79..b39e761 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -84,60 +84,66 @@ ASTNode *parse_expression_statement(ParserState *state) { } ASTNode *parse_declaration(ParserState *state, ASTNodeType type) { + // Parse keyword (`let` or `const`) if (type == AST_CONST_DECLARATION) { debug_print_par("Starting constant declaration parse\n"); expect_token(state, TOKEN_KEYWORD, "Expected `const` keyword"); - } else { + } else if (type == AST_VAR_DECLARATION) { debug_print_par("Starting variable declaration parse\n"); expect_token(state, TOKEN_KEYWORD, "Expected `let` keyword"); + } else { + parser_error("Unknown declaration type", get_current_token(state)); } // Parse variable/constant name Token *name = get_current_token(state); - if (type == AST_CONST_DECLARATION) { - expect_token(state, TOKEN_IDENTIFIER, "Expected constant name"); - expect_token(state, TOKEN_OPERATOR, "Expected `=` after constant name"); - } else { - expect_token(state, TOKEN_IDENTIFIER, "Expected variable name"); - expect_token(state, TOKEN_OPERATOR, "Expected `=` after variable name"); + if (name->type != TOKEN_IDENTIFIER && name->type != TOKEN_FUNCTION_NAME) { + parser_error("Expected name in declaration", name); } - - // Create AST node - ASTNode *node = malloc(sizeof(ASTNode)); - if (!node) { - parser_error("Memory allocation failed", get_current_token(state)); + char *decl_name = strdup(name->lexeme); + if (!decl_name) { + parser_error("Memory allocation failed for declaration name", name); } - node->type = type; + advance_token(state); // Consume name - // Create a deep copy of the variable/constant name - if (name && name->lexeme) { - node->assignment.variable_name = strdup(name->lexeme); - if (!node->assignment.variable_name) { - parser_error(AST_CONST_DECLARATION - ? "Memory allocation failed for constant name" - : "Memory allocation failed for variable name", - name); - } - } else { - parser_error(AST_CONST_DECLARATION ? "Invalid constant name token" - : "Invalid variable name token", - name); - } + // Expect `=` operator + expect_token(state, TOKEN_OPERATOR, "Expected `=` after name"); - node->assignment.lhs = NULL; - node->assignment.rhs = parse_expression(state); - node->next = NULL; + // Parse initializer expression + ASTNode *initializer = parse_expression(state); + if (!initializer) { + parser_error("Expected initializer expression", + get_current_token(state)); + } + // Expect `;` delimiter expect_token(state, TOKEN_DELIMITER, - AST_CONST_DECLARATION + type == AST_CONST_DECLARATION ? "Expected `;` after constant declaration" : "Expected `;` after variable declaration"); + // Create AST node based on type + ASTNode *node = malloc(sizeof(ASTNode)); + if (!node) { + parser_error("Memory allocation failed for declaration node", + get_current_token(state)); + } + node->type = type; + node->next = NULL; + + if (type == AST_VAR_DECLARATION) { + node->var_declaration.variable_name = decl_name; + node->var_declaration.initializer = initializer; + } else if (type == AST_CONST_DECLARATION) { + node->const_declaration.constant_name = decl_name; + node->const_declaration.initializer = initializer; + } + return node; } ASTNode *parse_variable_declaration(ParserState *state) { - return parse_declaration(state, AST_ASSIGNMENT); + return parse_declaration(state, AST_VAR_DECLARATION); } ASTNode *parse_constant_declaration(ParserState *state) { @@ -145,13 +151,19 @@ ASTNode *parse_constant_declaration(ParserState *state) { } ASTNode *create_variable_reference_node(char *name) { - ASTNode *node = malloc(sizeof(ASTNode)); + ASTNode *node = calloc( + 1, sizeof(ASTNode)); // use `calloc` instead of `malloc` to ensure + // all fields are initialized to zero (`NULL`) if (!node) { parser_error("Memory allocation failed for variable reference node", NULL); } node->type = AST_VARIABLE_REFERENCE; node->variable_name = strdup(name); + if (!node->variable_name) { + free(node); + parser_error("Memory allocation failed for variable name", NULL); + } node->next = NULL; return node; } diff --git a/src/parser/utils.c b/src/parser/utils.c index f45748c..35119f0 100644 --- a/src/parser/utils.c +++ b/src/parser/utils.c @@ -6,7 +6,7 @@ void free_ast(ASTNode *node) { switch (node->type) { case AST_ASSIGNMENT: - free(node->assignment.variable_name); + // free(node->assignment.variable_name); free_ast(node->assignment.lhs); free_ast(node->assignment.rhs); break; @@ -170,11 +170,29 @@ void print_ast(ASTNode *node, int depth) { while (node != NULL) { print_indent(depth); switch (node->type) { + case AST_VAR_DECLARATION: + printf("Variable Declaration: %s\n", + node->var_declaration.variable_name); + if (node->var_declaration.initializer) { + print_indent(depth + 1); + printf("Initializer:\n"); + print_ast(node->var_declaration.initializer, depth + 2); + } + break; + + case AST_CONST_DECLARATION: + printf("Constant Declaration: %s\n", + node->const_declaration.constant_name); + if (node->const_declaration.initializer) { + print_indent(depth + 1); + printf("Initializer:\n"); + print_ast(node->const_declaration.initializer, depth + 2); + } + break; + case AST_ASSIGNMENT: printf("Assignment:\n"); print_indent(depth + 1); - printf("Variable Name: %s\n", node->assignment.variable_name); - print_indent(depth + 1); printf("LHS:\n"); print_ast(node->assignment.lhs, depth + 2); print_indent(depth + 1); @@ -314,9 +332,14 @@ void print_ast(ASTNode *node, int depth) { while (case_node != NULL) { print_indent(depth + 2); printf("Case:\n"); - print_indent(depth + 3); - printf("Condition:\n"); - print_ast(case_node->condition, depth + 4); + if (case_node->condition) { + print_indent(depth + 3); + printf("Condition:\n"); + print_ast(case_node->condition, depth + 4); + } else { + print_indent(depth + 3); + printf("Condition: None (Default)\n"); + } print_indent(depth + 3); printf("Body:\n"); print_ast(case_node->body, depth + 4); @@ -342,26 +365,6 @@ void print_ast(ASTNode *node, int depth) { print_ast(node->ternary.false_expr, depth + 2); break; - case AST_VAR_DECLARATION: - printf("Variable Declaration: %s\n", node->variable_name); - if (node->assignment.rhs) { // Assuming variable declaration can - // have an initializer - print_indent(depth + 1); - printf("Initializer:\n"); - print_ast(node->assignment.rhs, depth + 2); - } - break; - - case AST_CONST_DECLARATION: - printf("Constant Declaration: %s\n", node->variable_name); - if (node->assignment.rhs) { // Assuming constant declaration can - // have an initializer - print_indent(depth + 1); - printf("Initializer:\n"); - print_ast(node->assignment.rhs, depth + 2); - } - break; - case AST_TRY: printf("Try Block:\n"); print_indent(depth + 1); diff --git a/src/shared/ast_types.h b/src/shared/ast_types.h index 09e2795..9a2a17d 100644 --- a/src/shared/ast_types.h +++ b/src/shared/ast_types.h @@ -5,15 +5,15 @@ #include #include -#define MAX_ARGUMENTS 1024 - // AST Node Types typedef enum { + AST_VAR_DECLARATION, + AST_CONST_DECLARATION, AST_ASSIGNMENT, + AST_LITERAL, AST_FUNCTION_DECLARATION, AST_FUNCTION_CALL, AST_FUNCTION_RETURN, - AST_LITERAL, AST_CONDITIONAL, AST_UNARY_OP, AST_BINARY_OP, @@ -22,8 +22,6 @@ typedef enum { AST_SWITCH, AST_BREAK, AST_TERNARY, - AST_VAR_DECLARATION, - AST_CONST_DECLARATION, AST_TRY, AST_CATCH, AST_FINALLY, @@ -102,8 +100,7 @@ typedef struct { // AST Function Parameter typedef struct ASTFunctionParameter { - char *parameter_name; // Parameter name - // LiteralNode *type; // Optional: parameter type (e.g., int, string, etc.) + char *parameter_name; // Parameter name struct ASTFunctionParameter *next; // Linked list for multiple parameters } ASTFunctionParameter; @@ -132,18 +129,18 @@ typedef struct { struct ASTNode *false_expr; } ASTTernary; -// AST Rescue Node (optional error object) +// AST Catch Node typedef struct ASTCatchNode { char *error_variable; // Optional: Variable name to hold the error object struct ASTNode *body; // Body of the rescue block - struct ASTCatchNode *next; // For multiple rescue clauses (future feature) + struct ASTCatchNode *next; // For multiple `rescue` clauses } ASTCatchNode; // AST Try Node typedef struct { struct ASTNode *try_block; // Code within the try block ASTCatchNode *catch_blocks; // Linked list of rescue blocks - struct ASTNode *finally_block; // Optional finish block + struct ASTNode *finally_block; // Optional `finish` block } ASTTry; // AST Array Literal Node @@ -158,7 +155,7 @@ typedef struct { struct ASTNode *index; // The index expression } ASTArrayIndexAccess; -// AST Slice Access Node (New) +// AST Slice Access Node typedef struct { struct ASTNode *array; // The array expression struct ASTNode *start; // Start index (can be NULL) @@ -176,39 +173,50 @@ typedef struct { typedef struct ASTNode { ASTNodeType type; union { - // Variable/Constant Name - char *variable_name; + // Variable Declaration + struct { + char *variable_name; + struct ASTNode *initializer; + } var_declaration; + + // Constant Declaration + struct { + char *constant_name; + struct ASTNode *initializer; + } const_declaration; // Assignment struct { - char *variable_name; struct ASTNode *lhs; struct ASTNode *rhs; } assignment; - LiteralNode literal; - - ASTUnaryOp unary_op; - ASTBinaryOp binary_op; - ASTTernary ternary; + // Function Nodes + ASTFunctionDeclaration function_declaration; + ASTFunctionCall function_call; + ASTFunctionReturn function_return; + // Control Flow Nodes ASTConditional conditional; ASTSwitch switch_case; ASTWhileLoop while_loop; ASTForLoop for_loop; - + ASTTernary ternary; ASTTry try_block; - // Function Nodes - ASTFunctionDeclaration function_declaration; - ASTFunctionCall function_call; - ASTFunctionReturn function_return; + // Operations + ASTUnaryOp unary_op; + ASTBinaryOp binary_op; // Array Nodes - ASTArrayLiteral array_literal; // Array Literal - ASTArrayOperation array_operation; // Array Operation - ASTArrayIndexAccess array_index_access; // Array Index Access - ASTArraySliceAccess array_slice_access; // Array Slice Access + ASTArrayLiteral array_literal; + ASTArrayOperation array_operation; + ASTArrayIndexAccess array_index_access; + ASTArraySliceAccess array_slice_access; + + // Literal and Reference + LiteralNode literal; + char *variable_name; // For AST_VARIABLE_REFERENCE }; struct ASTNode *next;