194 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef GROUND_LIB_H
 | |
| #define GROUND_LIB_H
 | |
| 
 | |
| #include <cstring>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| #include <iostream>
 | |
| 
 | |
| // 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<std::string> function_names;
 | |
|     std::vector<void*> 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<const char*> 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
 |