about summary refs log tree commit diff stats
path: root/js/scripting-lang/baba-yaga-c/src/function.c
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src/function.c')
-rw-r--r--js/scripting-lang/baba-yaga-c/src/function.c290
1 files changed, 290 insertions, 0 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/function.c b/js/scripting-lang/baba-yaga-c/src/function.c
new file mode 100644
index 0000000..39265ef
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/function.c
@@ -0,0 +1,290 @@
+/**
+ * @file function.c
+ * @brief Function implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements the function system for the Baba Yaga language.
+ * Functions support closures, partial application, and first-class behavior.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "baba_yaga.h"
+
+/* Forward declarations */
+extern Scope* scope_create(Scope* parent);
+extern void scope_destroy(Scope* scope);
+extern bool scope_define(Scope* scope, const char* name, Value value, bool is_constant);
+extern Value interpreter_evaluate_expression(void* node, Scope* scope);
+
+/* ============================================================================
+ * Function Structure Definitions
+ * ============================================================================ */
+
+/**
+ * @brief Function parameter
+ */
+typedef struct {
+    char* name;         /**< Parameter name */
+    bool is_optional;   /**< Whether parameter is optional */
+} FunctionParam;
+
+typedef enum {
+    FUNC_NATIVE,    /**< Native C function */
+    FUNC_USER       /**< User-defined function */
+} FunctionType;
+
+/**
+ * @brief Function body (placeholder for AST node)
+ */
+typedef struct {
+    void* ast_node;     /**< AST node representing function body */
+    char* source;       /**< Source code for debugging */
+} FunctionBody;
+
+/**
+ * @brief Function value structure
+ */
+typedef struct {
+    char* name;                 /**< Function name (can be NULL for anonymous) */
+    FunctionType type;          /**< Function type */
+    FunctionParam* params;      /**< Array of parameters */
+    int param_count;            /**< Number of parameters */
+    int required_params;        /**< Number of required parameters */
+    union {
+        Value (*native_func)(Value*, int);  /**< Native function pointer */
+        FunctionBody user_body;             /**< User function body */
+    } body;
+    void* closure_scope;        /**< Closure scope (placeholder) */
+    int ref_count;              /**< Reference count for memory management */
+} FunctionValue;
+
+/* ============================================================================
+ * Function Creation and Management
+ * ============================================================================ */
+
+/* TODO: Implement parameter management functions */
+
+/**
+ * @brief Destroy a function body
+ * 
+ * @param body Function body to destroy
+ */
+static void function_body_destroy(FunctionBody* body) {
+    if (body != NULL && body->source != NULL) {
+        free(body->source);
+        body->source = NULL;
+    }
+    /* Note: ast_node cleanup will be handled by AST system */
+}
+
+/* ============================================================================
+ * Public Function API
+ * ============================================================================ */
+
+Value baba_yaga_value_function(const char* name, Value (*body)(Value*, int), 
+                              int param_count, int required_param_count) {
+    Value value;
+    value.type = VAL_FUNCTION;
+    
+    FunctionValue* func_value = malloc(sizeof(FunctionValue));
+    if (func_value == NULL) {
+        value.type = VAL_NIL;
+        return value;
+    }
+    
+    func_value->name = name != NULL ? strdup(name) : NULL;
+    func_value->type = FUNC_NATIVE;
+    func_value->param_count = param_count;
+    func_value->required_params = required_param_count;
+    func_value->ref_count = 1;
+    func_value->closure_scope = NULL; /* TODO: Implement closure scope */
+    
+    /* Allocate parameter array */
+    if (param_count > 0) {
+        func_value->params = calloc(param_count, sizeof(FunctionParam));
+        if (func_value->params == NULL) {
+            free(func_value->name);
+            free(func_value);
+            value.type = VAL_NIL;
+            return value;
+        }
+        
+        /* Initialize parameters with placeholder names */
+        for (int i = 0; i < param_count; i++) {
+            char param_name[16];
+            snprintf(param_name, sizeof(param_name), "param_%d", i + 1);
+            func_value->params[i].name = strdup(param_name);
+            func_value->params[i].is_optional = (i >= required_param_count);
+        }
+    } else {
+        func_value->params = NULL;
+    }
+    
+    /* Set native function pointer */
+    func_value->body.native_func = body;
+    
+    value.data.function = func_value;
+    return value;
+}
+
+Value baba_yaga_function_call(const Value* func, const Value* args, 
+                             int arg_count, Scope* scope) {
+    if (func == NULL || func->type != VAL_FUNCTION || args == NULL) {
+        return baba_yaga_value_nil();
+    }
+    
+    FunctionValue* func_value = (FunctionValue*)func->data.function;
+    
+    /* Check if we have enough arguments */
+    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();
+    }
+    
+    /* 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);
+        }
+        break;
+        
+    case FUNC_USER:
+        /* 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 */
+            if (func_scope == NULL) {
+                DEBUG_ERROR("Failed to create function scope");
+                return baba_yaga_value_nil();
+            }
+            
+            /* Bind parameters to arguments */
+            for (int i = 0; i < arg_count && i < func_value->param_count; i++) {
+                const char* param_name = func_value->params[i].name;
+                if (param_name != NULL) {
+                    scope_define(func_scope, param_name, args[i], false);
+                }
+            }
+            
+            /* Execute function body */
+            Value result = interpreter_evaluate_expression(
+                func_value->body.user_body.ast_node, 
+                func_scope
+            );
+            
+            /* Clean up function scope */
+            scope_destroy(func_scope);
+            
+            return result;
+        }
+        break;
+    }
+    
+    return baba_yaga_value_nil();
+}
+
+/* ============================================================================
+ * Internal Function Management
+ * ============================================================================ */
+
+/**
+ * @brief Increment reference count for a function
+ * 
+ * @param func Function value
+ */
+void function_increment_ref(Value* func) {
+    if (func != NULL && func->type == VAL_FUNCTION) {
+        FunctionValue* func_value = (FunctionValue*)func->data.function;
+        func_value->ref_count++;
+    }
+}
+
+/**
+ * @brief Decrement reference count for a function
+ * 
+ * @param func Function value
+ */
+void function_decrement_ref(Value* func) {
+    if (func != NULL && func->type == VAL_FUNCTION) {
+        FunctionValue* func_value = (FunctionValue*)func->data.function;
+        func_value->ref_count--;
+        
+        if (func_value->ref_count <= 0) {
+            /* Clean up function */
+            free(func_value->name);
+            
+            /* Clean up parameters */
+            if (func_value->params != NULL) {
+                for (int i = 0; i < func_value->param_count; i++) {
+                    free(func_value->params[i].name);
+                }
+                free(func_value->params);
+            }
+            
+                    /* Clean up function body */
+        if (func_value->type == FUNC_USER) {
+            function_body_destroy(&func_value->body.user_body);
+        }
+            
+            /* TODO: Clean up closure scope */
+            
+            free(func_value);
+        }
+    }
+}
+
+/* ============================================================================
+ * Function Utility Functions
+ * ============================================================================ */
+
+/**
+ * @brief Get function name
+ * 
+ * @param func Function value
+ * @return Function name, or NULL if anonymous
+ */
+const char* function_get_name(const Value* func) {
+    if (func == NULL || func->type != VAL_FUNCTION) {
+        return NULL;
+    }
+    
+    FunctionValue* func_value = (FunctionValue*)func->data.function;
+    return func_value->name;
+}
+
+/**
+ * @brief Get function parameter count
+ * 
+ * @param func Function value
+ * @return Number of parameters
+ */
+int function_get_param_count(const Value* func) {
+    if (func == NULL || func->type != VAL_FUNCTION) {
+        return 0;
+    }
+    
+    FunctionValue* func_value = (FunctionValue*)func->data.function;
+    return func_value->param_count;
+}
+
+/**
+ * @brief Get function required parameter count
+ * 
+ * @param func Function value
+ * @return Number of required parameters
+ */
+int function_get_required_param_count(const Value* func) {
+    if (func == NULL || func->type != VAL_FUNCTION) {
+        return 0;
+    }
+    
+    FunctionValue* func_value = (FunctionValue*)func->data.function;
+    return func_value->required_params;
+}