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/function.c53
-rw-r--r--js/scripting-lang/baba-yaga-c/src/interpreter.c390
-rw-r--r--js/scripting-lang/baba-yaga-c/src/lexer.c27
-rw-r--r--js/scripting-lang/baba-yaga-c/src/parser.c1087
-rw-r--r--js/scripting-lang/baba-yaga-c/src/scope.c23
-rw-r--r--js/scripting-lang/baba-yaga-c/src/stdlib.c1050
-rw-r--r--js/scripting-lang/baba-yaga-c/src/table.c82
-rw-r--r--js/scripting-lang/baba-yaga-c/src/value.c21
8 files changed, 2481 insertions, 252 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/function.c b/js/scripting-lang/baba-yaga-c/src/function.c
index 39265ef..bb5bedf 100644
--- a/js/scripting-lang/baba-yaga-c/src/function.c
+++ b/js/scripting-lang/baba-yaga-c/src/function.c
@@ -46,6 +46,8 @@ typedef struct {
     char* source;       /**< Source code for debugging */
 } FunctionBody;
 
+
+
 /**
  * @brief Function value structure
  */
@@ -56,7 +58,7 @@ typedef struct {
     int param_count;            /**< Number of parameters */
     int required_params;        /**< Number of required parameters */
     union {
-        Value (*native_func)(Value*, int);  /**< Native function pointer */
+        Value (*native_func)(Value*, int, Scope*);  /**< Native function pointer */
         FunctionBody user_body;             /**< User function body */
     } body;
     void* closure_scope;        /**< Closure scope (placeholder) */
@@ -86,7 +88,9 @@ static void function_body_destroy(FunctionBody* body) {
  * Public Function API
  * ============================================================================ */
 
-Value baba_yaga_value_function(const char* name, Value (*body)(Value*, int), 
+
+
+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;
@@ -140,18 +144,41 @@ Value baba_yaga_function_call(const Value* func, const Value* args,
     
     FunctionValue* func_value = (FunctionValue*)func->data.function;
     
-    /* Check if we have enough arguments */
+
+    
+    /* Check if we have enough arguments for partial application */
     if (arg_count < func_value->required_params) {
-        /* TODO: Implement partial application */
-        /* For now, return a new function with fewer required parameters */
-        return baba_yaga_value_nil();
+        /* 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);
+            return func_value->body.native_func((Value*)args, arg_count, scope);
         }
         break;
         
@@ -159,7 +186,9 @@ Value baba_yaga_function_call(const Value* func, const Value* args,
         /* Execute user-defined function */
         if (func_value->body.user_body.ast_node != NULL) {
             /* Create new scope for function execution */
-            Scope* func_scope = scope_create(scope); /* Pass current scope as parent for closures */
+            /* 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();
@@ -185,6 +214,8 @@ Value baba_yaga_function_call(const Value* func, const Value* args,
             return result;
         }
         break;
+        
+
     }
     
     return baba_yaga_value_nil();
@@ -229,9 +260,9 @@ void function_decrement_ref(Value* func) {
             }
             
                     /* Clean up function body */
-        if (func_value->type == FUNC_USER) {
-            function_body_destroy(&func_value->body.user_body);
-        }
+            if (func_value->type == FUNC_USER) {
+                function_body_destroy(&func_value->body.user_body);
+            }
             
             /* TODO: Clean up closure scope */
             
diff --git a/js/scripting-lang/baba-yaga-c/src/interpreter.c b/js/scripting-lang/baba-yaga-c/src/interpreter.c
index d06eb30..70d26f8 100644
--- a/js/scripting-lang/baba-yaga-c/src/interpreter.c
+++ b/js/scripting-lang/baba-yaga-c/src/interpreter.c
@@ -48,6 +48,9 @@ typedef struct {
 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
  * ============================================================================ */
@@ -71,7 +74,7 @@ static void register_stdlib(Scope* scope) {
     DEBUG_INFO("Registering standard library functions");
     
     /* Core combinator */
-    Value apply_func = baba_yaga_value_function("apply", stdlib_apply, 10, 1);
+    Value apply_func = baba_yaga_value_function("apply", stdlib_apply_wrapper, 10, 1);
     scope_define(scope, "apply", apply_func, true);
     
     /* Predefined variables for testing */
@@ -79,73 +82,92 @@ static void register_stdlib(Scope* scope) {
     scope_define(scope, "hello", hello_var, true);
     
     /* Arithmetic functions */
-    Value add_func = baba_yaga_value_function("add", stdlib_add, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 1, 1);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 2, 2);
+    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, 1, 1);
+    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, 4, 2);
+    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, 1, 1);
+    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, 0, 0);
+    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, 1, 1);
+    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);
@@ -156,7 +178,63 @@ static void register_stdlib(Scope* scope) {
     Value reduce_func = baba_yaga_value_function("reduce", stdlib_reduce, 3, 3);
     scope_define(scope, "reduce", reduce_func, true);
     
-    DEBUG_INFO("Registered %d standard library functions", 20);
+    /* 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);
 }
 
 /* ============================================================================
@@ -328,11 +406,14 @@ Value interpreter_evaluate_expression(void* node, Scope* scope) {
     }
     
     NodeType node_type = baba_yaga_ast_get_type(node);
-    DEBUG_TRACE("Evaluating expression: type %d", node_type);
+    DEBUG_DEBUG("Evaluating expression: type %d", node_type);
     
     switch (node_type) {
-    case NODE_LITERAL:
-        return baba_yaga_ast_get_literal(node);
+    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);
@@ -366,6 +447,7 @@ Value interpreter_evaluate_expression(void* node, Scope* scope) {
     }
     
     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);
@@ -540,7 +622,9 @@ Value interpreter_evaluate_expression(void* node, Scope* scope) {
             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;
     }
@@ -571,10 +655,14 @@ Value interpreter_evaluate_expression(void* node, Scope* scope) {
     }
     
     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);
         
@@ -589,9 +677,69 @@ Value interpreter_evaluate_expression(void* node, Scope* scope) {
             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;
-            if (pattern_test_value.type == VAL_NUMBER && test_value.type == VAL_NUMBER) {
+            
+            /* 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);
@@ -601,6 +749,57 @@ Value interpreter_evaluate_expression(void* node, Scope* scope) {
                        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);
@@ -620,6 +819,143 @@ Value interpreter_evaluate_expression(void* node, Scope* scope) {
         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();
diff --git a/js/scripting-lang/baba-yaga-c/src/lexer.c b/js/scripting-lang/baba-yaga-c/src/lexer.c
index a261da7..31a582f 100644
--- a/js/scripting-lang/baba-yaga-c/src/lexer.c
+++ b/js/scripting-lang/baba-yaga-c/src/lexer.c
@@ -72,7 +72,9 @@ typedef enum {
     TOKEN_FUNCTION_REF,  /* @function */
     TOKEN_IO_IN,         /* ..in */
     TOKEN_IO_OUT,        /* ..out */
-    TOKEN_IO_ASSERT      /* ..assert */
+    TOKEN_IO_ASSERT,     /* ..assert */
+    TOKEN_IO_EMIT,       /* ..emit */
+    TOKEN_IO_LISTEN      /* ..listen */
 } TokenType;
 
 /* ============================================================================
@@ -461,15 +463,10 @@ static Token lexer_read_identifier(Lexer* lexer) {
     
     /* 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, "and") == 0) {
-        token.type = TOKEN_KEYWORD_AND;
-    } else if (strcmp(token.lexeme, "or") == 0) {
-        token.type = TOKEN_KEYWORD_OR;
-    } else if (strcmp(token.lexeme, "xor") == 0) {
-        token.type = TOKEN_KEYWORD_XOR;
     } else if (strcmp(token.lexeme, "then") == 0) {
         token.type = TOKEN_KEYWORD_THEN;
     } else if (strcmp(token.lexeme, "not") == 0) {
@@ -585,6 +582,10 @@ static Token lexer_read_special(Lexer* lexer) {
             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;
@@ -683,8 +684,16 @@ static Token lexer_next_token(Lexer* lexer) {
         if (lexer_match(lexer, '>')) {
             return token_create(TOKEN_ARROW, "->", lexer->line, lexer->column - 2);
         }
-        /* For now, always treat minus as binary operator */
-        /* TODO: Implement proper unary vs binary minus detection */
+        
+        /* 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);
diff --git a/js/scripting-lang/baba-yaga-c/src/parser.c b/js/scripting-lang/baba-yaga-c/src/parser.c
index 68a4870..6c94913 100644
--- a/js/scripting-lang/baba-yaga-c/src/parser.c
+++ b/js/scripting-lang/baba-yaga-c/src/parser.c
@@ -60,7 +60,9 @@ typedef enum {
     TOKEN_FUNCTION_REF,
     TOKEN_IO_IN,
     TOKEN_IO_OUT,
-    TOKEN_IO_ASSERT
+    TOKEN_IO_ASSERT,
+    TOKEN_IO_EMIT,
+    TOKEN_IO_LISTEN
 } TokenType;
 
 typedef struct {
@@ -333,6 +335,7 @@ static ASTNode* ast_when_expr_node(ASTNode* test, ASTNode** patterns,
     node->data.when_expr.patterns = patterns;
     node->data.when_expr.pattern_count = pattern_count;
     
+
     return node;
 }
 
@@ -587,7 +590,10 @@ 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)
@@ -604,25 +610,25 @@ static ASTNode* parser_parse_primary(Parser* parser) {
     
     switch (token->type) {
     case TOKEN_NUMBER: {
-        printf("DEBUG: parser_parse_primary consuming number: %g\n", token->literal.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: {
-        printf("DEBUG: parser_parse_primary consuming string: %s\n", token->lexeme);
+        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: {
-        printf("DEBUG: parser_parse_primary consuming boolean: %s\n", token->literal.boolean ? "true" : "false");
+        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: {
-        printf("DEBUG: parser_parse_primary consuming identifier: %s\n", token->lexeme);
+        DEBUG_TRACE("parser_parse_primary consuming identifier: %s", token->lexeme);
         parser_advance(parser);
         /* Special handling for wildcard pattern */
         if (strcmp(token->lexeme, "_") == 0) {
@@ -633,8 +639,10 @@ static ASTNode* parser_parse_primary(Parser* parser) {
     }
     case TOKEN_IO_IN:
     case TOKEN_IO_OUT:
-    case TOKEN_IO_ASSERT: {
-        printf("DEBUG: parser_parse_primary consuming io operation: %s\n", token->lexeme);
+    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 ".." */
@@ -665,18 +673,55 @@ static ASTNode* parser_parse_primary(Parser* parser) {
             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: {
-        printf("DEBUG: parser_parse_primary consuming function ref: %s\n", token->lexeme);
+        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) {
-            printf("DEBUG: parser_parse_primary consuming '('\n");
+            DEBUG_TRACE("parser_parse_primary consuming '('");
             parser_advance(parser); /* consume '(' */
             
             /* Parse the expression inside parentheses */
@@ -702,6 +747,7 @@ static ASTNode* parser_parse_primary(Parser* parser) {
         }
         
         /* 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 && 
@@ -724,6 +770,11 @@ static ASTNode* parser_parse_primary(Parser* parser) {
                 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;
@@ -757,7 +808,7 @@ static ASTNode* parser_parse_primary(Parser* parser) {
                     }
                     
                     /* Parse argument */
-                    ASTNode* arg = parser_parse_primary(parser);
+                    ASTNode* arg = parser_parse_postfix(parser);
                     if (arg == NULL) {
                         /* Cleanup on error */
                         for (int i = 0; i < arg_count; i++) {
@@ -805,7 +856,7 @@ static ASTNode* parser_parse_primary(Parser* parser) {
         return func_node;
     }
     case TOKEN_LPAREN: {
-        printf("DEBUG: parser_parse_primary consuming '('\n");
+        DEBUG_TRACE("parser_parse_primary consuming '('");
         parser_advance(parser); /* consume '(' */
         ASTNode* expr = parser_parse_expression(parser);
         if (expr == NULL) {
@@ -819,19 +870,327 @@ static ASTNode* parser_parse_primary(Parser* parser) {
         
         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: {
-        printf("DEBUG: parser_parse_primary consuming unary minus\n");
+        DEBUG_TRACE("parser_parse_primary consuming unary minus");
         parser_advance(parser); /* consume '-' */
-        ASTNode* operand = parser_parse_primary(parser);
+        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: {
-        printf("DEBUG: parser_parse_primary consuming 'not'\n");
+        DEBUG_TRACE("parser_parse_primary consuming 'not'");
         parser_advance(parser); /* consume 'not' */
-        ASTNode* operand = parser_parse_primary(parser);
+        ASTNode* operand = parser_parse_postfix(parser);
         if (operand == NULL) {
             return NULL;
         }
@@ -859,14 +1218,14 @@ static ASTNode* parser_parse_primary(Parser* parser) {
  * @return Parsed expression node
  */
 static ASTNode* parser_parse_power(Parser* parser) {
-    ASTNode* left = parser_parse_primary(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_primary(parser);
+        ASTNode* right = parser_parse_postfix(parser);
         if (right == NULL) {
             ast_destroy_node(left);
             return NULL;
@@ -1025,9 +1384,13 @@ static ASTNode* parser_parse_logical(Parser* parser) {
     }
     
     /* Handle logical operators */
-    while (parser_check(parser, TOKEN_KEYWORD_AND) || 
-           parser_check(parser, TOKEN_KEYWORD_OR) || 
-           parser_check(parser, TOKEN_KEYWORD_XOR)) {
+    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) {
@@ -1036,11 +1399,17 @@ static ASTNode* parser_parse_logical(Parser* parser) {
         }
         
         const char* operator_name;
-        switch (op->type) {
-        case TOKEN_KEYWORD_AND: operator_name = "and"; break;
-        case TOKEN_KEYWORD_OR: operator_name = "or"; break;
-        case TOKEN_KEYWORD_XOR: operator_name = "xor"; break;
-        default: operator_name = "unknown"; break;
+        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);
@@ -1053,16 +1422,43 @@ static ASTNode* parser_parse_logical(Parser* parser) {
         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 ||
@@ -1084,9 +1480,14 @@ static ASTNode* parser_parse_logical(Parser* parser) {
                                   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 ||
@@ -1102,16 +1503,17 @@ static ASTNode* parser_parse_logical(Parser* parser) {
                 Token* next_next_token = parser->tokens[parser->current + 1];
                 if (next_next_token && next_next_token->type == TOKEN_KEYWORD_THEN) {
                     is_pattern_boundary = true;
-                    printf("DEBUG: Found pattern boundary: %s followed by 'then'\n", next_token->lexeme);
+                    DEBUG_TRACE("Found pattern boundary: %s followed by 'then'", next_token->lexeme);
                 }
             }
         }
         
-        printf("DEBUG: Function application check: can_be_arg=%d, should_not_trigger=%d, is_pattern_boundary=%d\n", 
+                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;
         }
         
@@ -1128,6 +1530,7 @@ static ASTNode* parser_parse_logical(Parser* parser) {
                               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 ||
@@ -1167,7 +1570,7 @@ static ASTNode* parser_parse_logical(Parser* parser) {
                     Token* next_next_token = parser->tokens[parser->current + 1];
                     if (next_next_token && next_next_token->type == TOKEN_KEYWORD_THEN) {
                         is_pattern_boundary = true;
-                        printf("DEBUG: Inner loop found pattern boundary: %s followed by 'then'\n", arg_token->lexeme);
+                        DEBUG_TRACE("Inner loop found pattern boundary: %s followed by 'then'", arg_token->lexeme);
                     }
                 }
             }
@@ -1258,137 +1661,95 @@ static ASTNode* parser_parse_composition(Parser* parser) {
 }
 */
 
+
+
 /**
- * @brief Parse function application (juxtaposition)
- * 
- * @param parser Parser instance
- * @return Parsed expression node
- */
-/**
- * @brief Parse function application (juxtaposition)
+ * @brief Parse postfix operations (table access, function calls, etc.)
  * 
  * @param parser Parser instance
  * @return Parsed expression node
  */
-static ASTNode* parser_parse_application(Parser* parser) {
-    ASTNode* left = parser_parse_logical(parser);
+static ASTNode* parser_parse_postfix(Parser* parser) {
+    ASTNode* left = parser_parse_primary(parser);
     if (left == NULL) {
         return NULL;
     }
     
-    /* Function application is left-associative */
-    while (!parser_is_at_end(parser) && 
-           (parser_peek(parser)->type == TOKEN_IDENTIFIER ||
-            parser_peek(parser)->type == TOKEN_FUNCTION_REF ||
-            parser_peek(parser)->type == TOKEN_NUMBER ||
-            parser_peek(parser)->type == TOKEN_STRING ||
-            parser_peek(parser)->type == TOKEN_LPAREN ||
-            parser_peek(parser)->type == TOKEN_LBRACE ||
-            parser_peek(parser)->type == TOKEN_OP_UNARY_MINUS ||
-            parser_peek(parser)->type == TOKEN_KEYWORD_NOT) &&
-           parser_peek(parser)->type != TOKEN_OP_PLUS &&
-           parser_peek(parser)->type != TOKEN_OP_MINUS &&
-           parser_peek(parser)->type != TOKEN_OP_MULTIPLY &&
-           parser_peek(parser)->type != TOKEN_OP_DIVIDE &&
-           parser_peek(parser)->type != TOKEN_OP_MODULO &&
-           parser_peek(parser)->type != TOKEN_OP_POWER &&
-           parser_peek(parser)->type != TOKEN_OP_EQUALS &&
-           parser_peek(parser)->type != TOKEN_OP_NOT_EQUALS &&
-           parser_peek(parser)->type != TOKEN_OP_LESS &&
-           parser_peek(parser)->type != TOKEN_OP_LESS_EQUAL &&
-           parser_peek(parser)->type != TOKEN_OP_GREATER &&
-           parser_peek(parser)->type != TOKEN_OP_GREATER_EQUAL &&
-           parser_peek(parser)->type != TOKEN_KEYWORD_AND &&
-           parser_peek(parser)->type != TOKEN_KEYWORD_OR &&
-           parser_peek(parser)->type != TOKEN_KEYWORD_XOR &&
-           parser_peek(parser)->type != TOKEN_KEYWORD_WHEN &&
-           parser_peek(parser)->type != TOKEN_KEYWORD_IS &&
-           parser_peek(parser)->type != TOKEN_KEYWORD_THEN &&
-           parser_peek(parser)->type != TOKEN_RPAREN &&
-           parser_peek(parser)->type != TOKEN_RBRACE &&
-           parser_peek(parser)->type != TOKEN_RBRACKET &&
-           parser_peek(parser)->type != TOKEN_SEMICOLON &&
-           parser_peek(parser)->type != TOKEN_COMMA &&
-           parser_peek(parser)->type != TOKEN_EOF) {
-        
-        /* Collect all arguments for this function call */
-        ASTNode** args = NULL;
-        int arg_count = 0;
+    while (!parser_is_at_end(parser)) {
+        Token* token = parser_peek(parser);
+        if (token == NULL) {
+            break;
+        }
         
-        while (!parser_is_at_end(parser) && 
-               (parser_peek(parser)->type == TOKEN_IDENTIFIER ||
-                parser_peek(parser)->type == TOKEN_FUNCTION_REF ||
-                parser_peek(parser)->type == TOKEN_NUMBER ||
-                parser_peek(parser)->type == TOKEN_STRING ||
-                parser_peek(parser)->type == TOKEN_LPAREN ||
-                parser_peek(parser)->type == TOKEN_LBRACE ||
-                parser_peek(parser)->type == TOKEN_OP_UNARY_MINUS ||
-                parser_peek(parser)->type == TOKEN_KEYWORD_NOT) &&
-               parser_peek(parser)->type != TOKEN_OP_PLUS &&
-               parser_peek(parser)->type != TOKEN_OP_MINUS &&
-               parser_peek(parser)->type != TOKEN_OP_MULTIPLY &&
-               parser_peek(parser)->type != TOKEN_OP_DIVIDE &&
-               parser_peek(parser)->type != TOKEN_OP_MODULO &&
-               parser_peek(parser)->type != TOKEN_OP_POWER &&
-               parser_peek(parser)->type != TOKEN_OP_EQUALS &&
-               parser_peek(parser)->type != TOKEN_OP_NOT_EQUALS &&
-               parser_peek(parser)->type != TOKEN_OP_LESS &&
-               parser_peek(parser)->type != TOKEN_OP_LESS_EQUAL &&
-               parser_peek(parser)->type != TOKEN_OP_GREATER &&
-               parser_peek(parser)->type != TOKEN_OP_GREATER_EQUAL &&
-               parser_peek(parser)->type != TOKEN_KEYWORD_AND &&
-               parser_peek(parser)->type != TOKEN_KEYWORD_OR &&
-               parser_peek(parser)->type != TOKEN_KEYWORD_XOR &&
-               parser_peek(parser)->type != TOKEN_KEYWORD_WHEN &&
-               parser_peek(parser)->type != TOKEN_KEYWORD_IS &&
-               parser_peek(parser)->type != TOKEN_KEYWORD_THEN &&
-               parser_peek(parser)->type != TOKEN_RPAREN &&
-               parser_peek(parser)->type != TOKEN_RBRACE &&
-               parser_peek(parser)->type != TOKEN_RBRACKET &&
-               parser_peek(parser)->type != TOKEN_SEMICOLON &&
-               parser_peek(parser)->type != TOKEN_COMMA &&
-               parser_peek(parser)->type != TOKEN_EOF) {
+        switch (token->type) {
+        case TOKEN_DOT: {
+            /* Table property access: table.property */
+            parser_advance(parser); /* consume '.' */
             
-            ASTNode* arg = parser_parse_logical(parser);
-            if (arg == NULL) {
-                /* Cleanup on error */
-                for (int i = 0; i < arg_count; i++) {
-                    ast_destroy_node(args[i]);
-                }
-                free(args);
+            Token* property = parser_consume(parser, TOKEN_IDENTIFIER, "Expected property name after '.'");
+            if (property == NULL) {
                 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);
+            ASTNode* key = ast_literal_node(baba_yaga_value_string(property->lexeme), property->line, property->column);
+            if (key == NULL) {
                 ast_destroy_node(left);
                 return NULL;
             }
-            args = new_args;
-            args[arg_count++] = arg;
+            
+            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;
         }
-        
-        /* 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]);
+        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;
             }
-            free(args);
-            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;
         }
-        
-        left = new_left;
     }
     
     return left;
@@ -1401,7 +1762,7 @@ static ASTNode* parser_parse_application(Parser* parser) {
  * @return Parsed expression node
  */
 static ASTNode* parser_parse_expression(Parser* parser) {
-    return parser_parse_application(parser);
+    return parser_parse_logical(parser);
 }
 
 /* ============================================================================
@@ -1429,6 +1790,8 @@ static ASTNode* parser_parse_variable_decl(Parser* parser) {
         return NULL;
     }
     
+
+    
     ASTNode* node = malloc(sizeof(ASTNode));
     if (node == NULL) {
         ast_destroy_node(value);
@@ -1441,6 +1804,7 @@ static ASTNode* parser_parse_variable_decl(Parser* parser) {
     node->data.variable_decl.name = strdup(name->lexeme);
     node->data.variable_decl.value = value;
     
+
     return node;
 }
 
@@ -1521,6 +1885,73 @@ static ASTNode* parser_parse_function_def(Parser* parser) {
 }
 
 /**
+ * @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
@@ -1992,6 +2423,61 @@ void* baba_yaga_ast_get_when_pattern_result(void* node) {
     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;
@@ -2073,9 +2559,100 @@ void baba_yaga_print_ast(void* node, int indent) {
  * @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;
-    ASTNode* test = parser_parse_expression(parser);
+    
+
+    
+    /* 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; }
@@ -2110,6 +2687,7 @@ static ASTNode* parser_parse_when_expression(Parser* parser) {
     }
     // 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;
 }
 
@@ -2133,19 +2711,19 @@ static bool parser_is_next_pattern(Parser* parser) {
 
 // Parse a result expression for a when pattern, stopping at pattern boundaries
 static ASTNode* parser_parse_when_result_expression(Parser* parser) {
-    printf("DEBUG: parser_parse_when_result_expression start at token %d\n", parser->current);
+    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) {
-        printf("DEBUG: Before parsing result, token type=%d, lexeme='%s'\n", 
+        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)) {
-        printf("DEBUG: Detected next pattern, returning empty result\n");
+        DEBUG_TRACE("Detected next pattern, returning empty result");
         return ast_literal_node(baba_yaga_value_string(""), parser_peek(parser)->line, parser_peek(parser)->column);
     }
     
@@ -2159,68 +2737,219 @@ static ASTNode* parser_parse_when_result_expression(Parser* parser) {
     // Show current token after parsing
     Token* after_token = parser_peek(parser);
     if (after_token) {
-        printf("DEBUG: After parsing result, token type=%d, lexeme='%s'\n", 
+        DEBUG_TRACE("After parsing result, token type=%d, lexeme='%s'", 
                after_token->type, after_token->lexeme ? after_token->lexeme : "NULL");
     }
     
-    printf("DEBUG: parser_parse_when_result_expression end at token %d\n", parser->current);
+    DEBUG_TRACE("parser_parse_when_result_expression end at token %d", parser->current);
     return result;
 }
 
 static ASTNode* parser_parse_when_pattern(Parser* parser) {
-    printf("DEBUG: parser_parse_when_pattern start\n");
+    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) {
-        printf("DEBUG: Current token type=%d, lexeme='%s'\n", current_token->type, current_token->lexeme ? current_token->lexeme : "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;
     }
     
-    /* Check if this is a wildcard pattern (_) */
     ASTNode* pattern_test;
-    if (current_token && current_token->type == TOKEN_IDENTIFIER && 
-        current_token->lexeme && strcmp(current_token->lexeme, "_") == 0) {
-        /* Special handling for wildcard pattern */
-        printf("DEBUG: Found wildcard pattern\n");
+    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("__WILDCARD__"), 
+        pattern_test = ast_literal_node(baba_yaga_value_string("_"), 
                                        current_token->line, current_token->column);
         /* Consume the _ token */
         parser_advance(parser);
-        printf("DEBUG: Consumed _ token, current token type=%d, lexeme='%s'\n", 
+        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 */
-        pattern_test = parser_parse_expression(parser);
+        /* 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) {
-            printf("DEBUG: Failed to parse pattern test expression\n");
+            DEBUG_TRACE("Failed to parse pattern test expression");
             return NULL;
         }
-        printf("DEBUG: Parsed pattern test expression\n");
-    }
-    
-    /* Consume 'then' keyword */
-    Token* then_token = parser_consume(parser, TOKEN_KEYWORD_THEN, "Expected 'then' after pattern");
-    if (then_token == NULL) {
-        printf("DEBUG: Failed to consume 'then' token\n");
-        ast_destroy_node(pattern_test);
-        return NULL;
-    }
-    printf("DEBUG: Consumed 'then' token\n");
-    
-    /* Parse result expression (bounded) */
-    ASTNode* result = parser_parse_when_result_expression(parser);
-    if (result == NULL) {
-        ast_destroy_node(pattern_test);
-        return NULL;
+        DEBUG_TRACE("Parsed pattern test expression");
     }
-    printf("DEBUG: Parsed result expression\n");
     
-    printf("DEBUG: parser_parse_when_pattern success\n");
+    DEBUG_TRACE("parser_parse_when_pattern success");
     
-    /* Create when pattern node */
-    return ast_when_pattern_node(pattern_test, result, 
-                                then_token->line, then_token->column);
+    /* Create when pattern node - only the pattern test, result will be added by caller */
+    return pattern_test;
 }
 
 /* Helper function to get node type name */
diff --git a/js/scripting-lang/baba-yaga-c/src/scope.c b/js/scripting-lang/baba-yaga-c/src/scope.c
index d546989..93ba957 100644
--- a/js/scripting-lang/baba-yaga-c/src/scope.c
+++ b/js/scripting-lang/baba-yaga-c/src/scope.c
@@ -89,6 +89,25 @@ void scope_destroy(Scope* 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
@@ -123,9 +142,11 @@ Value scope_get(Scope* scope, const char* name) {
     
     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);
 }
@@ -218,6 +239,8 @@ bool scope_define(Scope* scope, const char* name, Value value, bool is_constant)
     scope->entries = entry;
     scope->entry_count++;
     
+    DEBUG_DEBUG("scope_define: defined variable '%s' in scope with type %d", name, entry->value.type);
+    
     return true;
 }
 
diff --git a/js/scripting-lang/baba-yaga-c/src/stdlib.c b/js/scripting-lang/baba-yaga-c/src/stdlib.c
index b1b216b..d3ebdea 100644
--- a/js/scripting-lang/baba-yaga-c/src/stdlib.c
+++ b/js/scripting-lang/baba-yaga-c/src/stdlib.c
@@ -16,6 +16,191 @@
 #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
  * ============================================================================ */
 
@@ -409,9 +594,43 @@ Value stdlib_compose(Value* args, int argc) {
         return baba_yaga_value_nil();
     }
     
-    /* For now, implement a simple composition that works with the test case */
-    /* The test "compose add 5 multiply 2" expects: add(5, multiply(x, 2)) */
-    /* This is not true function composition, but matches the test expectation */
+    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 */
@@ -488,8 +707,41 @@ Value stdlib_assert(Value* args, int argc) {
     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) {
+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();
@@ -508,40 +760,547 @@ Value stdlib_map(Value* args, int argc) {
         return baba_yaga_value_nil();
     }
     
-    /* For now, return the original table */
-    /* TODO: Implement actual mapping */
-    DEBUG_DEBUG("map: mapping function over table");
-    return baba_yaga_value_copy(&table);
+    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) {
+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("filter: first argument must be a function");
+        DEBUG_ERROR("t.map: 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");
+        DEBUG_ERROR("t.map: second argument must be a table");
         return baba_yaga_value_nil();
     }
     
-    /* For now, return the original table */
-    /* TODO: Implement actual filtering */
-    DEBUG_DEBUG("filter: filtering table with function");
-    return baba_yaga_value_copy(&table);
+    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;
 }
 
-Value stdlib_reduce(Value* args, int argc) {
+/**
+ * @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("reduce: expected 3 arguments, got %d", argc);
+        DEBUG_ERROR("t.reduce: expected 3 arguments, got %d", argc);
         return baba_yaga_value_nil();
     }
     
@@ -550,17 +1309,262 @@ Value stdlib_reduce(Value* args, int argc) {
     Value table = args[2];
     
     if (func.type != VAL_FUNCTION) {
-        DEBUG_ERROR("reduce: first argument must be a function");
+        DEBUG_ERROR("t.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");
+        DEBUG_ERROR("t.reduce: third argument must be a table");
         return baba_yaga_value_nil();
     }
     
-    /* For now, return the initial value */
-    /* TODO: Implement actual reduction */
-    DEBUG_DEBUG("reduce: reducing table with function");
-    return baba_yaga_value_copy(&initial);
+    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
index 18c3292..0614929 100644
--- a/js/scripting-lang/baba-yaga-c/src/table.c
+++ b/js/scripting-lang/baba-yaga-c/src/table.c
@@ -304,33 +304,44 @@ Value baba_yaga_value_table(void) {
 
 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];
@@ -355,10 +366,12 @@ Value baba_yaga_table_set(const Value* table, const char* key, const Value* valu
     
     /* 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;
 }
 
@@ -444,6 +457,75 @@ bool baba_yaga_table_has_key(const Value* table, const char* key) {
     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
  * ============================================================================ */
diff --git a/js/scripting-lang/baba-yaga-c/src/value.c b/js/scripting-lang/baba-yaga-c/src/value.c
index 25a52fc..562f3a7 100644
--- a/js/scripting-lang/baba-yaga-c/src/value.c
+++ b/js/scripting-lang/baba-yaga-c/src/value.c
@@ -86,6 +86,8 @@ Value baba_yaga_value_copy(const Value* value) {
         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);
@@ -99,9 +101,22 @@ Value baba_yaga_value_copy(const Value* value) {
             return baba_yaga_value_nil();
         }
         
-        /* Copy all entries from the original table */
-        /* This is a simplified copy - in practice we'd need to iterate through all entries */
-        table_increment_ref(&new_table);
+        /* 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: {