/** * @file baba_yaga.h * @brief Main public API header for Baba Yaga interpreter * @author eli_oat * @version 0.0.1 * @date 2025 * * This header provides the public API for the Baba Yaga scripting language * implementation in C. It includes all necessary types, functions, and * constants for interacting with the language interpreter. */ #ifndef BABA_YAGA_H #define BABA_YAGA_H #include #include #ifdef __cplusplus extern "C" { #endif /** * @brief Baba Yaga interpreter instance * * This opaque structure represents a Baba Yaga interpreter instance. * All interpreter operations are performed through this handle. */ typedef struct Interpreter Interpreter; /* Forward declarations for internal types */ typedef struct Scope Scope; typedef struct ASTNode ASTNode; /** * @brief Baba Yaga value types */ typedef enum { VAL_NUMBER, /**< Numeric value (double) */ VAL_STRING, /**< String value (char*) */ VAL_BOOLEAN, /**< Boolean value (bool) */ VAL_TABLE, /**< Table value (opaque) */ VAL_FUNCTION, /**< Function value (opaque) */ VAL_NIL /**< Nil/null value */ } ValueType; /** * @brief Baba Yaga value structure * * Represents a value in the Baba Yaga language. The actual data * is stored in the union based on the type field. */ typedef struct { ValueType type; /**< Type of the value */ union { double number; /**< Numeric value */ char* string; /**< String value */ bool boolean; /**< Boolean value */ void* table; /**< Table value (opaque) */ void* function; /**< Function value (opaque) */ } data; } Value; /** * @brief Baba Yaga execution result */ typedef enum { EXEC_SUCCESS, /**< Execution completed successfully */ EXEC_ERROR, /**< Execution failed with error */ EXEC_SYNTAX_ERROR, /**< Syntax error in source code */ EXEC_RUNTIME_ERROR /**< Runtime error during execution */ } ExecResult; /** * @brief Baba Yaga error information */ typedef struct { char* message; /**< Error message */ int line; /**< Line number where error occurred */ int column; /**< Column number where error occurred */ char* source_file; /**< Source file where error occurred */ } BabaYagaError; /* ============================================================================ * Core API Functions * ============================================================================ */ /** * @brief Create a new Baba Yaga interpreter instance * * @return New interpreter instance, or NULL on failure * * @note The returned interpreter must be freed with baba_yaga_destroy() */ Interpreter* baba_yaga_create(void); /** * @brief Destroy a Baba Yaga interpreter instance * * @param interp Interpreter instance to destroy * * @note This function frees all memory associated with the interpreter */ void baba_yaga_destroy(Interpreter* interp); /** * @brief Execute Baba Yaga source code * * @param interp Interpreter instance * @param source Source code to execute * @param source_len Length of source code (0 for null-terminated) * @param result Output parameter for execution result * @return Value result of execution * * @note The returned value must be freed with baba_yaga_value_destroy() */ Value baba_yaga_execute(Interpreter* interp, const char* source, size_t source_len, ExecResult* result); /** * @brief Execute Baba Yaga source code from file * * @param interp Interpreter instance * @param filename Path to source file * @param result Output parameter for execution result * @return Value result of execution * * @note The returned value must be freed with baba_yaga_value_destroy() */ Value baba_yaga_execute_file(Interpreter* interp, const char* filename, ExecResult* result); /* ============================================================================ * Value Management Functions * ============================================================================ */ /** * @brief Create a number value * * @param number Numeric value * @return New number value */ Value baba_yaga_value_number(double number); /** * @brief Create a string value * * @param string String value (will be copied) * @return New string value * * @note The string is copied internally */ Value baba_yaga_value_string(const char* string); /** * @brief Create a boolean value * * @param boolean Boolean value * @return New boolean value */ Value baba_yaga_value_boolean(bool boolean); /** * @brief Create a nil value * * @return New nil value */ Value baba_yaga_value_nil(void); /** * @brief Destroy a Baba Yaga value * * @param value Value to destroy * * @note This function frees all memory associated with the value */ void baba_yaga_value_destroy(Value* value); /** * @brief Copy a Baba Yaga value * * @param value Value to copy * @return New copy of the value * * @note The returned value must be freed with baba_yaga_value_destroy() */ Value baba_yaga_value_copy(const Value* value); /* ============================================================================ * Table Management Functions * ============================================================================ */ /** * @brief Create a new empty table * * @return New table value */ Value baba_yaga_value_table(void); /** * @brief Get a value from a table by key * * @param table Table value * @param key Key to look up (string) * @return Value at key, or nil if not found */ Value baba_yaga_table_get(const Value* table, const char* key); /** * @brief Set a value in a table by key * * @param table Table value to modify * @param key Key to set (string) * @param value Value to set * @return New table with the updated value * * @note Tables are immutable, so this returns a new table */ Value baba_yaga_table_set(const Value* table, const char* key, const Value* value); /** * @brief Get a value from a table by numeric index * * @param table Table value * @param index Numeric index (1-based) * @return Value at index, or nil if not found */ Value baba_yaga_table_get_index(const Value* table, int index); /** * @brief Set a value in a table by numeric index * * @param table Table value to modify * @param index Numeric index (1-based) * @param value Value to set * @return New table with the updated value * * @note Tables are immutable, so this returns a new table */ Value baba_yaga_table_set_index(const Value* table, int index, const Value* value); /** * @brief Get the size of a table * * @param table Table value * @return Number of elements in the table */ size_t baba_yaga_table_size(const Value* table); /** * @brief Check if a table contains a key * * @param table Table value * @param key Key to check * @return true if key exists, false otherwise */ bool baba_yaga_table_has_key(const Value* table, const char* key); /** * @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); /** * @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); /* ============================================================================ * Function Management Functions * ============================================================================ */ /** * @brief Create a new function value * * @param name Function name (can be NULL for anonymous) * @param param_count Number of parameters * @param required_param_count Number of required parameters * @param body Function body (function pointer) * @return New function value */ Value baba_yaga_value_function(const char* name, Value (*body)(Value*, int), int param_count, int required_param_count); /** * @brief Call a function with arguments * * @param func Function value to call * @param args Array of argument values * @param arg_count Number of arguments * @param scope Current scope for function execution * @return Result of function call */ Value baba_yaga_function_call(const Value* func, const Value* args, int arg_count, Scope* scope); /* ============================================================================ * Internal Table Management Functions * ============================================================================ */ /** * @brief Increment reference count for a table * * @param table Table value */ void table_increment_ref(Value* table); /** * @brief Decrement reference count for a table * * @param table Table value */ void table_decrement_ref(Value* table); /* ============================================================================ * Internal Function Management Functions * ============================================================================ */ /** * @brief Increment reference count for a function * * @param func Function value */ void function_increment_ref(Value* func); /** * @brief Decrement reference count for a function * * @param func Function value */ void function_decrement_ref(Value* func); /* ============================================================================ * 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); /** * @brief Get function parameter count * * @param func Function value * @return Number of parameters */ int function_get_param_count(const Value* func); /** * @brief Get function required parameter count * * @param func Function value * @return Number of required parameters */ int function_get_required_param_count(const Value* func); /* ============================================================================ * Lexer Functions * ============================================================================ */ /** * @brief Tokenize source code * * @param source Source code to tokenize * @param source_len Length of source code * @param tokens Output array for tokens * @param max_tokens Maximum number of tokens to read * @return Number of tokens read, or -1 on error */ int baba_yaga_tokenize(const char* source, size_t source_len, void** tokens, size_t max_tokens); /** * @brief Free tokens * * @param tokens Array of tokens * @param count Number of tokens */ void baba_yaga_free_tokens(void** tokens, size_t count); /* ============================================================================ * Parser Functions * ============================================================================ */ /** * @brief Parse source code into AST * * @param tokens Array of tokens * @param token_count Number of tokens * @return Root AST node, or NULL on error */ /* ============================================================================ * AST Node Types * ============================================================================ */ typedef enum { NODE_LITERAL, NODE_IDENTIFIER, NODE_BINARY_OP, NODE_UNARY_OP, NODE_FUNCTION_CALL, NODE_FUNCTION_DEF, NODE_VARIABLE_DECL, NODE_WHEN_EXPR, NODE_WHEN_PATTERN, NODE_TABLE, NODE_TABLE_ACCESS, NODE_IO_OPERATION, NODE_SEQUENCE } NodeType; void* baba_yaga_parse(void** tokens, size_t token_count); /** * @brief Destroy AST * * @param node Root AST node */ void baba_yaga_destroy_ast(void* node); /* ============================================================================ * AST Accessor Functions * ============================================================================ */ NodeType baba_yaga_ast_get_type(void* node); Value baba_yaga_ast_get_literal(void* node); const char* baba_yaga_ast_get_identifier(void* node); void* baba_yaga_ast_get_function_call_func(void* node); int baba_yaga_ast_get_function_call_arg_count(void* node); void* baba_yaga_ast_get_function_call_arg(void* node, int index); void* baba_yaga_ast_get_binary_op_left(void* node); void* baba_yaga_ast_get_binary_op_right(void* node); const char* baba_yaga_ast_get_binary_op_operator(void* node); void* baba_yaga_ast_get_unary_op_operand(void* node); const char* baba_yaga_ast_get_unary_op_operator(void* node); const char* baba_yaga_ast_get_function_def_name(void* node); int baba_yaga_ast_get_function_def_param_count(void* node); void* baba_yaga_ast_get_function_def_param(void* node, int index); void* baba_yaga_ast_get_function_def_body(void* node); const char* baba_yaga_ast_get_variable_decl_name(void* node); void* baba_yaga_ast_get_variable_decl_value(void* node); /* Sequence node accessors */ int baba_yaga_ast_get_sequence_statement_count(void* node); void* baba_yaga_ast_get_sequence_statement(void* node, int index); /* When expression accessors */ void* baba_yaga_ast_get_when_expr_test(void* node); int baba_yaga_ast_get_when_expr_pattern_count(void* node); void* baba_yaga_ast_get_when_expr_pattern(void* node, int index); void* baba_yaga_ast_get_when_pattern_test(void* node); void* baba_yaga_ast_get_when_pattern_result(void* node); /* Table AST accessor functions */ int baba_yaga_ast_get_table_element_count(void* node); void* baba_yaga_ast_get_table_element(void* node, int index); void* baba_yaga_ast_get_table_access_object(void* node); void* baba_yaga_ast_get_table_access_key(void* node); /** * @brief Print AST for debugging * * @param node Root AST node * @param indent Initial indentation level */ void baba_yaga_print_ast(void* node, int indent); /* ============================================================================ * Debug and Logging Functions * ============================================================================ */ /** * @brief Debug levels */ typedef enum { DEBUG_NONE = 0, DEBUG_ERROR = 1, DEBUG_WARN = 2, DEBUG_INFO = 3, DEBUG_DEBUG = 4, DEBUG_TRACE = 5 } DebugLevel; /** * @brief Set debug level * * @param level Debug level to set */ void baba_yaga_set_debug_level(DebugLevel level); /** * @brief Get current debug level * * @return Current debug level */ DebugLevel baba_yaga_get_debug_level(void); /** * @brief Debug logging function * * @param level Debug level for this message * @param file Source file name * @param line Line number * @param func Function name * @param format Format string * @param ... Variable arguments */ void baba_yaga_debug_log(DebugLevel level, const char* file, int line, const char* func, const char* format, ...); /* Debug macros */ #define DEBUG_ERROR(fmt, ...) \ baba_yaga_debug_log(DEBUG_ERROR, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #define DEBUG_WARN(fmt, ...) \ baba_yaga_debug_log(DEBUG_WARN, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #define DEBUG_INFO(fmt, ...) \ baba_yaga_debug_log(DEBUG_INFO, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #define DEBUG_DEBUG(fmt, ...) \ baba_yaga_debug_log(DEBUG_DEBUG, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) #define DEBUG_TRACE(fmt, ...) \ baba_yaga_debug_log(DEBUG_TRACE, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__) /* ============================================================================ * Error Handling Functions * ============================================================================ */ /** * @brief Get the last error from an interpreter * * @param interp Interpreter instance * @return Error information, or NULL if no error * * @note The returned error must be freed with baba_yaga_error_destroy() */ BabaYagaError* baba_yaga_get_error(const Interpreter* interp); /** * @brief Destroy error information * * @param error Error to destroy * * @note This function frees all memory associated with the error */ void baba_yaga_error_destroy(BabaYagaError* error); /* ============================================================================ * Standard Library Functions * ============================================================================ */ /* Core combinator */ Value stdlib_apply(Value* args, int argc); /* Arithmetic functions */ Value stdlib_add(Value* args, int argc); Value stdlib_subtract(Value* args, int argc); Value stdlib_multiply(Value* args, int argc); Value stdlib_divide(Value* args, int argc); Value stdlib_modulo(Value* args, int argc); Value stdlib_pow(Value* args, int argc); Value stdlib_negate(Value* args, int argc); /* Comparison functions */ Value stdlib_equals(Value* args, int argc); Value stdlib_not_equals(Value* args, int argc); Value stdlib_less(Value* args, int argc); Value stdlib_less_equal(Value* args, int argc); Value stdlib_greater(Value* args, int argc); Value stdlib_greater_equal(Value* args, int argc); /* Logical functions */ Value stdlib_and(Value* args, int argc); Value stdlib_or(Value* args, int argc); Value stdlib_xor(Value* args, int argc); Value stdlib_not(Value* args, int argc); /* Function composition */ Value stdlib_compose(Value* args, int argc); /* IO functions */ Value stdlib_out(Value* args, int argc); Value stdlib_in(Value* args, int argc); Value stdlib_assert(Value* args, int argc); Value stdlib_emit(Value* args, int argc); Value stdlib_listen(Value* args, int argc); /* Higher-order functions */ Value stdlib_map(Value* args, int argc); Value stdlib_filter(Value* args, int argc); Value stdlib_reduce(Value* args, int argc); Value stdlib_each(Value* args, int argc); Value stdlib_flip(Value* args, int argc); Value stdlib_constant(Value* args, int argc); /* Table operations namespace */ Value stdlib_t_map(Value* args, int argc); Value stdlib_t_filter(Value* args, int argc); Value stdlib_t_reduce(Value* args, int argc); Value stdlib_t_set(Value* args, int argc); Value stdlib_t_delete(Value* args, int argc); Value stdlib_t_merge(Value* args, int argc); Value stdlib_t_length(Value* args, int argc); Value stdlib_t_has(Value* args, int argc); Value stdlib_t_get(Value* args, int argc); /* ============================================================================ * Scope Management Functions * ============================================================================ */ /* Scope creation and destruction */ Scope* scope_create(Scope* parent); void scope_destroy(Scope* scope); /* Variable operations */ Value scope_get(Scope* scope, const char* name); bool scope_set(Scope* scope, const char* name, Value value); bool scope_define(Scope* scope, const char* name, Value value, bool is_constant); bool scope_has(Scope* scope, const char* name); /* Scope utilities */ Scope* scope_get_global(Scope* scope); int scope_get_names(Scope* scope, char** names, int max_names); void scope_print(Scope* scope, int indent); /* ============================================================================ * Utility Functions * ============================================================================ */ /** * @brief Get the type of a value * * @param value Value to check * @return Type of the value */ ValueType baba_yaga_value_get_type(const Value* value); /** * @brief Check if a value is truthy * * @param value Value to check * @return true if value is truthy, false otherwise */ bool baba_yaga_value_is_truthy(const Value* value); /** * @brief Convert a value to string representation * * @param value Value to convert * @return String representation (must be freed by caller) * * @note The returned string must be freed with free() */ char* baba_yaga_value_to_string(const Value* value); /* ============================================================================ * Version Information * ============================================================================ */ /** * @brief Get the Baba Yaga C implementation version * * @return Version string (do not free) */ const char* baba_yaga_get_version(void); #ifdef __cplusplus } #endif #endif /* BABA_YAGA_H */