#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