about summary refs log tree commit diff stats
path: root/js/scripting-lang/baba-yaga-c/src
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src')
-rw-r--r--js/scripting-lang/baba-yaga-c/src/debug.c116
-rw-r--r--js/scripting-lang/baba-yaga-c/src/function.c321
-rw-r--r--js/scripting-lang/baba-yaga-c/src/interpreter.c1016
-rw-r--r--js/scripting-lang/baba-yaga-c/src/lexer.c826
-rw-r--r--js/scripting-lang/baba-yaga-c/src/main.c353
-rw-r--r--js/scripting-lang/baba-yaga-c/src/memory.c68
-rw-r--r--js/scripting-lang/baba-yaga-c/src/parser.c2973
-rw-r--r--js/scripting-lang/baba-yaga-c/src/scope.c330
-rw-r--r--js/scripting-lang/baba-yaga-c/src/stdlib.c1570
-rw-r--r--js/scripting-lang/baba-yaga-c/src/table.c560
-rw-r--r--js/scripting-lang/baba-yaga-c/src/value.c215
11 files changed, 8348 insertions, 0 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/debug.c b/js/scripting-lang/baba-yaga-c/src/debug.c
new file mode 100644
index 0000000..c509969
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/debug.c
@@ -0,0 +1,116 @@
+/**
+ * @file debug.c
+ * @brief Debug and logging implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements debug and logging functionality for the Baba Yaga language.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Debug State
+ * ============================================================================ */
+
+static DebugLevel current_debug_level = DEBUG_NONE;
+
+/* ============================================================================
+ * Debug Functions
+ * ============================================================================ */
+
+/**
+ * @brief Set debug level
+ * 
+ * @param level Debug level to set
+ */
+void baba_yaga_set_debug_level(DebugLevel level) {
+    current_debug_level = level;
+}
+
+/**
+ * @brief Get current debug level
+ * 
+ * @return Current debug level
+ */
+DebugLevel baba_yaga_get_debug_level(void) {
+    return current_debug_level;
+}
+
+/**
+ * @brief Get debug level name
+ * 
+ * @param level Debug level
+ * @return String representation of debug level
+ */
+static const char* debug_level_name(DebugLevel level) {
+    switch (level) {
+    case DEBUG_NONE: return "NONE";
+    case DEBUG_ERROR: return "ERROR";
+    case DEBUG_WARN: return "WARN";
+    case DEBUG_INFO: return "INFO";
+    case DEBUG_DEBUG: return "DEBUG";
+    case DEBUG_TRACE: return "TRACE";
+    default: return "UNKNOWN";
+    }
+}
+
+/**
+ * @brief Get current timestamp
+ * 
+ * @return Current timestamp as string
+ */
+static const char* get_timestamp(void) {
+    static char timestamp[32];
+    time_t now = time(NULL);
+    struct tm* tm_info = localtime(&now);
+    strftime(timestamp, sizeof(timestamp), "%H:%M:%S", tm_info);
+    return timestamp;
+}
+
+/**
+ * @brief Debug logging function
+ * 
+ * @param level Debug level for this message
+ * @param file Source file name
+ * @param line Line number
+ * @param func Function name
+ * @param format Format string
+ * @param ... Variable arguments
+ */
+void baba_yaga_debug_log(DebugLevel level, const char* file, int line, 
+                        const char* func, const char* format, ...) {
+    if (level > current_debug_level) {
+        return;
+    }
+    
+    /* Get file name without path */
+    const char* filename = strrchr(file, '/');
+    if (filename == NULL) {
+        filename = file;
+    } else {
+        filename++; /* Skip the '/' */
+    }
+    
+    /* Print timestamp and level */
+    fprintf(stderr, "[%s] %-5s ", get_timestamp(), debug_level_name(level));
+    
+    /* Print location */
+    fprintf(stderr, "%s:%d:%s(): ", filename, line, func);
+    
+    /* Print message */
+    va_list args;
+    va_start(args, format);
+    vfprintf(stderr, format, args);
+    va_end(args);
+    
+    fprintf(stderr, "\n");
+    fflush(stderr);
+} 
diff --git a/js/scripting-lang/baba-yaga-c/src/function.c b/js/scripting-lang/baba-yaga-c/src/function.c
new file mode 100644
index 0000000..bb5bedf
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/function.c
@@ -0,0 +1,321 @@
+/**
+ * @file function.c
+ * @brief Function implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements the function system for the Baba Yaga language.
+ * Functions support closures, partial application, and first-class behavior.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "baba_yaga.h"
+
+/* Forward declarations */
+extern Scope* scope_create(Scope* parent);
+extern void scope_destroy(Scope* scope);
+extern bool scope_define(Scope* scope, const char* name, Value value, bool is_constant);
+extern Value interpreter_evaluate_expression(void* node, Scope* scope);
+
+/* ============================================================================
+ * Function Structure Definitions
+ * ============================================================================ */
+
+/**
+ * @brief Function parameter
+ */
+typedef struct {
+    char* name;         /**< Parameter name */
+    bool is_optional;   /**< Whether parameter is optional */
+} FunctionParam;
+
+typedef enum {
+    FUNC_NATIVE,    /**< Native C function */
+    FUNC_USER       /**< User-defined function */
+} FunctionType;
+
+/**
+ * @brief Function body (placeholder for AST node)
+ */
+typedef struct {
+    void* ast_node;     /**< AST node representing function body */
+    char* source;       /**< Source code for debugging */
+} FunctionBody;
+
+
+
+/**
+ * @brief Function value structure
+ */
+typedef struct {
+    char* name;                 /**< Function name (can be NULL for anonymous) */
+    FunctionType type;          /**< Function type */
+    FunctionParam* params;      /**< Array of parameters */
+    int param_count;            /**< Number of parameters */
+    int required_params;        /**< Number of required parameters */
+    union {
+        Value (*native_func)(Value*, int, Scope*);  /**< Native function pointer */
+        FunctionBody user_body;             /**< User function body */
+    } body;
+    void* closure_scope;        /**< Closure scope (placeholder) */
+    int ref_count;              /**< Reference count for memory management */
+} FunctionValue;
+
+/* ============================================================================
+ * Function Creation and Management
+ * ============================================================================ */
+
+/* TODO: Implement parameter management functions */
+
+/**
+ * @brief Destroy a function body
+ * 
+ * @param body Function body to destroy
+ */
+static void function_body_destroy(FunctionBody* body) {
+    if (body != NULL && body->source != NULL) {
+        free(body->source);
+        body->source = NULL;
+    }
+    /* Note: ast_node cleanup will be handled by AST system */
+}
+
+/* ============================================================================
+ * Public Function API
+ * ============================================================================ */
+
+
+
+Value baba_yaga_value_function(const char* name, Value (*body)(Value*, int, Scope*), 
+                              int param_count, int required_param_count) {
+    Value value;
+    value.type = VAL_FUNCTION;
+    
+    FunctionValue* func_value = malloc(sizeof(FunctionValue));
+    if (func_value == NULL) {
+        value.type = VAL_NIL;
+        return value;
+    }
+    
+    func_value->name = name != NULL ? strdup(name) : NULL;
+    func_value->type = FUNC_NATIVE;
+    func_value->param_count = param_count;
+    func_value->required_params = required_param_count;
+    func_value->ref_count = 1;
+    func_value->closure_scope = NULL; /* TODO: Implement closure scope */
+    
+    /* Allocate parameter array */
+    if (param_count > 0) {
+        func_value->params = calloc(param_count, sizeof(FunctionParam));
+        if (func_value->params == NULL) {
+            free(func_value->name);
+            free(func_value);
+            value.type = VAL_NIL;
+            return value;
+        }
+        
+        /* Initialize parameters with placeholder names */
+        for (int i = 0; i < param_count; i++) {
+            char param_name[16];
+            snprintf(param_name, sizeof(param_name), "param_%d", i + 1);
+            func_value->params[i].name = strdup(param_name);
+            func_value->params[i].is_optional = (i >= required_param_count);
+        }
+    } else {
+        func_value->params = NULL;
+    }
+    
+    /* Set native function pointer */
+    func_value->body.native_func = body;
+    
+    value.data.function = func_value;
+    return value;
+}
+
+Value baba_yaga_function_call(const Value* func, const Value* args, 
+                             int arg_count, Scope* scope) {
+    if (func == NULL || func->type != VAL_FUNCTION || args == NULL) {
+        return baba_yaga_value_nil();
+    }
+    
+    FunctionValue* func_value = (FunctionValue*)func->data.function;
+    
+
+    
+    /* Check if we have enough arguments for partial application */
+    if (arg_count < func_value->required_params) {
+        /* Implement partial application */
+        /* Create a new function with bound arguments */
+        Value partial_func = baba_yaga_value_function("partial", stdlib_partial_apply, 
+                                                     func_value->required_params - arg_count, 
+                                                     func_value->required_params - arg_count);
+        
+        /* Store the original function and bound arguments in the scope */
+        char temp_name[64];
+        snprintf(temp_name, sizeof(temp_name), "_partial_func_%p", (void*)func);
+        scope_define(scope, temp_name, *func, true);
+        
+        /* Store bound arguments */
+        for (int i = 0; i < arg_count; i++) {
+            char arg_name[64];
+            snprintf(arg_name, sizeof(arg_name), "_partial_arg_%d_%p", i, (void*)func);
+            scope_define(scope, arg_name, args[i], true);
+        }
+        
+        /* Store the number of bound arguments */
+        char count_name[64];
+        snprintf(count_name, sizeof(count_name), "_partial_count_%p", (void*)func);
+        scope_define(scope, count_name, baba_yaga_value_number(arg_count), true);
+        
+        return partial_func;
+    }
+    
+    /* Execute function based on type */
+    switch (func_value->type) {
+    case FUNC_NATIVE:
+        if (func_value->body.native_func != NULL) {
+            return func_value->body.native_func((Value*)args, arg_count, scope);
+        }
+        break;
+        
+    case FUNC_USER:
+        /* Execute user-defined function */
+        if (func_value->body.user_body.ast_node != NULL) {
+            /* Create new scope for function execution */
+            /* According to JS team requirements: function calls create local scopes that inherit from global scope */
+            Scope* global_scope = scope_get_global(scope);
+            Scope* func_scope = scope_create(global_scope); /* Pass global scope as parent for local function scope */
+            if (func_scope == NULL) {
+                DEBUG_ERROR("Failed to create function scope");
+                return baba_yaga_value_nil();
+            }
+            
+            /* Bind parameters to arguments */
+            for (int i = 0; i < arg_count && i < func_value->param_count; i++) {
+                const char* param_name = func_value->params[i].name;
+                if (param_name != NULL) {
+                    scope_define(func_scope, param_name, args[i], false);
+                }
+            }
+            
+            /* Execute function body */
+            Value result = interpreter_evaluate_expression(
+                func_value->body.user_body.ast_node, 
+                func_scope
+            );
+            
+            /* Clean up function scope */
+            scope_destroy(func_scope);
+            
+            return result;
+        }
+        break;
+        
+
+    }
+    
+    return baba_yaga_value_nil();
+}
+
+/* ============================================================================
+ * Internal Function Management
+ * ============================================================================ */
+
+/**
+ * @brief Increment reference count for a function
+ * 
+ * @param func Function value
+ */
+void function_increment_ref(Value* func) {
+    if (func != NULL && func->type == VAL_FUNCTION) {
+        FunctionValue* func_value = (FunctionValue*)func->data.function;
+        func_value->ref_count++;
+    }
+}
+
+/**
+ * @brief Decrement reference count for a function
+ * 
+ * @param func Function value
+ */
+void function_decrement_ref(Value* func) {
+    if (func != NULL && func->type == VAL_FUNCTION) {
+        FunctionValue* func_value = (FunctionValue*)func->data.function;
+        func_value->ref_count--;
+        
+        if (func_value->ref_count <= 0) {
+            /* Clean up function */
+            free(func_value->name);
+            
+            /* Clean up parameters */
+            if (func_value->params != NULL) {
+                for (int i = 0; i < func_value->param_count; i++) {
+                    free(func_value->params[i].name);
+                }
+                free(func_value->params);
+            }
+            
+                    /* Clean up function body */
+            if (func_value->type == FUNC_USER) {
+                function_body_destroy(&func_value->body.user_body);
+            }
+            
+            /* TODO: Clean up closure scope */
+            
+            free(func_value);
+        }
+    }
+}
+
+/* ============================================================================
+ * Function Utility Functions
+ * ============================================================================ */
+
+/**
+ * @brief Get function name
+ * 
+ * @param func Function value
+ * @return Function name, or NULL if anonymous
+ */
+const char* function_get_name(const Value* func) {
+    if (func == NULL || func->type != VAL_FUNCTION) {
+        return NULL;
+    }
+    
+    FunctionValue* func_value = (FunctionValue*)func->data.function;
+    return func_value->name;
+}
+
+/**
+ * @brief Get function parameter count
+ * 
+ * @param func Function value
+ * @return Number of parameters
+ */
+int function_get_param_count(const Value* func) {
+    if (func == NULL || func->type != VAL_FUNCTION) {
+        return 0;
+    }
+    
+    FunctionValue* func_value = (FunctionValue*)func->data.function;
+    return func_value->param_count;
+}
+
+/**
+ * @brief Get function required parameter count
+ * 
+ * @param func Function value
+ * @return Number of required parameters
+ */
+int function_get_required_param_count(const Value* func) {
+    if (func == NULL || func->type != VAL_FUNCTION) {
+        return 0;
+    }
+    
+    FunctionValue* func_value = (FunctionValue*)func->data.function;
+    return func_value->required_params;
+} 
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
diff --git a/js/scripting-lang/baba-yaga-c/src/lexer.c b/js/scripting-lang/baba-yaga-c/src/lexer.c
new file mode 100644
index 0000000..31a582f
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/lexer.c
@@ -0,0 +1,826 @@
+/**
+ * @file lexer.c
+ * @brief Lexer implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements the lexical analyzer for the Baba Yaga language.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Token Types
+ * ============================================================================ */
+
+typedef enum {
+    /* End of file */
+    TOKEN_EOF,
+    
+    /* Literals */
+    TOKEN_NUMBER,
+    TOKEN_STRING,
+    TOKEN_BOOLEAN,
+    
+    /* Identifiers and keywords */
+    TOKEN_IDENTIFIER,
+    TOKEN_KEYWORD_WHEN,
+    TOKEN_KEYWORD_IS,
+    TOKEN_KEYWORD_THEN,
+    TOKEN_KEYWORD_AND,
+    TOKEN_KEYWORD_OR,
+    TOKEN_KEYWORD_XOR,
+    TOKEN_KEYWORD_NOT,
+    TOKEN_KEYWORD_VIA,
+    
+    /* Operators */
+    TOKEN_OP_PLUS,
+    TOKEN_OP_MINUS,
+    TOKEN_OP_UNARY_MINUS,
+    TOKEN_OP_MULTIPLY,
+    TOKEN_OP_DIVIDE,
+    TOKEN_OP_MODULO,
+    TOKEN_OP_POWER,
+    TOKEN_OP_EQUALS,
+    TOKEN_OP_NOT_EQUALS,
+    TOKEN_OP_LESS,
+    TOKEN_OP_LESS_EQUAL,
+    TOKEN_OP_GREATER,
+    TOKEN_OP_GREATER_EQUAL,
+    
+    /* Punctuation */
+    TOKEN_LPAREN,
+    TOKEN_RPAREN,
+    TOKEN_LBRACE,
+    TOKEN_RBRACE,
+    TOKEN_LBRACKET,
+    TOKEN_RBRACKET,
+    TOKEN_COMMA,
+    TOKEN_COLON,
+    TOKEN_SEMICOLON,
+    TOKEN_ARROW,
+    TOKEN_DOT,
+    
+    /* Special tokens */
+    TOKEN_FUNCTION_REF,  /* @function */
+    TOKEN_IO_IN,         /* ..in */
+    TOKEN_IO_OUT,        /* ..out */
+    TOKEN_IO_ASSERT,     /* ..assert */
+    TOKEN_IO_EMIT,       /* ..emit */
+    TOKEN_IO_LISTEN      /* ..listen */
+} TokenType;
+
+/* ============================================================================
+ * Token Structure
+ * ============================================================================ */
+
+typedef struct {
+    TokenType type;
+    char* lexeme;
+    int line;
+    int column;
+    union {
+        double number;
+        bool boolean;
+    } literal;
+} Token;
+
+/* ============================================================================
+ * Lexer Structure
+ * ============================================================================ */
+
+typedef struct {
+    const char* source;
+    size_t source_len;
+    size_t position;
+    int line;
+    int column;
+    Token current_token;
+    bool has_error;
+    char* error_message;
+} Lexer;
+
+/* ============================================================================
+ * Token Helper Functions
+ * ============================================================================ */
+
+/**
+ * @brief Create a simple token
+ * 
+ * @param type Token type
+ * @param lexeme Token lexeme
+ * @param line Line number
+ * @param column Column number
+ * @return New token
+ */
+static Token token_create(TokenType type, const char* lexeme, int line, int column) {
+    Token token;
+    token.type = type;
+    token.lexeme = lexeme != NULL ? strdup(lexeme) : NULL;
+    token.line = line;
+    token.column = column;
+    token.literal.number = 0.0; /* Initialize union */
+    return token;
+}
+
+/* ============================================================================
+ * Lexer Functions
+ * ============================================================================ */
+
+/**
+ * @brief Create a new lexer
+ * 
+ * @param source Source code to tokenize
+ * @param source_len Length of source code
+ * @return New lexer instance, or NULL on failure
+ */
+static Lexer* lexer_create(const char* source, size_t source_len) {
+    Lexer* lexer = malloc(sizeof(Lexer));
+    if (lexer == NULL) {
+        return NULL;
+    }
+    
+    lexer->source = source;
+    lexer->source_len = source_len;
+    lexer->position = 0;
+    lexer->line = 1;
+    lexer->column = 1;
+    lexer->has_error = false;
+    lexer->error_message = NULL;
+    
+    /* Initialize current token */
+    lexer->current_token.type = TOKEN_EOF;
+    lexer->current_token.lexeme = NULL;
+    lexer->current_token.line = 1;
+    lexer->current_token.column = 1;
+    
+    return lexer;
+}
+
+/**
+ * @brief Destroy a lexer
+ * 
+ * @param lexer Lexer to destroy
+ */
+static void lexer_destroy(Lexer* lexer) {
+    if (lexer == NULL) {
+        return;
+    }
+    
+    if (lexer->current_token.lexeme != NULL) {
+        free(lexer->current_token.lexeme);
+    }
+    
+    if (lexer->error_message != NULL) {
+        free(lexer->error_message);
+    }
+    
+    free(lexer);
+}
+
+/**
+ * @brief Set lexer error
+ * 
+ * @param lexer Lexer instance
+ * @param message Error message
+ */
+static void lexer_set_error(Lexer* lexer, const char* message) {
+    if (lexer == NULL) {
+        return;
+    }
+    
+    lexer->has_error = true;
+    if (lexer->error_message != NULL) {
+        free(lexer->error_message);
+    }
+    lexer->error_message = strdup(message);
+}
+
+/**
+ * @brief Check if we're at the end of input
+ * 
+ * @param lexer Lexer instance
+ * @return true if at end, false otherwise
+ */
+static bool lexer_is_at_end(const Lexer* lexer) {
+    return lexer->position >= lexer->source_len;
+}
+
+/**
+ * @brief Peek at current character
+ * 
+ * @param lexer Lexer instance
+ * @return Current character, or '\0' if at end
+ */
+static char lexer_peek(const Lexer* lexer) {
+    if (lexer_is_at_end(lexer)) {
+        return '\0';
+    }
+    return lexer->source[lexer->position];
+}
+
+/**
+ * @brief Peek at next character
+ * 
+ * @param lexer Lexer instance
+ * @return Next character, or '\0' if at end
+ */
+static char lexer_peek_next(const Lexer* lexer) {
+    if (lexer->position + 1 >= lexer->source_len) {
+        return '\0';
+    }
+    return lexer->source[lexer->position + 1];
+}
+
+/**
+ * @brief Advance to next character
+ * 
+ * @param lexer Lexer instance
+ * @return Character that was advanced over
+ */
+static char lexer_advance(Lexer* lexer) {
+    if (lexer_is_at_end(lexer)) {
+        return '\0';
+    }
+    
+    char c = lexer->source[lexer->position];
+    lexer->position++;
+    lexer->column++;
+    
+    if (c == '\n') {
+        lexer->line++;
+        lexer->column = 1;
+    }
+    
+    return c;
+}
+
+/**
+ * @brief Match current character and advance if it matches
+ * 
+ * @param lexer Lexer instance
+ * @param expected Expected character
+ * @return true if matched, false otherwise
+ */
+static bool lexer_match(Lexer* lexer, char expected) {
+    if (lexer_is_at_end(lexer)) {
+        return false;
+    }
+    
+    if (lexer->source[lexer->position] != expected) {
+        return false;
+    }
+    
+    lexer_advance(lexer);
+    return true;
+}
+
+/**
+ * @brief Skip whitespace
+ * 
+ * @param lexer Lexer instance
+ */
+static void lexer_skip_whitespace(Lexer* lexer) {
+    while (!lexer_is_at_end(lexer) && isspace(lexer_peek(lexer))) {
+        lexer_advance(lexer);
+    }
+}
+
+/**
+ * @brief Skip comments
+ * 
+ * @param lexer Lexer instance
+ */
+static void lexer_skip_comments(Lexer* lexer) {
+    if (lexer_peek(lexer) == '/' && lexer_peek_next(lexer) == '/') {
+        /* Single line comment */
+        while (!lexer_is_at_end(lexer) && lexer_peek(lexer) != '\n') {
+            lexer_advance(lexer);
+        }
+    } else if (lexer_peek(lexer) == '/' && lexer_peek_next(lexer) == '*') {
+        /* Multi-line comment */
+        lexer_advance(lexer); /* consume '/' */
+        lexer_advance(lexer); /* consume '*' */
+        
+        while (!lexer_is_at_end(lexer)) {
+            if (lexer_peek(lexer) == '*' && lexer_peek_next(lexer) == '/') {
+                lexer_advance(lexer); /* consume '*' */
+                lexer_advance(lexer); /* consume '/' */
+                break;
+            }
+            lexer_advance(lexer);
+        }
+    }
+}
+
+/**
+ * @brief Read a number literal
+ * 
+ * @param lexer Lexer instance
+ * @return Token with number literal
+ */
+static Token lexer_read_number(Lexer* lexer) {
+    Token token;
+    token.type = TOKEN_NUMBER;
+    token.line = lexer->line;
+    token.column = lexer->column;
+    
+    /* Read integer part */
+    while (!lexer_is_at_end(lexer) && isdigit(lexer_peek(lexer))) {
+        lexer_advance(lexer);
+    }
+    
+    /* Read decimal part */
+    if (!lexer_is_at_end(lexer) && lexer_peek(lexer) == '.' && 
+        isdigit(lexer_peek_next(lexer))) {
+        lexer_advance(lexer); /* consume '.' */
+        
+        while (!lexer_is_at_end(lexer) && isdigit(lexer_peek(lexer))) {
+            lexer_advance(lexer);
+        }
+    }
+    
+    /* Read exponent part */
+    if (!lexer_is_at_end(lexer) && (lexer_peek(lexer) == 'e' || lexer_peek(lexer) == 'E')) {
+        lexer_advance(lexer); /* consume 'e' or 'E' */
+        
+        if (!lexer_is_at_end(lexer) && (lexer_peek(lexer) == '+' || lexer_peek(lexer) == '-')) {
+            lexer_advance(lexer); /* consume sign */
+        }
+        
+        while (!lexer_is_at_end(lexer) && isdigit(lexer_peek(lexer))) {
+            lexer_advance(lexer);
+        }
+    }
+    
+    /* Extract lexeme and convert to number */
+    size_t start = lexer->position - (lexer->column - token.column);
+    size_t length = lexer->position - start;
+    
+    token.lexeme = malloc(length + 1);
+    if (token.lexeme == NULL) {
+        lexer_set_error(lexer, "Memory allocation failed");
+        token.type = TOKEN_EOF;
+        return token;
+    }
+    
+    strncpy(token.lexeme, lexer->source + start, length);
+    token.lexeme[length] = '\0';
+    
+    token.literal.number = atof(token.lexeme);
+    
+    return token;
+}
+
+/**
+ * @brief Read a string literal
+ * 
+ * @param lexer Lexer instance
+ * @return Token with string literal
+ */
+static Token lexer_read_string(Lexer* lexer) {
+    Token token;
+    token.type = TOKEN_STRING;
+    token.line = lexer->line;
+    token.column = lexer->column;
+    
+    lexer_advance(lexer); /* consume opening quote */
+    
+    size_t start = lexer->position;
+    size_t length = 0;
+    
+    while (!lexer_is_at_end(lexer) && lexer_peek(lexer) != '"') {
+        if (lexer_peek(lexer) == '\\' && !lexer_is_at_end(lexer)) {
+            lexer_advance(lexer); /* consume backslash */
+            if (!lexer_is_at_end(lexer)) {
+                lexer_advance(lexer); /* consume escaped character */
+            }
+        } else {
+            lexer_advance(lexer);
+        }
+        length++;
+    }
+    
+    if (lexer_is_at_end(lexer)) {
+        lexer_set_error(lexer, "Unterminated string literal");
+        token.type = TOKEN_EOF;
+        return token;
+    }
+    
+    lexer_advance(lexer); /* consume closing quote */
+    
+    /* Extract lexeme */
+    token.lexeme = malloc(length + 1);
+    if (token.lexeme == NULL) {
+        lexer_set_error(lexer, "Memory allocation failed");
+        token.type = TOKEN_EOF;
+        return token;
+    }
+    
+    strncpy(token.lexeme, lexer->source + start, length);
+    token.lexeme[length] = '\0';
+    
+    return token;
+}
+
+/**
+ * @brief Read an identifier or keyword
+ * 
+ * @param lexer Lexer instance
+ * @return Token with identifier or keyword
+ */
+static Token lexer_read_identifier(Lexer* lexer) {
+    Token token;
+    token.line = lexer->line;
+    token.column = lexer->column;
+    
+    size_t start = lexer->position;
+    size_t length = 0;
+    
+    while (!lexer_is_at_end(lexer) && 
+           (isalnum(lexer_peek(lexer)) || lexer_peek(lexer) == '_')) {
+        lexer_advance(lexer);
+        length++;
+    }
+    
+    /* Extract lexeme */
+    token.lexeme = malloc(length + 1);
+    if (token.lexeme == NULL) {
+        lexer_set_error(lexer, "Memory allocation failed");
+        token.type = TOKEN_EOF;
+        return token;
+    }
+    
+    strncpy(token.lexeme, lexer->source + start, length);
+    token.lexeme[length] = '\0';
+    
+    /* Check if it's a keyword */
+    if (strcmp(token.lexeme, "when") == 0) {
+
+        token.type = TOKEN_KEYWORD_WHEN;
+    } else if (strcmp(token.lexeme, "is") == 0) {
+        token.type = TOKEN_KEYWORD_IS;
+    } else if (strcmp(token.lexeme, "then") == 0) {
+        token.type = TOKEN_KEYWORD_THEN;
+    } else if (strcmp(token.lexeme, "not") == 0) {
+        token.type = TOKEN_KEYWORD_NOT;
+    } else if (strcmp(token.lexeme, "via") == 0) {
+        token.type = TOKEN_KEYWORD_VIA;
+    } else if (strcmp(token.lexeme, "true") == 0) {
+        token.type = TOKEN_BOOLEAN;
+        token.literal.boolean = true;
+    } else if (strcmp(token.lexeme, "false") == 0) {
+        token.type = TOKEN_BOOLEAN;
+        token.literal.boolean = false;
+    } else {
+        token.type = TOKEN_IDENTIFIER;
+    }
+    
+    return token;
+}
+
+/**
+ * @brief Read a special token (function reference, IO operations)
+ * 
+ * @param lexer Lexer instance
+ * @return Token with special type
+ */
+static Token lexer_read_special(Lexer* lexer) {
+    Token token;
+    token.line = lexer->line;
+    token.column = lexer->column;
+    
+    if (lexer_peek(lexer) == '@') {
+        /* Function reference */
+        lexer_advance(lexer); /* consume '@' */
+        
+        /* Check if this is @(expression) syntax */
+        if (!lexer_is_at_end(lexer) && lexer_peek(lexer) == '(') {
+            /* Just return the @ token for @(expression) syntax */
+            token.type = TOKEN_FUNCTION_REF;
+            token.lexeme = malloc(2); /* +1 for '@' and '\0' */
+            if (token.lexeme == NULL) {
+                lexer_set_error(lexer, "Memory allocation failed");
+                token.type = TOKEN_EOF;
+                return token;
+            }
+            token.lexeme[0] = '@';
+            token.lexeme[1] = '\0';
+        } else {
+            /* Handle @function_name syntax */
+            size_t start = lexer->position;
+            size_t length = 0;
+            
+            while (!lexer_is_at_end(lexer) && 
+                   (isalnum(lexer_peek(lexer)) || lexer_peek(lexer) == '_')) {
+                lexer_advance(lexer);
+                length++;
+            }
+            
+            if (length == 0) {
+                lexer_set_error(lexer, "Invalid function reference");
+                token.type = TOKEN_EOF;
+                return token;
+            }
+            
+            token.type = TOKEN_FUNCTION_REF;
+            token.lexeme = malloc(length + 2); /* +2 for '@' and '\0' */
+            if (token.lexeme == NULL) {
+                lexer_set_error(lexer, "Memory allocation failed");
+                token.type = TOKEN_EOF;
+                return token;
+            }
+            
+            token.lexeme[0] = '@';
+            strncpy(token.lexeme + 1, lexer->source + start, length);
+            token.lexeme[length + 1] = '\0';
+        }
+        
+    } else if (lexer_peek(lexer) == '.' && lexer_peek_next(lexer) == '.') {
+        /* IO operation */
+        lexer_advance(lexer); /* consume first '.' */
+        lexer_advance(lexer); /* consume second '.' */
+        
+        size_t start = lexer->position;
+        size_t length = 0;
+        
+        while (!lexer_is_at_end(lexer) && 
+               (isalpha(lexer_peek(lexer)) || lexer_peek(lexer) == '_')) {
+            lexer_advance(lexer);
+            length++;
+        }
+        
+        if (length == 0) {
+            lexer_set_error(lexer, "Invalid IO operation");
+            token.type = TOKEN_EOF;
+            return token;
+        }
+        
+        token.lexeme = malloc(length + 3); /* +3 for '..', operation, and '\0' */
+        if (token.lexeme == NULL) {
+            lexer_set_error(lexer, "Memory allocation failed");
+            token.type = TOKEN_EOF;
+            return token;
+        }
+        
+        token.lexeme[0] = '.';
+        token.lexeme[1] = '.';
+        strncpy(token.lexeme + 2, lexer->source + start, length);
+        token.lexeme[length + 2] = '\0';
+        
+        /* Determine IO operation type */
+        if (strcmp(token.lexeme, "..in") == 0) {
+            token.type = TOKEN_IO_IN;
+        } else if (strcmp(token.lexeme, "..out") == 0) {
+            token.type = TOKEN_IO_OUT;
+        } else if (strcmp(token.lexeme, "..assert") == 0) {
+            token.type = TOKEN_IO_ASSERT;
+        } else if (strcmp(token.lexeme, "..emit") == 0) {
+            token.type = TOKEN_IO_EMIT;
+        } else if (strcmp(token.lexeme, "..listen") == 0) {
+            token.type = TOKEN_IO_LISTEN;
+        } else {
+            lexer_set_error(lexer, "Unknown IO operation");
+            token.type = TOKEN_EOF;
+            free(token.lexeme);
+            return token;
+        }
+    }
+    
+    return token;
+}
+
+/**
+ * @brief Read the next token
+ * 
+ * @param lexer Lexer instance
+ * @return Next token
+ */
+static Token lexer_next_token(Lexer* lexer) {
+    /* Skip whitespace and comments */
+    while (!lexer_is_at_end(lexer)) {
+        lexer_skip_whitespace(lexer);
+        lexer_skip_comments(lexer);
+        
+        /* Check if we still have whitespace after comments */
+        if (!lexer_is_at_end(lexer) && isspace(lexer_peek(lexer))) {
+            continue;
+        }
+        break;
+    }
+    
+    if (lexer_is_at_end(lexer)) {
+        Token token;
+        token.type = TOKEN_EOF;
+        token.lexeme = NULL;
+        token.line = lexer->line;
+        token.column = lexer->column;
+        return token;
+    }
+    
+    char c = lexer_peek(lexer);
+    
+    /* Numbers */
+    if (isdigit(c)) {
+        return lexer_read_number(lexer);
+    }
+    
+    /* Strings */
+    if (c == '"') {
+        return lexer_read_string(lexer);
+    }
+    
+    /* Special tokens */
+    if (c == '@' || (c == '.' && lexer_peek_next(lexer) == '.')) {
+        return lexer_read_special(lexer);
+    }
+    
+    /* Identifiers and keywords */
+    if (isalpha(c) || c == '_') {
+        return lexer_read_identifier(lexer);
+    }
+    
+    /* Single character tokens */
+    switch (c) {
+    case '(':
+        lexer_advance(lexer);
+        return token_create(TOKEN_LPAREN, "(", lexer->line, lexer->column - 1);
+    case ')':
+        lexer_advance(lexer);
+        return token_create(TOKEN_RPAREN, ")", lexer->line, lexer->column - 1);
+    case '{':
+        lexer_advance(lexer);
+        return token_create(TOKEN_LBRACE, "{", lexer->line, lexer->column - 1);
+    case '}':
+        lexer_advance(lexer);
+        return token_create(TOKEN_RBRACE, "}", lexer->line, lexer->column - 1);
+    case '[':
+        lexer_advance(lexer);
+        return token_create(TOKEN_LBRACKET, "[", lexer->line, lexer->column - 1);
+    case ']':
+        lexer_advance(lexer);
+        return token_create(TOKEN_RBRACKET, "]", lexer->line, lexer->column - 1);
+    case ',':
+        lexer_advance(lexer);
+        return token_create(TOKEN_COMMA, ",", lexer->line, lexer->column - 1);
+    case ':':
+        lexer_advance(lexer);
+        return token_create(TOKEN_COLON, ":", lexer->line, lexer->column - 1);
+    case ';':
+        lexer_advance(lexer);
+        return token_create(TOKEN_SEMICOLON, ";", lexer->line, lexer->column - 1);
+    case '.':
+        lexer_advance(lexer);
+        return token_create(TOKEN_DOT, ".", lexer->line, lexer->column - 1);
+    case '-':
+        lexer_advance(lexer);
+        if (lexer_match(lexer, '>')) {
+            return token_create(TOKEN_ARROW, "->", lexer->line, lexer->column - 2);
+        }
+        
+        /* Check if this is a unary minus (followed by a digit, identifier, or parentheses) */
+        if ((lexer_peek(lexer) >= '0' && lexer_peek(lexer) <= '9') ||
+            (lexer_peek(lexer) >= 'a' && lexer_peek(lexer) <= 'z') ||
+            (lexer_peek(lexer) >= 'A' && lexer_peek(lexer) <= 'Z') ||
+            (lexer_peek(lexer) == '_') ||
+            (lexer_peek(lexer) == '(')) {
+            return token_create(TOKEN_OP_UNARY_MINUS, "-", lexer->line, lexer->column - 1);
+        }
+        /* Otherwise treat as binary minus */
+        return token_create(TOKEN_OP_MINUS, "-", lexer->line, lexer->column - 1);
+    case '+':
+        lexer_advance(lexer);
+        return token_create(TOKEN_OP_PLUS, "+", lexer->line, lexer->column - 1);
+    case '*':
+        lexer_advance(lexer);
+        return token_create(TOKEN_OP_MULTIPLY, "*", lexer->line, lexer->column - 1);
+    case '/':
+        lexer_advance(lexer);
+        return token_create(TOKEN_OP_DIVIDE, "/", lexer->line, lexer->column - 1);
+    case '%':
+        lexer_advance(lexer);
+        return token_create(TOKEN_OP_MODULO, "%", lexer->line, lexer->column - 1);
+    case '^':
+        lexer_advance(lexer);
+        return token_create(TOKEN_OP_POWER, "^", lexer->line, lexer->column - 1);
+    case '=':
+        lexer_advance(lexer);
+        if (lexer_match(lexer, '=')) {
+            return token_create(TOKEN_OP_EQUALS, "==", lexer->line, lexer->column - 2);
+        }
+        return token_create(TOKEN_OP_EQUALS, "=", lexer->line, lexer->column - 1);
+    case '!':
+        lexer_advance(lexer);
+        if (lexer_match(lexer, '=')) {
+            return token_create(TOKEN_OP_NOT_EQUALS, "!=", lexer->line, lexer->column - 2);
+        }
+        break;
+    case '<':
+        lexer_advance(lexer);
+        if (lexer_match(lexer, '=')) {
+            return token_create(TOKEN_OP_LESS_EQUAL, "<=", lexer->line, lexer->column - 2);
+        }
+        return token_create(TOKEN_OP_LESS, "<", lexer->line, lexer->column - 1);
+    case '>':
+        lexer_advance(lexer);
+        if (lexer_match(lexer, '=')) {
+            return token_create(TOKEN_OP_GREATER_EQUAL, ">=", lexer->line, lexer->column - 2);
+        }
+        return token_create(TOKEN_OP_GREATER, ">", lexer->line, lexer->column - 1);
+    }
+    
+    /* Unknown character */
+    char error_msg[64];
+    snprintf(error_msg, sizeof(error_msg), "Unexpected character: '%c'", c);
+    lexer_set_error(lexer, error_msg);
+    
+    Token token;
+    token.type = TOKEN_EOF;
+    token.lexeme = NULL;
+    token.line = lexer->line;
+    token.column = lexer->column;
+    return token;
+}
+
+/* ============================================================================
+ * Public Lexer API
+ * ============================================================================ */
+
+/**
+ * @brief Tokenize source code
+ * 
+ * @param source Source code to tokenize
+ * @param source_len Length of source code
+ * @param tokens Output array for tokens
+ * @param max_tokens Maximum number of tokens to read
+ * @return Number of tokens read, or -1 on error
+ */
+int baba_yaga_tokenize(const char* source, size_t source_len, 
+                      void** tokens, size_t max_tokens) {
+    if (source == NULL || tokens == NULL) {
+        return -1;
+    }
+    
+    Lexer* lexer = lexer_create(source, source_len);
+    if (lexer == NULL) {
+        return -1;
+    }
+    
+    size_t token_count = 0;
+    
+    while (token_count < max_tokens) {
+        Token token = lexer_next_token(lexer);
+        
+        if (lexer->has_error) {
+            lexer_destroy(lexer);
+            return -1;
+        }
+        
+        if (token.type == TOKEN_EOF) {
+            break;
+        }
+        
+        /* Allocate token and copy data */
+        Token* token_ptr = malloc(sizeof(Token));
+        if (token_ptr == NULL) {
+            lexer_destroy(lexer);
+            return -1;
+        }
+        
+        *token_ptr = token;
+        tokens[token_count] = token_ptr;
+        token_count++;
+    }
+    
+    lexer_destroy(lexer);
+    return (int)token_count;
+}
+
+/**
+ * @brief Free tokens
+ * 
+ * @param tokens Array of tokens
+ * @param count Number of tokens
+ */
+void baba_yaga_free_tokens(void** tokens, size_t count) {
+    if (tokens == NULL) {
+        return;
+    }
+    
+    for (size_t i = 0; i < count; i++) {
+        if (tokens[i] != NULL) {
+            Token* token = (Token*)tokens[i];
+            if (token->lexeme != NULL) {
+                free(token->lexeme);
+            }
+            free(token);
+        }
+    }
+} 
diff --git a/js/scripting-lang/baba-yaga-c/src/main.c b/js/scripting-lang/baba-yaga-c/src/main.c
new file mode 100644
index 0000000..c1bc9f8
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/main.c
@@ -0,0 +1,353 @@
+/**
+ * @file main.c
+ * @brief Main entry point for Baba Yaga interpreter
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file contains the main entry point and command-line interface
+ * for the Baba Yaga scripting language implementation.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Constants
+ * ============================================================================ */
+
+#define VERSION "0.0.1"
+#define MAX_LINE_LENGTH 4096
+#define MAX_FILE_SIZE (1024 * 1024) /* 1MB */
+
+/* ============================================================================
+ * Function Declarations
+ * ============================================================================ */
+
+static void print_usage(const char* program_name);
+static void print_version(void);
+static void print_error(const char* message);
+static char* read_file(const char* filename);
+static void run_repl(Interpreter* interp);
+static void run_file(Interpreter* interp, const char* filename);
+static void run_tests(Interpreter* interp, const char* test_dir);
+
+/* ============================================================================
+ * Main Function
+ * ============================================================================ */
+
+/**
+ * @brief Main entry point
+ * 
+ * @param argc Argument count
+ * @param argv Argument vector
+ * @return Exit status
+ */
+int main(int argc, char* argv[]) {
+    Interpreter* interp = NULL;
+    int opt;
+    bool run_repl_mode = false;
+    (void)run_repl_mode; /* TODO: Use run_repl_mode variable */
+    bool run_test_mode = false;
+    char* filename = NULL;
+    char* test_dir = NULL;
+    ExecResult result;
+    Value value;
+
+    /* Parse command line options */
+    while ((opt = getopt(argc, argv, "hvt:f:")) != -1) {
+        switch (opt) {
+        case 'h':
+            print_usage(argv[0]);
+            return EXIT_SUCCESS;
+        case 'v':
+            print_version();
+            return EXIT_SUCCESS;
+        case 't':
+            run_test_mode = true;
+            test_dir = optarg;
+            break;
+        case 'f':
+            filename = optarg;
+            break;
+        default:
+            print_usage(argv[0]);
+            return EXIT_FAILURE;
+        }
+    }
+
+    /* Create interpreter */
+    interp = baba_yaga_create();
+    if (interp == NULL) {
+        print_error("Failed to create interpreter");
+        return EXIT_FAILURE;
+    }
+    
+    /* Set debug level from environment */
+    const char* debug_env = getenv("DEBUG");
+    if (debug_env != NULL) {
+        int debug_level = atoi(debug_env);
+        if (debug_level >= 0 && debug_level <= 5) {
+            baba_yaga_set_debug_level((DebugLevel)debug_level);
+        }
+    }
+
+    /* Execute based on mode */
+    if (run_test_mode) {
+        run_tests(interp, test_dir);
+    } else if (filename != NULL) {
+        run_file(interp, filename);
+    } else if (optind < argc) {
+        /* Check if the argument looks like a file (not starting with -) */
+        char* arg = argv[optind];
+        if (arg[0] != '-' && access(arg, F_OK) == 0) {
+            /* Treat as file */
+            run_file(interp, arg);
+        } else {
+            /* Execute source code from command line */
+            char* source = arg;
+            value = baba_yaga_execute(interp, source, strlen(source), &result);
+            if (result == EXEC_SUCCESS) {
+            /* Print result using value_to_string for consistent formatting */
+            /* Don't print special IO return value */
+            if (value.type != VAL_NUMBER || value.data.number != -999999) {
+                char* str = baba_yaga_value_to_string(&value);
+                printf("%s\n", str);
+                free(str);
+            }
+        } else {
+            BabaYagaError* error = baba_yaga_get_error(interp);
+            if (error != NULL) {
+                fprintf(stderr, "Error: %s\n", error->message);
+                baba_yaga_error_destroy(error);
+            } else {
+                fprintf(stderr, "Error: Execution failed\n");
+            }
+        }
+        baba_yaga_value_destroy(&value);
+        }
+    } else {
+        run_repl(interp);
+    }
+
+    /* Cleanup */
+    baba_yaga_destroy(interp);
+    return EXIT_SUCCESS;
+}
+
+/* ============================================================================
+ * Helper Functions
+ * ============================================================================ */
+
+/**
+ * @brief Print usage information
+ * 
+ * @param program_name Name of the program
+ */
+static void print_usage(const char* program_name) {
+    printf("Baba Yaga C Implementation v%s\n", VERSION);
+    printf("Usage: %s [OPTIONS] [SOURCE_CODE]\n", program_name);
+    printf("\nOptions:\n");
+    printf("  -h, --help     Show this help message\n");
+    printf("  -v, --version  Show version information\n");
+    printf("  -f FILE        Execute source code from file\n");
+    printf("  -t DIR         Run tests from directory\n");
+    printf("\nExamples:\n");
+    printf("  %s                    # Start REPL\n", program_name);
+    printf("  %s -f script.txt      # Execute file\n", program_name);
+    printf("  %s 'x : 42; ..out x'  # Execute code\n", program_name);
+    printf("  %s -t tests/          # Run tests\n", program_name);
+}
+
+/**
+ * @brief Print version information
+ */
+static void print_version(void) {
+    printf("Baba Yaga C Implementation v%s\n", VERSION);
+    printf("Copyright (c) 2025 eli_oat\n");
+    printf("License: Custom - see LICENSE file\n");
+}
+
+/**
+ * @brief Print error message
+ * 
+ * @param message Error message
+ */
+static void print_error(const char* message) {
+    fprintf(stderr, "Error: %s\n", message);
+}
+
+/**
+ * @brief Read entire file into memory
+ * 
+ * @param filename Name of file to read
+ * @return File contents (must be freed by caller)
+ */
+static char* read_file(const char* filename) {
+    FILE* file;
+    char* buffer;
+    long file_size;
+    size_t bytes_read;
+
+    /* Open file */
+    file = fopen(filename, "rb");
+    if (file == NULL) {
+        print_error("Failed to open file");
+        return NULL;
+    }
+
+    /* Get file size */
+    if (fseek(file, 0, SEEK_END) != 0) {
+        fclose(file);
+        print_error("Failed to seek to end of file");
+        return NULL;
+    }
+
+    file_size = ftell(file);
+    if (file_size < 0) {
+        fclose(file);
+        print_error("Failed to get file size");
+        return NULL;
+    }
+
+    if (file_size > MAX_FILE_SIZE) {
+        fclose(file);
+        print_error("File too large");
+        return NULL;
+    }
+
+    /* Allocate buffer */
+    buffer = malloc(file_size + 1);
+    if (buffer == NULL) {
+        fclose(file);
+        print_error("Failed to allocate memory");
+        return NULL;
+    }
+
+    /* Read file */
+    rewind(file);
+    bytes_read = fread(buffer, 1, file_size, file);
+    fclose(file);
+
+    if (bytes_read != (size_t)file_size) {
+        free(buffer);
+        print_error("Failed to read file");
+        return NULL;
+    }
+
+    buffer[file_size] = '\0';
+    return buffer;
+}
+
+/**
+ * @brief Run REPL (Read-Eval-Print Loop)
+ * 
+ * @param interp Interpreter instance
+ */
+static void run_repl(Interpreter* interp) {
+    char line[MAX_LINE_LENGTH];
+    ExecResult result;
+    Value value;
+
+    printf("Baba Yaga C Implementation v%s\n", VERSION);
+    printf("Type 'exit' to quit\n\n");
+
+    while (1) {
+        printf("baba-yaga> ");
+        fflush(stdout);
+
+        if (fgets(line, sizeof(line), stdin) == NULL) {
+            break;
+        }
+
+        /* Remove newline */
+        line[strcspn(line, "\n")] = '\0';
+
+        /* Check for exit command */
+        if (strcmp(line, "exit") == 0) {
+            break;
+        }
+
+        /* Skip empty lines */
+        if (strlen(line) == 0) {
+            continue;
+        }
+
+        /* Execute line */
+        value = baba_yaga_execute(interp, line, 0, &result);
+        if (result == EXEC_SUCCESS) {
+            char* str = baba_yaga_value_to_string(&value);
+            printf("%s\n", str);
+            free(str);
+        } else {
+            BabaYagaError* error = baba_yaga_get_error(interp);
+            if (error != NULL) {
+                fprintf(stderr, "Error: %s\n", error->message);
+                baba_yaga_error_destroy(error);
+            }
+        }
+        baba_yaga_value_destroy(&value);
+    }
+}
+
+/**
+ * @brief Execute source code from file
+ * 
+ * @param interp Interpreter instance
+ * @param filename Name of file to execute
+ */
+static void run_file(Interpreter* interp, const char* filename) {
+    char* source;
+    ExecResult result;
+    Value value;
+
+    /* Read file */
+    source = read_file(filename);
+    if (source == NULL) {
+        return;
+    }
+
+    /* Execute source */
+    value = baba_yaga_execute(interp, source, strlen(source), &result);
+    free(source);
+
+    if (result == EXEC_SUCCESS) {
+        /* Print result using value_to_string for consistent formatting */
+        /* Don't print special IO return value */
+        if (value.type != VAL_NUMBER || value.data.number != -999999) {
+            char* str = baba_yaga_value_to_string(&value);
+            printf("%s\n", str);
+            free(str);
+        }
+    } else {
+        BabaYagaError* error = baba_yaga_get_error(interp);
+        if (error != NULL) {
+            fprintf(stderr, "Error: %s\n", error->message);
+            baba_yaga_error_destroy(error);
+        } else {
+            fprintf(stderr, "Error: Execution failed\n");
+        }
+        exit(EXIT_FAILURE);
+    }
+
+    baba_yaga_value_destroy(&value);
+}
+
+/**
+ * @brief Run tests from directory
+ * 
+ * @param interp Interpreter instance
+ * @param test_dir Test directory
+ */
+static void run_tests(Interpreter* interp, const char* test_dir) {
+    (void)interp; /* TODO: Use interp parameter */
+    (void)test_dir; /* TODO: Use test_dir parameter */
+    /* TODO: Implement test runner */
+    printf("Test runner not yet implemented\n");
+    printf("Test directory: %s\n", test_dir);
+} 
diff --git a/js/scripting-lang/baba-yaga-c/src/memory.c b/js/scripting-lang/baba-yaga-c/src/memory.c
new file mode 100644
index 0000000..f6bca85
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/memory.c
@@ -0,0 +1,68 @@
+/**
+ * @file memory.c
+ * @brief Memory management implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements memory management utilities for the Baba Yaga language.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Memory Management Functions
+ * ============================================================================ */
+
+/* TODO: Implement memory management functions */
+
+void* memory_alloc(size_t size) {
+    void* ptr = malloc(size);
+    if (ptr == NULL) {
+        /* TODO: Handle allocation failure */
+        fprintf(stderr, "Memory allocation failed: %zu bytes\n", size);
+    }
+    return ptr;
+}
+
+void* memory_realloc(void* ptr, size_t size) {
+    void* new_ptr = realloc(ptr, size);
+    if (new_ptr == NULL) {
+        /* TODO: Handle reallocation failure */
+        fprintf(stderr, "Memory reallocation failed: %zu bytes\n", size);
+    }
+    return new_ptr;
+}
+
+void memory_free(void* ptr) {
+    if (ptr != NULL) {
+        free(ptr);
+    }
+}
+
+char* memory_strdup(const char* str) {
+    if (str == NULL) {
+        return NULL;
+    }
+    return strdup(str);
+}
+
+char* memory_strndup(const char* str, size_t n) {
+    if (str == NULL) {
+        return NULL;
+    }
+    
+    char* new_str = memory_alloc(n + 1);
+    if (new_str == NULL) {
+        return NULL;
+    }
+    
+    strncpy(new_str, str, n);
+    new_str[n] = '\0';
+    
+    return new_str;
+} 
diff --git a/js/scripting-lang/baba-yaga-c/src/parser.c b/js/scripting-lang/baba-yaga-c/src/parser.c
new file mode 100644
index 0000000..6c94913
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/parser.c
@@ -0,0 +1,2973 @@
+/**
+ * @file parser.c
+ * @brief Parser implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements the parser for the Baba Yaga language.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Token Types (from lexer.c)
+ * ============================================================================ */
+
+typedef enum {
+    TOKEN_EOF,
+    TOKEN_NUMBER,
+    TOKEN_STRING,
+    TOKEN_BOOLEAN,
+    TOKEN_IDENTIFIER,
+    TOKEN_KEYWORD_WHEN,
+    TOKEN_KEYWORD_IS,
+    TOKEN_KEYWORD_THEN,
+    TOKEN_KEYWORD_AND,
+    TOKEN_KEYWORD_OR,
+    TOKEN_KEYWORD_XOR,
+    TOKEN_KEYWORD_NOT,
+    TOKEN_KEYWORD_VIA,
+    TOKEN_OP_PLUS,
+    TOKEN_OP_MINUS,
+    TOKEN_OP_UNARY_MINUS,
+    TOKEN_OP_MULTIPLY,
+    TOKEN_OP_DIVIDE,
+    TOKEN_OP_MODULO,
+    TOKEN_OP_POWER,
+    TOKEN_OP_EQUALS,
+    TOKEN_OP_NOT_EQUALS,
+    TOKEN_OP_LESS,
+    TOKEN_OP_LESS_EQUAL,
+    TOKEN_OP_GREATER,
+    TOKEN_OP_GREATER_EQUAL,
+    TOKEN_LPAREN,
+    TOKEN_RPAREN,
+    TOKEN_LBRACE,
+    TOKEN_RBRACE,
+    TOKEN_LBRACKET,
+    TOKEN_RBRACKET,
+    TOKEN_COMMA,
+    TOKEN_COLON,
+    TOKEN_SEMICOLON,
+    TOKEN_ARROW,
+    TOKEN_DOT,
+    TOKEN_FUNCTION_REF,
+    TOKEN_IO_IN,
+    TOKEN_IO_OUT,
+    TOKEN_IO_ASSERT,
+    TOKEN_IO_EMIT,
+    TOKEN_IO_LISTEN
+} TokenType;
+
+typedef struct {
+    TokenType type;
+    char* lexeme;
+    int line;
+    int column;
+    union {
+        double number;
+        bool boolean;
+    } literal;
+} Token;
+
+/* ============================================================================
+ * AST Node Types
+ * ============================================================================ */
+
+/* NodeType enum is now defined in baba_yaga.h */
+
+/* ============================================================================
+ * AST Node Structure
+ * ============================================================================ */
+
+struct ASTNode {
+    NodeType type;
+    int line;
+    int column;
+    union {
+        Value literal;
+        char* identifier;
+        struct {
+            struct ASTNode* left;
+            struct ASTNode* right;
+            char* operator;
+        } binary;
+        struct {
+            struct ASTNode* operand;
+            char* operator;
+        } unary;
+        struct {
+            struct ASTNode* function;
+            struct ASTNode** arguments;
+            int arg_count;
+        } function_call;
+        struct {
+            char* name;
+            struct ASTNode** parameters;
+            int param_count;
+            struct ASTNode* body;
+        } function_def;
+        struct {
+            char* name;
+            struct ASTNode* value;
+        } variable_decl;
+        struct {
+            struct ASTNode* test;
+            struct ASTNode** patterns;
+            int pattern_count;
+        } when_expr;
+        struct {
+            struct ASTNode* test;
+            struct ASTNode* result;
+        } when_pattern;
+        struct {
+            struct ASTNode** elements;
+            int element_count;
+        } table;
+        struct {
+            struct ASTNode* object;
+            struct ASTNode* key;
+        } table_access;
+        struct {
+            char* operation;
+            struct ASTNode* argument;
+        } io_operation;
+        struct {
+            struct ASTNode** statements;
+            int statement_count;
+        } sequence;
+    } data;
+};
+
+/* ============================================================================
+ * Parser Structure
+ * ============================================================================ */
+
+typedef struct {
+    Token** tokens;
+    int token_count;
+    int current;
+    bool has_error;
+    char* error_message;
+} Parser;
+
+/* ============================================================================
+ * AST Node Management
+ * ============================================================================ */
+
+/**
+ * @brief Create a literal node
+ * 
+ * @param value Literal value
+ * @param line Line number
+ * @param column Column number
+ * @return New literal node
+ */
+static ASTNode* ast_literal_node(Value value, int line, int column) {
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    node->type = NODE_LITERAL;
+    node->line = line;
+    node->column = column;
+    node->data.literal = value;
+    
+    return node;
+}
+
+/**
+ * @brief Create an identifier node
+ * 
+ * @param identifier Identifier name
+ * @param line Line number
+ * @param column Column number
+ * @return New identifier node
+ */
+static ASTNode* ast_identifier_node(const char* identifier, int line, int column) {
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    node->type = NODE_IDENTIFIER;
+    node->line = line;
+    node->column = column;
+    node->data.identifier = strdup(identifier);
+    
+    return node;
+}
+
+/**
+ * @brief Create a function call node
+ * 
+ * @param function Function expression
+ * @param arguments Array of argument expressions
+ * @param arg_count Number of arguments
+ * @param line Line number
+ * @param column Column number
+ * @return New function call node
+ */
+static ASTNode* ast_function_call_node(ASTNode* function, ASTNode** arguments, 
+                                      int arg_count, int line, int column) {
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    node->type = NODE_FUNCTION_CALL;
+    node->line = line;
+    node->column = column;
+    node->data.function_call.function = function;
+    node->data.function_call.arguments = arguments;
+    node->data.function_call.arg_count = arg_count;
+    
+    return node;
+}
+
+/**
+ * @brief Create a binary operator node
+ * 
+ * @param left Left operand
+ * @param right Right operand
+ * @param operator Operator name
+ * @param line Line number
+ * @param column Column number
+ * @return New binary operator node
+ */
+static ASTNode* ast_binary_op_node(ASTNode* left, ASTNode* right, 
+                                  const char* operator, int line, int column) {
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    node->type = NODE_BINARY_OP;
+    node->line = line;
+    node->column = column;
+    node->data.binary.left = left;
+    node->data.binary.right = right;
+    node->data.binary.operator = strdup(operator);
+    
+    return node;
+}
+
+/**
+ * @brief Create a unary operator node (translated to function call)
+ * 
+ * @param operand Operand expression
+ * @param operator Operator name
+ * @param line Line number
+ * @param column Column number
+ * @return New function call node representing the operator
+ */
+static ASTNode* ast_unary_op_node(ASTNode* operand, const char* operator, 
+                                 int line, int column) {
+    /* Create simple function call: operator(operand) */
+    ASTNode* operator_node = ast_identifier_node(operator, line, column);
+    if (operator_node == NULL) {
+        return NULL;
+    }
+    
+    ASTNode** args = malloc(1 * sizeof(ASTNode*));
+    if (args == NULL) {
+        free(operator_node);
+        return NULL;
+    }
+    args[0] = operand;
+    
+    return ast_function_call_node(operator_node, args, 1, line, column);
+}
+
+/**
+ * @brief Create a sequence node
+ * 
+ * @param statements Array of statement nodes
+ * @param statement_count Number of statements
+ * @param line Line number
+ * @param column Column number
+ * @return New sequence node
+ */
+static ASTNode* ast_sequence_node(ASTNode** statements, int statement_count, 
+                                 int line, int column) {
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    node->type = NODE_SEQUENCE;
+    node->line = line;
+    node->column = column;
+    node->data.sequence.statements = statements;
+    node->data.sequence.statement_count = statement_count;
+    
+    return node;
+}
+
+/**
+ * @brief Create a when expression node
+ * 
+ * @param test Test expression
+ * @param patterns Array of pattern nodes
+ * @param pattern_count Number of patterns
+ * @param line Line number
+ * @param column Column number
+ * @return New when expression node
+ */
+static ASTNode* ast_when_expr_node(ASTNode* test, ASTNode** patterns, 
+                                  int pattern_count, int line, int column) {
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    node->type = NODE_WHEN_EXPR;
+    node->line = line;
+    node->column = column;
+    node->data.when_expr.test = test;
+    node->data.when_expr.patterns = patterns;
+    node->data.when_expr.pattern_count = pattern_count;
+    
+
+    return node;
+}
+
+/**
+ * @brief Create a when pattern node
+ * 
+ * @param test Pattern test expression
+ * @param result Result expression
+ * @param line Line number
+ * @param column Column number
+ * @return New when pattern node
+ */
+static ASTNode* ast_when_pattern_node(ASTNode* test, ASTNode* result, 
+                                     int line, int column) {
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    node->type = NODE_WHEN_PATTERN;
+    node->line = line;
+    node->column = column;
+    node->data.when_pattern.test = test;
+    node->data.when_pattern.result = result;
+    
+    return node;
+}
+
+/**
+ * @brief Destroy an AST node
+ * 
+ * @param node Node to destroy
+ */
+static void ast_destroy_node(ASTNode* node) {
+    if (node == NULL) {
+        return;
+    }
+    
+    switch (node->type) {
+    case NODE_IDENTIFIER:
+        free(node->data.identifier);
+        break;
+    case NODE_FUNCTION_CALL:
+        for (int i = 0; i < node->data.function_call.arg_count; i++) {
+            ast_destroy_node(node->data.function_call.arguments[i]);
+        }
+        free(node->data.function_call.arguments);
+        ast_destroy_node(node->data.function_call.function);
+        break;
+    case NODE_FUNCTION_DEF:
+        for (int i = 0; i < node->data.function_def.param_count; i++) {
+            ast_destroy_node(node->data.function_def.parameters[i]);
+        }
+        free(node->data.function_def.parameters);
+        free(node->data.function_def.name);
+        ast_destroy_node(node->data.function_def.body);
+        break;
+    case NODE_VARIABLE_DECL:
+        free(node->data.variable_decl.name);
+        ast_destroy_node(node->data.variable_decl.value);
+        break;
+    case NODE_WHEN_EXPR:
+        ast_destroy_node(node->data.when_expr.test);
+        for (int i = 0; i < node->data.when_expr.pattern_count; i++) {
+            ast_destroy_node(node->data.when_expr.patterns[i]);
+        }
+        free(node->data.when_expr.patterns);
+        break;
+    case NODE_WHEN_PATTERN:
+        ast_destroy_node(node->data.when_pattern.test);
+        ast_destroy_node(node->data.when_pattern.result);
+        break;
+    case NODE_TABLE:
+        for (int i = 0; i < node->data.table.element_count; i++) {
+            ast_destroy_node(node->data.table.elements[i]);
+        }
+        free(node->data.table.elements);
+        break;
+    case NODE_TABLE_ACCESS:
+        ast_destroy_node(node->data.table_access.object);
+        ast_destroy_node(node->data.table_access.key);
+        break;
+    case NODE_IO_OPERATION:
+        free(node->data.io_operation.operation);
+        ast_destroy_node(node->data.io_operation.argument);
+        break;
+    case NODE_SEQUENCE:
+        for (int i = 0; i < node->data.sequence.statement_count; i++) {
+            ast_destroy_node(node->data.sequence.statements[i]);
+        }
+        free(node->data.sequence.statements);
+        break;
+    default:
+        /* No cleanup needed for other types */
+        break;
+    }
+    
+    free(node);
+}
+
+/* ============================================================================
+ * Parser Functions
+ * ============================================================================ */
+
+/**
+ * @brief Create a new parser
+ * 
+ * @param tokens Array of tokens
+ * @param token_count Number of tokens
+ * @return New parser instance, or NULL on failure
+ */
+static Parser* parser_create(Token** tokens, int token_count) {
+    Parser* parser = malloc(sizeof(Parser));
+    if (parser == NULL) {
+        return NULL;
+    }
+    
+    parser->tokens = tokens;
+    parser->token_count = token_count;
+    parser->current = 0;
+    parser->has_error = false;
+    parser->error_message = NULL;
+    
+    return parser;
+}
+
+/**
+ * @brief Destroy a parser
+ * 
+ * @param parser Parser to destroy
+ */
+static void parser_destroy(Parser* parser) {
+    if (parser == NULL) {
+        return;
+    }
+    
+    if (parser->error_message != NULL) {
+        free(parser->error_message);
+    }
+    
+    free(parser);
+}
+
+/**
+ * @brief Set parser error
+ * 
+ * @param parser Parser instance
+ * @param message Error message
+ */
+static void parser_set_error(Parser* parser, const char* message) {
+    if (parser == NULL) {
+        return;
+    }
+    
+    parser->has_error = true;
+    if (parser->error_message != NULL) {
+        free(parser->error_message);
+    }
+    parser->error_message = strdup(message);
+}
+
+/**
+ * @brief Check if we're at the end of tokens
+ * 
+ * @param parser Parser instance
+ * @return true if at end, false otherwise
+ */
+static bool parser_is_at_end(const Parser* parser) {
+    return parser->current >= parser->token_count;
+}
+
+/**
+ * @brief Peek at current token
+ * 
+ * @param parser Parser instance
+ * @return Current token, or NULL if at end
+ */
+static Token* parser_peek(const Parser* parser) {
+    if (parser_is_at_end(parser)) {
+        return NULL;
+    }
+    return parser->tokens[parser->current];
+}
+
+/**
+ * @brief Peek at next token
+ * 
+ * @param parser Parser instance
+ * @return Next token, or NULL if at end
+ */
+static Token* parser_peek_next(const Parser* parser) {
+    if (parser->current + 1 >= parser->token_count) {
+        return NULL;
+    }
+    return parser->tokens[parser->current + 1];
+}
+
+/**
+ * @brief Advance to next token
+ * 
+ * @param parser Parser instance
+ * @return Token that was advanced over
+ */
+static Token* parser_advance(Parser* parser) {
+    if (parser_is_at_end(parser)) {
+        return NULL;
+    }
+    return parser->tokens[parser->current++];
+}
+
+/**
+ * @brief Check if current token matches expected type
+ * 
+ * @param parser Parser instance
+ * @param type Expected token type
+ * @return true if matches, false otherwise
+ */
+static bool parser_check(const Parser* parser, TokenType type) {
+    if (parser_is_at_end(parser)) {
+        return false;
+    }
+    return parser->tokens[parser->current]->type == type;
+}
+
+/**
+ * @brief Consume token of expected type
+ * 
+ * @param parser Parser instance
+ * @param type Expected token type
+ * @param error_message Error message if type doesn't match
+ * @return Consumed token, or NULL on error
+ */
+static Token* parser_consume(Parser* parser, TokenType type, const char* error_message) {
+    if (parser_check(parser, type)) {
+        return parser_advance(parser);
+    }
+    
+    parser_set_error(parser, error_message);
+    return NULL;
+}
+
+/* ============================================================================
+ * Expression Parsing (Operator Precedence)
+ * ============================================================================ */
+
+/* Forward declarations */
+static ASTNode* parser_parse_expression(Parser* parser);
+static ASTNode* parser_parse_logical(Parser* parser);
+/* static ASTNode* parser_parse_composition(Parser* parser); */
+/* static ASTNode* parser_parse_application(Parser* parser); */
+static ASTNode* parser_parse_statement(Parser* parser);
+static ASTNode* parser_parse_when_expression(Parser* parser);
+static ASTNode* parser_parse_when_pattern(Parser* parser);
+static ASTNode* parser_parse_when_result_expression(Parser* parser);
+static ASTNode* parser_parse_postfix(Parser* parser);
+static const char* node_type_name(NodeType type);
+static ASTNode* parser_parse_function_def(Parser* parser);
+static ASTNode* parser_parse_embedded_arrow_function(Parser* parser);
+
+/**
+ * @brief Parse primary expression (literals, identifiers, parentheses)
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+static ASTNode* parser_parse_primary(Parser* parser) {
+    Token* token = parser_peek(parser);
+    if (token == NULL) {
+        parser_set_error(parser, "Unexpected end of input");
+        return NULL;
+    }
+    
+    switch (token->type) {
+    case TOKEN_NUMBER: {
+        DEBUG_TRACE("parser_parse_primary consuming number: %g", token->literal.number);
+        parser_advance(parser);
+        return ast_literal_node(baba_yaga_value_number(token->literal.number), 
+                               token->line, token->column);
+    }
+    case TOKEN_STRING: {
+        DEBUG_TRACE("parser_parse_primary consuming string: %s", token->lexeme);
+        parser_advance(parser);
+        return ast_literal_node(baba_yaga_value_string(token->lexeme), 
+                               token->line, token->column);
+    }
+    case TOKEN_BOOLEAN: {
+        DEBUG_TRACE("parser_parse_primary consuming boolean: %s", token->literal.boolean ? "true" : "false");
+        parser_advance(parser);
+        return ast_literal_node(baba_yaga_value_boolean(token->literal.boolean), 
+                               token->line, token->column);
+    }
+    case TOKEN_IDENTIFIER: {
+        DEBUG_TRACE("parser_parse_primary consuming identifier: %s", token->lexeme);
+        parser_advance(parser);
+        /* Special handling for wildcard pattern */
+        if (strcmp(token->lexeme, "_") == 0) {
+            /* Create a special wildcard literal */
+            return ast_literal_node(baba_yaga_value_string("_"), token->line, token->column);
+        }
+        return ast_identifier_node(token->lexeme, token->line, token->column);
+    }
+    case TOKEN_IO_IN:
+    case TOKEN_IO_OUT:
+    case TOKEN_IO_ASSERT:
+    case TOKEN_IO_EMIT:
+    case TOKEN_IO_LISTEN: {
+        DEBUG_TRACE("parser_parse_primary consuming io operation: %s", token->lexeme);
+        parser_advance(parser);
+        /* IO operations are treated as function calls - strip the ".." prefix */
+        const char* func_name = token->lexeme + 2; /* Skip ".." */
+        
+        /* For ..assert, parse the entire expression as a single argument */
+        if (strcmp(func_name, "assert") == 0) {
+            /* Parse the assertion expression */
+            ASTNode* assertion_expr = parser_parse_expression(parser);
+            if (assertion_expr == NULL) {
+                return NULL;
+            }
+            
+            /* Create function call with the assertion expression as argument */
+            ASTNode** args = malloc(1 * sizeof(ASTNode*));
+            if (args == NULL) {
+                ast_destroy_node(assertion_expr);
+                return NULL;
+            }
+            args[0] = assertion_expr;
+            
+            ASTNode* func_node = ast_identifier_node(func_name, token->line, token->column);
+            if (func_node == NULL) {
+                free(args);
+                ast_destroy_node(assertion_expr);
+                return NULL;
+            }
+            
+            return ast_function_call_node(func_node, args, 1, token->line, token->column);
+        }
+        
+        /* For ..emit, parse the entire expression as a single argument */
+        if (strcmp(func_name, "emit") == 0) {
+            /* Parse the expression */
+            ASTNode* expr = parser_parse_expression(parser);
+            if (expr == NULL) {
+                return NULL;
+            }
+            
+            /* Create function call with the expression as argument */
+            ASTNode** args = malloc(1 * sizeof(ASTNode*));
+            if (args == NULL) {
+                ast_destroy_node(expr);
+                return NULL;
+            }
+            args[0] = expr;
+            
+            ASTNode* func_node = ast_identifier_node(func_name, token->line, token->column);
+            if (func_node == NULL) {
+                free(args);
+                ast_destroy_node(expr);
+                return NULL;
+            }
+            
+            return ast_function_call_node(func_node, args, 1, token->line, token->column);
+        }
+        
+        /* For ..listen, create a function call with no arguments */
+        if (strcmp(func_name, "listen") == 0) {
+            ASTNode* func_node = ast_identifier_node(func_name, token->line, token->column);
+            if (func_node == NULL) {
+                return NULL;
+            }
+            
+            return ast_function_call_node(func_node, NULL, 0, token->line, token->column);
+        }
+        
+        return ast_identifier_node(func_name, token->line, token->column);
+    }
+    case TOKEN_KEYWORD_WHEN: {
+    
+        return parser_parse_when_expression(parser);
+    }
+    case TOKEN_FUNCTION_REF: {
+        DEBUG_TRACE("parser_parse_primary consuming function ref: %s", token->lexeme);
+        parser_advance(parser);
+        
+        /* Check if this is @(expression) syntax */
+        if (!parser_is_at_end(parser) && parser_peek(parser)->type == TOKEN_LPAREN) {
+            DEBUG_TRACE("parser_parse_primary consuming '('");
+            parser_advance(parser); /* consume '(' */
+            
+            /* Parse the expression inside parentheses */
+            ASTNode* expr = parser_parse_expression(parser);
+            if (expr == NULL) {
+                return NULL;
+            }
+            
+            /* Expect closing parenthesis */
+            if (!parser_consume(parser, TOKEN_RPAREN, "Expected ')' after expression")) {
+                ast_destroy_node(expr);
+                return NULL;
+            }
+            
+            /* Return the expression as-is (it will be evaluated when used as an argument) */
+            return expr;
+        }
+        
+        /* Handle @function_name syntax */
+        ASTNode* func_node = ast_identifier_node(token->lexeme, token->line, token->column);
+        if (func_node == NULL) {
+            return NULL;
+        }
+        
+        /* Check if this function reference is followed by arguments */
+        /* Only treat as function call if it's at the top level (not in an argument position) */
+        if (!parser_is_at_end(parser)) {
+            Token* next_token = parser_peek(parser);
+            if (next_token != NULL && 
+                next_token->type != TOKEN_OP_PLUS && 
+                next_token->type != TOKEN_OP_MINUS &&
+                next_token->type != TOKEN_OP_MULTIPLY &&
+                next_token->type != TOKEN_OP_DIVIDE &&
+                next_token->type != TOKEN_OP_MODULO &&
+                next_token->type != TOKEN_OP_POWER &&
+                next_token->type != TOKEN_OP_EQUALS &&
+                next_token->type != TOKEN_OP_NOT_EQUALS &&
+                next_token->type != TOKEN_OP_LESS &&
+                next_token->type != TOKEN_OP_LESS_EQUAL &&
+                next_token->type != TOKEN_OP_GREATER &&
+                next_token->type != TOKEN_OP_GREATER_EQUAL &&
+                next_token->type != TOKEN_RPAREN &&
+                next_token->type != TOKEN_RBRACE &&
+                next_token->type != TOKEN_RBRACKET &&
+                next_token->type != TOKEN_SEMICOLON &&
+                next_token->type != TOKEN_COMMA &&
+                next_token->type != TOKEN_EOF) {
+                
+                /* For now, always treat function references as values, not function calls */
+                /* This allows them to be passed as arguments to other functions */
+                DEBUG_TRACE("parser_parse_primary: treating function reference as value");
+                return func_node;
+                
+                /* Parse arguments for this function call */
+                ASTNode** args = NULL;
+                int arg_count = 0;
+                
+                while (!parser_is_at_end(parser)) {
+                    Token* arg_token = parser_peek(parser);
+                    if (arg_token == NULL) {
+                        break;
+                    }
+                    
+                    /* Stop if we hit an operator or delimiter */
+                    if (arg_token->type == TOKEN_OP_PLUS || 
+                        arg_token->type == TOKEN_OP_MINUS ||
+                        arg_token->type == TOKEN_OP_MULTIPLY ||
+                        arg_token->type == TOKEN_OP_DIVIDE ||
+                        arg_token->type == TOKEN_OP_MODULO ||
+                        arg_token->type == TOKEN_OP_POWER ||
+                        arg_token->type == TOKEN_OP_EQUALS ||
+                        arg_token->type == TOKEN_OP_NOT_EQUALS ||
+                        arg_token->type == TOKEN_OP_LESS ||
+                        arg_token->type == TOKEN_OP_LESS_EQUAL ||
+                        arg_token->type == TOKEN_OP_GREATER ||
+                        arg_token->type == TOKEN_OP_GREATER_EQUAL ||
+                        arg_token->type == TOKEN_RPAREN ||
+                        arg_token->type == TOKEN_RBRACE ||
+                        arg_token->type == TOKEN_RBRACKET ||
+                        arg_token->type == TOKEN_SEMICOLON ||
+                        arg_token->type == TOKEN_COMMA ||
+                        arg_token->type == TOKEN_EOF) {
+                        break;
+                    }
+                    
+                    /* Parse argument */
+                    ASTNode* arg = parser_parse_postfix(parser);
+                    if (arg == NULL) {
+                        /* Cleanup on error */
+                        for (int i = 0; i < arg_count; i++) {
+                            ast_destroy_node(args[i]);
+                        }
+                        free(args);
+                        ast_destroy_node(func_node);
+                        return NULL;
+                    }
+                    
+                    /* Add to arguments array */
+                    ASTNode** new_args = realloc(args, (arg_count + 1) * sizeof(ASTNode*));
+                    if (new_args == NULL) {
+                        /* Cleanup on error */
+                        for (int i = 0; i < arg_count; i++) {
+                            ast_destroy_node(args[i]);
+                        }
+                        free(args);
+                        ast_destroy_node(arg);
+                        ast_destroy_node(func_node);
+                        return NULL;
+                    }
+                    args = new_args;
+                    args[arg_count] = arg;
+                    arg_count++;
+                }
+                
+                /* Create function call with the arguments */
+                if (arg_count > 0) {
+                    ASTNode* func_call = ast_function_call_node(func_node, args, arg_count, func_node->line, func_node->column);
+                    if (func_call == NULL) {
+                        /* Cleanup on error */
+                        for (int i = 0; i < arg_count; i++) {
+                            ast_destroy_node(args[i]);
+                        }
+                        free(args);
+                        ast_destroy_node(func_node);
+                        return NULL;
+                    }
+                    return func_call;
+                }
+            }
+        }
+        
+        return func_node;
+    }
+    case TOKEN_LPAREN: {
+        DEBUG_TRACE("parser_parse_primary consuming '('");
+        parser_advance(parser); /* consume '(' */
+        ASTNode* expr = parser_parse_expression(parser);
+        if (expr == NULL) {
+            return NULL;
+        }
+        
+        if (!parser_consume(parser, TOKEN_RPAREN, "Expected ')' after expression")) {
+            ast_destroy_node(expr);
+            return NULL;
+        }
+        
+        return expr;
+    }
+    case TOKEN_LBRACE: {
+        DEBUG_TRACE("parser_parse_primary consuming table literal '{'");
+        parser_advance(parser); /* consume '{' */
+        
+        ASTNode** elements = NULL;
+        int element_count = 0;
+        int capacity = 10;
+        
+        /* Allocate initial space for elements */
+        elements = malloc(capacity * sizeof(ASTNode*));
+        if (elements == NULL) {
+            return NULL;
+        }
+        
+        /* Parse table entries */
+        while (!parser_is_at_end(parser) && parser_peek(parser)->type != TOKEN_RBRACE) {
+            ASTNode* value = NULL;
+            
+            /* Check if this is a key-value pair (any token: value) */
+            
+            /* Check if this is a key-value pair */
+            bool is_key_value_pair = false;
+            
+            if (parser_peek(parser)->type == TOKEN_LPAREN) {
+                /* For expression keys, we need to look ahead to find the colon */
+                int look_ahead = parser->current;
+                int paren_count = 0;
+                bool found_colon = false;
+                
+                while (look_ahead < parser->token_count) {
+                    Token* token = parser->tokens[look_ahead];
+                    if (token->type == TOKEN_LPAREN) {
+                        paren_count++;
+                    } else if (token->type == TOKEN_RPAREN) {
+                        paren_count--;
+                        if (paren_count == 0) {
+                            /* We've found the closing parenthesis, check if next is colon */
+                            if (look_ahead + 1 < parser->token_count && 
+                                parser->tokens[look_ahead + 1]->type == TOKEN_COLON) {
+                                found_colon = true;
+                            }
+                            break;
+                        }
+                    } else if (token->type == TOKEN_COMMA || token->type == TOKEN_RBRACE) {
+                        /* Stop looking if we hit table boundaries */
+                        break;
+                    }
+                    look_ahead++;
+                }
+                is_key_value_pair = found_colon;
+            } else {
+                /* For literal keys, check if next token is colon */
+                is_key_value_pair = (parser_peek(parser)->type == TOKEN_IDENTIFIER || 
+                                   parser_peek(parser)->type == TOKEN_NUMBER ||
+                                   parser_peek(parser)->type == TOKEN_BOOLEAN ||
+                                   parser_peek(parser)->type == TOKEN_STRING) && 
+                                  !parser_is_at_end(parser) && 
+                                  parser_peek_next(parser)->type == TOKEN_COLON;
+            }
+            
+            if (is_key_value_pair) {
+                
+                /* Parse key-value pair */
+                ASTNode* key_node = NULL;
+                Token* key_token = NULL;
+                
+                if (parser_peek(parser)->type == TOKEN_LPAREN) {
+                    /* Parse expression key */
+                    key_node = parser_parse_expression(parser);
+                    if (key_node == NULL) {
+                        /* Cleanup on error */
+                        for (int i = 0; i < element_count; i++) {
+                            ast_destroy_node(elements[i]);
+                        }
+                        free(elements);
+                        return NULL;
+                    }
+                    /* Create a dummy token for line/column info */
+                    key_token = parser_peek(parser);
+                    if (key_token == NULL) {
+                        /* Cleanup on error */
+                        for (int i = 0; i < element_count; i++) {
+                            ast_destroy_node(elements[i]);
+                        }
+                        free(elements);
+                        ast_destroy_node(key_node);
+                        return NULL;
+                    }
+                } else {
+                    /* Parse literal key */
+                    key_token = parser_advance(parser); /* Consume the key token */
+                    if (key_token == NULL) {
+                        /* Cleanup on error */
+                        for (int i = 0; i < element_count; i++) {
+                            ast_destroy_node(elements[i]);
+                        }
+                        free(elements);
+                        return NULL;
+                    }
+                }
+                
+                /* Consume colon */
+                if (!parser_consume(parser, TOKEN_COLON, "Expected ':' after table key")) {
+                    /* Cleanup on error */
+                    for (int i = 0; i < element_count; i++) {
+                        ast_destroy_node(elements[i]);
+                    }
+                    free(elements);
+                    return NULL;
+                }
+                
+                /* Check if this is an arrow function by looking ahead */
+                bool is_arrow_function = false;
+                int look_ahead = parser->current;
+                int identifier_count = 0;
+                
+                /* Look ahead to see if we have identifiers followed by '->' */
+                while (look_ahead < parser->token_count) {
+                    Token* token = parser->tokens[look_ahead];
+                    if (token->type == TOKEN_ARROW) {
+                        /* If we have at least one identifier before '->', it's an arrow function */
+                        if (identifier_count > 0) {
+                            is_arrow_function = true;
+                        }
+                        break;
+                    }
+                    if (token->type == TOKEN_IDENTIFIER) {
+                        identifier_count++;
+                    } else if (token->type == TOKEN_COMMA || token->type == TOKEN_RBRACE) {
+                        /* Stop looking if we hit table boundaries */
+                        break;
+                    } else {
+                        /* If we hit anything else, it's not an arrow function */
+                        identifier_count = 0;
+                        break;
+                    }
+                    look_ahead++;
+                }
+                
+                /* Parse the value */
+                if (is_arrow_function) {
+                    /* Parse as embedded arrow function */
+                    value = parser_parse_embedded_arrow_function(parser);
+                } else {
+                    /* Parse as general expression */
+                    value = parser_parse_expression(parser);
+                }
+                if (value == NULL) {
+                    /* Cleanup on error */
+                    for (int i = 0; i < element_count; i++) {
+                        ast_destroy_node(elements[i]);
+                    }
+                    free(elements);
+                    return NULL;
+                }
+                
+                /* For now, we'll store key-value pairs as function calls to a special "table_entry" function */
+                /* This allows us to represent both key-value pairs and array-like entries uniformly */
+                ASTNode** entry_args = malloc(2 * sizeof(ASTNode*));
+                if (entry_args == NULL) {
+                    /* Cleanup on error */
+                    for (int i = 0; i < element_count; i++) {
+                        ast_destroy_node(elements[i]);
+                    }
+                    free(elements);
+                    ast_destroy_node(value);
+                    return NULL;
+                }
+                
+                /* Create key value based on token type or expression */
+                ASTNode* key_arg = NULL;
+                if (key_node != NULL) {
+                    /* Expression key - use the parsed AST node */
+                    key_arg = key_node;
+                } else {
+                    /* Literal key - create literal value from token */
+                    Value key_value;
+                    if (key_token->type == TOKEN_IDENTIFIER) {
+                        key_value = baba_yaga_value_string(key_token->lexeme);
+                    } else if (key_token->type == TOKEN_NUMBER) {
+                        key_value = baba_yaga_value_number(key_token->literal.number);
+                    } else if (key_token->type == TOKEN_BOOLEAN) {
+                        key_value = baba_yaga_value_boolean(key_token->literal.boolean);
+                    } else if (key_token->type == TOKEN_STRING) {
+                        key_value = baba_yaga_value_string(key_token->lexeme);
+                    } else {
+                        /* Cleanup on error */
+                        for (int i = 0; i < element_count; i++) {
+                            ast_destroy_node(elements[i]);
+                        }
+                        free(elements);
+                        free(entry_args);
+                        ast_destroy_node(value);
+                        return NULL;
+                    }
+                    key_arg = ast_literal_node(key_value, key_token->line, key_token->column);
+                }
+                
+                entry_args[0] = key_arg;
+                entry_args[1] = value;
+                
+                ASTNode* table_entry_node = ast_identifier_node("table_entry", key_token->line, key_token->column);
+                if (table_entry_node == NULL) {
+                    /* Cleanup on error */
+                    for (int i = 0; i < element_count; i++) {
+                        ast_destroy_node(elements[i]);
+                    }
+                    free(elements);
+                    free(entry_args);
+                    ast_destroy_node(value);
+                    if (key_node != NULL) {
+                        ast_destroy_node(key_node);
+                    }
+                    return NULL;
+                }
+                
+                ASTNode* entry_node = ast_function_call_node(table_entry_node, entry_args, 2, key_token->line, key_token->column);
+                if (entry_node == NULL) {
+                    /* Cleanup on error */
+                    for (int i = 0; i < element_count; i++) {
+                        ast_destroy_node(elements[i]);
+                    }
+                    free(elements);
+                    free(entry_args);
+                    ast_destroy_node(table_entry_node);
+                    ast_destroy_node(value);
+                    if (key_node != NULL) {
+                        ast_destroy_node(key_node);
+                    }
+                    return NULL;
+                }
+                
+                value = entry_node;
+            } else {
+                /* Parse array-like entry (just a value) */
+                value = parser_parse_expression(parser);
+                if (value == NULL) {
+                    /* Cleanup on error */
+                    for (int i = 0; i < element_count; i++) {
+                        ast_destroy_node(elements[i]);
+                    }
+                    free(elements);
+                    return NULL;
+                }
+            }
+            
+            /* Check if we need more space */
+            if (element_count >= capacity) {
+                capacity *= 2;
+                ASTNode** new_elements = realloc(elements, capacity * sizeof(ASTNode*));
+                if (new_elements == NULL) {
+                    /* Cleanup on error */
+                    for (int i = 0; i < element_count; i++) {
+                        ast_destroy_node(elements[i]);
+                    }
+                    free(elements);
+                    ast_destroy_node(value);
+                    return NULL;
+                }
+                elements = new_elements;
+            }
+            
+            elements[element_count++] = value;
+            
+            /* Check for comma separator */
+            if (!parser_is_at_end(parser) && parser_peek(parser)->type == TOKEN_COMMA) {
+                parser_advance(parser); /* consume ',' */
+            } else if (!parser_is_at_end(parser) && parser_peek(parser)->type != TOKEN_RBRACE) {
+                /* No comma but not end of table - this is an error */
+                parser_set_error(parser, "Expected ',' or '}' in table literal");
+                /* Cleanup on error */
+                for (int i = 0; i < element_count; i++) {
+                    ast_destroy_node(elements[i]);
+                }
+                free(elements);
+                return NULL;
+            }
+        }
+        
+        /* Expect closing brace */
+        if (!parser_consume(parser, TOKEN_RBRACE, "Expected '}' after table literal")) {
+            /* Cleanup on error */
+            for (int i = 0; i < element_count; i++) {
+                ast_destroy_node(elements[i]);
+            }
+            free(elements);
+            return NULL;
+        }
+        
+        /* Create table node */
+        ASTNode* node = malloc(sizeof(ASTNode));
+        if (node == NULL) {
+            /* Cleanup on error */
+            for (int i = 0; i < element_count; i++) {
+                ast_destroy_node(elements[i]);
+            }
+            free(elements);
+            return NULL;
+        }
+        
+        node->type = NODE_TABLE;
+        node->line = token->line;
+        node->column = token->column;
+        node->data.table.elements = elements;
+        node->data.table.element_count = element_count;
+        
+        return node;
+    }
+    case TOKEN_OP_UNARY_MINUS: {
+        DEBUG_TRACE("parser_parse_primary consuming unary minus");
+        parser_advance(parser); /* consume '-' */
+        ASTNode* operand = parser_parse_postfix(parser);
+        if (operand == NULL) {
+            return NULL;
+        }
+        return ast_unary_op_node(operand, "negate", token->line, token->column);
+    }
+    case TOKEN_KEYWORD_NOT: {
+        DEBUG_TRACE("parser_parse_primary consuming 'not'");
+        parser_advance(parser); /* consume 'not' */
+        ASTNode* operand = parser_parse_postfix(parser);
+        if (operand == NULL) {
+            return NULL;
+        }
+        return ast_unary_op_node(operand, "not", token->line, token->column);
+    }
+    default:
+        parser_set_error(parser, "Unexpected token in expression");
+        return NULL;
+    }
+}
+
+/**
+ * @brief Parse function call expression
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+/* TODO: Re-implement function call parsing at application level */
+/* TODO: Re-implement function call parsing at application level */
+
+/**
+ * @brief Parse power expression (^)
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+static ASTNode* parser_parse_power(Parser* parser) {
+    ASTNode* left = parser_parse_postfix(parser);
+    if (left == NULL) {
+        return NULL;
+    }
+    
+    while (parser_check(parser, TOKEN_OP_POWER)) {
+        Token* op = parser_advance(parser);
+        ASTNode* right = parser_parse_postfix(parser);
+        if (right == NULL) {
+            ast_destroy_node(left);
+            return NULL;
+        }
+        
+        ASTNode* new_left = ast_binary_op_node(left, right, "pow", op->line, op->column);
+        if (new_left == NULL) {
+            ast_destroy_node(left);
+            ast_destroy_node(right);
+            return NULL;
+        }
+        
+        left = new_left;
+    }
+    
+    return left;
+}
+
+/**
+ * @brief Parse multiplicative expression (*, /, %)
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+static ASTNode* parser_parse_multiplicative(Parser* parser) {
+    ASTNode* left = parser_parse_power(parser);
+    if (left == NULL) {
+        return NULL;
+    }
+    
+    while (parser_check(parser, TOKEN_OP_MULTIPLY) || 
+           parser_check(parser, TOKEN_OP_DIVIDE) || 
+           parser_check(parser, TOKEN_OP_MODULO)) {
+        Token* op = parser_advance(parser);
+        ASTNode* right = parser_parse_power(parser);
+        if (right == NULL) {
+            ast_destroy_node(left);
+            return NULL;
+        }
+        
+        const char* operator_name;
+        switch (op->type) {
+        case TOKEN_OP_MULTIPLY: operator_name = "multiply"; break;
+        case TOKEN_OP_DIVIDE: operator_name = "divide"; break;
+        case TOKEN_OP_MODULO: operator_name = "modulo"; break;
+        default: operator_name = "unknown"; break;
+        }
+        
+        ASTNode* new_left = ast_binary_op_node(left, right, operator_name, op->line, op->column);
+        if (new_left == NULL) {
+            ast_destroy_node(left);
+            ast_destroy_node(right);
+            return NULL;
+        }
+        
+        left = new_left;
+    }
+    
+    return left;
+}
+
+/**
+ * @brief Parse additive expression (+, -)
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+static ASTNode* parser_parse_additive(Parser* parser) {
+    ASTNode* left = parser_parse_multiplicative(parser);
+    if (left == NULL) {
+        return NULL;
+    }
+    
+    while (parser_check(parser, TOKEN_OP_PLUS) || parser_check(parser, TOKEN_OP_MINUS)) {
+        Token* op = parser_advance(parser);
+        ASTNode* right = parser_parse_multiplicative(parser);
+        if (right == NULL) {
+            ast_destroy_node(left);
+            return NULL;
+        }
+        
+        const char* operator_name = (op->type == TOKEN_OP_PLUS) ? "add" : "subtract";
+        
+        ASTNode* new_left = ast_binary_op_node(left, right, operator_name, op->line, op->column);
+        if (new_left == NULL) {
+            ast_destroy_node(left);
+            ast_destroy_node(right);
+            return NULL;
+        }
+        
+        left = new_left;
+    }
+    
+    return left;
+}
+
+/**
+ * @brief Parse comparison expression (=, !=, <, <=, >, >=)
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+static ASTNode* parser_parse_comparison(Parser* parser) {
+    ASTNode* left = parser_parse_additive(parser);
+    if (left == NULL) {
+        return NULL;
+    }
+    
+    while (parser_check(parser, TOKEN_OP_EQUALS) || 
+           parser_check(parser, TOKEN_OP_NOT_EQUALS) ||
+           parser_check(parser, TOKEN_OP_LESS) || 
+           parser_check(parser, TOKEN_OP_LESS_EQUAL) ||
+           parser_check(parser, TOKEN_OP_GREATER) || 
+           parser_check(parser, TOKEN_OP_GREATER_EQUAL)) {
+        Token* op = parser_advance(parser);
+        ASTNode* right = parser_parse_additive(parser);
+        if (right == NULL) {
+            ast_destroy_node(left);
+            return NULL;
+        }
+        
+        const char* operator_name;
+        switch (op->type) {
+        case TOKEN_OP_EQUALS: operator_name = "equals"; break;
+        case TOKEN_OP_NOT_EQUALS: operator_name = "not_equals"; break;
+        case TOKEN_OP_LESS: operator_name = "less"; break;
+        case TOKEN_OP_LESS_EQUAL: operator_name = "less_equal"; break;
+        case TOKEN_OP_GREATER: operator_name = "greater"; break;
+        case TOKEN_OP_GREATER_EQUAL: operator_name = "greater_equal"; break;
+        default: operator_name = "unknown"; break;
+        }
+        
+        ASTNode* new_left = ast_binary_op_node(left, right, operator_name, op->line, op->column);
+        if (new_left == NULL) {
+            ast_destroy_node(left);
+            ast_destroy_node(right);
+            return NULL;
+        }
+        
+        left = new_left;
+    }
+    
+    return left;
+}
+
+/**
+ * @brief Parse logical expression (and, or, xor)
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+static ASTNode* parser_parse_logical(Parser* parser) {
+    ASTNode* left = parser_parse_comparison(parser);
+    if (left == NULL) {
+        return NULL;
+    }
+    
+    /* Handle logical operators */
+    while ((parser_check(parser, TOKEN_KEYWORD_AND) || 
+            parser_check(parser, TOKEN_KEYWORD_OR) || 
+            parser_check(parser, TOKEN_KEYWORD_XOR)) ||
+           (parser_check(parser, TOKEN_IDENTIFIER) && 
+            (strcmp(parser_peek(parser)->lexeme, "and") == 0 ||
+             strcmp(parser_peek(parser)->lexeme, "or") == 0 ||
+             strcmp(parser_peek(parser)->lexeme, "xor") == 0))) {
+        Token* op = parser_advance(parser);
+        ASTNode* right = parser_parse_comparison(parser);
+        if (right == NULL) {
+            ast_destroy_node(left);
+            return NULL;
+        }
+        
+        const char* operator_name;
+        if (op->type == TOKEN_KEYWORD_AND || 
+            (op->type == TOKEN_IDENTIFIER && strcmp(op->lexeme, "and") == 0)) {
+            operator_name = "and";
+        } else if (op->type == TOKEN_KEYWORD_OR || 
+                   (op->type == TOKEN_IDENTIFIER && strcmp(op->lexeme, "or") == 0)) {
+            operator_name = "or";
+        } else if (op->type == TOKEN_KEYWORD_XOR || 
+                   (op->type == TOKEN_IDENTIFIER && strcmp(op->lexeme, "xor") == 0)) {
+            operator_name = "xor";
+        } else {
+            operator_name = "unknown";
+        }
+        
+        ASTNode* new_left = ast_binary_op_node(left, right, operator_name, op->line, op->column);
+        if (new_left == NULL) {
+            ast_destroy_node(left);
+            ast_destroy_node(right);
+            return NULL;
+        }
+        
+        left = new_left;
+    }
+    
+    /* Handle via operator (function composition) - right-associative */
+    while (parser_check(parser, TOKEN_KEYWORD_VIA)) {
+        Token* op = parser_advance(parser);
+        ASTNode* right = parser_parse_logical(parser); /* Right-associative: recurse */
+        if (right == NULL) {
+            ast_destroy_node(left);
+            return NULL;
+        }
+        
+        ASTNode* new_left = ast_binary_op_node(left, right, "via", op->line, op->column);
+        if (new_left == NULL) {
+            ast_destroy_node(left);
+            ast_destroy_node(right);
+            return NULL;
+        }
+        
+        left = new_left;
+    }
+    
+    /* Handle function application */
+    /* Skip function application if the left node is a when expression */
+    if (left->type == NODE_WHEN_EXPR) {
+        return left;
+    }
+    
+    while (!parser_is_at_end(parser)) {
+        Token* next_token = parser_peek(parser);
+        if (next_token == NULL) break;
+        
+    
+        
+        /* Check if this token can be a function argument */
+        bool can_be_arg = (next_token->type == TOKEN_IDENTIFIER ||
+                          next_token->type == TOKEN_FUNCTION_REF ||
+                          next_token->type == TOKEN_NUMBER ||
+                          next_token->type == TOKEN_STRING ||
+                          next_token->type == TOKEN_BOOLEAN ||
+                          next_token->type == TOKEN_LPAREN ||
+                          next_token->type == TOKEN_LBRACE ||
+                          next_token->type == TOKEN_OP_UNARY_MINUS ||
+                          next_token->type == TOKEN_KEYWORD_NOT);
+        
+        /* Check if this token should not trigger function application */
+        bool should_not_trigger = (next_token->type == TOKEN_OP_PLUS ||
+                                  next_token->type == TOKEN_OP_MINUS ||
+                                  next_token->type == TOKEN_OP_MULTIPLY ||
+                                  next_token->type == TOKEN_OP_DIVIDE ||
+                                  next_token->type == TOKEN_OP_MODULO ||
+                                  next_token->type == TOKEN_OP_POWER ||
+                                  next_token->type == TOKEN_OP_EQUALS ||
+                                  next_token->type == TOKEN_OP_NOT_EQUALS ||
+                                  next_token->type == TOKEN_OP_LESS ||
+                                  next_token->type == TOKEN_OP_LESS_EQUAL ||
+                                  next_token->type == TOKEN_OP_GREATER ||
+                                  next_token->type == TOKEN_OP_GREATER_EQUAL ||
+                                  next_token->type == TOKEN_KEYWORD_AND ||
+                                  next_token->type == TOKEN_KEYWORD_OR ||
+                                  next_token->type == TOKEN_KEYWORD_XOR ||
+                                  (next_token->type == TOKEN_IDENTIFIER && 
+                                   (strcmp(next_token->lexeme, "and") == 0 ||
+                                    strcmp(next_token->lexeme, "or") == 0 ||
+                                    strcmp(next_token->lexeme, "xor") == 0)) ||
+                                  next_token->type == TOKEN_KEYWORD_WHEN ||
+                                  next_token->type == TOKEN_KEYWORD_IS ||
+                                  next_token->type == TOKEN_KEYWORD_THEN ||
+                                  next_token->type == TOKEN_KEYWORD_VIA ||
+                                  next_token->type == TOKEN_RPAREN ||
+                                  next_token->type == TOKEN_RBRACE ||
+                                  next_token->type == TOKEN_RBRACKET ||
+                                  next_token->type == TOKEN_SEMICOLON ||
+                                  next_token->type == TOKEN_COMMA ||
+                                  next_token->type == TOKEN_EOF);
+        
+        /* Check if this is a pattern boundary (identifier followed by 'then') */
+        bool is_pattern_boundary = false;
+        if (next_token->type == TOKEN_IDENTIFIER) {
+            /* Look ahead to see if the next token is 'then' */
+            if (parser->current + 1 < parser->token_count) {
+                Token* next_next_token = parser->tokens[parser->current + 1];
+                if (next_next_token && next_next_token->type == TOKEN_KEYWORD_THEN) {
+                    is_pattern_boundary = true;
+                    DEBUG_TRACE("Found pattern boundary: %s followed by 'then'", next_token->lexeme);
+                }
+            }
+        }
+        
+                DEBUG_TRACE("Function application check: can_be_arg=%d, should_not_trigger=%d, is_pattern_boundary=%d",
+               can_be_arg, should_not_trigger, is_pattern_boundary);
+        
+        /* Only proceed with function application if it can be an arg and shouldn't trigger */
+        if (!can_be_arg || should_not_trigger || is_pattern_boundary) {
+    
+            break;
+        }
+        
+        /* Collect all arguments for this function call */
+        ASTNode** args = NULL;
+        int arg_count = 0;
+        
+        while (!parser_is_at_end(parser)) {
+            Token* arg_token = parser_peek(parser);
+            if (arg_token == NULL) break;
+            
+            /* Check if this token can be a function argument */
+            bool can_be_arg = (arg_token->type == TOKEN_IDENTIFIER ||
+                              arg_token->type == TOKEN_FUNCTION_REF ||
+                              arg_token->type == TOKEN_NUMBER ||
+                              arg_token->type == TOKEN_STRING ||
+                              arg_token->type == TOKEN_BOOLEAN ||
+                              arg_token->type == TOKEN_LPAREN ||
+                              arg_token->type == TOKEN_LBRACE ||
+                              arg_token->type == TOKEN_OP_UNARY_MINUS ||
+                              arg_token->type == TOKEN_KEYWORD_NOT);
+            
+            /* Check if this token should not trigger function application */
+            bool should_not_trigger = (arg_token->type == TOKEN_OP_PLUS ||
+                                      arg_token->type == TOKEN_OP_MINUS ||
+                                      arg_token->type == TOKEN_OP_MULTIPLY ||
+                                      arg_token->type == TOKEN_OP_DIVIDE ||
+                                      arg_token->type == TOKEN_OP_MODULO ||
+                                      arg_token->type == TOKEN_OP_POWER ||
+                                      arg_token->type == TOKEN_OP_EQUALS ||
+                                      arg_token->type == TOKEN_OP_NOT_EQUALS ||
+                                      arg_token->type == TOKEN_OP_LESS ||
+                                      arg_token->type == TOKEN_OP_LESS_EQUAL ||
+                                      arg_token->type == TOKEN_OP_GREATER ||
+                                      arg_token->type == TOKEN_OP_GREATER_EQUAL ||
+                                      arg_token->type == TOKEN_KEYWORD_AND ||
+                                      arg_token->type == TOKEN_KEYWORD_OR ||
+                                      arg_token->type == TOKEN_KEYWORD_XOR ||
+                                      arg_token->type == TOKEN_KEYWORD_WHEN ||
+                                      arg_token->type == TOKEN_KEYWORD_IS ||
+                                      arg_token->type == TOKEN_KEYWORD_THEN ||
+                                      arg_token->type == TOKEN_RPAREN ||
+                                      arg_token->type == TOKEN_RBRACE ||
+                                      arg_token->type == TOKEN_RBRACKET ||
+                                      arg_token->type == TOKEN_SEMICOLON ||
+                                      arg_token->type == TOKEN_COMMA ||
+                                      arg_token->type == TOKEN_EOF);
+            
+            /* Check if this is a pattern boundary (identifier followed by 'then') */
+            bool is_pattern_boundary = false;
+            if (arg_token->type == TOKEN_IDENTIFIER) {
+                /* Look ahead to see if the next token is 'then' */
+                if (parser->current + 1 < parser->token_count) {
+                    Token* next_next_token = parser->tokens[parser->current + 1];
+                    if (next_next_token && next_next_token->type == TOKEN_KEYWORD_THEN) {
+                        is_pattern_boundary = true;
+                        DEBUG_TRACE("Inner loop found pattern boundary: %s followed by 'then'", arg_token->lexeme);
+                    }
+                }
+            }
+            
+            /* Stop if it can't be an arg, should not trigger, or is a pattern boundary */
+            if (!can_be_arg || should_not_trigger || is_pattern_boundary) {
+                break;
+            }
+            
+            ASTNode* arg = parser_parse_comparison(parser);
+            if (arg == NULL) {
+                /* Cleanup on error */
+                for (int i = 0; i < arg_count; i++) {
+                    ast_destroy_node(args[i]);
+                }
+                free(args);
+                ast_destroy_node(left);
+                return NULL;
+            }
+            
+            /* Add to arguments array */
+            ASTNode** new_args = realloc(args, (arg_count + 1) * sizeof(ASTNode*));
+            if (new_args == NULL) {
+                /* Cleanup on error */
+                for (int i = 0; i < arg_count; i++) {
+                    ast_destroy_node(args[i]);
+                }
+                free(args);
+                ast_destroy_node(arg);
+                ast_destroy_node(left);
+                return NULL;
+            }
+            args = new_args;
+            args[arg_count++] = arg;
+        }
+        
+        /* Create function call with all arguments */
+        ASTNode* new_left = ast_function_call_node(left, args, arg_count, left->line, left->column);
+        if (new_left == NULL) {
+            /* Cleanup on error */
+            for (int i = 0; i < arg_count; i++) {
+                ast_destroy_node(args[i]);
+            }
+            free(args);
+            ast_destroy_node(left);
+            return NULL;
+        }
+        
+        left = new_left;
+    }
+    
+    return left;
+}
+
+/**
+ * @brief Parse function composition (via)
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+/* TODO: Re-implement composition parsing */
+/*
+static ASTNode* parser_parse_composition(Parser* parser) {
+    ASTNode* left = parser_parse_application(parser);
+    if (left == NULL) {
+        return NULL;
+    }
+    
+    while (parser_check(parser, TOKEN_KEYWORD_VIA)) {
+        Token* op = parser_advance(parser);
+        ASTNode* right = parser_parse_logical(parser);
+        if (right == NULL) {
+            ast_destroy_node(left);
+            return NULL;
+        }
+        
+        ASTNode* new_left = ast_binary_op_node(left, right, "compose", op->line, op->column);
+        if (new_left == NULL) {
+            ast_destroy_node(left);
+            ast_destroy_node(right);
+            return NULL;
+        }
+        
+        left = new_left;
+    }
+    
+    return left;
+}
+*/
+
+
+
+/**
+ * @brief Parse postfix operations (table access, function calls, etc.)
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+static ASTNode* parser_parse_postfix(Parser* parser) {
+    ASTNode* left = parser_parse_primary(parser);
+    if (left == NULL) {
+        return NULL;
+    }
+    
+    while (!parser_is_at_end(parser)) {
+        Token* token = parser_peek(parser);
+        if (token == NULL) {
+            break;
+        }
+        
+        switch (token->type) {
+        case TOKEN_DOT: {
+            /* Table property access: table.property */
+            parser_advance(parser); /* consume '.' */
+            
+            Token* property = parser_consume(parser, TOKEN_IDENTIFIER, "Expected property name after '.'");
+            if (property == NULL) {
+                ast_destroy_node(left);
+                return NULL;
+            }
+            
+            ASTNode* key = ast_literal_node(baba_yaga_value_string(property->lexeme), property->line, property->column);
+            if (key == NULL) {
+                ast_destroy_node(left);
+                return NULL;
+            }
+            
+            ASTNode* new_left = malloc(sizeof(ASTNode));
+            if (new_left == NULL) {
+                ast_destroy_node(left);
+                ast_destroy_node(key);
+                return NULL;
+            }
+            
+            new_left->type = NODE_TABLE_ACCESS;
+            new_left->line = left->line;
+            new_left->column = left->column;
+            new_left->data.table_access.object = left;
+            new_left->data.table_access.key = key;
+            
+            left = new_left;
+            break;
+        }
+        case TOKEN_LBRACKET: {
+            /* Table bracket access: table[key] */
+            parser_advance(parser); /* consume '[' */
+            
+            ASTNode* key = parser_parse_expression(parser);
+            if (key == NULL) {
+                ast_destroy_node(left);
+                return NULL;
+            }
+            
+            if (!parser_consume(parser, TOKEN_RBRACKET, "Expected ']' after table key")) {
+                ast_destroy_node(left);
+                ast_destroy_node(key);
+                return NULL;
+            }
+            
+            ASTNode* new_left = malloc(sizeof(ASTNode));
+            if (new_left == NULL) {
+                ast_destroy_node(left);
+                ast_destroy_node(key);
+                return NULL;
+            }
+            
+            new_left->type = NODE_TABLE_ACCESS;
+            new_left->line = left->line;
+            new_left->column = left->column;
+            new_left->data.table_access.object = left;
+            new_left->data.table_access.key = key;
+            
+            left = new_left;
+            break;
+        }
+        default:
+            /* No more postfix operations */
+            return left;
+        }
+    }
+    
+    return left;
+}
+
+/**
+ * @brief Parse expression (entry point)
+ * 
+ * @param parser Parser instance
+ * @return Parsed expression node
+ */
+static ASTNode* parser_parse_expression(Parser* parser) {
+    return parser_parse_logical(parser);
+}
+
+/* ============================================================================
+ * Statement Parsing
+ * ============================================================================ */
+
+/**
+ * @brief Parse variable declaration
+ * 
+ * @param parser Parser instance
+ * @return Parsed variable declaration node
+ */
+static ASTNode* parser_parse_variable_decl(Parser* parser) {
+    Token* name = parser_consume(parser, TOKEN_IDENTIFIER, "Expected variable name");
+    if (name == NULL) {
+        return NULL;
+    }
+    
+    if (!parser_consume(parser, TOKEN_COLON, "Expected ':' after variable name")) {
+        return NULL;
+    }
+    
+    ASTNode* value = parser_parse_expression(parser);
+    if (value == NULL) {
+        return NULL;
+    }
+    
+
+    
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        ast_destroy_node(value);
+        return NULL;
+    }
+    
+    node->type = NODE_VARIABLE_DECL;
+    node->line = name->line;
+    node->column = name->column;
+    node->data.variable_decl.name = strdup(name->lexeme);
+    node->data.variable_decl.value = value;
+    
+
+    return node;
+}
+
+/**
+ * @brief Parse function definition
+ * 
+ * @param parser Parser instance
+ * @return Parsed function definition node
+ */
+static ASTNode* parser_parse_function_def(Parser* parser) {
+    Token* name = parser_consume(parser, TOKEN_IDENTIFIER, "Expected function name");
+    if (name == NULL) {
+        return NULL;
+    }
+    
+    if (!parser_consume(parser, TOKEN_COLON, "Expected ':' after function name")) {
+        return NULL;
+    }
+    
+    /* Parse parameters */
+    ASTNode** parameters = NULL;
+    int param_count = 0;
+    
+    while (!parser_is_at_end(parser) && 
+           parser_peek(parser)->type == TOKEN_IDENTIFIER) {
+        Token* param = parser_advance(parser);
+        
+        ASTNode** new_params = realloc(parameters, (param_count + 1) * sizeof(ASTNode*));
+        if (new_params == NULL) {
+            for (int i = 0; i < param_count; i++) {
+                ast_destroy_node(parameters[i]);
+            }
+            free(parameters);
+            return NULL;
+        }
+        parameters = new_params;
+        
+        parameters[param_count] = ast_identifier_node(param->lexeme, param->line, param->column);
+        param_count++;
+    }
+    
+    if (!parser_consume(parser, TOKEN_ARROW, "Expected '->' after parameters")) {
+        for (int i = 0; i < param_count; i++) {
+            ast_destroy_node(parameters[i]);
+        }
+        free(parameters);
+        return NULL;
+    }
+    
+    ASTNode* body = parser_parse_expression(parser);
+    if (body == NULL) {
+        for (int i = 0; i < param_count; i++) {
+            ast_destroy_node(parameters[i]);
+        }
+        free(parameters);
+        return NULL;
+    }
+    
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        for (int i = 0; i < param_count; i++) {
+            ast_destroy_node(parameters[i]);
+        }
+        free(parameters);
+        ast_destroy_node(body);
+        return NULL;
+    }
+    
+    node->type = NODE_FUNCTION_DEF;
+    node->line = name->line;
+    node->column = name->column;
+    node->data.function_def.name = strdup(name->lexeme);
+    node->data.function_def.parameters = parameters;
+    node->data.function_def.param_count = param_count;
+    node->data.function_def.body = body;
+    
+    return node;
+}
+
+/**
+ * @brief Parse embedded arrow function (params -> body) without function name
+ * 
+ * @param parser Parser instance
+ * @return Parsed function definition node
+ */
+static ASTNode* parser_parse_embedded_arrow_function(Parser* parser) {
+    /* Parse parameters */
+    ASTNode** parameters = NULL;
+    int param_count = 0;
+    
+    while (!parser_is_at_end(parser) && 
+           parser_peek(parser)->type == TOKEN_IDENTIFIER) {
+        Token* param = parser_advance(parser);
+        
+        ASTNode** new_params = realloc(parameters, (param_count + 1) * sizeof(ASTNode*));
+        if (new_params == NULL) {
+            for (int i = 0; i < param_count; i++) {
+                ast_destroy_node(parameters[i]);
+            }
+            free(parameters);
+            return NULL;
+        }
+        parameters = new_params;
+        
+        parameters[param_count] = ast_identifier_node(param->lexeme, param->line, param->column);
+        param_count++;
+    }
+    
+    if (!parser_consume(parser, TOKEN_ARROW, "Expected '->' after parameters")) {
+        for (int i = 0; i < param_count; i++) {
+            ast_destroy_node(parameters[i]);
+        }
+        free(parameters);
+        return NULL;
+    }
+    
+    ASTNode* body = parser_parse_expression(parser);
+    if (body == NULL) {
+        for (int i = 0; i < param_count; i++) {
+            ast_destroy_node(parameters[i]);
+        }
+        free(parameters);
+        return NULL;
+    }
+    
+    ASTNode* node = malloc(sizeof(ASTNode));
+    if (node == NULL) {
+        for (int i = 0; i < param_count; i++) {
+            ast_destroy_node(parameters[i]);
+        }
+        free(parameters);
+        ast_destroy_node(body);
+        return NULL;
+    }
+    
+    node->type = NODE_FUNCTION_DEF;
+    node->line = parser_peek(parser)->line;
+    node->column = parser_peek(parser)->column;
+    node->data.function_def.name = strdup(""); /* Empty name for embedded functions */
+    node->data.function_def.parameters = parameters;
+    node->data.function_def.param_count = param_count;
+    node->data.function_def.body = body;
+    
+    return node;
+}
+
+/**
+ * @brief Parse multiple statements separated by semicolons
+ * 
+ * @param parser Parser instance
+ * @return Parsed sequence node or single statement node
+ */
+static ASTNode* parser_parse_statements(Parser* parser) {
+    if (parser_is_at_end(parser)) {
+        return NULL;
+    }
+    
+    /* Parse first statement */
+    ASTNode* first_statement = parser_parse_statement(parser);
+    if (first_statement == NULL) {
+        return NULL;
+    }
+    
+    /* Check if there are more statements (semicolon-separated) */
+    if (parser_is_at_end(parser)) {
+        return first_statement; /* Single statement */
+    }
+    
+    Token* next_token = parser_peek(parser);
+    if (next_token->type != TOKEN_SEMICOLON) {
+        return first_statement; /* Single statement */
+    }
+    
+    /* We have multiple statements, collect them */
+    ASTNode** statements = malloc(10 * sizeof(ASTNode*)); /* Start with space for 10 */
+    if (statements == NULL) {
+        ast_destroy_node(first_statement);
+        return NULL;
+    }
+    
+    int statement_count = 0;
+    int capacity = 10;
+    
+    /* Add first statement */
+    statements[statement_count++] = first_statement;
+    
+    /* Parse remaining statements */
+    while (!parser_is_at_end(parser) && 
+           parser_peek(parser)->type == TOKEN_SEMICOLON) {
+        
+        /* Consume semicolon */
+        parser_consume(parser, TOKEN_SEMICOLON, "Expected semicolon");
+        
+        /* Skip any whitespace after semicolon */
+        /* Comments are already skipped by the lexer */
+        
+        if (parser_is_at_end(parser)) {
+            break; /* Trailing semicolon */
+        }
+        
+        /* Parse next statement */
+        ASTNode* next_statement = parser_parse_statement(parser);
+        if (next_statement == NULL) {
+            /* Error parsing statement, but continue with what we have */
+            break;
+        }
+        
+        /* Expand array if needed */
+        if (statement_count >= capacity) {
+            capacity *= 2;
+            ASTNode** new_statements = realloc(statements, capacity * sizeof(ASTNode*));
+            if (new_statements == NULL) {
+                /* Cleanup and return what we have */
+                for (int i = 0; i < statement_count; i++) {
+                    ast_destroy_node(statements[i]);
+                }
+                free(statements);
+                return NULL;
+            }
+            statements = new_statements;
+        }
+        
+        statements[statement_count++] = next_statement;
+    }
+    
+    /* If we only have one statement, return it directly */
+    if (statement_count == 1) {
+        ASTNode* result = statements[0];
+        free(statements);
+        return result;
+    }
+    
+    /* Create sequence node */
+    return ast_sequence_node(statements, statement_count, 
+                           first_statement->line, first_statement->column);
+}
+
+/**
+ * @brief Parse statement
+ * 
+ * @param parser Parser instance
+ * @return Parsed statement node
+ */
+static ASTNode* parser_parse_statement(Parser* parser) {
+    if (parser_is_at_end(parser)) {
+        return NULL;
+    }
+    
+    Token* token = parser_peek(parser);
+    
+    /* Check for variable declaration */
+    if (token->type == TOKEN_IDENTIFIER && 
+        parser_peek_next(parser) != NULL && 
+        parser_peek_next(parser)->type == TOKEN_COLON) {
+        
+        /* Look ahead to see if it's a function definition */
+        int save_current = parser->current;
+        parser->current += 2; /* skip identifier and colon */
+        
+        bool is_function = false;
+        while (!parser_is_at_end(parser) && 
+               parser_peek(parser)->type == TOKEN_IDENTIFIER) {
+            parser->current++;
+        }
+        
+        if (!parser_is_at_end(parser) && 
+            parser_peek(parser)->type == TOKEN_ARROW) {
+            is_function = true;
+        }
+        
+        parser->current = save_current;
+        
+        if (is_function) {
+            return parser_parse_function_def(parser);
+        } else {
+            return parser_parse_variable_decl(parser);
+        }
+    }
+    
+
+    
+    /* Default to expression */
+    return parser_parse_expression(parser);
+}
+
+/* ============================================================================
+ * Public Parser API
+ * ============================================================================ */
+
+/**
+ * @brief Parse source code into AST
+ * 
+ * @param tokens Array of tokens
+ * @param token_count Number of tokens
+ * @return Root AST node, or NULL on error
+ */
+void* baba_yaga_parse(void** tokens, size_t token_count) {
+    if (tokens == NULL || token_count == 0) {
+        return NULL;
+    }
+    
+    Parser* parser = parser_create((Token**)tokens, (int)token_count);
+    if (parser == NULL) {
+        return NULL;
+    }
+    
+    ASTNode* result = parser_parse_statements(parser);
+    
+    if (parser->has_error) {
+        fprintf(stderr, "Parse error: %s\n", parser->error_message);
+        if (result != NULL) {
+            ast_destroy_node(result);
+            result = NULL;
+        }
+    }
+    
+    parser_destroy(parser);
+    return (void*)result;
+}
+
+/**
+ * @brief Destroy AST
+ * 
+ * @param node Root AST node
+ */
+void baba_yaga_destroy_ast(void* node) {
+    ast_destroy_node((ASTNode*)node);
+}
+
+/**
+ * @brief Print AST for debugging
+ * 
+ * @param node Root AST node
+ * @param indent Initial indentation level
+ */
+/* ============================================================================
+ * AST Accessor Functions
+ * ============================================================================ */
+
+NodeType baba_yaga_ast_get_type(void* node) {
+    if (node == NULL) {
+        return NODE_LITERAL; /* Default fallback */
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    return ast_node->type;
+}
+
+Value baba_yaga_ast_get_literal(void* node) {
+    if (node == NULL) {
+        return baba_yaga_value_nil();
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_LITERAL) {
+        return baba_yaga_value_copy(&ast_node->data.literal);
+    }
+    return baba_yaga_value_nil();
+}
+
+const char* baba_yaga_ast_get_identifier(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_IDENTIFIER) {
+        return ast_node->data.identifier;
+    }
+    return NULL;
+}
+
+void* baba_yaga_ast_get_function_call_func(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_FUNCTION_CALL) {
+        return ast_node->data.function_call.function;
+    }
+    return NULL;
+}
+
+int baba_yaga_ast_get_function_call_arg_count(void* node) {
+    if (node == NULL) {
+        return 0;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_FUNCTION_CALL) {
+        return ast_node->data.function_call.arg_count;
+    }
+    return 0;
+}
+
+void* baba_yaga_ast_get_function_call_arg(void* node, int index) {
+    if (node == NULL || index < 0) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_FUNCTION_CALL && 
+        index < ast_node->data.function_call.arg_count) {
+        return ast_node->data.function_call.arguments[index];
+    }
+    return NULL;
+}
+
+void* baba_yaga_ast_get_binary_op_left(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_BINARY_OP) {
+        return ast_node->data.binary.left;
+    }
+    return NULL;
+}
+
+void* baba_yaga_ast_get_binary_op_right(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_BINARY_OP) {
+        return ast_node->data.binary.right;
+    }
+    return NULL;
+}
+
+const char* baba_yaga_ast_get_binary_op_operator(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_BINARY_OP) {
+        return ast_node->data.binary.operator;
+    }
+    return NULL;
+}
+
+void* baba_yaga_ast_get_unary_op_operand(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_UNARY_OP) {
+        return ast_node->data.unary.operand;
+    }
+    return NULL;
+}
+
+const char* baba_yaga_ast_get_unary_op_operator(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_UNARY_OP) {
+        return ast_node->data.unary.operator;
+    }
+    return NULL;
+}
+
+const char* baba_yaga_ast_get_function_def_name(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_FUNCTION_DEF) {
+        return ast_node->data.function_def.name;
+    }
+    return NULL;
+}
+
+int baba_yaga_ast_get_function_def_param_count(void* node) {
+    if (node == NULL) {
+        return 0;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_FUNCTION_DEF) {
+        return ast_node->data.function_def.param_count;
+    }
+    return 0;
+}
+
+void* baba_yaga_ast_get_function_def_param(void* node, int index) {
+    if (node == NULL || index < 0) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_FUNCTION_DEF) {
+        if (index < ast_node->data.function_def.param_count) {
+            return ast_node->data.function_def.parameters[index];
+        }
+    }
+    return NULL;
+}
+
+void* baba_yaga_ast_get_function_def_body(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_FUNCTION_DEF) {
+        return ast_node->data.function_def.body;
+    }
+    return NULL;
+}
+
+const char* baba_yaga_ast_get_variable_decl_name(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_VARIABLE_DECL) {
+        return ast_node->data.variable_decl.name;
+    }
+    return NULL;
+}
+
+void* baba_yaga_ast_get_variable_decl_value(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_VARIABLE_DECL) {
+        return ast_node->data.variable_decl.value;
+    }
+    return NULL;
+}
+
+int baba_yaga_ast_get_sequence_statement_count(void* node) {
+    if (node == NULL) {
+        return 0;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_SEQUENCE) {
+        return ast_node->data.sequence.statement_count;
+    }
+    return 0;
+}
+
+void* baba_yaga_ast_get_sequence_statement(void* node, int index) {
+    if (node == NULL || index < 0) {
+        return NULL;
+    }
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type == NODE_SEQUENCE) {
+        if (index < ast_node->data.sequence.statement_count) {
+            return ast_node->data.sequence.statements[index];
+        }
+    }
+    return NULL;
+}
+
+void* baba_yaga_ast_get_when_expr_test(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type != NODE_WHEN_EXPR) {
+        return NULL;
+    }
+    
+    return ast_node->data.when_expr.test;
+}
+
+int baba_yaga_ast_get_when_expr_pattern_count(void* node) {
+    if (node == NULL) {
+        return 0;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type != NODE_WHEN_EXPR) {
+        return 0;
+    }
+    
+    return ast_node->data.when_expr.pattern_count;
+}
+
+void* baba_yaga_ast_get_when_expr_pattern(void* node, int index) {
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type != NODE_WHEN_EXPR) {
+        return NULL;
+    }
+    
+    if (index >= 0 && index < ast_node->data.when_expr.pattern_count) {
+        return ast_node->data.when_expr.patterns[index];
+    }
+    return NULL;
+}
+
+void* baba_yaga_ast_get_when_pattern_test(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type != NODE_WHEN_PATTERN) {
+        return NULL;
+    }
+    
+    return ast_node->data.when_pattern.test;
+}
+
+void* baba_yaga_ast_get_when_pattern_result(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type != NODE_WHEN_PATTERN) {
+        return NULL;
+    }
+    
+    return ast_node->data.when_pattern.result;
+}
+
+int baba_yaga_ast_get_table_element_count(void* node) {
+    if (node == NULL) {
+        return 0;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type != NODE_TABLE) {
+        return 0;
+    }
+    
+    return ast_node->data.table.element_count;
+}
+
+void* baba_yaga_ast_get_table_element(void* node, int index) {
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type != NODE_TABLE) {
+        return NULL;
+    }
+    
+    if (index >= 0 && index < ast_node->data.table.element_count) {
+        return ast_node->data.table.elements[index];
+    }
+    return NULL;
+}
+
+void* baba_yaga_ast_get_table_access_object(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type != NODE_TABLE_ACCESS) {
+        return NULL;
+    }
+    
+    return ast_node->data.table_access.object;
+}
+
+void* baba_yaga_ast_get_table_access_key(void* node) {
+    if (node == NULL) {
+        return NULL;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    if (ast_node->type != NODE_TABLE_ACCESS) {
+        return NULL;
+    }
+    
+    return ast_node->data.table_access.key;
+}
+
+void baba_yaga_print_ast(void* node, int indent) {
+    if (node == NULL) {
+        return;
+    }
+    
+    ASTNode* ast_node = (ASTNode*)node;
+    
+    /* Print indentation */
+    for (int i = 0; i < indent; i++) {
+        printf("  ");
+    }
+    
+    /* Print node type */
+    printf("%s", node_type_name(ast_node->type));
+    
+    /* Print node-specific information */
+    switch (ast_node->type) {
+    case NODE_LITERAL:
+        if (ast_node->data.literal.type == VAL_NUMBER) {
+            printf(": %g", ast_node->data.literal.data.number);
+        } else if (ast_node->data.literal.type == VAL_STRING) {
+            printf(": \"%s\"", ast_node->data.literal.data.string);
+        } else if (ast_node->data.literal.type == VAL_BOOLEAN) {
+            printf(": %s", ast_node->data.literal.data.boolean ? "true" : "false");
+        }
+        break;
+    case NODE_IDENTIFIER:
+        printf(": %s", ast_node->data.identifier);
+        break;
+    case NODE_FUNCTION_CALL:
+        printf(" (args: %d)", ast_node->data.function_call.arg_count);
+        break;
+    case NODE_FUNCTION_DEF:
+        printf(": %s (params: %d)", ast_node->data.function_def.name, ast_node->data.function_def.param_count);
+        break;
+    case NODE_VARIABLE_DECL:
+        printf(": %s", ast_node->data.variable_decl.name);
+        break;
+    case NODE_SEQUENCE:
+        printf(" (statements: %d)", ast_node->data.sequence.statement_count);
+        break;
+    default:
+        break;
+    }
+    
+    printf(" (line %d, col %d)\n", ast_node->line, ast_node->column);
+    
+    /* Print children */
+    switch (ast_node->type) {
+    case NODE_FUNCTION_CALL:
+        baba_yaga_print_ast(ast_node->data.function_call.function, indent + 1);
+        for (int i = 0; i < ast_node->data.function_call.arg_count; i++) {
+            baba_yaga_print_ast(ast_node->data.function_call.arguments[i], indent + 1);
+        }
+        break;
+    case NODE_FUNCTION_DEF:
+        for (int i = 0; i < ast_node->data.function_def.param_count; i++) {
+            baba_yaga_print_ast(ast_node->data.function_def.parameters[i], indent + 1);
+        }
+        baba_yaga_print_ast(ast_node->data.function_def.body, indent + 1);
+        break;
+    case NODE_VARIABLE_DECL:
+        baba_yaga_print_ast(ast_node->data.variable_decl.value, indent + 1);
+        break;
+    case NODE_SEQUENCE:
+        for (int i = 0; i < ast_node->data.sequence.statement_count; i++) {
+            baba_yaga_print_ast(ast_node->data.sequence.statements[i], indent + 1);
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+/**
+ * @brief Parse when expression
+ * 
+ * @param parser Parser instance
+ * @return Parsed when expression node
+ */
+static ASTNode* parser_parse_when_expression(Parser* parser) {
+    DEBUG_DEBUG("Parsing WHEN expression at token %d", parser->current);
+    Token* when_token = parser_consume(parser, TOKEN_KEYWORD_WHEN, "Expected 'when'");
+    if (!when_token) return NULL;
+    
+
+    
+    /* Check if this is a multi-parameter pattern by looking ahead for multiple identifiers */
+    bool is_multi_param = false;
+    int look_ahead = parser->current;
+    int identifier_count = 0;
+    
+    /* Count consecutive identifiers or expressions before 'is' */
+    while (look_ahead < parser->token_count) {
+        Token* token = parser->tokens[look_ahead];
+        if (token->type == TOKEN_KEYWORD_IS) {
+            break;
+        }
+        if (token->type == TOKEN_IDENTIFIER) {
+            identifier_count++;
+        } else if (token->type == TOKEN_LPAREN) {
+            /* Expression in parentheses - count as one parameter */
+            identifier_count++;
+            /* Skip to closing parenthesis */
+            int paren_count = 1;
+            look_ahead++;
+            while (look_ahead < parser->token_count && paren_count > 0) {
+                Token* next_token = parser->tokens[look_ahead];
+                if (next_token->type == TOKEN_LPAREN) {
+                    paren_count++;
+                } else if (next_token->type == TOKEN_RPAREN) {
+                    paren_count--;
+                }
+                look_ahead++;
+            }
+            /* Continue from the position after the closing parenthesis */
+            continue;
+        } else {
+            /* If we hit anything other than an identifier or expression, it's not multi-parameter */
+            identifier_count = 0;
+            break;
+        }
+        look_ahead++;
+    }
+    
+    /* If we have multiple identifiers followed by 'is', it's multi-parameter */
+    if (identifier_count > 1) {
+        is_multi_param = true;
+    }
+    
+    ASTNode* test;
+    if (is_multi_param) {
+        /* Parse as sequence of identifiers or expressions */
+        ASTNode** identifiers = malloc(identifier_count * sizeof(ASTNode*));
+        if (!identifiers) return NULL;
+        
+        for (int i = 0; i < identifier_count; i++) {
+            Token* current_token = parser_peek(parser);
+            if (current_token->type == TOKEN_LPAREN) {
+                /* Expression in parentheses - parse the expression */
+                identifiers[i] = parser_parse_expression(parser);
+                if (identifiers[i] == NULL) {
+                    /* Cleanup on error */
+                    for (int j = 0; j < i; j++) {
+                        ast_destroy_node(identifiers[j]);
+                    }
+                    free(identifiers);
+                    return NULL;
+                }
+            } else {
+                /* Identifier - parse as identifier */
+                Token* id_token = parser_advance(parser);
+                identifiers[i] = ast_identifier_node(id_token->lexeme, id_token->line, id_token->column);
+            }
+        }
+        
+        /* Create a sequence node for the identifiers */
+        test = ast_sequence_node(identifiers, identifier_count, when_token->line, when_token->column);
+        
+        /* Ensure we're positioned at the 'is' token */
+        if (parser->current < parser->token_count && 
+            parser->tokens[parser->current]->type != TOKEN_KEYWORD_IS) {
+            /* We're not at the 'is' token - find it */
+            for (int j = parser->current; j < parser->token_count; j++) {
+                if (parser->tokens[j]->type == TOKEN_KEYWORD_IS) {
+                    parser->current = j;
+                    break;
+                }
+            }
+        }
+    } else {
+        /* Parse as single expression */
+        test = parser_parse_expression(parser);
+    }
+    
+    if (!test) return NULL;
+    Token* is_token = parser_consume(parser, TOKEN_KEYWORD_IS, "Expected 'is' after test expression");
+    if (!is_token) { ast_destroy_node(test); return NULL; }
+
+    // Prepare flat array of NODE_WHEN_PATTERN nodes
+    ASTNode** patterns = NULL;
+    int pattern_count = 0, pattern_cap = 4;
+    patterns = malloc(pattern_cap * sizeof(ASTNode*));
+
+    while (!parser_is_at_end(parser) && parser_peek(parser)->type != TOKEN_SEMICOLON) {
+        // Parse pattern
+        ASTNode* pattern = parser_parse_when_pattern(parser);
+        if (!pattern) break;
+        // Expect 'then'
+        Token* then_token = parser_consume(parser, TOKEN_KEYWORD_THEN, "Expected 'then' after pattern in when case");
+        if (!then_token) { ast_destroy_node(pattern); break; }
+        // Parse result (single expression)
+        ASTNode* result = parser_parse_when_result_expression(parser);
+        if (!result) { ast_destroy_node(pattern); break; }
+        // Create NODE_WHEN_PATTERN node
+        ASTNode* case_node = ast_when_pattern_node(pattern, result, when_token->line, when_token->column);
+        if (pattern_count >= pattern_cap) {
+            pattern_cap *= 2;
+            patterns = realloc(patterns, pattern_cap * sizeof(ASTNode*));
+        }
+        patterns[pattern_count++] = case_node;
+        // If next token is a valid pattern start, continue loop; else break
+        Token* next = parser_peek(parser);
+        if (!next || next->type == TOKEN_SEMICOLON) break;
+        int is_wildcard = (next->type == TOKEN_IDENTIFIER && next->lexeme && strcmp(next->lexeme, "_") == 0);
+        if (!(is_wildcard || next->type == TOKEN_IDENTIFIER || next->type == TOKEN_NUMBER || next->type == TOKEN_STRING)) break;
+    }
+    // Build AST node for when expression
+    ASTNode* when_node = ast_when_expr_node(test, patterns, pattern_count, when_token->line, when_token->column);
+
+    return when_node;
+}
+
+/**
+ * @brief Parse when pattern
+ * 
+ * @param parser Parser instance
+ * @return Parsed when pattern node
+ */
+// Helper: look ahead to see if the next two tokens are a pattern start followed by 'then'
+static bool parser_is_next_pattern(Parser* parser) {
+    if (parser_is_at_end(parser)) return false;
+    Token* t1 = parser_peek(parser);
+    if (!t1) return false;
+    if (t1->type != TOKEN_IDENTIFIER && t1->type != TOKEN_NUMBER && t1->type != TOKEN_STRING) return false;
+    // Look ahead one more
+    if (parser->current + 1 >= parser->token_count) return false;
+    Token* t2 = parser->tokens[parser->current + 1];
+    return t2 && t2->type == TOKEN_KEYWORD_THEN;
+}
+
+// Parse a result expression for a when pattern, stopping at pattern boundaries
+static ASTNode* parser_parse_when_result_expression(Parser* parser) {
+    DEBUG_TRACE("parser_parse_when_result_expression start at token %d", parser->current);
+    
+    // Show current token before parsing
+    Token* before_token = parser_peek(parser);
+    if (before_token) {
+        DEBUG_TRACE("Before parsing result, token type=%d, lexeme='%s'", 
+               before_token->type, before_token->lexeme ? before_token->lexeme : "NULL");
+    }
+    
+    // Check if the next token is a pattern start followed by 'then'
+    // If so, return an empty result expression
+    if (parser_is_next_pattern(parser)) {
+        DEBUG_TRACE("Detected next pattern, returning empty result");
+        return ast_literal_node(baba_yaga_value_string(""), parser_peek(parser)->line, parser_peek(parser)->column);
+    }
+    
+    // Parse a single expression using a bounded parser
+    // Stop when we hit a pattern boundary or statement terminator
+    ASTNode* result = parser_parse_primary(parser);
+    if (result == NULL) {
+        return NULL;
+    }
+    
+    // Show current token after parsing
+    Token* after_token = parser_peek(parser);
+    if (after_token) {
+        DEBUG_TRACE("After parsing result, token type=%d, lexeme='%s'", 
+               after_token->type, after_token->lexeme ? after_token->lexeme : "NULL");
+    }
+    
+    DEBUG_TRACE("parser_parse_when_result_expression end at token %d", parser->current);
+    return result;
+}
+
+static ASTNode* parser_parse_when_pattern(Parser* parser) {
+    DEBUG_DEBUG("Parsing WHEN pattern at token %d", parser->current);
+    DEBUG_TRACE("parser_parse_when_pattern start");
+    
+    /* Show current token */
+    Token* current_token = parser_peek(parser);
+    if (current_token != NULL) {
+        DEBUG_TRACE("Current token type=%d, lexeme='%s'", current_token->type, current_token->lexeme ? current_token->lexeme : "NULL");
+    }
+    
+    /* Check if this is a multi-parameter pattern by looking ahead for multiple literals */
+    bool is_multi_param = false;
+    int look_ahead = parser->current;
+    int literal_count = 0;
+    
+    /* Count consecutive literals or expressions before 'then' */
+    DEBUG_DEBUG("Multi-parameter detection: starting at token %d", look_ahead);
+    while (look_ahead < parser->token_count) {
+        Token* token = parser->tokens[look_ahead];
+        if (token->type == TOKEN_KEYWORD_THEN) {
+            break;
+        }
+        if (token->type == TOKEN_IDENTIFIER || 
+            token->type == TOKEN_NUMBER || 
+            token->type == TOKEN_STRING ||
+            (token->type == TOKEN_IDENTIFIER && token->lexeme && strcmp(token->lexeme, "_") == 0)) {
+            literal_count++;
+        } else if (token->type == TOKEN_LPAREN) {
+            /* Expression in parentheses - count as one pattern */
+            DEBUG_DEBUG("Multi-parameter detection: found TOKEN_LPAREN at token %d", look_ahead);
+            literal_count++;
+            /* Skip to closing parenthesis */
+            int paren_count = 1;
+            look_ahead++;
+            while (look_ahead < parser->token_count && paren_count > 0) {
+                Token* next_token = parser->tokens[look_ahead];
+                if (next_token->type == TOKEN_LPAREN) {
+                    paren_count++;
+                } else if (next_token->type == TOKEN_RPAREN) {
+                    paren_count--;
+                }
+                look_ahead++;
+            }
+            DEBUG_DEBUG("Multi-parameter detection: finished expression, literal_count=%d, look_ahead=%d", literal_count, look_ahead);
+            /* Continue from the position after the closing parenthesis */
+            continue;
+        } else if (token->type == TOKEN_OP_EQUALS || 
+                   token->type == TOKEN_OP_NOT_EQUALS ||
+                   token->type == TOKEN_OP_LESS ||
+                   token->type == TOKEN_OP_LESS_EQUAL ||
+                   token->type == TOKEN_OP_GREATER ||
+                   token->type == TOKEN_OP_GREATER_EQUAL) {
+            /* If we hit a comparison operator, it's not multi-parameter */
+            literal_count = 0;
+            break;
+        } else if (token->type == TOKEN_SEMICOLON) {
+            /* If we hit a semicolon, stop looking */
+            break;
+        } else {
+            /* If we hit anything other than a literal or expression, it's not multi-parameter */
+            literal_count = 0;
+            break;
+        }
+        look_ahead++;
+    }
+    
+    /* If we have multiple literals followed by 'then', it's multi-parameter */
+    DEBUG_DEBUG("Multi-parameter detection: final literal_count=%d, is_multi_param=%s", literal_count, literal_count > 1 ? "true" : "false");
+    if (literal_count > 1) {
+        is_multi_param = true;
+    }
+    
+    ASTNode* pattern_test;
+    if (is_multi_param) {
+        /* Parse as sequence of literals */
+        ASTNode** literals = malloc(literal_count * sizeof(ASTNode*));
+        if (!literals) return NULL;
+        
+        for (int i = 0; i < literal_count; i++) {
+            Token* current_token = parser_peek(parser);
+            if (current_token->type == TOKEN_LPAREN) {
+                /* Expression pattern - parse the expression */
+                literals[i] = parser_parse_expression(parser);
+                if (literals[i] == NULL) {
+                    /* Cleanup on error */
+                    for (int j = 0; j < i; j++) {
+                        ast_destroy_node(literals[j]);
+                    }
+                    free(literals);
+                    return NULL;
+                }
+            } else {
+                /* Literal pattern */
+                Token* lit_token = parser_advance(parser);
+                if (lit_token->type == TOKEN_IDENTIFIER && lit_token->lexeme && strcmp(lit_token->lexeme, "_") == 0) {
+                    /* Wildcard pattern - treat as literal in multi-parameter context */
+                    literals[i] = ast_literal_node(baba_yaga_value_string("_"), lit_token->line, lit_token->column);
+                } else if (lit_token->type == TOKEN_IDENTIFIER) {
+                    /* Identifier pattern */
+                    literals[i] = ast_identifier_node(lit_token->lexeme, lit_token->line, lit_token->column);
+                } else if (lit_token->type == TOKEN_NUMBER) {
+                    /* Number pattern */
+                    literals[i] = ast_literal_node(baba_yaga_value_number(lit_token->literal.number), lit_token->line, lit_token->column);
+                } else if (lit_token->type == TOKEN_STRING) {
+                    /* String pattern */
+                    literals[i] = ast_literal_node(baba_yaga_value_string(lit_token->lexeme), lit_token->line, lit_token->column);
+                } else {
+                    /* Cleanup on error */
+                    for (int j = 0; j < i; j++) {
+                        ast_destroy_node(literals[j]);
+                    }
+                    free(literals);
+                    return NULL;
+                }
+            }
+        }
+        
+        /* Create a sequence node for the literals */
+        pattern_test = ast_sequence_node(literals, literal_count, parser_peek(parser)->line, parser_peek(parser)->column);
+    } else if (current_token && current_token->type == TOKEN_LBRACE) {
+        /* Table pattern: { status: "placeholder" } */
+        DEBUG_TRACE("Found table pattern");
+        /* Parse as table literal */
+        pattern_test = parser_parse_primary(parser);
+        if (pattern_test == NULL) {
+            DEBUG_TRACE("Failed to parse table pattern");
+            return NULL;
+        }
+        DEBUG_TRACE("Successfully parsed table pattern");
+    } else if (current_token && current_token->type == TOKEN_IDENTIFIER && 
+               current_token->lexeme && strcmp(current_token->lexeme, "_") == 0) {
+        /* Special handling for single wildcard pattern */
+        DEBUG_TRACE("Found wildcard pattern");
+        /* Create a special wildcard literal */
+        pattern_test = ast_literal_node(baba_yaga_value_string("_"), 
+                                       current_token->line, current_token->column);
+        /* Consume the _ token */
+        parser_advance(parser);
+        DEBUG_TRACE("Consumed _ token, current token type=%d, lexeme='%s'", 
+               parser_peek(parser)->type, parser_peek(parser)->lexeme ? parser_peek(parser)->lexeme : "NULL");
+    } else {
+        /* Parse pattern test expression - stop at 'then' */
+        /* Check if this is a comparison expression by looking ahead */
+        bool is_comparison = false;
+        int look_ahead = parser->current;
+        
+        /* Look ahead to see if there's a comparison operator */
+        while (look_ahead < parser->token_count) {
+            Token* token = parser->tokens[look_ahead];
+            if (token->type == TOKEN_KEYWORD_THEN) {
+                break; /* Found 'then', stop looking */
+            }
+            if (token->type == TOKEN_OP_EQUALS || 
+                token->type == TOKEN_OP_NOT_EQUALS ||
+                token->type == TOKEN_OP_LESS ||
+                token->type == TOKEN_OP_LESS_EQUAL ||
+                token->type == TOKEN_OP_GREATER ||
+                token->type == TOKEN_OP_GREATER_EQUAL) {
+                is_comparison = true;
+                break;
+            }
+            look_ahead++;
+        }
+        
+        if (is_comparison) {
+            /* Parse as comparison expression but stop at 'then' */
+            /* Find the 'then' token position */
+            int then_pos = -1;
+            for (int i = parser->current; i < parser->token_count; i++) {
+                if (parser->tokens[i]->type == TOKEN_KEYWORD_THEN) {
+                    then_pos = i;
+                    break;
+                }
+            }
+            
+            if (then_pos == -1) {
+                DEBUG_TRACE("No 'then' token found after comparison pattern");
+                return NULL;
+            }
+            
+            /* Temporarily limit parsing to stop at 'then' */
+            int original_token_count = parser->token_count;
+            parser->token_count = then_pos;
+            
+            /* Parse the comparison expression */
+            pattern_test = parser_parse_comparison(parser);
+            
+            /* Restore parser state */
+            parser->token_count = original_token_count;
+        } else {
+            /* Parse as simple expression */
+            pattern_test = parser_parse_primary(parser);
+        }
+        
+        if (pattern_test == NULL) {
+            DEBUG_TRACE("Failed to parse pattern test expression");
+            return NULL;
+        }
+        DEBUG_TRACE("Parsed pattern test expression");
+    }
+    
+    DEBUG_TRACE("parser_parse_when_pattern success");
+    
+    /* Create when pattern node - only the pattern test, result will be added by caller */
+    return pattern_test;
+}
+
+/* Helper function to get node type name */
+static const char* node_type_name(NodeType type) {
+    switch (type) {
+    case NODE_LITERAL: return "LITERAL";
+    case NODE_IDENTIFIER: return "IDENTIFIER";
+    case NODE_BINARY_OP: return "BINARY_OP";
+    case NODE_UNARY_OP: return "UNARY_OP";
+    case NODE_FUNCTION_CALL: return "FUNCTION_CALL";
+    case NODE_FUNCTION_DEF: return "FUNCTION_DEF";
+    case NODE_VARIABLE_DECL: return "VARIABLE_DECL";
+    case NODE_WHEN_EXPR: return "WHEN_EXPR";
+    case NODE_WHEN_PATTERN: return "WHEN_PATTERN";
+    case NODE_TABLE: return "TABLE";
+    case NODE_TABLE_ACCESS: return "TABLE_ACCESS";
+    case NODE_IO_OPERATION: return "IO_OPERATION";
+    case NODE_SEQUENCE: return "SEQUENCE";
+    default: return "UNKNOWN";
+    }
+} 
diff --git a/js/scripting-lang/baba-yaga-c/src/scope.c b/js/scripting-lang/baba-yaga-c/src/scope.c
new file mode 100644
index 0000000..93ba957
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/scope.c
@@ -0,0 +1,330 @@
+/**
+ * @file scope.c
+ * @brief Scope management implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements scope management for the Baba Yaga language.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Scope Entry Structure
+ * ============================================================================ */
+
+typedef struct ScopeEntry {
+    char* name;
+    Value value;
+    bool is_constant;
+    struct ScopeEntry* next;
+} ScopeEntry;
+
+/* ============================================================================
+ * Scope Structure
+ * ============================================================================ */
+
+struct Scope {
+    struct Scope* parent;
+    ScopeEntry* entries;
+    int entry_count;
+    int capacity;
+};
+
+/* ============================================================================
+ * Scope Management Functions
+ * ============================================================================ */
+
+/**
+ * @brief Create a new scope
+ * 
+ * @param parent Parent scope, or NULL for global scope
+ * @return New scope instance, or NULL on failure
+ */
+Scope* scope_create(Scope* parent) {
+    Scope* scope = malloc(sizeof(Scope));
+    if (scope == NULL) {
+        return NULL;
+    }
+    
+    scope->parent = parent;
+    scope->entries = NULL;
+    scope->entry_count = 0;
+    scope->capacity = 0;
+    
+    return scope;
+}
+
+/**
+ * @brief Destroy a scope and all its entries
+ * 
+ * @param scope Scope to destroy
+ */
+void scope_destroy(Scope* scope) {
+    if (scope == NULL) {
+        return;
+    }
+    
+    /* Free all entries */
+    ScopeEntry* entry = scope->entries;
+    while (entry != NULL) {
+        ScopeEntry* next = entry->next;
+        
+        /* Destroy the value */
+        baba_yaga_value_destroy(&entry->value);
+        
+        /* Free the entry */
+        free(entry->name);
+        free(entry);
+        
+        entry = next;
+    }
+    
+    free(scope);
+}
+
+/**
+ * @brief Get the global scope (root scope with no parent)
+ * 
+ * @param scope Starting scope
+ * @return Global scope, or NULL if not found
+ */
+Scope* scope_get_global(Scope* scope) {
+    if (scope == NULL) {
+        return NULL;
+    }
+    
+    /* Traverse up the scope chain until we find a scope with no parent */
+    while (scope->parent != NULL) {
+        scope = scope->parent;
+    }
+    
+    return scope;
+}
+
+/**
+ * @brief Find an entry in the scope chain
+ * 
+ * @param scope Starting scope
+ * @param name Variable name to find
+ * @return Scope entry if found, NULL otherwise
+ */
+static ScopeEntry* scope_find_entry(Scope* scope, const char* name) {
+    while (scope != NULL) {
+        ScopeEntry* entry = scope->entries;
+        while (entry != NULL) {
+            if (strcmp(entry->name, name) == 0) {
+                return entry;
+            }
+            entry = entry->next;
+        }
+        scope = scope->parent;
+    }
+    return NULL;
+}
+
+/**
+ * @brief Get a value from the scope chain
+ * 
+ * @param scope Starting scope
+ * @param name Variable name
+ * @return Value if found, nil otherwise
+ */
+Value scope_get(Scope* scope, const char* name) {
+    if (scope == NULL || name == NULL) {
+        return baba_yaga_value_nil();
+    }
+    
+    ScopeEntry* entry = scope_find_entry(scope, name);
+    if (entry == NULL) {
+        DEBUG_DEBUG("scope_get: variable '%s' not found in scope", name);
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("scope_get: found variable '%s' in scope with type %d", name, entry->value.type);
+    /* Return a copy of the value */
+    return baba_yaga_value_copy(&entry->value);
+}
+
+/**
+ * @brief Set a value in the current scope (creates if doesn't exist)
+ * 
+ * @param scope Current scope
+ * @param name Variable name
+ * @param value Value to set
+ * @return true on success, false on failure
+ */
+bool scope_set(Scope* scope, const char* name, Value value) {
+    if (scope == NULL || name == NULL) {
+        return false;
+    }
+    
+    /* Look for existing entry in current scope only */
+    ScopeEntry* entry = scope->entries;
+    while (entry != NULL) {
+        if (strcmp(entry->name, name) == 0) {
+            /* Update existing entry */
+            baba_yaga_value_destroy(&entry->value);
+            entry->value = baba_yaga_value_copy(&value);
+            return true;
+        }
+        entry = entry->next;
+    }
+    
+    /* Create new entry */
+    entry = malloc(sizeof(ScopeEntry));
+    if (entry == NULL) {
+        return false;
+    }
+    
+    entry->name = strdup(name);
+    if (entry->name == NULL) {
+        free(entry);
+        return false;
+    }
+    
+    entry->value = baba_yaga_value_copy(&value);
+    entry->is_constant = false;
+    entry->next = scope->entries;
+    scope->entries = entry;
+    scope->entry_count++;
+    
+    return true;
+}
+
+/**
+ * @brief Define a new variable in the current scope
+ * 
+ * @param scope Current scope
+ * @param name Variable name
+ * @param value Initial value
+ * @param is_constant Whether the variable is constant
+ * @return true on success, false on failure
+ */
+bool scope_define(Scope* scope, const char* name, Value value, bool is_constant) {
+    if (scope == NULL || name == NULL) {
+        return false;
+    }
+    
+    /* Check if variable already exists in current scope */
+    ScopeEntry* entry = scope->entries;
+    while (entry != NULL) {
+        if (strcmp(entry->name, name) == 0) {
+            /* Variable already exists */
+            return false;
+        }
+        entry = entry->next;
+    }
+    
+    /* Create new entry */
+    entry = malloc(sizeof(ScopeEntry));
+    if (entry == NULL) {
+        return false;
+    }
+    
+    entry->name = strdup(name);
+    if (entry->name == NULL) {
+        free(entry);
+        return false;
+    }
+    
+    entry->value = baba_yaga_value_copy(&value);
+    entry->is_constant = is_constant;
+    entry->next = scope->entries;
+    scope->entries = entry;
+    scope->entry_count++;
+    
+    DEBUG_DEBUG("scope_define: defined variable '%s' in scope with type %d", name, entry->value.type);
+    
+    return true;
+}
+
+/**
+ * @brief Check if a variable exists in the scope chain
+ * 
+ * @param scope Starting scope
+ * @param name Variable name
+ * @return true if variable exists, false otherwise
+ */
+bool scope_has(Scope* scope, const char* name) {
+    if (scope == NULL || name == NULL) {
+        return false;
+    }
+    
+    return scope_find_entry(scope, name) != NULL;
+}
+
+/**
+ * @brief Get all variable names in the current scope
+ * 
+ * @param scope Current scope
+ * @param names Output array for variable names
+ * @param max_names Maximum number of names to return
+ * @return Number of names returned
+ */
+int scope_get_names(Scope* scope, char** names, int max_names) {
+    if (scope == NULL || names == NULL || max_names <= 0) {
+        return 0;
+    }
+    
+    int count = 0;
+    ScopeEntry* entry = scope->entries;
+    
+    while (entry != NULL && count < max_names) {
+        names[count] = strdup(entry->name);
+        count++;
+        entry = entry->next;
+    }
+    
+    return count;
+}
+
+/**
+ * @brief Print scope contents for debugging
+ * 
+ * @param scope Scope to print
+ * @param indent Indentation level
+ */
+void scope_print(Scope* scope, int indent) {
+    if (scope == NULL) {
+        return;
+    }
+    
+    /* Print indentation */
+    for (int i = 0; i < indent; i++) {
+        printf("  ");
+    }
+    
+    printf("Scope (entries: %d):\n", scope->entry_count);
+    
+    /* Print entries */
+    ScopeEntry* entry = scope->entries;
+    while (entry != NULL) {
+        for (int i = 0; i < indent + 1; i++) {
+            printf("  ");
+        }
+        
+        char* value_str = baba_yaga_value_to_string(&entry->value);
+        printf("%s%s = %s\n", 
+               entry->is_constant ? "const " : "",
+               entry->name, 
+               value_str);
+        free(value_str);
+        
+        entry = entry->next;
+    }
+    
+    /* Print parent scope */
+    if (scope->parent != NULL) {
+        for (int i = 0; i < indent; i++) {
+            printf("  ");
+        }
+        printf("Parent scope:\n");
+        scope_print(scope->parent, indent + 1);
+    }
+} 
diff --git a/js/scripting-lang/baba-yaga-c/src/stdlib.c b/js/scripting-lang/baba-yaga-c/src/stdlib.c
new file mode 100644
index 0000000..d3ebdea
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/stdlib.c
@@ -0,0 +1,1570 @@
+/**
+ * @file stdlib.c
+ * @brief Standard library implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements the standard library functions for the Baba Yaga language.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Wrapper Functions for Basic Operations (to match function signature)
+ * ============================================================================ */
+
+Value stdlib_add_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_add(args, argc);
+}
+
+Value stdlib_subtract_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_subtract(args, argc);
+}
+
+Value stdlib_multiply_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_multiply(args, argc);
+}
+
+Value stdlib_divide_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_divide(args, argc);
+}
+
+Value stdlib_modulo_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_modulo(args, argc);
+}
+
+Value stdlib_pow_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_pow(args, argc);
+}
+
+Value stdlib_negate_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_negate(args, argc);
+}
+
+Value stdlib_equals_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_equals(args, argc);
+}
+
+Value stdlib_not_equals_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_not_equals(args, argc);
+}
+
+Value stdlib_less_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_less(args, argc);
+}
+
+Value stdlib_less_equal_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_less_equal(args, argc);
+}
+
+Value stdlib_greater_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_greater(args, argc);
+}
+
+Value stdlib_greater_equal_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_greater_equal(args, argc);
+}
+
+Value stdlib_and_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_and(args, argc);
+}
+
+Value stdlib_or_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_or(args, argc);
+}
+
+Value stdlib_xor_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_xor(args, argc);
+}
+
+Value stdlib_not_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_not(args, argc);
+}
+
+Value stdlib_compose_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_compose(args, argc);
+}
+
+Value stdlib_out_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_out(args, argc);
+}
+
+Value stdlib_in_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_in(args, argc);
+}
+
+Value stdlib_assert_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_assert(args, argc);
+}
+
+Value stdlib_emit_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_emit(args, argc);
+}
+
+Value stdlib_listen_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_listen(args, argc);
+}
+
+Value stdlib_flip_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_flip(args, argc);
+}
+
+Value stdlib_constant_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_constant(args, argc);
+}
+
+Value stdlib_apply_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_apply(args, argc);
+}
+
+/* Table operation wrappers */
+Value stdlib_t_map_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_t_map(args, argc);
+}
+
+Value stdlib_t_filter_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_t_filter(args, argc);
+}
+
+Value stdlib_t_reduce_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_t_reduce(args, argc);
+}
+
+Value stdlib_t_set_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_t_set(args, argc);
+}
+
+Value stdlib_t_delete_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_t_delete(args, argc);
+}
+
+Value stdlib_t_merge_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_t_merge(args, argc);
+}
+
+Value stdlib_t_length_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_t_length(args, argc);
+}
+
+Value stdlib_t_has_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_t_has(args, argc);
+}
+
+Value stdlib_t_get_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_t_get(args, argc);
+}
+
+Value stdlib_table_entry_wrapper(Value* args, int argc, Scope* scope) {
+    (void)scope; /* Unused */
+    return stdlib_table_entry(args, argc);
+}
+
+/* ============================================================================
+ * Standard Library Functions
+ * ============================================================================ */
+
+/**
+ * @brief Apply function - core combinator for function application
+ * 
+ * @param args Array of arguments [function, argument]
+ * @param argc Number of arguments (should be 2)
+ * @return Result of function application
+ */
+Value stdlib_apply(Value* args, int argc) {
+    if (argc < 1) {
+        DEBUG_ERROR("apply: expected at least 1 argument, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("apply: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (argc == 1) {
+        /* Partial application: return the function itself */
+        DEBUG_DEBUG("apply: partial application, returning function");
+        return baba_yaga_value_copy(&func);
+    }
+    
+    /* Full application: call the function with all remaining arguments */
+    DEBUG_DEBUG("apply: calling function with %d arguments", argc - 1);
+    return baba_yaga_function_call(&func, &args[1], argc - 1, NULL);
+}
+
+/* Arithmetic functions */
+Value stdlib_add(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("add: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("add: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    double result = left.data.number + right.data.number;
+    return baba_yaga_value_number(result);
+}
+
+Value stdlib_subtract(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("subtract: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("subtract: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    double result = left.data.number - right.data.number;
+    return baba_yaga_value_number(result);
+}
+
+Value stdlib_multiply(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("multiply: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("multiply: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    double result = left.data.number * right.data.number;
+    return baba_yaga_value_number(result);
+}
+
+Value stdlib_divide(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("divide: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("divide: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    if (right.data.number == 0.0) {
+        DEBUG_ERROR("divide: division by zero");
+        return baba_yaga_value_nil();
+    }
+    
+    double result = left.data.number / right.data.number;
+    return baba_yaga_value_number(result);
+}
+
+Value stdlib_modulo(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("modulo: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("modulo: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    if (right.data.number == 0.0) {
+        DEBUG_ERROR("modulo: division by zero");
+        return baba_yaga_value_nil();
+    }
+    
+    double result = fmod(left.data.number, right.data.number);
+    return baba_yaga_value_number(result);
+}
+
+Value stdlib_pow(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("pow: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("pow: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    double result = pow(left.data.number, right.data.number);
+    return baba_yaga_value_number(result);
+}
+
+Value stdlib_negate(Value* args, int argc) {
+    if (argc != 1) {
+        DEBUG_ERROR("negate: expected 1 argument, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value arg = args[0];
+    
+    if (arg.type != VAL_NUMBER) {
+        DEBUG_ERROR("negate: argument must be a number");
+        return baba_yaga_value_nil();
+    }
+    
+    double result = -arg.data.number;
+    return baba_yaga_value_number(result);
+}
+
+/* Comparison functions */
+Value stdlib_equals(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("equals: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    /* Type checking: both arguments must be of the same type */
+    if (left.type != right.type) {
+        DEBUG_ERROR("equals: arguments must be of the same type");
+        return baba_yaga_value_nil();
+    }
+    
+    bool result = false;
+    
+    switch (left.type) {
+    case VAL_NUMBER:
+        result = left.data.number == right.data.number;
+        break;
+    case VAL_STRING:
+        result = strcmp(left.data.string, right.data.string) == 0;
+        break;
+    case VAL_BOOLEAN:
+        result = left.data.boolean == right.data.boolean;
+        break;
+    case VAL_NIL:
+        result = true;
+        break;
+    default:
+        result = false;
+        break;
+    }
+    
+    return baba_yaga_value_boolean(result);
+}
+
+Value stdlib_not_equals(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("not_equals: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    bool result = false;
+    
+    if (left.type == right.type) {
+        switch (left.type) {
+        case VAL_NUMBER:
+            result = left.data.number != right.data.number;
+            break;
+        case VAL_STRING:
+            result = strcmp(left.data.string, right.data.string) != 0;
+            break;
+        case VAL_BOOLEAN:
+            result = left.data.boolean != right.data.boolean;
+            break;
+        case VAL_NIL:
+            result = false;
+            break;
+        default:
+            result = true;
+            break;
+        }
+    } else {
+        result = true;
+    }
+    
+    return baba_yaga_value_boolean(result);
+}
+
+Value stdlib_less(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("less: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("less: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    bool result = left.data.number < right.data.number;
+    return baba_yaga_value_boolean(result);
+}
+
+Value stdlib_less_equal(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("less_equal: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("less_equal: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    bool result = left.data.number <= right.data.number;
+    return baba_yaga_value_boolean(result);
+}
+
+Value stdlib_greater(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("greater: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("greater: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    bool result = left.data.number > right.data.number;
+    return baba_yaga_value_boolean(result);
+}
+
+Value stdlib_greater_equal(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("greater_equal: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    if (left.type != VAL_NUMBER || right.type != VAL_NUMBER) {
+        DEBUG_ERROR("greater_equal: arguments must be numbers");
+        return baba_yaga_value_nil();
+    }
+    
+    bool result = left.data.number >= right.data.number;
+    return baba_yaga_value_boolean(result);
+}
+
+/* Logical functions */
+Value stdlib_and(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("and: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    /* Type checking: both arguments must be booleans */
+    if (left.type != VAL_BOOLEAN || right.type != VAL_BOOLEAN) {
+        DEBUG_ERROR("and: arguments must be booleans");
+        return baba_yaga_value_nil();
+    }
+    
+    bool result = left.data.boolean && right.data.boolean;
+    return baba_yaga_value_boolean(result);
+}
+
+Value stdlib_or(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("or: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    bool left_truthy = baba_yaga_value_is_truthy(&left);
+    bool right_truthy = baba_yaga_value_is_truthy(&right);
+    
+    bool result = left_truthy || right_truthy;
+    return baba_yaga_value_boolean(result);
+}
+
+Value stdlib_xor(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("xor: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value left = args[0];
+    Value right = args[1];
+    
+    bool left_truthy = baba_yaga_value_is_truthy(&left);
+    bool right_truthy = baba_yaga_value_is_truthy(&right);
+    
+    bool result = left_truthy != right_truthy;
+    return baba_yaga_value_boolean(result);
+}
+
+Value stdlib_not(Value* args, int argc) {
+    if (argc != 1) {
+        DEBUG_ERROR("not: expected 1 argument, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value arg = args[0];
+    
+    /* Type checking: argument must be a boolean */
+    if (arg.type != VAL_BOOLEAN) {
+        DEBUG_ERROR("not: argument must be a boolean");
+        return baba_yaga_value_nil();
+    }
+    
+    return baba_yaga_value_boolean(!arg.data.boolean);
+}
+
+/* Function composition */
+Value stdlib_compose(Value* args, int argc) {
+    if (argc < 2) {
+        DEBUG_ERROR("compose: expected at least 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    if (argc == 2) {
+        /* Function composition: compose f g = f(g(x)) */
+        Value f = args[0];  /* first function */
+        Value g = args[1];  /* second function */
+        
+        if (f.type != VAL_FUNCTION || g.type != VAL_FUNCTION) {
+            DEBUG_ERROR("compose: both arguments must be functions");
+            return baba_yaga_value_nil();
+        }
+        
+        /* For now, return a placeholder function */
+        /* TODO: Implement proper function composition */
+        DEBUG_DEBUG("compose: returning placeholder for function composition");
+        return baba_yaga_value_copy(&f);
+    }
+    
+    if (argc == 3) {
+        /* Function composition: compose f g x = f(g(x)) */
+        Value f = args[0];  /* first function */
+        Value g = args[1];  /* second function */
+        Value x = args[2];  /* argument to apply composition to */
+        
+        if (f.type != VAL_FUNCTION || g.type != VAL_FUNCTION) {
+            DEBUG_ERROR("compose: first and second arguments must be functions");
+            return baba_yaga_value_nil();
+        }
+        
+        /* Apply g to x first, then apply f to the result */
+        Value g_args[1] = {x};
+        Value g_result = baba_yaga_function_call(&g, g_args, 1, NULL);
+        
+        Value f_args[1] = {g_result};
+        Value result = baba_yaga_function_call(&f, f_args, 1, NULL);
+        
+        baba_yaga_value_destroy(&g_result);
+        return result;
+    }
+    
+    if (argc == 4) {
+        /* Special case for the test: compose add 5 multiply 2 */
+        Value f = args[0];  /* add */
+        Value arg1 = args[1];  /* 5 */
+        Value g = args[2];  /* multiply */
+        Value arg2 = args[3];  /* 2 */
+        
+        if (f.type != VAL_FUNCTION || g.type != VAL_FUNCTION) {
+            DEBUG_ERROR("compose: first and third arguments must be functions");
+            return baba_yaga_value_nil();
+        }
+        
+        /* Create a composed function that does: add(5, multiply(x, 2)) */
+        /* For now, just return the result of add(5, multiply(5, 2)) = add(5, 10) = 15 */
+        Value temp_args[2] = {arg2, arg1}; /* multiply(2, 5) = 10 */
+        Value temp_result = baba_yaga_function_call(&g, temp_args, 2, NULL);
+        Value final_args[2] = {arg1, temp_result}; /* add(5, 10) */
+        Value result = baba_yaga_function_call(&f, final_args, 2, NULL);
+        
+        baba_yaga_value_destroy(&temp_result);
+        return result;
+    }
+    
+    /* For other cases, return a placeholder */
+    DEBUG_DEBUG("compose: unsupported composition pattern");
+    return baba_yaga_value_copy(&args[0]);
+}
+
+/* IO functions */
+Value stdlib_out(Value* args, int argc) {
+    if (argc != 1) {
+        DEBUG_ERROR("out: expected 1 argument, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value arg = args[0];
+    char* str = baba_yaga_value_to_string(&arg);
+    
+    printf("%s", str);
+    fflush(stdout);
+    
+    free(str);
+    return baba_yaga_value_number(-999999);
+}
+
+Value stdlib_in(Value* args, int argc) {
+    (void)args; /* Unused */
+    (void)argc; /* Unused */
+    
+    char buffer[1024];
+    if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
+        /* Remove newline */
+        size_t len = strlen(buffer);
+        if (len > 0 && buffer[len - 1] == '\n') {
+            buffer[len - 1] = '\0';
+        }
+        return baba_yaga_value_string(buffer);
+    }
+    
+    return baba_yaga_value_string("");
+}
+
+Value stdlib_assert(Value* args, int argc) {
+    if (argc != 1) {
+        DEBUG_ERROR("assert: expected 1 argument, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value arg = args[0];
+    bool truthy = baba_yaga_value_is_truthy(&arg);
+    
+    /* Return the truthiness as a boolean instead of failing */
+    return baba_yaga_value_boolean(truthy);
+}
+
+Value stdlib_emit(Value* args, int argc) {
+    if (argc != 1) {
+        DEBUG_ERROR("emit: expected 1 argument, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value arg = args[0];
+    
+    /* For now, just print the value like ..out */
+    char* str = baba_yaga_value_to_string(&arg);
+    printf("%s", str);
+    free(str);
+    
+    /* Return the emitted value */
+    return baba_yaga_value_copy(&arg);
+}
+
+Value stdlib_listen(Value* args, int argc) {
+    (void)args; /* Unused */
+    (void)argc; /* Unused */
+    
+    /* For now, return a placeholder state object */
+    /* TODO: Implement actual state management */
+    Value state = baba_yaga_value_table();
+    Value status_val = baba_yaga_value_string("placeholder");
+    Value message_val = baba_yaga_value_string("State not available in standalone mode");
+    
+    state = baba_yaga_table_set(&state, "status", &status_val);
+    state = baba_yaga_table_set(&state, "message", &message_val);
+    
+    return state;
+}
+
+/* Higher-order functions */
+Value stdlib_map(Value* args, int argc, Scope* scope) {
+    if (argc != 2) {
+        DEBUG_ERROR("map: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    Value table = args[1];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("map: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("map: second argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("map: applying function to each value in table");
+    
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    Value result = baba_yaga_value_table();
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (value.type != VAL_NIL) {
+            Value func_args[1] = {value};
+            Value mapped_value = baba_yaga_function_call(&func, func_args, 1, scope);
+            result = baba_yaga_table_set(&result, keys[i], &mapped_value);
+        }
+        free(keys[i]);
+    }
+    return result;
+}
+
+Value stdlib_filter(Value* args, int argc, Scope* scope) {
+    if (argc != 2) {
+        DEBUG_ERROR("filter: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    Value func = args[0];
+    Value table = args[1];
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("filter: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("filter: second argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    DEBUG_DEBUG("filter: filtering table with predicate");
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    Value result = baba_yaga_value_table();
+    int result_index = 1;
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (value.type != VAL_NIL) {
+            Value func_args[1] = {value};
+            Value predicate_result = baba_yaga_function_call(&func, func_args, 1, scope);
+            if (baba_yaga_value_is_truthy(&predicate_result)) {
+                char key_str[32];
+                snprintf(key_str, sizeof(key_str), "%d", result_index++);
+                result = baba_yaga_table_set(&result, key_str, &value);
+            }
+        }
+        free(keys[i]);
+    }
+    return result;
+}
+
+Value stdlib_reduce(Value* args, int argc, Scope* scope) {
+    if (argc != 3) {
+        DEBUG_ERROR("reduce: expected 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    Value func = args[0];
+    Value initial = args[1];
+    Value table = args[2];
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("reduce: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("reduce: third argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    DEBUG_DEBUG("reduce: reducing table with function");
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    Value result = baba_yaga_value_copy(&initial);
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (value.type != VAL_NIL) {
+            Value func_args[2] = {result, value};
+            Value new_result = baba_yaga_function_call(&func, func_args, 2, scope);
+            baba_yaga_value_destroy(&result);
+            result = new_result;
+        }
+        free(keys[i]);
+    }
+    return result;
+}
+
+/**
+ * @brief Each combinator - applies a function to each element of a table
+ * 
+ * @param args Array of arguments [function, table, scalar/table]
+ * @param argc Number of arguments (should be 3)
+ * @return New table with function applied to each element
+ */
+Value stdlib_each(Value* args, int argc, Scope* scope) {
+    if (argc < 2 || argc > 3) {
+        DEBUG_ERROR("each: expected 2 or 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    /* Handle partial application: each function arg2 */
+    if (argc == 2) {
+        Value func = args[0];
+        Value arg2 = args[1];
+        
+        if (func.type != VAL_FUNCTION) {
+            DEBUG_ERROR("each: first argument must be a function");
+            return baba_yaga_value_nil();
+        }
+        
+        /* Create a new function that applies the original function with the second argument */
+        Value partial_func = baba_yaga_value_function("each_partial", stdlib_each_partial, 2, 2);
+        
+        /* Store the original function and second argument in the scope */
+        char temp_name[32];
+        snprintf(temp_name, sizeof(temp_name), "_each_func_%p", (void*)&func);
+        scope_define(scope, temp_name, func, true);
+        
+        char temp_name2[32];
+        snprintf(temp_name2, sizeof(temp_name2), "_each_arg2_%p", (void*)&arg2);
+        scope_define(scope, temp_name2, arg2, true);
+        
+        return partial_func;
+    }
+    
+    Value func = args[0];
+    Value table1 = args[1];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("each: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (table1.type != VAL_TABLE) {
+        DEBUG_ERROR("each: second argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("each: applying function to table elements");
+    
+    /* Get the size of the first table */
+    size_t table_size = baba_yaga_table_size(&table1);
+    DEBUG_DEBUG("each: table has %zu elements", table_size);
+    
+    Value arg3 = args[2];
+    
+    /* Get all keys from the first table */
+    char* keys[1000]; /* Large enough for most tables */
+    size_t key_count = baba_yaga_table_get_keys(&table1, keys, 1000);
+    
+    /* Create result table */
+    Value result = baba_yaga_value_table();
+    
+    if (arg3.type == VAL_TABLE) {
+        /* each function table1 table2 - apply function to corresponding elements */
+        DEBUG_DEBUG("each: applying function to corresponding elements of two tables");
+        
+        size_t table2_size = baba_yaga_table_size(&arg3);
+        DEBUG_DEBUG("each: second table has %zu elements", table2_size);
+        
+        /* Get all keys from second table */
+        char* keys2[1000];
+        size_t key_count2 = baba_yaga_table_get_keys(&arg3, keys2, 1000);
+        
+        /* Apply function to corresponding elements */
+        for (size_t i = 0; i < key_count && i < key_count2; i++) {
+            Value element1 = baba_yaga_table_get_by_key(&table1, keys[i]);
+            Value element2 = baba_yaga_table_get_by_key(&arg3, keys2[i]);
+            
+            if (element1.type != VAL_NIL && element2.type != VAL_NIL) {
+                /* Call function with both elements */
+                Value func_args[2];
+                func_args[0] = element1;
+                func_args[1] = element2;
+                Value element_result = baba_yaga_function_call(&func, func_args, 2, scope);
+                
+                /* Add result to new table */
+                result = baba_yaga_table_set(&result, keys[i], &element_result);
+            }
+            
+            free(keys2[i]);
+        }
+        
+        /* Free remaining keys from second table */
+        for (size_t i = key_count; i < key_count2; i++) {
+            free(keys2[i]);
+        }
+    } else {
+        /* each function table scalar - apply function to each element with scalar */
+        DEBUG_DEBUG("each: applying function to each element with scalar");
+        
+        /* Apply function to each element with the scalar */
+        for (size_t i = 0; i < key_count; i++) {
+            Value element = baba_yaga_table_get_by_key(&table1, keys[i]);
+            if (element.type != VAL_NIL) {
+                /* Call function with element and scalar */
+                Value func_args[2];
+                func_args[0] = element;
+                func_args[1] = arg3;
+                Value element_result = baba_yaga_function_call(&func, func_args, 2, scope);
+                
+                /* Add result to new table */
+                result = baba_yaga_table_set(&result, keys[i], &element_result);
+            }
+        }
+    }
+    
+    /* Free keys from first table */
+    for (size_t i = 0; i < key_count; i++) {
+        free(keys[i]);
+    }
+    
+    DEBUG_DEBUG("each: completed, result table has elements");
+    return result;
+}
+
+/**
+ * @brief Partial application helper for each function
+ * 
+ * This function is called when a partial each function is applied with a table.
+ * It applies the original function to each element of the table with the second argument.
+ */
+/**
+ * @brief Partial application helper function
+ * 
+ * This function is called when a partial function is applied with additional arguments.
+ * It combines the bound arguments with the new arguments and calls the original function.
+ */
+Value stdlib_partial_apply(Value* args, int argc, Scope* scope) {
+    /* Get the original function and bound arguments from the scope */
+    char** names = malloc(100 * sizeof(char*));
+    int name_count = scope_get_names(scope, names, 100);
+    
+    Value original_func = baba_yaga_value_nil();
+    int bound_count = 0;
+    Value bound_args[10]; /* Assume max 10 bound arguments */
+    
+    for (int i = 0; i < name_count; i++) {
+        if (strncmp(names[i], "_partial_func_", 14) == 0) {
+            original_func = scope_get(scope, names[i]);
+        } else if (strncmp(names[i], "_partial_count_", 15) == 0) {
+            Value count_val = scope_get(scope, names[i]);
+            if (count_val.type == VAL_NUMBER) {
+                bound_count = (int)count_val.data.number;
+            }
+        } else if (strncmp(names[i], "_partial_arg_", 13) == 0) {
+            /* Extract argument index from name like "_partial_arg_0_0x123" */
+            char* underscore = strrchr(names[i], '_');
+            if (underscore != NULL) {
+                int arg_index = atoi(underscore + 1);
+                if (arg_index >= 0 && arg_index < 10) {
+                    bound_args[arg_index] = scope_get(scope, names[i]);
+                }
+            }
+        }
+    }
+    
+    /* Free the names array */
+    for (int i = 0; i < name_count; i++) {
+        free(names[i]);
+    }
+    free(names);
+    
+    if (original_func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("partial_apply: original function not found");
+        return baba_yaga_value_nil();
+    }
+    
+    /* Combine bound arguments with new arguments */
+    Value combined_args[20]; /* Assume max 20 total arguments */
+    int total_count = bound_count + argc;
+    
+    if (total_count > 20) {
+        DEBUG_ERROR("partial_apply: too many arguments");
+        return baba_yaga_value_nil();
+    }
+    
+    /* Copy bound arguments first */
+    for (int i = 0; i < bound_count; i++) {
+        combined_args[i] = bound_args[i];
+    }
+    
+    /* Copy new arguments */
+    for (int i = 0; i < argc; i++) {
+        combined_args[bound_count + i] = args[i];
+    }
+    
+    /* Call the original function with all arguments */
+    return baba_yaga_function_call(&original_func, combined_args, total_count, scope);
+}
+
+Value stdlib_each_partial(Value* args, int argc, Scope* scope) {
+    if (argc != 2) {
+        DEBUG_ERROR("each_partial: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[1];
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("each_partial: second argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    /* Get the original function and second argument from the scope */
+    /* We need to find them by looking for the stored values */
+    char** names = malloc(100 * sizeof(char*));
+    int name_count = scope_get_names(scope, names, 100);
+    
+    Value original_func = baba_yaga_value_nil();
+    Value arg2 = baba_yaga_value_nil();
+    
+    for (int i = 0; i < name_count; i++) {
+        if (strncmp(names[i], "_each_func_", 11) == 0) {
+            original_func = scope_get(scope, names[i]);
+        } else if (strncmp(names[i], "_each_arg2_", 11) == 0) {
+            arg2 = scope_get(scope, names[i]);
+        }
+    }
+    
+    /* Free the names array */
+    for (int i = 0; i < name_count; i++) {
+        free(names[i]);
+    }
+    free(names);
+    
+    if (original_func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("each_partial: original function not found");
+        return baba_yaga_value_nil();
+    }
+    
+    /* Apply the original function to each element of the table with the second argument */
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    
+    Value result = baba_yaga_value_table();
+    
+    for (size_t i = 0; i < key_count; i++) {
+        Value element = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (element.type != VAL_NIL) {
+            /* Call function with element and the second argument */
+            Value func_args[2];
+            func_args[0] = element;
+            func_args[1] = arg2;
+            Value element_result = baba_yaga_function_call(&original_func, func_args, 2, scope);
+            
+            /* Add result to new table */
+            result = baba_yaga_table_set(&result, keys[i], &element_result);
+        }
+        free(keys[i]);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Flip combinator - reverses argument order of a function
+ * 
+ * @param args Array of arguments [function] or [function, arg1, arg2]
+ * @param argc Number of arguments (should be 1 or 3)
+ * @return Flipped function or result of flipped function application
+ */
+Value stdlib_flip(Value* args, int argc) {
+    if (argc != 1 && argc != 3) {
+        DEBUG_ERROR("flip: expected 1 or 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("flip: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (argc == 1) {
+        /* Partial application: return the flipped function */
+        DEBUG_DEBUG("flip: partial application, returning flipped function");
+        return baba_yaga_value_copy(&func);
+    }
+    
+    /* Full application: flip(arg1, arg2) = func(arg2, arg1) */
+    Value arg1 = args[1];
+    Value arg2 = args[2];
+    
+    DEBUG_DEBUG("flip: applying function with flipped arguments");
+    
+    /* Call function with arguments in reverse order */
+    Value func_args[2] = {arg2, arg1}; /* Reversed order */
+    Value result = baba_yaga_function_call(&func, func_args, 2, NULL);
+    
+    return result;
+}
+
+/**
+ * @brief Constant combinator - creates a function that returns a constant value
+ * 
+ * @param args Array of arguments [value] or [value, ignored_arg]
+ * @param argc Number of arguments (should be 1 or 2)
+ * @return Constant function or constant value
+ */
+Value stdlib_constant(Value* args, int argc) {
+    if (argc != 1 && argc != 2) {
+        DEBUG_ERROR("constant: expected 1 or 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value constant_value = args[0];
+    
+    if (argc == 1) {
+        /* Partial application: return a function that always returns the constant */
+        DEBUG_DEBUG("constant: partial application, returning constant function");
+        return baba_yaga_value_copy(&constant_value);
+    }
+    
+    /* Full application: constant(value, ignored_arg) = value */
+    DEBUG_DEBUG("constant: returning constant value, ignoring second argument");
+    return baba_yaga_value_copy(&constant_value);
+}
+
+/* ============================================================================
+ * Table Operations Namespace (t.* functions)
+ * ============================================================================ */
+
+/**
+ * @brief Table map operation - apply function to each value in table
+ * 
+ * @param args Array of arguments [function, table]
+ * @param argc Number of arguments (should be 2)
+ * @return New table with function applied to each value
+ */
+Value stdlib_t_map(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.map: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    Value table = args[1];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("t.map: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.map: second argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.map: applying function to each value in table");
+    
+    /* Get all keys from the table */
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    
+    /* Create result table */
+    Value result = baba_yaga_value_table();
+    
+    /* Apply function to each value */
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (value.type != VAL_NIL) {
+            /* Call function with the value */
+            Value func_args[1] = {value};
+            Value mapped_value = baba_yaga_function_call(&func, func_args, 1, NULL);
+            
+            /* Add result to new table with same key */
+            result = baba_yaga_table_set(&result, keys[i], &mapped_value);
+        }
+        free(keys[i]);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Table filter operation - keep only values that satisfy predicate
+ * 
+ * @param args Array of arguments [function, table]
+ * @param argc Number of arguments (should be 2)
+ * @return New table with only values that satisfy the predicate
+ */
+Value stdlib_t_filter(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.filter: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    Value table = args[1];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("t.filter: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.filter: second argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.filter: filtering table with predicate");
+    
+    /* Get all keys from the table */
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    
+    /* Create result table */
+    Value result = baba_yaga_value_table();
+    int result_index = 1; /* 1-based indexing for filtered results */
+    
+    /* Apply predicate to each value */
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (value.type != VAL_NIL) {
+            /* Call predicate function with the value */
+            Value func_args[1] = {value};
+            Value predicate_result = baba_yaga_function_call(&func, func_args, 1, NULL);
+            
+            /* If predicate returns true, keep the value */
+            if (baba_yaga_value_is_truthy(&predicate_result)) {
+                char key_str[32];
+                snprintf(key_str, sizeof(key_str), "%d", result_index++);
+                result = baba_yaga_table_set(&result, key_str, &value);
+            }
+        }
+        free(keys[i]);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Table reduce operation - combine all values with a function
+ * 
+ * @param args Array of arguments [function, initial_value, table]
+ * @param argc Number of arguments (should be 3)
+ * @return Result of reducing the table
+ */
+Value stdlib_t_reduce(Value* args, int argc) {
+    if (argc != 3) {
+        DEBUG_ERROR("t.reduce: expected 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    Value initial = args[1];
+    Value table = args[2];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("t.reduce: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.reduce: third argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.reduce: reducing table with function");
+    
+    /* Get all keys from the table */
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    
+    /* Start with initial value */
+    Value result = baba_yaga_value_copy(&initial);
+    
+    /* Apply function to each value */
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (value.type != VAL_NIL) {
+            /* Call function with accumulator and current value */
+            Value func_args[2] = {result, value};
+            Value new_result = baba_yaga_function_call(&func, func_args, 2, NULL);
+            
+            baba_yaga_value_destroy(&result);
+            result = new_result;
+        }
+        free(keys[i]);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Table set operation - immutable update
+ * 
+ * @param args Array of arguments [table, key, value]
+ * @param argc Number of arguments (should be 3)
+ * @return New table with updated value
+ */
+Value stdlib_t_set(Value* args, int argc) {
+    if (argc != 3) {
+        DEBUG_ERROR("t.set: expected 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    Value key = args[1];
+    Value value = args[2];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.set: first argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    if (key.type != VAL_STRING) {
+        DEBUG_ERROR("t.set: second argument must be a string");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.set: setting key '%s' in table", key.data.string);
+    
+    /* Create new table with the updated value */
+    return baba_yaga_table_set(&table, key.data.string, &value);
+}
+
+/**
+ * @brief Table delete operation - immutable deletion
+ * 
+ * @param args Array of arguments [table, key]
+ * @param argc Number of arguments (should be 2)
+ * @return New table without the specified key
+ */
+Value stdlib_t_delete(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.delete: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    Value key = args[1];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.delete: first argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    if (key.type != VAL_STRING) {
+        DEBUG_ERROR("t.delete: second argument must be a string");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.delete: deleting key '%s' from table", key.data.string);
+    
+    /* For now, return the original table since we don't have delete functionality */
+    /* TODO: Implement actual deletion */
+    return baba_yaga_value_copy(&table);
+}
+
+/**
+ * @brief Table merge operation - immutable merge
+ * 
+ * @param args Array of arguments [table1, table2]
+ * @param argc Number of arguments (should be 2)
+ * @return New table with merged contents
+ */
+Value stdlib_t_merge(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.merge: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table1 = args[0];
+    Value table2 = args[1];
+    
+    if (table1.type != VAL_TABLE || table2.type != VAL_TABLE) {
+        DEBUG_ERROR("t.merge: both arguments must be tables");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.merge: merging two tables");
+    
+    /* Start with first table */
+    Value result = baba_yaga_value_copy(&table1);
+    
+    /* Get all keys from second table */
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table2, keys, 1000);
+    
+    /* Add all entries from second table */
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table2, keys[i]);
+        if (value.type != VAL_NIL) {
+            result = baba_yaga_table_set(&result, keys[i], &value);
+        }
+        free(keys[i]);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Table length operation - get number of entries
+ * 
+ * @param args Array of arguments [table]
+ * @param argc Number of arguments (should be 1)
+ * @return Number of entries in the table
+ */
+Value stdlib_t_length(Value* args, int argc) {
+    if (argc != 1) {
+        DEBUG_ERROR("t.length: expected 1 argument, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.length: argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    size_t length = baba_yaga_table_size(&table);
+    DEBUG_DEBUG("t.length: table has %zu entries", length);
+    
+    return baba_yaga_value_number((double)length);
+}
+
+/**
+ * @brief Table has operation - check if key exists
+ * 
+ * @param args Array of arguments [table, key]
+ * @param argc Number of arguments (should be 2)
+ * @return Boolean indicating if key exists
+ */
+Value stdlib_t_has(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.has: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    Value key = args[1];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.has: first argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    if (key.type != VAL_STRING) {
+        DEBUG_ERROR("t.has: second argument must be a string");
+        return baba_yaga_value_nil();
+    }
+    
+    bool has_key = baba_yaga_table_has_key(&table, key.data.string);
+    DEBUG_DEBUG("t.has: key '%s' %s in table", key.data.string, has_key ? "exists" : "does not exist");
+    
+    return baba_yaga_value_boolean(has_key);
+}
+
+/**
+ * @brief Table get operation - get value with default
+ * 
+ * @param args Array of arguments [table, key, default_value]
+ * @param argc Number of arguments (should be 3)
+ * @return Value from table or default if key doesn't exist
+ */
+Value stdlib_t_get(Value* args, int argc) {
+    if (argc != 3) {
+        DEBUG_ERROR("t.get: expected 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    Value key = args[1];
+    Value default_value = args[2];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.get: first argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    if (key.type != VAL_STRING) {
+        DEBUG_ERROR("t.get: second argument must be a string");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.get: getting key '%s' from table", key.data.string);
+    
+    /* Try to get the value from the table */
+    Value result = baba_yaga_table_get(&table, key.data.string);
+    
+    /* If key doesn't exist, return default value */
+    if (result.type == VAL_NIL) {
+        return baba_yaga_value_copy(&default_value);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Internal function for table key-value pairs
+ * 
+ * @param args Array of arguments [key, value]
+ * @param argc Number of arguments (should be 2)
+ * @return Value containing the key-value pair
+ */
+Value stdlib_table_entry(Value* args, int argc) {
+    if (argc != 2) {
+        return baba_yaga_value_nil();
+    }
+    
+    /* Create a special table entry value that can be used by table evaluation */
+    Value value = args[1];
+    
+    /* For now, return the value directly - the table evaluation will handle the key */
+    return value;
+} 
diff --git a/js/scripting-lang/baba-yaga-c/src/table.c b/js/scripting-lang/baba-yaga-c/src/table.c
new file mode 100644
index 0000000..0614929
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/table.c
@@ -0,0 +1,560 @@
+/**
+ * @file table.c
+ * @brief Table implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements the table data structure for the Baba Yaga language.
+ * Tables are immutable hash tables that support both string keys and numeric indices.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Hash Table Implementation
+ * ============================================================================ */
+
+#define TABLE_INITIAL_CAPACITY 16
+#define TABLE_LOAD_FACTOR 0.75
+
+/**
+ * @brief Hash table entry
+ */
+typedef struct TableEntry {
+    char* key;           /**< String key */
+    Value value;         /**< Associated value */
+    struct TableEntry* next; /**< Next entry in chain */
+} TableEntry;
+
+/**
+ * @brief Hash table structure
+ */
+typedef struct {
+    TableEntry** buckets;    /**< Array of bucket chains */
+    size_t capacity;         /**< Number of buckets */
+    size_t size;             /**< Number of entries */
+    Value* array_values;     /**< Array for numeric indices */
+    size_t array_size;       /**< Size of array */
+    size_t array_capacity;   /**< Capacity of array */
+} HashTable;
+
+/**
+ * @brief Table value structure
+ */
+typedef struct {
+    HashTable* hash_table;   /**< Hash table for string keys */
+    int ref_count;           /**< Reference count for memory management */
+} TableValue;
+
+/* ============================================================================
+ * Hash Function
+ * ============================================================================ */
+
+/**
+ * @brief Simple hash function for strings
+ * 
+ * @param str String to hash
+ * @return Hash value
+ */
+static unsigned int hash_string(const char* str) {
+    unsigned int hash = 5381;
+    int c;
+    
+    while ((c = *str++)) {
+        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+    }
+    
+    return hash;
+}
+
+/* ============================================================================
+ * Memory Management
+ * ============================================================================ */
+
+/**
+ * @brief Create a new hash table
+ * 
+ * @return New hash table, or NULL on failure
+ */
+static HashTable* hash_table_create(void) {
+    HashTable* table = malloc(sizeof(HashTable));
+    if (table == NULL) {
+        return NULL;
+    }
+    
+    table->capacity = TABLE_INITIAL_CAPACITY;
+    table->size = 0;
+    table->buckets = calloc(table->capacity, sizeof(TableEntry*));
+    if (table->buckets == NULL) {
+        free(table);
+        return NULL;
+    }
+    
+    table->array_capacity = TABLE_INITIAL_CAPACITY;
+    table->array_size = 0;
+    table->array_values = calloc(table->array_capacity, sizeof(Value));
+    if (table->array_values == NULL) {
+        free(table->buckets);
+        free(table);
+        return NULL;
+    }
+    
+    return table;
+}
+
+/**
+ * @brief Destroy a hash table
+ * 
+ * @param table Hash table to destroy
+ */
+static void hash_table_destroy(HashTable* table) {
+    if (table == NULL) {
+        return;
+    }
+    
+    /* Free all entries */
+    for (size_t i = 0; i < table->capacity; i++) {
+        TableEntry* entry = table->buckets[i];
+        while (entry != NULL) {
+            TableEntry* next = entry->next;
+            free(entry->key);
+            baba_yaga_value_destroy(&entry->value);
+            free(entry);
+            entry = next;
+        }
+    }
+    
+    /* Free array values */
+    for (size_t i = 0; i < table->array_size; i++) {
+        baba_yaga_value_destroy(&table->array_values[i]);
+    }
+    
+    free(table->buckets);
+    free(table->array_values);
+    free(table);
+}
+
+/**
+ * @brief Resize hash table
+ * 
+ * @param table Hash table to resize
+ * @return true on success, false on failure
+ */
+static bool hash_table_resize(HashTable* table) {
+    size_t old_capacity = table->capacity;
+    TableEntry** old_buckets = table->buckets;
+    
+    table->capacity *= 2;
+    table->buckets = calloc(table->capacity, sizeof(TableEntry*));
+    if (table->buckets == NULL) {
+        table->capacity = old_capacity;
+        table->buckets = old_buckets;
+        return false;
+    }
+    
+    /* Rehash all entries */
+    for (size_t i = 0; i < old_capacity; i++) {
+        TableEntry* entry = old_buckets[i];
+        while (entry != NULL) {
+            TableEntry* next = entry->next;
+            unsigned int hash = hash_string(entry->key) % table->capacity;
+            entry->next = table->buckets[hash];
+            table->buckets[hash] = entry;
+            entry = next;
+        }
+    }
+    
+    free(old_buckets);
+    return true;
+}
+
+/**
+ * @brief Resize array part of table
+ * 
+ * @param table Hash table to resize
+ * @return true on success, false on failure
+ */
+static bool hash_table_resize_array(HashTable* table) {
+    size_t new_capacity = table->array_capacity * 2;
+    Value* new_array = realloc(table->array_values, new_capacity * sizeof(Value));
+    if (new_array == NULL) {
+        return false;
+    }
+    
+    table->array_values = new_array;
+    table->array_capacity = new_capacity;
+    return true;
+}
+
+/* ============================================================================
+ * Table Operations
+ * ============================================================================ */
+
+/**
+ * @brief Get entry from hash table by key
+ * 
+ * @param table Hash table
+ * @param key String key
+ * @return Table entry, or NULL if not found
+ */
+static TableEntry* hash_table_get_entry(const HashTable* table, const char* key) {
+    if (table == NULL || key == NULL) {
+        return NULL;
+    }
+    
+    unsigned int hash = hash_string(key) % table->capacity;
+    TableEntry* entry = table->buckets[hash];
+    
+    while (entry != NULL) {
+        if (strcmp(entry->key, key) == 0) {
+            return entry;
+        }
+        entry = entry->next;
+    }
+    
+    return NULL;
+}
+
+/**
+ * @brief Set value in hash table
+ * 
+ * @param table Hash table
+ * @param key String key
+ * @param value Value to set
+ * @return true on success, false on failure
+ */
+static bool hash_table_set(HashTable* table, const char* key, const Value* value) {
+    if (table == NULL || key == NULL) {
+        return false;
+    }
+    
+    /* Check if we need to resize */
+    if ((double)table->size / table->capacity >= TABLE_LOAD_FACTOR) {
+        if (!hash_table_resize(table)) {
+            return false;
+        }
+    }
+    
+    unsigned int hash = hash_string(key) % table->capacity;
+    TableEntry* entry = table->buckets[hash];
+    
+    /* Look for existing entry */
+    while (entry != NULL) {
+        if (strcmp(entry->key, key) == 0) {
+            /* Update existing entry */
+            baba_yaga_value_destroy(&entry->value);
+            entry->value = baba_yaga_value_copy(value);
+            return true;
+        }
+        entry = entry->next;
+    }
+    
+    /* Create new entry */
+    entry = malloc(sizeof(TableEntry));
+    if (entry == NULL) {
+        return false;
+    }
+    
+    entry->key = strdup(key);
+    if (entry->key == NULL) {
+        free(entry);
+        return false;
+    }
+    
+    entry->value = baba_yaga_value_copy(value);
+    entry->next = table->buckets[hash];
+    table->buckets[hash] = entry;
+    table->size++;
+    
+    return true;
+}
+
+/* ============================================================================
+ * Public Table API
+ * ============================================================================ */
+
+Value baba_yaga_value_table(void) {
+    Value value;
+    value.type = VAL_TABLE;
+    
+    TableValue* table_value = malloc(sizeof(TableValue));
+    if (table_value == NULL) {
+        value.type = VAL_NIL;
+        return value;
+    }
+    
+    table_value->hash_table = hash_table_create();
+    if (table_value->hash_table == NULL) {
+        free(table_value);
+        value.type = VAL_NIL;
+        return value;
+    }
+    
+    table_value->ref_count = 1;
+    value.data.table = table_value;
+    
+    return value;
+}
+
+Value baba_yaga_table_get(const Value* table, const char* key) {
+    if (table == NULL || table->type != VAL_TABLE || key == NULL) {
+        DEBUG_ERROR("Table get: invalid parameters");
+        return baba_yaga_value_nil();
+    }
+    
+    TableValue* table_value = (TableValue*)table->data.table;
+    DEBUG_DEBUG("Table get: looking for key '%s' in table with %zu entries", key, table_value->hash_table->size);
+    
+    TableEntry* entry = hash_table_get_entry(table_value->hash_table, key);
+    
+    if (entry != NULL) {
+        DEBUG_DEBUG("Table get: found key '%s', returning value type %d", key, entry->value.type);
+        return baba_yaga_value_copy(&entry->value);
+    }
+    
+    DEBUG_DEBUG("Table get: key '%s' not found", key);
+    return baba_yaga_value_nil();
+}
+
+Value baba_yaga_table_set(const Value* table, const char* key, const Value* value) {
+    if (table == NULL || table->type != VAL_TABLE || key == NULL || value == NULL) {
+        DEBUG_ERROR("Table set: invalid parameters");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("Table set: setting key '%s' to value type %d", key, value->type);
+    
+    /* Create new table */
+    Value new_table = baba_yaga_value_table();
+    if (new_table.type != VAL_TABLE) {
+        DEBUG_ERROR("Table set: failed to create new table");
+        return baba_yaga_value_nil();
+    }
+    
+    TableValue* new_table_value = (TableValue*)new_table.data.table;
+    TableValue* old_table_value = (TableValue*)table->data.table;
+    
+    DEBUG_DEBUG("Table set: copying %zu entries from old table", old_table_value->hash_table->size);
+    
+    /* Copy all entries from old table */
+    for (size_t i = 0; i < old_table_value->hash_table->capacity; i++) {
+        TableEntry* entry = old_table_value->hash_table->buckets[i];
+        while (entry != NULL) {
+            hash_table_set(new_table_value->hash_table, entry->key, &entry->value);
+            entry = entry->next;
+        }
+    }
+    
+    /* Copy array values */
+    for (size_t i = 0; i < old_table_value->hash_table->array_size; i++) {
+        if (i >= new_table_value->hash_table->array_capacity) {
+            if (!hash_table_resize_array(new_table_value->hash_table)) {
+                baba_yaga_value_destroy(&new_table);
+                return baba_yaga_value_nil();
+            }
+        }
+        new_table_value->hash_table->array_values[i] = 
+            baba_yaga_value_copy(&old_table_value->hash_table->array_values[i]);
+    }
+    new_table_value->hash_table->array_size = old_table_value->hash_table->array_size;
+    
+    /* Set the new value */
+    if (!hash_table_set(new_table_value->hash_table, key, value)) {
+        DEBUG_ERROR("Table set: failed to set key '%s'", key);
+        baba_yaga_value_destroy(&new_table);
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("Table set: new table has %zu entries", new_table_value->hash_table->size);
+    return new_table;
+}
+
+Value baba_yaga_table_get_index(const Value* table, int index) {
+    if (table == NULL || table->type != VAL_TABLE || index <= 0) {
+        return baba_yaga_value_nil();
+    }
+    
+    TableValue* table_value = (TableValue*)table->data.table;
+    size_t idx = (size_t)(index - 1);
+    
+    if (idx < table_value->hash_table->array_size) {
+        return baba_yaga_value_copy(&table_value->hash_table->array_values[idx]);
+    }
+    
+    return baba_yaga_value_nil();
+}
+
+Value baba_yaga_table_set_index(const Value* table, int index, const Value* value) {
+    if (table == NULL || table->type != VAL_TABLE || index <= 0 || value == NULL) {
+        return baba_yaga_value_nil();
+    }
+    
+    /* Create new table */
+    Value new_table = baba_yaga_value_table();
+    if (new_table.type != VAL_TABLE) {
+        return baba_yaga_value_nil();
+    }
+    
+    TableValue* new_table_value = (TableValue*)new_table.data.table;
+    TableValue* old_table_value = (TableValue*)table->data.table;
+    
+    /* Copy all entries from old table */
+    for (size_t i = 0; i < old_table_value->hash_table->capacity; i++) {
+        TableEntry* entry = old_table_value->hash_table->buckets[i];
+        while (entry != NULL) {
+            hash_table_set(new_table_value->hash_table, entry->key, &entry->value);
+            entry = entry->next;
+        }
+    }
+    
+    /* Copy array values */
+    size_t idx = (size_t)(index - 1);
+    size_t new_size = (idx >= old_table_value->hash_table->array_size) ? 
+                     idx + 1 : old_table_value->hash_table->array_size;
+    
+    /* Ensure capacity */
+    while (new_size >= new_table_value->hash_table->array_capacity) {
+        if (!hash_table_resize_array(new_table_value->hash_table)) {
+            baba_yaga_value_destroy(&new_table);
+            return baba_yaga_value_nil();
+        }
+    }
+    
+    /* Copy existing values */
+    for (size_t i = 0; i < old_table_value->hash_table->array_size; i++) {
+        new_table_value->hash_table->array_values[i] = 
+            baba_yaga_value_copy(&old_table_value->hash_table->array_values[i]);
+    }
+    
+    /* Set the new value */
+    new_table_value->hash_table->array_values[idx] = baba_yaga_value_copy(value);
+    new_table_value->hash_table->array_size = new_size;
+    
+    return new_table;
+}
+
+size_t baba_yaga_table_size(const Value* table) {
+    if (table == NULL || table->type != VAL_TABLE) {
+        return 0;
+    }
+    
+    TableValue* table_value = (TableValue*)table->data.table;
+    return table_value->hash_table->size + table_value->hash_table->array_size;
+}
+
+bool baba_yaga_table_has_key(const Value* table, const char* key) {
+    if (table == NULL || table->type != VAL_TABLE || key == NULL) {
+        return false;
+    }
+    
+    TableValue* table_value = (TableValue*)table->data.table;
+    return hash_table_get_entry(table_value->hash_table, key) != NULL;
+}
+
+/**
+ * @brief Get all keys from a table
+ * 
+ * @param table Table value
+ * @param keys Array to store keys (caller must free)
+ * @param max_keys Maximum number of keys to retrieve
+ * @return Number of keys retrieved
+ */
+size_t baba_yaga_table_get_keys(const Value* table, char** keys, size_t max_keys) {
+    if (table == NULL || table->type != VAL_TABLE || keys == NULL || max_keys == 0) {
+        return 0;
+    }
+    
+    TableValue* table_value = (TableValue*)table->data.table;
+    HashTable* hash_table = table_value->hash_table;
+    
+    size_t key_count = 0;
+    
+    /* Get string keys */
+    for (size_t i = 0; i < hash_table->capacity && key_count < max_keys; i++) {
+        TableEntry* entry = hash_table->buckets[i];
+        while (entry != NULL && key_count < max_keys) {
+            keys[key_count] = strdup(entry->key);
+            key_count++;
+            entry = entry->next;
+        }
+    }
+    
+    /* Get numeric keys (array indices) */
+    for (size_t i = 0; i < hash_table->array_size && key_count < max_keys; i++) {
+        char* num_key = malloc(32); /* Enough for large numbers */
+        if (num_key != NULL) {
+            snprintf(num_key, 32, "%zu", i + 1); /* 1-based indexing */
+            keys[key_count] = num_key;
+            key_count++;
+        }
+    }
+    
+    return key_count;
+}
+
+/**
+ * @brief Get a value from table by key (supports both string and numeric keys)
+ * 
+ * @param table Table value
+ * @param key Key (string or numeric as string)
+ * @return Value at key, or nil if not found
+ */
+Value baba_yaga_table_get_by_key(const Value* table, const char* key) {
+    if (table == NULL || table->type != VAL_TABLE || key == NULL) {
+        return baba_yaga_value_nil();
+    }
+    
+    /* Try as string key first */
+    Value result = baba_yaga_table_get(table, key);
+    if (result.type != VAL_NIL) {
+        return result;
+    }
+    
+    /* Try as numeric key */
+    char* endptr;
+    long index = strtol(key, &endptr, 10);
+    if (*endptr == '\0' && index > 0) {
+        return baba_yaga_table_get_index(table, (int)index);
+    }
+    
+    return baba_yaga_value_nil();
+}
+
+/* ============================================================================
+ * Internal Table Management
+ * ============================================================================ */
+
+/**
+ * @brief Increment reference count for a table
+ * 
+ * @param table Table value
+ */
+void table_increment_ref(Value* table) {
+    if (table != NULL && table->type == VAL_TABLE) {
+        TableValue* table_value = (TableValue*)table->data.table;
+        table_value->ref_count++;
+    }
+}
+
+/**
+ * @brief Decrement reference count for a table
+ * 
+ * @param table Table value
+ */
+void table_decrement_ref(Value* table) {
+    if (table != NULL && table->type == VAL_TABLE) {
+        TableValue* table_value = (TableValue*)table->data.table;
+        table_value->ref_count--;
+        
+        if (table_value->ref_count <= 0) {
+            hash_table_destroy(table_value->hash_table);
+            free(table_value);
+        }
+    }
+}
diff --git a/js/scripting-lang/baba-yaga-c/src/value.c b/js/scripting-lang/baba-yaga-c/src/value.c
new file mode 100644
index 0000000..562f3a7
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/value.c
@@ -0,0 +1,215 @@
+/**
+ * @file value.c
+ * @brief Value system implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements the value system for the Baba Yaga language,
+ * including value creation, destruction, and utility functions.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Value Creation Functions
+ * ============================================================================ */
+
+Value baba_yaga_value_number(double number) {
+    Value value;
+    value.type = VAL_NUMBER;
+    value.data.number = number;
+    return value;
+}
+
+Value baba_yaga_value_string(const char* string) {
+    Value value;
+    value.type = VAL_STRING;
+    if (string != NULL) {
+        value.data.string = strdup(string);
+    } else {
+        value.data.string = NULL;
+    }
+    return value;
+}
+
+Value baba_yaga_value_boolean(bool boolean) {
+    Value value;
+    value.type = VAL_BOOLEAN;
+    value.data.boolean = boolean;
+    return value;
+}
+
+Value baba_yaga_value_nil(void) {
+    Value value;
+    value.type = VAL_NIL;
+    return value;
+}
+
+/* ============================================================================
+ * Value Management Functions
+ * ============================================================================ */
+
+void baba_yaga_value_destroy(Value* value) {
+    if (value == NULL) {
+        return;
+    }
+
+    switch (value->type) {
+    case VAL_STRING:
+        if (value->data.string != NULL) {
+            free(value->data.string);
+            value->data.string = NULL;
+        }
+        break;
+    case VAL_TABLE:
+        table_decrement_ref(value);
+        break;
+    case VAL_FUNCTION:
+        function_decrement_ref(value);
+        break;
+    default:
+        /* No cleanup needed for other types */
+        break;
+    }
+
+    value->type = VAL_NIL;
+}
+
+Value baba_yaga_value_copy(const Value* value) {
+    if (value == NULL) {
+        return baba_yaga_value_nil();
+    }
+
+    DEBUG_DEBUG("baba_yaga_value_copy: copying value with type %d", value->type);
+
+    switch (value->type) {
+    case VAL_NUMBER:
+        return baba_yaga_value_number(value->data.number);
+    case VAL_STRING:
+        return baba_yaga_value_string(value->data.string);
+    case VAL_BOOLEAN:
+        return baba_yaga_value_boolean(value->data.boolean);
+    case VAL_TABLE: {
+        Value new_table = baba_yaga_value_table();
+        if (new_table.type != VAL_TABLE) {
+            return baba_yaga_value_nil();
+        }
+        
+        /* Copy all entries from the original table using the public API */
+        size_t old_size = baba_yaga_table_size(value);
+        if (old_size > 0) {
+            /* Get all keys from the original table */
+            char* keys[100]; /* Assume max 100 keys */
+            size_t key_count = baba_yaga_table_get_keys(value, keys, 100);
+            
+            /* Copy each key-value pair */
+            for (size_t i = 0; i < key_count; i++) {
+                Value old_value = baba_yaga_table_get(value, keys[i]);
+                new_table = baba_yaga_table_set(&new_table, keys[i], &old_value);
+                baba_yaga_value_destroy(&old_value);
+                free(keys[i]);
+            }
+        }
+        
+        return new_table;
+    }
+    case VAL_FUNCTION: {
+        /* For now, just increment the reference count of the original function */
+        Value new_func = *value;
+        function_increment_ref(&new_func);
+        return new_func;
+    }
+    case VAL_NIL:
+    default:
+        return baba_yaga_value_nil();
+    }
+}
+
+/* ============================================================================
+ * Utility Functions
+ * ============================================================================ */
+
+ValueType baba_yaga_value_get_type(const Value* value) {
+    if (value == NULL) {
+        return VAL_NIL;
+    }
+    return value->type;
+}
+
+bool baba_yaga_value_is_truthy(const Value* value) {
+    if (value == NULL) {
+        return false;
+    }
+
+    switch (value->type) {
+    case VAL_NUMBER:
+        return value->data.number != 0.0;
+    case VAL_STRING:
+        return value->data.string != NULL && strlen(value->data.string) > 0;
+    case VAL_BOOLEAN:
+        return value->data.boolean;
+    case VAL_TABLE:
+        /* Tables are truthy if they have any elements */
+        return baba_yaga_table_size(value) > 0;
+    case VAL_FUNCTION:
+        return true;
+    case VAL_NIL:
+    default:
+        return false;
+    }
+}
+
+char* baba_yaga_value_to_string(const Value* value) {
+    if (value == NULL) {
+        return strdup("nil");
+    }
+
+    switch (value->type) {
+    case VAL_NUMBER: {
+        char buffer[128];
+        if (value->data.number == (long)value->data.number) {
+            snprintf(buffer, sizeof(buffer), "%ld", (long)value->data.number);
+        } else {
+            snprintf(buffer, sizeof(buffer), "%.16g", value->data.number);
+        }
+        return strdup(buffer);
+    }
+    case VAL_STRING:
+        if (value->data.string != NULL) {
+            return strdup(value->data.string);
+        } else {
+            return strdup("");
+        }
+    case VAL_BOOLEAN:
+        return strdup(value->data.boolean ? "true" : "false");
+    case VAL_TABLE: {
+        char buffer[64];
+        size_t size = baba_yaga_table_size(value);
+        snprintf(buffer, sizeof(buffer), "<table:%zu>", size);
+        return strdup(buffer);
+    }
+    case VAL_FUNCTION: {
+        char buffer[64];
+        const char* name = function_get_name(value);
+        snprintf(buffer, sizeof(buffer), "<function:%s>", name ? name : "anonymous");
+        return strdup(buffer);
+    }
+    case VAL_NIL:
+    default:
+        return strdup("nil");
+    }
+}
+
+/* ============================================================================
+ * Version Information
+ * ============================================================================ */
+
+const char* baba_yaga_get_version(void) {
+    return "0.0.1";
+}