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.c431
1 files changed, 404 insertions, 27 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/stdlib.c b/js/scripting-lang/baba-yaga-c/src/stdlib.c
index ed34541..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
  * ============================================================================ */
 
@@ -556,7 +741,7 @@ Value stdlib_listen(Value* args, int argc) {
 }
 
 /* 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();
@@ -575,61 +760,90 @@ 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();
     }
-    
-    /* 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("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) {
+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();
     }
-    
-    /* For now, return the initial value */
-    /* TODO: Implement actual reduction */
     DEBUG_DEBUG("reduce: reducing table with function");
-    return baba_yaga_value_copy(&initial);
+    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;
 }
 
 /**
@@ -639,12 +853,37 @@ Value stdlib_reduce(Value* args, int argc) {
  * @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);
+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];
     
@@ -694,7 +933,7 @@ Value stdlib_each(Value* args, int argc) {
                 Value func_args[2];
                 func_args[0] = element1;
                 func_args[1] = element2;
-                Value element_result = baba_yaga_function_call(&func, func_args, 2, NULL);
+                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);
@@ -719,7 +958,7 @@ Value stdlib_each(Value* args, int argc) {
                 Value func_args[2];
                 func_args[0] = element;
                 func_args[1] = arg3;
-                Value element_result = baba_yaga_function_call(&func, func_args, 2, NULL);
+                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);
@@ -737,6 +976,144 @@ Value stdlib_each(Value* args, int argc) {
 }
 
 /**
+ * @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]