diff --git a/src/ground_lib.h b/src/ground_lib.h new file mode 100644 index 0000000..7567cf1 --- /dev/null +++ b/src/ground_lib.h @@ -0,0 +1,193 @@ +#ifndef GROUND_LIB_H +#define GROUND_LIB_H + +#include +#include +#include +#include + +// Ground types - must match the interpreter +typedef enum { + GROUND_INT, + GROUND_DOUBLE, + GROUND_BOOL, + GROUND_STRING, + GROUND_CHAR +} GroundType; + +typedef struct { + GroundType type; + union { + int int_val; + double double_val; + int bool_val; + char* string_val; + char char_val; + } data; +} GroundValue; + +// Helper macros for creating GroundValue objects +#define GROUND_INT_VAL(x) ({ GroundValue v; v.type = GROUND_INT; v.data.int_val = (x); v; }) +#define GROUND_DOUBLE_VAL(x) ({ GroundValue v; v.type = GROUND_DOUBLE; v.data.double_val = (x); v; }) +#define GROUND_BOOL_VAL(x) ({ GroundValue v; v.type = GROUND_BOOL; v.data.bool_val = (x) ? 1 : 0; v; }) +#define GROUND_CHAR_VAL(x) ({ GroundValue v; v.type = GROUND_CHAR; v.data.char_val = (x); v; }) + +// Helper function for creating string values +inline GroundValue ground_string_val(const std::string& str) { + GroundValue v; + v.type = GROUND_STRING; + char* result_str = new char[str.length() + 1]; + std::strcpy(result_str, str.c_str()); + v.data.string_val = result_str; + return v; +} + +// Helper function for creating string values from C strings +inline GroundValue ground_cstring_val(const char* str) { + GroundValue v; + v.type = GROUND_STRING; + if (str) { + size_t len = std::strlen(str); + char* result_str = new char[len + 1]; + std::strcpy(result_str, str); + v.data.string_val = result_str; + } else { + v.data.string_val = nullptr; + } + return v; +} + +// Helper macros for type checking +#define IS_INT(v) ((v).type == GROUND_INT) +#define IS_DOUBLE(v) ((v).type == GROUND_DOUBLE) +#define IS_BOOL(v) ((v).type == GROUND_BOOL) +#define IS_STRING(v) ((v).type == GROUND_STRING) +#define IS_CHAR(v) ((v).type == GROUND_CHAR) + +// Helper macros for extracting values +#define GET_INT(v) ((v).data.int_val) +#define GET_DOUBLE(v) ((v).data.double_val) +#define GET_BOOL(v) ((v).data.bool_val != 0) +#define GET_STRING(v) ((v).data.string_val) +#define GET_CHAR(v) ((v).data.char_val) + +// Helper macros for argument validation +#define REQUIRE_ARGS(count) \ + if (arg_count < (count)) { \ + std::cerr << "Error: Expected at least " << (count) << " arguments, got " << arg_count << std::endl; \ + return GROUND_BOOL_VAL(false); \ + } + +#define REQUIRE_TYPE(arg_index, expected_type) \ + if (args[arg_index].type != expected_type) { \ + std::cerr << "Error: Argument " << (arg_index + 1) << " must be of type " << #expected_type << std::endl; \ + return GROUND_BOOL_VAL(false); \ + } + +// Convenience macro for checking both arg count and types +#define VALIDATE_ARGS_1(type1) \ + REQUIRE_ARGS(1); \ + REQUIRE_TYPE(0, type1); + +#define VALIDATE_ARGS_2(type1, type2) \ + REQUIRE_ARGS(2); \ + REQUIRE_TYPE(0, type1); \ + REQUIRE_TYPE(1, type2); + +#define VALIDATE_ARGS_3(type1, type2, type3) \ + REQUIRE_ARGS(3); \ + REQUIRE_TYPE(0, type1); \ + REQUIRE_TYPE(1, type2); \ + REQUIRE_TYPE(2, type3); + +// Function registration helpers +class GroundLibrary { +private: + std::vector function_names; + std::vector function_pointers; + +public: + void register_function(const std::string& name, void* ptr) { + function_names.push_back(name); + function_pointers.push_back(ptr); + } + + const char** get_function_names() { + static std::vector names; + names.clear(); + for (const auto& name : function_names) { + names.push_back(name.c_str()); + } + names.push_back(nullptr); // Null terminator + return names.data(); + } + + void* get_function(const char* name) { + for (size_t i = 0; i < function_names.size(); i++) { + if (function_names[i] == name) { + return function_pointers[i]; + } + } + return nullptr; + } +}; + +// Global library instance +extern GroundLibrary ground_lib_registry; + +// Macro to register functions easily +#define REGISTER_GROUND_FUNCTION(func_name) \ + ground_lib_registry.register_function(#func_name, (void*)func_name) + +// Macro to define the library interface +#define GROUND_LIBRARY_INTERFACE() \ + GroundLibrary ground_lib_registry; \ + extern "C" { \ + const char** ground_get_functions() { \ + return ground_lib_registry.get_function_names(); \ + } \ + void* ground_get_function(const char* name) { \ + return ground_lib_registry.get_function(name); \ + } \ + } + +// Optional initialization macro +#define GROUND_LIBRARY_INIT() \ + extern "C" { \ + void ground_lib_init() { + +#define GROUND_LIBRARY_INIT_END() \ + } \ + } + +// Optional cleanup macro +#define GROUND_LIBRARY_CLEANUP() \ + extern "C" { \ + void ground_lib_cleanup() { + +#define GROUND_LIBRARY_CLEANUP_END() \ + } \ + } + +// Utility function to print GroundValue for debugging +inline void debug_print_ground_value(const GroundValue& v) { + switch (v.type) { + case GROUND_INT: + std::cout << "INT: " << v.data.int_val << std::endl; + break; + case GROUND_DOUBLE: + std::cout << "DOUBLE: " << v.data.double_val << std::endl; + break; + case GROUND_BOOL: + std::cout << "BOOL: " << (v.data.bool_val ? "true" : "false") << std::endl; + break; + case GROUND_STRING: + std::cout << "STRING: " << (v.data.string_val ? v.data.string_val : "(null)") << std::endl; + break; + case GROUND_CHAR: + std::cout << "CHAR: '" << v.data.char_val << "'" << std::endl; + break; + } +} + +#endif // GROUND_LIB_H