diff options
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src/interpreter.c')
-rw-r--r-- | js/scripting-lang/baba-yaga-c/src/interpreter.c | 1016 |
1 files changed, 0 insertions, 1016 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/interpreter.c b/js/scripting-lang/baba-yaga-c/src/interpreter.c deleted file mode 100644 index 70d26f8..0000000 --- a/js/scripting-lang/baba-yaga-c/src/interpreter.c +++ /dev/null @@ -1,1016 +0,0 @@ -/** - * @file interpreter.c - * @brief Interpreter implementation for Baba Yaga - * @author eli_oat - * @version 0.0.1 - * @date 2025 - * - * This file implements the main interpreter for the Baba Yaga language. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "baba_yaga.h" - -/* Forward declarations for function types */ -typedef struct { - char* name; - bool is_optional; -} FunctionParam; - -typedef enum { - FUNC_NATIVE, - FUNC_USER -} FunctionType; - -typedef struct { - void* ast_node; - char* source; -} FunctionBody; - -typedef struct { - char* name; - FunctionType type; - FunctionParam* params; - int param_count; - int required_params; - union { - Value (*native_func)(Value*, int); - FunctionBody user_body; - } body; - void* closure_scope; - int ref_count; -} FunctionValue; - -/* Forward declarations */ -Value interpreter_evaluate_expression(void* node, Scope* scope); -static Value interpreter_evaluate_statement(void* node, Scope* scope); - -/* Standard library function declarations */ -Value stdlib_table_entry(Value* args, int argc); - -/* ============================================================================ - * Interpreter Structure - * ============================================================================ */ - -struct Interpreter { - Scope* global_scope; - BabaYagaError* last_error; - DebugLevel debug_level; -}; - -/* ============================================================================ - * Standard Library Registration - * ============================================================================ */ - -/** - * @brief Register standard library functions in the global scope - * - * @param scope Global scope to register functions in - */ -static void register_stdlib(Scope* scope) { - DEBUG_INFO("Registering standard library functions"); - - /* Core combinator */ - Value apply_func = baba_yaga_value_function("apply", stdlib_apply_wrapper, 10, 1); - scope_define(scope, "apply", apply_func, true); - - /* Predefined variables for testing */ - Value hello_var = baba_yaga_value_string("hello"); - scope_define(scope, "hello", hello_var, true); - - /* Arithmetic functions */ - Value add_func = baba_yaga_value_function("add", stdlib_add_wrapper, 2, 2); - scope_define(scope, "add", add_func, true); - - Value subtract_func = baba_yaga_value_function("subtract", stdlib_subtract_wrapper, 2, 2); - scope_define(scope, "subtract", subtract_func, true); - - Value multiply_func = baba_yaga_value_function("multiply", stdlib_multiply_wrapper, 2, 2); - scope_define(scope, "multiply", multiply_func, true); - - Value divide_func = baba_yaga_value_function("divide", stdlib_divide_wrapper, 2, 2); - scope_define(scope, "divide", divide_func, true); - - Value modulo_func = baba_yaga_value_function("modulo", stdlib_modulo_wrapper, 2, 2); - scope_define(scope, "modulo", modulo_func, true); - - Value pow_func = baba_yaga_value_function("pow", stdlib_pow_wrapper, 2, 2); - scope_define(scope, "pow", pow_func, true); - - Value negate_func = baba_yaga_value_function("negate", stdlib_negate_wrapper, 1, 1); - scope_define(scope, "negate", negate_func, true); - - /* Comparison functions */ - Value equals_func = baba_yaga_value_function("equals", stdlib_equals_wrapper, 2, 2); - scope_define(scope, "equals", equals_func, true); - - Value not_equals_func = baba_yaga_value_function("not_equals", stdlib_not_equals_wrapper, 2, 2); - scope_define(scope, "not_equals", not_equals_func, true); - - Value less_func = baba_yaga_value_function("less", stdlib_less_wrapper, 2, 2); - scope_define(scope, "less", less_func, true); - - Value less_equal_func = baba_yaga_value_function("less_equal", stdlib_less_equal_wrapper, 2, 2); - scope_define(scope, "less_equal", less_equal_func, true); - - Value greater_func = baba_yaga_value_function("greater", stdlib_greater_wrapper, 2, 2); - scope_define(scope, "greater", greater_func, true); - - Value greater_equal_func = baba_yaga_value_function("greater_equal", stdlib_greater_equal_wrapper, 2, 2); - scope_define(scope, "greater_equal", greater_equal_func, true); - - /* Add canonical names for JavaScript compatibility */ - Value greater_than_func = baba_yaga_value_function("greaterThan", stdlib_greater_wrapper, 2, 2); - scope_define(scope, "greaterThan", greater_than_func, true); - - Value less_than_func = baba_yaga_value_function("lessThan", stdlib_less_wrapper, 2, 2); - scope_define(scope, "lessThan", less_than_func, true); - - Value greater_equal_than_func = baba_yaga_value_function("greaterEqual", stdlib_greater_equal_wrapper, 2, 2); - scope_define(scope, "greaterEqual", greater_equal_than_func, true); - - Value less_equal_than_func = baba_yaga_value_function("lessEqual", stdlib_less_equal_wrapper, 2, 2); - scope_define(scope, "lessEqual", less_equal_than_func, true); - - /* Logical functions */ - Value and_func = baba_yaga_value_function("and", stdlib_and_wrapper, 2, 2); - scope_define(scope, "and", and_func, true); - - Value or_func = baba_yaga_value_function("or", stdlib_or_wrapper, 2, 2); - scope_define(scope, "or", or_func, true); - - Value xor_func = baba_yaga_value_function("xor", stdlib_xor_wrapper, 2, 2); - scope_define(scope, "xor", xor_func, true); - - Value not_func = baba_yaga_value_function("not", stdlib_not_wrapper, 1, 1); - scope_define(scope, "not", not_func, true); - - /* Function composition */ - Value compose_func = baba_yaga_value_function("compose", stdlib_compose_wrapper, 4, 2); - scope_define(scope, "compose", compose_func, true); - - /* IO functions */ - Value out_func = baba_yaga_value_function("out", stdlib_out_wrapper, 1, 1); - scope_define(scope, "out", out_func, true); - - Value in_func = baba_yaga_value_function("in", stdlib_in_wrapper, 0, 0); - scope_define(scope, "in", in_func, true); - - Value assert_func = baba_yaga_value_function("assert", stdlib_assert_wrapper, 1, 1); - scope_define(scope, "assert", assert_func, true); - - Value emit_func = baba_yaga_value_function("emit", stdlib_emit_wrapper, 1, 1); - scope_define(scope, "emit", emit_func, true); - - Value listen_func = baba_yaga_value_function("listen", stdlib_listen_wrapper, 0, 0); - scope_define(scope, "listen", listen_func, true); - - /* Higher-order functions */ - Value map_func = baba_yaga_value_function("map", stdlib_map, 2, 2); - scope_define(scope, "map", map_func, true); - - Value filter_func = baba_yaga_value_function("filter", stdlib_filter, 2, 2); - scope_define(scope, "filter", filter_func, true); - - Value reduce_func = baba_yaga_value_function("reduce", stdlib_reduce, 3, 3); - scope_define(scope, "reduce", reduce_func, true); - - /* Advanced combinators */ - Value each_func = baba_yaga_value_function("each", stdlib_each, 3, 3); - scope_define(scope, "each", each_func, true); - - Value flip_func = baba_yaga_value_function("flip", stdlib_flip_wrapper, 3, 1); - scope_define(scope, "flip", flip_func, true); - - Value constant_func = baba_yaga_value_function("constant", stdlib_constant_wrapper, 2, 1); - scope_define(scope, "constant", constant_func, true); - - /* Table operations namespace */ - Value t_map_func = baba_yaga_value_function("t.map", stdlib_t_map_wrapper, 2, 2); - scope_define(scope, "t.map", t_map_func, true); - - Value t_filter_func = baba_yaga_value_function("t.filter", stdlib_t_filter_wrapper, 2, 2); - scope_define(scope, "t.filter", t_filter_func, true); - - Value t_reduce_func = baba_yaga_value_function("t.reduce", stdlib_t_reduce_wrapper, 3, 3); - scope_define(scope, "t.reduce", t_reduce_func, true); - - Value t_set_func = baba_yaga_value_function("t.set", stdlib_t_set_wrapper, 3, 3); - scope_define(scope, "t.set", t_set_func, true); - - Value t_delete_func = baba_yaga_value_function("t.delete", stdlib_t_delete_wrapper, 2, 2); - scope_define(scope, "t.delete", t_delete_func, true); - - Value t_merge_func = baba_yaga_value_function("t.merge", stdlib_t_merge_wrapper, 2, 2); - scope_define(scope, "t.merge", t_merge_func, true); - - Value t_length_func = baba_yaga_value_function("t.length", stdlib_t_length_wrapper, 1, 1); - scope_define(scope, "t.length", t_length_func, true); - - Value t_has_func = baba_yaga_value_function("t.has", stdlib_t_has_wrapper, 2, 2); - scope_define(scope, "t.has", t_has_func, true); - - Value t_get_func = baba_yaga_value_function("t.get", stdlib_t_get_wrapper, 3, 3); - scope_define(scope, "t.get", t_get_func, true); - - /* Internal table entry function for key-value pairs */ - Value table_entry_func = baba_yaga_value_function("table_entry", stdlib_table_entry_wrapper, 2, 2); - scope_define(scope, "table_entry", table_entry_func, true); - - /* Create t namespace table */ - Value t_table = baba_yaga_value_table(); - t_table = baba_yaga_table_set(&t_table, "map", &t_map_func); - t_table = baba_yaga_table_set(&t_table, "filter", &t_filter_func); - t_table = baba_yaga_table_set(&t_table, "reduce", &t_reduce_func); - t_table = baba_yaga_table_set(&t_table, "set", &t_set_func); - t_table = baba_yaga_table_set(&t_table, "delete", &t_delete_func); - t_table = baba_yaga_table_set(&t_table, "merge", &t_merge_func); - t_table = baba_yaga_table_set(&t_table, "length", &t_length_func); - t_table = baba_yaga_table_set(&t_table, "has", &t_has_func); - t_table = baba_yaga_table_set(&t_table, "get", &t_get_func); - - scope_define(scope, "t", t_table, true); - - DEBUG_INFO("Registered %d standard library functions", 31); -} - -/* ============================================================================ - * Core API Functions - * ============================================================================ */ - -Interpreter* baba_yaga_create(void) { - Interpreter* interp = malloc(sizeof(Interpreter)); - if (interp == NULL) { - return NULL; - } - - /* Create global scope */ - interp->global_scope = scope_create(NULL); - if (interp->global_scope == NULL) { - free(interp); - return NULL; - } - - /* Initialize error handling */ - interp->last_error = NULL; - interp->debug_level = DEBUG_NONE; - - /* Register standard library */ - register_stdlib(interp->global_scope); - - DEBUG_INFO("Interpreter created successfully"); - return interp; -} - -void baba_yaga_destroy(Interpreter* interp) { - if (interp == NULL) { - return; - } - - /* Destroy global scope */ - if (interp->global_scope != NULL) { - scope_destroy(interp->global_scope); - } - - /* Destroy last error */ - if (interp->last_error != NULL) { - baba_yaga_error_destroy(interp->last_error); - } - - free(interp); - DEBUG_INFO("Interpreter destroyed"); -} - -Value baba_yaga_execute(Interpreter* interp, const char* source, - size_t source_len, ExecResult* result) { - if (interp == NULL || source == NULL || result == NULL) { - if (result != NULL) { - *result = EXEC_ERROR; - } - return baba_yaga_value_nil(); - } - - DEBUG_INFO("Executing source code (length: %zu)", source_len); - - /* Tokenize */ - void* tokens[1000]; - int token_count = baba_yaga_tokenize(source, source_len, tokens, 1000); - - if (token_count <= 0) { - DEBUG_ERROR("Failed to tokenize source code"); - *result = EXEC_ERROR; - return baba_yaga_value_nil(); - } - - DEBUG_DEBUG("Tokenized into %d tokens", token_count); - - /* Parse */ - void* ast = baba_yaga_parse(tokens, token_count); - baba_yaga_free_tokens(tokens, token_count); - - if (ast == NULL) { - DEBUG_ERROR("Failed to parse source code"); - *result = EXEC_ERROR; - return baba_yaga_value_nil(); - } - - DEBUG_DEBUG("Parsed AST successfully"); - - if (interp->debug_level >= DEBUG_DEBUG) { - printf("AST:\n"); - baba_yaga_print_ast(ast, 0); - } - - /* Execute */ - Value result_value = interpreter_evaluate_expression(ast, interp->global_scope); - baba_yaga_destroy_ast(ast); - - if (result_value.type == VAL_NIL) { - *result = EXEC_ERROR; - } else { - *result = EXEC_SUCCESS; - } - - DEBUG_INFO("Execution completed"); - return result_value; -} - -Value baba_yaga_execute_file(Interpreter* interp, const char* filename, - ExecResult* result) { - if (interp == NULL || filename == NULL || result == NULL) { - if (result != NULL) { - *result = EXEC_ERROR; - } - return baba_yaga_value_nil(); - } - - DEBUG_INFO("Executing file: %s", filename); - - /* Read file */ - FILE* file = fopen(filename, "r"); - if (file == NULL) { - DEBUG_ERROR("Failed to open file: %s", filename); - *result = EXEC_ERROR; - return baba_yaga_value_nil(); - } - - /* Get file size */ - fseek(file, 0, SEEK_END); - long file_size = ftell(file); - fseek(file, 0, SEEK_SET); - - if (file_size <= 0) { - DEBUG_ERROR("File is empty or invalid: %s", filename); - fclose(file); - *result = EXEC_ERROR; - return baba_yaga_value_nil(); - } - - /* Read content */ - char* source = malloc(file_size + 1); - if (source == NULL) { - DEBUG_ERROR("Failed to allocate memory for file content"); - fclose(file); - *result = EXEC_ERROR; - return baba_yaga_value_nil(); - } - - size_t bytes_read = fread(source, 1, file_size, file); - source[bytes_read] = '\0'; - fclose(file); - - /* Execute */ - Value result_value = baba_yaga_execute(interp, source, bytes_read, result); - free(source); - - return result_value; -} - -/* ============================================================================ - * Expression Evaluation - * ============================================================================ */ - -/** - * @brief Evaluate an expression node - * - * @param node AST node to evaluate - * @param scope Current scope - * @return Result value - */ -Value interpreter_evaluate_expression(void* node, Scope* scope) { - if (node == NULL) { - return baba_yaga_value_nil(); - } - - NodeType node_type = baba_yaga_ast_get_type(node); - DEBUG_DEBUG("Evaluating expression: type %d", node_type); - - switch (node_type) { - case NODE_LITERAL: { - Value literal = baba_yaga_ast_get_literal(node); - DEBUG_DEBUG("Literal evaluation: type %d", literal.type); - return literal; - } - - case NODE_IDENTIFIER: { - const char* identifier = baba_yaga_ast_get_identifier(node); - if (identifier == NULL) { - DEBUG_ERROR("Invalid identifier node"); - return baba_yaga_value_nil(); - } - - DEBUG_DEBUG("Looking up identifier: %s", identifier); - - /* Check if this is a function reference (starts with @) */ - if (identifier[0] == '@') { - /* Strip the @ prefix and look up the function */ - const char* func_name = identifier + 1; - DEBUG_DEBUG("Function reference: %s", func_name); - Value value = scope_get(scope, func_name); - DEBUG_DEBUG("Function '%s' lookup result type: %d", func_name, value.type); - if (value.type == VAL_NIL) { - DEBUG_ERROR("Undefined function: %s", func_name); - } - return value; - } else { - /* Regular variable lookup */ - Value value = scope_get(scope, identifier); - DEBUG_DEBUG("Identifier '%s' lookup result type: %d", identifier, value.type); - if (value.type == VAL_NIL) { - DEBUG_ERROR("Undefined variable: %s", identifier); - } - return value; - } - } - - case NODE_FUNCTION_CALL: { - DEBUG_DEBUG("Evaluating NODE_FUNCTION_CALL"); - /* Evaluate function */ - void* func_node = baba_yaga_ast_get_function_call_func(node); - Value func_value = interpreter_evaluate_expression(func_node, scope); - - DEBUG_DEBUG("Function call - function value type: %d", func_value.type); - - if (func_value.type != VAL_FUNCTION) { - DEBUG_ERROR("Cannot call non-function value"); - baba_yaga_value_destroy(&func_value); - return baba_yaga_value_nil(); - } - - /* Evaluate arguments */ - int arg_count = baba_yaga_ast_get_function_call_arg_count(node); - Value* args = malloc(arg_count * sizeof(Value)); - if (args == NULL) { - DEBUG_ERROR("Failed to allocate memory for function arguments"); - baba_yaga_value_destroy(&func_value); - return baba_yaga_value_nil(); - } - - for (int i = 0; i < arg_count; i++) { - void* arg_node = baba_yaga_ast_get_function_call_arg(node, i); - args[i] = interpreter_evaluate_expression(arg_node, scope); - } - - /* Call function */ - DEBUG_DEBUG("Calling function with %d arguments", arg_count); - Value result = baba_yaga_function_call(&func_value, args, arg_count, scope); - DEBUG_DEBUG("Function call returned type: %d", result.type); - - /* Cleanup */ - for (int i = 0; i < arg_count; i++) { - baba_yaga_value_destroy(&args[i]); - } - free(args); - baba_yaga_value_destroy(&func_value); - - return result; - } - - case NODE_BINARY_OP: { - void* left_node = baba_yaga_ast_get_binary_op_left(node); - void* right_node = baba_yaga_ast_get_binary_op_right(node); - const char* operator = baba_yaga_ast_get_binary_op_operator(node); - - if (left_node == NULL || right_node == NULL || operator == NULL) { - DEBUG_ERROR("Invalid binary operation node"); - return baba_yaga_value_nil(); - } - - DEBUG_DEBUG("Binary operator: %s", operator); - - Value left = interpreter_evaluate_expression(left_node, scope); - Value right = interpreter_evaluate_expression(right_node, scope); - - /* Create function call for the operator */ - Value func_value = scope_get(scope, operator); - DEBUG_DEBUG("Function lookup for '%s': type %d", operator, func_value.type); - if (func_value.type != VAL_FUNCTION) { - DEBUG_ERROR("Unknown operator: %s", operator); - baba_yaga_value_destroy(&left); - baba_yaga_value_destroy(&right); - return baba_yaga_value_nil(); - } - - Value args[2] = {left, right}; - Value result = baba_yaga_function_call(&func_value, args, 2, scope); - - baba_yaga_value_destroy(&left); - baba_yaga_value_destroy(&right); - baba_yaga_value_destroy(&func_value); - - return result; - } - - case NODE_UNARY_OP: { - void* operand_node = baba_yaga_ast_get_unary_op_operand(node); - const char* operator = baba_yaga_ast_get_unary_op_operator(node); - - if (operand_node == NULL || operator == NULL) { - DEBUG_ERROR("Invalid unary operation node"); - return baba_yaga_value_nil(); - } - - Value operand = interpreter_evaluate_expression(operand_node, scope); - - /* Create function call for the operator */ - Value func_value = scope_get(scope, operator); - if (func_value.type != VAL_FUNCTION) { - DEBUG_ERROR("Unknown operator: %s", operator); - baba_yaga_value_destroy(&operand); - return baba_yaga_value_nil(); - } - - Value args[1] = {operand}; - Value result = baba_yaga_function_call(&func_value, args, 1, scope); - - baba_yaga_value_destroy(&operand); - baba_yaga_value_destroy(&func_value); - - return result; - } - - case NODE_FUNCTION_DEF: { - const char* name = baba_yaga_ast_get_function_def_name(node); - int param_count = baba_yaga_ast_get_function_def_param_count(node); - void* body_node = baba_yaga_ast_get_function_def_body(node); - - if (name == NULL || body_node == NULL) { - DEBUG_ERROR("Invalid function definition node"); - return baba_yaga_value_nil(); - } - - /* Create user-defined function value */ - FunctionValue* func_value = malloc(sizeof(FunctionValue)); - if (func_value == NULL) { - DEBUG_ERROR("Failed to allocate memory for function"); - return baba_yaga_value_nil(); - } - - /* Initialize function value */ - func_value->name = strdup(name); - func_value->type = FUNC_USER; - func_value->param_count = param_count; - func_value->required_params = param_count; - func_value->ref_count = 1; - func_value->closure_scope = NULL; /* TODO: Implement closures */ - - /* Allocate and copy parameters */ - func_value->params = malloc(param_count * sizeof(FunctionParam)); - if (func_value->params == NULL) { - free(func_value->name); - free(func_value); - DEBUG_ERROR("Failed to allocate memory for function parameters"); - return baba_yaga_value_nil(); - } - - for (int i = 0; i < param_count; i++) { - void* param_node = baba_yaga_ast_get_function_def_param(node, i); - if (param_node != NULL && baba_yaga_ast_get_type(param_node) == NODE_IDENTIFIER) { - const char* param_name = baba_yaga_ast_get_identifier(param_node); - func_value->params[i].name = strdup(param_name); - func_value->params[i].is_optional = false; - } else { - func_value->params[i].name = NULL; - func_value->params[i].is_optional = false; - } - } - - /* Store function body */ - func_value->body.user_body.ast_node = body_node; - func_value->body.user_body.source = NULL; /* TODO: Store source for debugging */ - - /* Create function value */ - Value func_val; - func_val.type = VAL_FUNCTION; - func_val.data.function = func_value; - - /* Define in current scope */ - scope_define(scope, name, func_val, false); - - return func_val; - } - - case NODE_VARIABLE_DECL: { - const char* name = baba_yaga_ast_get_variable_decl_name(node); - void* value_node = baba_yaga_ast_get_variable_decl_value(node); - - if (name == NULL || value_node == NULL) { - DEBUG_ERROR("Invalid variable declaration node"); - return baba_yaga_value_nil(); - } - - - Value value = interpreter_evaluate_expression(value_node, scope); - DEBUG_DEBUG("Variable declaration: evaluating '%s' = value with type %d", name, value.type); - scope_define(scope, name, value, false); - return value; - } - - case NODE_SEQUENCE: { - int statement_count = baba_yaga_ast_get_sequence_statement_count(node); - DEBUG_DEBUG("Executing sequence with %d statements", statement_count); - - Value result = baba_yaga_value_nil(); - - /* Execute all statements in sequence */ - for (int i = 0; i < statement_count; i++) { - void* statement_node = baba_yaga_ast_get_sequence_statement(node, i); - if (statement_node == NULL) { - DEBUG_ERROR("Invalid statement node at index %d", i); - continue; - } - - /* Destroy previous result before evaluating next statement */ - baba_yaga_value_destroy(&result); - - /* Evaluate statement */ - result = interpreter_evaluate_expression(statement_node, scope); - DEBUG_DEBUG("Statement %d result type: %d", i, result.type); - } - - return result; /* Return result of last statement */ - } - - case NODE_WHEN_EXPR: { - DEBUG_DEBUG("Evaluating NODE_WHEN_EXPR"); - /* Evaluate the test expression */ - void* test_node = baba_yaga_ast_get_when_expr_test(node); - Value test_value = interpreter_evaluate_expression(test_node, scope); - - /* Check if test is a sequence (multi-parameter test) */ - bool is_multi_param_test = (baba_yaga_ast_get_type(test_node) == NODE_SEQUENCE); - - /* Get patterns */ - int pattern_count = baba_yaga_ast_get_when_expr_pattern_count(node); - - /* Try each pattern in order */ - for (int i = 0; i < pattern_count; i++) { - void* pattern_node = baba_yaga_ast_get_when_expr_pattern(node, i); - if (pattern_node == NULL) { - continue; - } - - /* Evaluate pattern test */ - void* pattern_test_node = baba_yaga_ast_get_when_pattern_test(pattern_node); - Value pattern_test_value = interpreter_evaluate_expression(pattern_test_node, scope); - - /* Check if pattern is a sequence (multi-parameter pattern) */ - bool is_multi_param_pattern = (baba_yaga_ast_get_type(pattern_test_node) == NODE_SEQUENCE); - - /* Check if pattern matches */ - bool matches = false; - - /* Handle multi-parameter pattern matching */ - if (is_multi_param_test && is_multi_param_pattern) { - /* Both test and pattern are sequences - compare element by element */ - int test_count = baba_yaga_ast_get_sequence_statement_count(test_node); - int pattern_count = baba_yaga_ast_get_sequence_statement_count(pattern_test_node); - - if (test_count == pattern_count) { - matches = true; - for (int j = 0; j < test_count; j++) { - void* test_elem_node = baba_yaga_ast_get_sequence_statement(test_node, j); - void* pattern_elem_node = baba_yaga_ast_get_sequence_statement(pattern_test_node, j); - - if (test_elem_node == NULL || pattern_elem_node == NULL) { - matches = false; - break; - } - - Value test_elem = interpreter_evaluate_expression(test_elem_node, scope); - Value pattern_elem = interpreter_evaluate_expression(pattern_elem_node, scope); - - /* Check if elements match */ - bool elem_matches = false; - if (pattern_elem.type == VAL_STRING && - strcmp(pattern_elem.data.string, "_") == 0) { - /* Wildcard element always matches */ - elem_matches = true; - } else if (pattern_elem.type == test_elem.type) { - switch (pattern_elem.type) { - case VAL_NUMBER: - elem_matches = (pattern_elem.data.number == test_elem.data.number); - break; - case VAL_STRING: - elem_matches = (strcmp(pattern_elem.data.string, test_elem.data.string) == 0); - break; - case VAL_BOOLEAN: - elem_matches = (pattern_elem.data.boolean == test_elem.data.boolean); - break; - default: - elem_matches = false; - break; - } - } - - if (!elem_matches) { - matches = false; - } - - /* Clean up element values */ - baba_yaga_value_destroy(&test_elem); - baba_yaga_value_destroy(&pattern_elem); - - if (!matches) { - break; - } - } - } - } else if (pattern_test_value.type == VAL_NUMBER && test_value.type == VAL_NUMBER) { - matches = (pattern_test_value.data.number == test_value.data.number); - } else if (pattern_test_value.type == VAL_STRING && test_value.type == VAL_STRING) { - matches = (strcmp(pattern_test_value.data.string, test_value.data.string) == 0); - } else if (pattern_test_value.type == VAL_BOOLEAN && test_value.type == VAL_BOOLEAN) { - matches = (pattern_test_value.data.boolean == test_value.data.boolean); - } else if (pattern_test_value.type == VAL_STRING && - strcmp(pattern_test_value.data.string, "_") == 0) { - /* Wildcard pattern always matches */ - matches = true; - } else if (pattern_test_value.type == VAL_NIL && test_value.type == VAL_NIL) { - /* Both are nil - match */ - matches = true; - } else if (pattern_test_value.type == VAL_TABLE && test_value.type == VAL_TABLE) { - /* Table pattern matching: check if all pattern properties exist and match */ - matches = true; - - /* Get all keys from the pattern table */ - char* pattern_keys[100]; /* Assume max 100 keys */ - size_t pattern_key_count = baba_yaga_table_get_keys(&pattern_test_value, pattern_keys, 100); - - /* Check each property in the pattern */ - for (size_t i = 0; i < pattern_key_count; i++) { - char* pattern_key = pattern_keys[i]; - - /* Check if this property exists in the test value */ - if (!baba_yaga_table_has_key(&test_value, pattern_key)) { - /* Property doesn't exist in test value */ - matches = false; - break; - } - - /* Get pattern property value */ - Value pattern_property = baba_yaga_table_get(&pattern_test_value, pattern_key); - /* Get test property value */ - Value test_property = baba_yaga_table_get(&test_value, pattern_key); - - /* Check if property values match */ - bool property_matches = false; - if (pattern_property.type == test_property.type) { - switch (pattern_property.type) { - case VAL_NUMBER: - property_matches = (pattern_property.data.number == test_property.data.number); - break; - case VAL_STRING: - property_matches = (strcmp(pattern_property.data.string, test_property.data.string) == 0); - break; - case VAL_BOOLEAN: - property_matches = (pattern_property.data.boolean == test_property.data.boolean); - break; - default: - property_matches = false; - break; - } - } - - if (!property_matches) { - matches = false; - break; - } - } - } - - baba_yaga_value_destroy(&pattern_test_value); - - if (matches) { - /* Pattern matches, evaluate result */ - void* result_node = baba_yaga_ast_get_when_pattern_result(pattern_node); - Value result = interpreter_evaluate_expression(result_node, scope); - baba_yaga_value_destroy(&test_value); - return result; - } - } - - /* No pattern matched */ - baba_yaga_value_destroy(&test_value); - DEBUG_ERROR("No matching pattern in when expression"); - return baba_yaga_value_nil(); - } - - case NODE_TABLE: { - DEBUG_DEBUG("Evaluating NODE_TABLE"); - /* Evaluate table literal */ - int element_count = baba_yaga_ast_get_table_element_count(node); - DEBUG_DEBUG("Evaluating table with %d elements", element_count); - - /* Create a new table value */ - Value table = baba_yaga_value_table(); - - /* Evaluate each element and add to table */ - for (int i = 0; i < element_count; i++) { - void* element_node = baba_yaga_ast_get_table_element(node, i); - if (element_node == NULL) { - DEBUG_ERROR("Table element %d is NULL", i); - continue; - } - - /* Check if this is a table_entry function call (key-value pair) */ - NodeType element_type = baba_yaga_ast_get_type(element_node); - if (element_type == NODE_FUNCTION_CALL) { - /* Get function name */ - void* func_node = baba_yaga_ast_get_function_call_func(element_node); - if (func_node != NULL && baba_yaga_ast_get_type(func_node) == NODE_IDENTIFIER) { - const char* func_name = baba_yaga_ast_get_identifier(func_node); - if (func_name && strcmp(func_name, "table_entry") == 0) { - /* This is a key-value pair */ - int arg_count = baba_yaga_ast_get_function_call_arg_count(element_node); - if (arg_count == 2) { - /* Get key and value */ - void* key_node = baba_yaga_ast_get_function_call_arg(element_node, 0); - void* value_node = baba_yaga_ast_get_function_call_arg(element_node, 1); - - if (key_node != NULL && value_node != NULL) { - Value key_value = interpreter_evaluate_expression(key_node, scope); - Value element_value = interpreter_evaluate_expression(value_node, scope); - - /* Extract key string */ - char* key_str = NULL; - if (key_value.type == VAL_STRING) { - key_str = strdup(key_value.data.string); - } else if (key_value.type == VAL_NUMBER) { - char num_str[32]; - snprintf(num_str, sizeof(num_str), "%g", key_value.data.number); - key_str = strdup(num_str); - } else { - key_str = strdup("unknown"); - } - - DEBUG_DEBUG("Setting table key '%s' to element %d", key_str, i); - table = baba_yaga_table_set(&table, key_str, &element_value); - - free(key_str); - baba_yaga_value_destroy(&key_value); - baba_yaga_value_destroy(&element_value); - continue; - } - } - } - } - } - - /* Fallback to array-like indexing (1-based) */ - Value element_value = interpreter_evaluate_expression(element_node, scope); - DEBUG_DEBUG("Table element %d evaluated to type %d", i, element_value.type); - - char key_str[32]; - snprintf(key_str, sizeof(key_str), "%d", i + 1); - Value key = baba_yaga_value_string(key_str); - - DEBUG_DEBUG("Setting table key '%s' to element %d", key_str, i); - table = baba_yaga_table_set(&table, key.data.string, &element_value); - - baba_yaga_value_destroy(&key); - baba_yaga_value_destroy(&element_value); - } - - DEBUG_DEBUG("Table evaluation complete, final size: %zu", baba_yaga_table_size(&table)); - return table; - } - - case NODE_TABLE_ACCESS: { - /* Evaluate table access: table.property or table[key] */ - void* object_node = baba_yaga_ast_get_table_access_object(node); - void* key_node = baba_yaga_ast_get_table_access_key(node); - - if (object_node == NULL || key_node == NULL) { - DEBUG_ERROR("Invalid table access node"); - return baba_yaga_value_nil(); - } - - /* Evaluate the object (table) */ - Value object = interpreter_evaluate_expression(object_node, scope); - DEBUG_DEBUG("Table access - object type: %d", object.type); - if (object.type != VAL_TABLE) { - DEBUG_ERROR("Cannot access property of non-table value"); - baba_yaga_value_destroy(&object); - return baba_yaga_value_nil(); - } - - /* Evaluate the key */ - Value key = interpreter_evaluate_expression(key_node, scope); - DEBUG_DEBUG("Table access - key type: %d", key.type); - if (key.type != VAL_STRING && key.type != VAL_NUMBER) { - DEBUG_ERROR("Table key must be string or number"); - baba_yaga_value_destroy(&object); - baba_yaga_value_destroy(&key); - return baba_yaga_value_nil(); - } - - /* Convert key to string for table lookup */ - char* key_str; - if (key.type == VAL_NUMBER) { - key_str = malloc(32); - if (key_str == NULL) { - baba_yaga_value_destroy(&object); - baba_yaga_value_destroy(&key); - return baba_yaga_value_nil(); - } - snprintf(key_str, 32, "%g", key.data.number); - } else { - key_str = strdup(key.data.string); - } - - DEBUG_DEBUG("Table access - looking up key: '%s'", key_str); - - /* Get the value from the table */ - Value result = baba_yaga_table_get(&object, key_str); - DEBUG_DEBUG("Table access - result type: %d", result.type); - - /* Cleanup */ - free(key_str); - baba_yaga_value_destroy(&object); - baba_yaga_value_destroy(&key); - - return result; - } - - default: - DEBUG_ERROR("Unsupported expression type: %d", node_type); - return baba_yaga_value_nil(); - } -} - -/** - * @brief Evaluate a statement node - * - * @param node AST node to evaluate - * @param scope Current scope - * @return Result value - */ -__attribute__((unused)) static Value interpreter_evaluate_statement(void* node, Scope* scope) { - if (node == NULL) { - return baba_yaga_value_nil(); - } - - NodeType node_type = baba_yaga_ast_get_type(node); - DEBUG_TRACE("Evaluating statement: type %d", node_type); - - switch (node_type) { - case NODE_VARIABLE_DECL: - case NODE_FUNCTION_DEF: - return interpreter_evaluate_expression(node, scope); - - default: - DEBUG_ERROR("Unsupported statement type: %d", node_type); - return baba_yaga_value_nil(); - } -} - -/* ============================================================================ - * Error Handling Functions - * ============================================================================ */ - -BabaYagaError* baba_yaga_get_error(const Interpreter* interp) { - if (interp == NULL) { - return NULL; - } - - return interp->last_error; -} - -void baba_yaga_error_destroy(BabaYagaError* error) { - if (error == NULL) { - return; - } - - if (error->message != NULL) { - free(error->message); - } - if (error->source_file != NULL) { - free(error->source_file); - } - - free(error); -} \ No newline at end of file |