about summary refs log tree commit diff stats
path: root/js/scripting-lang/baba-yaga-c/src/interpreter.c
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src/interpreter.c')
-rw-r--r--js/scripting-lang/baba-yaga-c/src/interpreter.c1016
1 files changed, 1016 insertions, 0 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/interpreter.c b/js/scripting-lang/baba-yaga-c/src/interpreter.c
new file mode 100644
index 0000000..70d26f8
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/interpreter.c
@@ -0,0 +1,1016 @@
+/**
+ * @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