diff options
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src/function.c')
-rw-r--r-- | js/scripting-lang/baba-yaga-c/src/function.c | 290 |
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; +} |