about summary refs log tree commit diff stats
path: root/js/scripting-lang/baba-yaga-c/src/stdlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src/stdlib.c')
-rw-r--r--js/scripting-lang/baba-yaga-c/src/stdlib.c697
1 files changed, 668 insertions, 29 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/stdlib.c b/js/scripting-lang/baba-yaga-c/src/stdlib.c
index d130f05..ed34541 100644
--- a/js/scripting-lang/baba-yaga-c/src/stdlib.c
+++ b/js/scripting-lang/baba-yaga-c/src/stdlib.c
@@ -47,7 +47,7 @@ Value stdlib_apply(Value* args, int argc) {
     
     /* Full application: call the function with all remaining arguments */
     DEBUG_DEBUG("apply: calling function with %d arguments", argc - 1);
-    return baba_yaga_function_call(&func, &args[1], argc - 1);
+    return baba_yaga_function_call(&func, &args[1], argc - 1, NULL);
 }
 
 /* Arithmetic functions */
@@ -196,26 +196,30 @@ Value stdlib_equals(Value* args, int argc) {
     Value left = args[0];
     Value right = args[1];
     
+    /* Type checking: both arguments must be of the same type */
+    if (left.type != right.type) {
+        DEBUG_ERROR("equals: arguments must be of the same type");
+        return baba_yaga_value_nil();
+    }
+    
     bool result = false;
     
-    if (left.type == right.type) {
-        switch (left.type) {
-        case VAL_NUMBER:
-            result = left.data.number == right.data.number;
-            break;
-        case VAL_STRING:
-            result = strcmp(left.data.string, right.data.string) == 0;
-            break;
-        case VAL_BOOLEAN:
-            result = left.data.boolean == right.data.boolean;
-            break;
-        case VAL_NIL:
-            result = true;
-            break;
-        default:
-            result = false;
-            break;
-        }
+    switch (left.type) {
+    case VAL_NUMBER:
+        result = left.data.number == right.data.number;
+        break;
+    case VAL_STRING:
+        result = strcmp(left.data.string, right.data.string) == 0;
+        break;
+    case VAL_BOOLEAN:
+        result = left.data.boolean == right.data.boolean;
+        break;
+    case VAL_NIL:
+        result = true;
+        break;
+    default:
+        result = false;
+        break;
     }
     
     return baba_yaga_value_boolean(result);
@@ -339,10 +343,13 @@ Value stdlib_and(Value* args, int argc) {
     Value left = args[0];
     Value right = args[1];
     
-    bool left_truthy = baba_yaga_value_is_truthy(&left);
-    bool right_truthy = baba_yaga_value_is_truthy(&right);
+    /* Type checking: both arguments must be booleans */
+    if (left.type != VAL_BOOLEAN || right.type != VAL_BOOLEAN) {
+        DEBUG_ERROR("and: arguments must be booleans");
+        return baba_yaga_value_nil();
+    }
     
-    bool result = left_truthy && right_truthy;
+    bool result = left.data.boolean && right.data.boolean;
     return baba_yaga_value_boolean(result);
 }
 
@@ -385,9 +392,14 @@ Value stdlib_not(Value* args, int argc) {
     }
     
     Value arg = args[0];
-    bool truthy = baba_yaga_value_is_truthy(&arg);
     
-    return baba_yaga_value_boolean(!truthy);
+    /* Type checking: argument must be a boolean */
+    if (arg.type != VAL_BOOLEAN) {
+        DEBUG_ERROR("not: argument must be a boolean");
+        return baba_yaga_value_nil();
+    }
+    
+    return baba_yaga_value_boolean(!arg.data.boolean);
 }
 
 /* Function composition */
@@ -397,9 +409,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 */
@@ -416,9 +462,9 @@ Value stdlib_compose(Value* args, int argc) {
         /* Create a composed function that does: add(5, multiply(x, 2)) */
         /* For now, just return the result of add(5, multiply(5, 2)) = add(5, 10) = 15 */
         Value temp_args[2] = {arg2, arg1}; /* multiply(2, 5) = 10 */
-        Value temp_result = baba_yaga_function_call(&g, temp_args, 2);
+        Value temp_result = baba_yaga_function_call(&g, temp_args, 2, NULL);
         Value final_args[2] = {arg1, temp_result}; /* add(5, 10) */
-        Value result = baba_yaga_function_call(&f, final_args, 2);
+        Value result = baba_yaga_function_call(&f, final_args, 2, NULL);
         
         baba_yaga_value_destroy(&temp_result);
         return result;
@@ -476,6 +522,39 @@ 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) {
     if (argc != 2) {
@@ -551,4 +630,564 @@ Value stdlib_reduce(Value* args, int argc) {
     /* TODO: Implement actual reduction */
     DEBUG_DEBUG("reduce: reducing table with function");
     return baba_yaga_value_copy(&initial);
+}
+
+/**
+ * @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) {
+    if (argc != 3) {
+        DEBUG_ERROR("each: expected 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    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, NULL);
+                
+                /* 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, NULL);
+                
+                /* 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 Flip combinator - reverses argument order of a function
+ * 
+ * @param args Array of arguments [function] or [function, arg1, arg2]
+ * @param argc Number of arguments (should be 1 or 3)
+ * @return Flipped function or result of flipped function application
+ */
+Value stdlib_flip(Value* args, int argc) {
+    if (argc != 1 && argc != 3) {
+        DEBUG_ERROR("flip: expected 1 or 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("flip: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (argc == 1) {
+        /* Partial application: return the flipped function */
+        DEBUG_DEBUG("flip: partial application, returning flipped function");
+        return baba_yaga_value_copy(&func);
+    }
+    
+    /* Full application: flip(arg1, arg2) = func(arg2, arg1) */
+    Value arg1 = args[1];
+    Value arg2 = args[2];
+    
+    DEBUG_DEBUG("flip: applying function with flipped arguments");
+    
+    /* Call function with arguments in reverse order */
+    Value func_args[2] = {arg2, arg1}; /* Reversed order */
+    Value result = baba_yaga_function_call(&func, func_args, 2, NULL);
+    
+    return result;
+}
+
+/**
+ * @brief Constant combinator - creates a function that returns a constant value
+ * 
+ * @param args Array of arguments [value] or [value, ignored_arg]
+ * @param argc Number of arguments (should be 1 or 2)
+ * @return Constant function or constant value
+ */
+Value stdlib_constant(Value* args, int argc) {
+    if (argc != 1 && argc != 2) {
+        DEBUG_ERROR("constant: expected 1 or 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value constant_value = args[0];
+    
+    if (argc == 1) {
+        /* Partial application: return a function that always returns the constant */
+        DEBUG_DEBUG("constant: partial application, returning constant function");
+        return baba_yaga_value_copy(&constant_value);
+    }
+    
+    /* Full application: constant(value, ignored_arg) = value */
+    DEBUG_DEBUG("constant: returning constant value, ignoring second argument");
+    return baba_yaga_value_copy(&constant_value);
+}
+
+/* ============================================================================
+ * Table Operations Namespace (t.* functions)
+ * ============================================================================ */
+
+/**
+ * @brief Table map operation - apply function to each value in table
+ * 
+ * @param args Array of arguments [function, table]
+ * @param argc Number of arguments (should be 2)
+ * @return New table with function applied to each value
+ */
+Value stdlib_t_map(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.map: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    Value table = args[1];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("t.map: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.map: second argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.map: applying function to each value in table");
+    
+    /* Get all keys from the table */
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    
+    /* Create result table */
+    Value result = baba_yaga_value_table();
+    
+    /* Apply function to each value */
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (value.type != VAL_NIL) {
+            /* Call function with the value */
+            Value func_args[1] = {value};
+            Value mapped_value = baba_yaga_function_call(&func, func_args, 1, NULL);
+            
+            /* Add result to new table with same key */
+            result = baba_yaga_table_set(&result, keys[i], &mapped_value);
+        }
+        free(keys[i]);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Table filter operation - keep only values that satisfy predicate
+ * 
+ * @param args Array of arguments [function, table]
+ * @param argc Number of arguments (should be 2)
+ * @return New table with only values that satisfy the predicate
+ */
+Value stdlib_t_filter(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.filter: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    Value table = args[1];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("t.filter: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.filter: second argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.filter: filtering table with predicate");
+    
+    /* Get all keys from the table */
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    
+    /* Create result table */
+    Value result = baba_yaga_value_table();
+    int result_index = 1; /* 1-based indexing for filtered results */
+    
+    /* Apply predicate to each value */
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (value.type != VAL_NIL) {
+            /* Call predicate function with the value */
+            Value func_args[1] = {value};
+            Value predicate_result = baba_yaga_function_call(&func, func_args, 1, NULL);
+            
+            /* If predicate returns true, keep the value */
+            if (baba_yaga_value_is_truthy(&predicate_result)) {
+                char key_str[32];
+                snprintf(key_str, sizeof(key_str), "%d", result_index++);
+                result = baba_yaga_table_set(&result, key_str, &value);
+            }
+        }
+        free(keys[i]);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Table reduce operation - combine all values with a function
+ * 
+ * @param args Array of arguments [function, initial_value, table]
+ * @param argc Number of arguments (should be 3)
+ * @return Result of reducing the table
+ */
+Value stdlib_t_reduce(Value* args, int argc) {
+    if (argc != 3) {
+        DEBUG_ERROR("t.reduce: expected 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value func = args[0];
+    Value initial = args[1];
+    Value table = args[2];
+    
+    if (func.type != VAL_FUNCTION) {
+        DEBUG_ERROR("t.reduce: first argument must be a function");
+        return baba_yaga_value_nil();
+    }
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.reduce: third argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.reduce: reducing table with function");
+    
+    /* Get all keys from the table */
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table, keys, 1000);
+    
+    /* Start with initial value */
+    Value result = baba_yaga_value_copy(&initial);
+    
+    /* Apply function to each value */
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table, keys[i]);
+        if (value.type != VAL_NIL) {
+            /* Call function with accumulator and current value */
+            Value func_args[2] = {result, value};
+            Value new_result = baba_yaga_function_call(&func, func_args, 2, NULL);
+            
+            baba_yaga_value_destroy(&result);
+            result = new_result;
+        }
+        free(keys[i]);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Table set operation - immutable update
+ * 
+ * @param args Array of arguments [table, key, value]
+ * @param argc Number of arguments (should be 3)
+ * @return New table with updated value
+ */
+Value stdlib_t_set(Value* args, int argc) {
+    if (argc != 3) {
+        DEBUG_ERROR("t.set: expected 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    Value key = args[1];
+    Value value = args[2];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.set: first argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    if (key.type != VAL_STRING) {
+        DEBUG_ERROR("t.set: second argument must be a string");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.set: setting key '%s' in table", key.data.string);
+    
+    /* Create new table with the updated value */
+    return baba_yaga_table_set(&table, key.data.string, &value);
+}
+
+/**
+ * @brief Table delete operation - immutable deletion
+ * 
+ * @param args Array of arguments [table, key]
+ * @param argc Number of arguments (should be 2)
+ * @return New table without the specified key
+ */
+Value stdlib_t_delete(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.delete: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    Value key = args[1];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.delete: first argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    if (key.type != VAL_STRING) {
+        DEBUG_ERROR("t.delete: second argument must be a string");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.delete: deleting key '%s' from table", key.data.string);
+    
+    /* For now, return the original table since we don't have delete functionality */
+    /* TODO: Implement actual deletion */
+    return baba_yaga_value_copy(&table);
+}
+
+/**
+ * @brief Table merge operation - immutable merge
+ * 
+ * @param args Array of arguments [table1, table2]
+ * @param argc Number of arguments (should be 2)
+ * @return New table with merged contents
+ */
+Value stdlib_t_merge(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.merge: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table1 = args[0];
+    Value table2 = args[1];
+    
+    if (table1.type != VAL_TABLE || table2.type != VAL_TABLE) {
+        DEBUG_ERROR("t.merge: both arguments must be tables");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.merge: merging two tables");
+    
+    /* Start with first table */
+    Value result = baba_yaga_value_copy(&table1);
+    
+    /* Get all keys from second table */
+    char* keys[1000];
+    size_t key_count = baba_yaga_table_get_keys(&table2, keys, 1000);
+    
+    /* Add all entries from second table */
+    for (size_t i = 0; i < key_count; i++) {
+        Value value = baba_yaga_table_get_by_key(&table2, keys[i]);
+        if (value.type != VAL_NIL) {
+            result = baba_yaga_table_set(&result, keys[i], &value);
+        }
+        free(keys[i]);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Table length operation - get number of entries
+ * 
+ * @param args Array of arguments [table]
+ * @param argc Number of arguments (should be 1)
+ * @return Number of entries in the table
+ */
+Value stdlib_t_length(Value* args, int argc) {
+    if (argc != 1) {
+        DEBUG_ERROR("t.length: expected 1 argument, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.length: argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    size_t length = baba_yaga_table_size(&table);
+    DEBUG_DEBUG("t.length: table has %zu entries", length);
+    
+    return baba_yaga_value_number((double)length);
+}
+
+/**
+ * @brief Table has operation - check if key exists
+ * 
+ * @param args Array of arguments [table, key]
+ * @param argc Number of arguments (should be 2)
+ * @return Boolean indicating if key exists
+ */
+Value stdlib_t_has(Value* args, int argc) {
+    if (argc != 2) {
+        DEBUG_ERROR("t.has: expected 2 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    Value key = args[1];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.has: first argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    if (key.type != VAL_STRING) {
+        DEBUG_ERROR("t.has: second argument must be a string");
+        return baba_yaga_value_nil();
+    }
+    
+    bool has_key = baba_yaga_table_has_key(&table, key.data.string);
+    DEBUG_DEBUG("t.has: key '%s' %s in table", key.data.string, has_key ? "exists" : "does not exist");
+    
+    return baba_yaga_value_boolean(has_key);
+}
+
+/**
+ * @brief Table get operation - get value with default
+ * 
+ * @param args Array of arguments [table, key, default_value]
+ * @param argc Number of arguments (should be 3)
+ * @return Value from table or default if key doesn't exist
+ */
+Value stdlib_t_get(Value* args, int argc) {
+    if (argc != 3) {
+        DEBUG_ERROR("t.get: expected 3 arguments, got %d", argc);
+        return baba_yaga_value_nil();
+    }
+    
+    Value table = args[0];
+    Value key = args[1];
+    Value default_value = args[2];
+    
+    if (table.type != VAL_TABLE) {
+        DEBUG_ERROR("t.get: first argument must be a table");
+        return baba_yaga_value_nil();
+    }
+    
+    if (key.type != VAL_STRING) {
+        DEBUG_ERROR("t.get: second argument must be a string");
+        return baba_yaga_value_nil();
+    }
+    
+    DEBUG_DEBUG("t.get: getting key '%s' from table", key.data.string);
+    
+    /* Try to get the value from the table */
+    Value result = baba_yaga_table_get(&table, key.data.string);
+    
+    /* If key doesn't exist, return default value */
+    if (result.type == VAL_NIL) {
+        return baba_yaga_value_copy(&default_value);
+    }
+    
+    return result;
+}
+
+/**
+ * @brief Internal function for table key-value pairs
+ * 
+ * @param args Array of arguments [key, value]
+ * @param argc Number of arguments (should be 2)
+ * @return Value containing the key-value pair
+ */
+Value stdlib_table_entry(Value* args, int argc) {
+    if (argc != 2) {
+        return baba_yaga_value_nil();
+    }
+    
+    /* Create a special table entry value that can be used by table evaluation */
+    Value value = args[1];
+    
+    /* For now, return the value directly - the table evaluation will handle the key */
+    return value;
 }