Initial commit
This commit is contained in:
		
							
								
								
									
										3
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # Ground Libraries | ||||
|  | ||||
| These are some libraries coded in C++ for Ground. All are avaliable for anyone to use. | ||||
							
								
								
									
										15
									
								
								compileall.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										15
									
								
								compileall.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| echo "This script is designed for Linux systems" | ||||
| echo "Please ensure CPR is installed on your system before continuing" | ||||
| echo "On Arch Linux: sudo pacman -S cpr" | ||||
|  | ||||
| echo "Compiling exec library" | ||||
| g++ -shared -fPIC -o exec.so exec/exec.cpp | ||||
| echo "Compiling file library" | ||||
| g++ -shared -fPIC -o file.so file/file.cpp | ||||
| echo "Compiling math library" | ||||
| g++ -shared -fPIC -o math.so math/math.cpp | ||||
| echo "Compiling request library" | ||||
| g++ -shared -fPIC -lcpr -o request.so request/request.cpp | ||||
| echo "Done" | ||||
							
								
								
									
										9
									
								
								compiling.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								compiling.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| ## Compiling External Libraries | ||||
|  | ||||
| On Linux: | ||||
|  | ||||
| `g++ -shared -fPIC -o filename.so filename.cpp` | ||||
|  | ||||
| On macOS: | ||||
|  | ||||
| `g++ -shared -fPIC -o filename.dylib filename.cpp` | ||||
							
								
								
									
										9
									
								
								exec/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								exec/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| # exec library | ||||
|  | ||||
| This library allows executing third party executables via the C++ "system" command. | ||||
|  | ||||
| ## Functions | ||||
|  | ||||
| ### fun -int !exec -string &command | ||||
|  | ||||
| Runs a command on a system. Returns the status code of that command. | ||||
							
								
								
									
										16
									
								
								exec/exec.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								exec/exec.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| #include "ground_lib.h" | ||||
|  | ||||
| GroundValue exec(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_STRING); | ||||
|     int exec = system(GET_STRING(args[0])); | ||||
|     return GROUND_INT_VAL(exec); | ||||
| } | ||||
|  | ||||
| GROUND_LIBRARY_INTERFACE() | ||||
|  | ||||
| GROUND_LIBRARY_INIT() | ||||
|     REGISTER_GROUND_FUNCTION(exec); | ||||
| GROUND_LIBRARY_INIT_END() | ||||
|  | ||||
| GROUND_LIBRARY_CLEANUP() | ||||
| GROUND_LIBRARY_CLEANUP_END() | ||||
							
								
								
									
										193
									
								
								exec/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								exec/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| #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 | ||||
							
								
								
									
										13
									
								
								file/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								file/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| # file library | ||||
|  | ||||
| This library allows reading from and writing to files on the system. | ||||
|  | ||||
| ## Functions | ||||
|  | ||||
| ### fun -string !readFile -string &fileName | ||||
|  | ||||
| This function reads all content from a file and returns it. | ||||
|  | ||||
| ### fun -bool !writeFile -string &fileName -string &content | ||||
|  | ||||
| This function overwrites a file with specified content. If successful, returns true. If not successful, returns false, and prints out a reason why it didn't work. | ||||
							
								
								
									
										43
									
								
								file/file.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								file/file.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| #include "ground_lib.h" | ||||
|  | ||||
| #include <fstream> | ||||
| #include <filesystem> | ||||
|  | ||||
| GroundValue readFile(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_STRING); | ||||
|  | ||||
|     std::ifstream ffile(GET_STRING(args[0])); | ||||
|  | ||||
|     std::string tmp; | ||||
|     std::string out; | ||||
|  | ||||
|     while (std::getline(ffile, tmp)) { | ||||
|         out += tmp + "\n"; | ||||
|     } | ||||
|      | ||||
|     return ground_string_val(out); | ||||
| } | ||||
|  | ||||
| GroundValue writeFile(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_2(GROUND_STRING, GROUND_STRING); | ||||
|  | ||||
|     std::ofstream file(GET_STRING(args[0])); | ||||
|     if (file.good()) { | ||||
|         file << GET_STRING(args[1]); | ||||
|     } else { | ||||
|         std::cout << "File isn't good for writing in" << std::endl; | ||||
|         return GROUND_BOOL_VAL(false); | ||||
|     } | ||||
|      | ||||
|     return GROUND_BOOL_VAL(true); | ||||
| } | ||||
|  | ||||
| GROUND_LIBRARY_INTERFACE() | ||||
|  | ||||
| GROUND_LIBRARY_INIT() | ||||
|     REGISTER_GROUND_FUNCTION(readFile); | ||||
|     REGISTER_GROUND_FUNCTION(writeFile); | ||||
| GROUND_LIBRARY_INIT_END() | ||||
|  | ||||
| GROUND_LIBRARY_CLEANUP() | ||||
| GROUND_LIBRARY_CLEANUP_END() | ||||
							
								
								
									
										193
									
								
								file/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								file/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| #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 | ||||
							
								
								
									
										193
									
								
								ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								ground_lib.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| #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 | ||||
							
								
								
									
										193
									
								
								httpserver/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								httpserver/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| #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 | ||||
							
								
								
									
										17
									
								
								httpserver/httpserver.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								httpserver/httpserver.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| #define CPPHTTPLIB_OPENSSL_SUPPORT | ||||
| #include "ground_lib.h" | ||||
| #include "libraries/httplib.h" | ||||
|  | ||||
| GroundValue startHttpServer(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_INT);   | ||||
|      | ||||
| } | ||||
|  | ||||
| GROUND_LIBRARY_INTERFACE() | ||||
|  | ||||
| GROUND_LIBRARY_INIT() | ||||
|     REGISTER_GROUND_FUNCTION(startHttpServer); | ||||
| GROUND_LIBRARY_INIT_END() | ||||
|  | ||||
| GROUND_LIBRARY_CLEANUP() | ||||
| GROUND_LIBRARY_CLEANUP_END() | ||||
							
								
								
									
										
											BIN
										
									
								
								httpserver/httpserver.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								httpserver/httpserver.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										0
									
								
								httpserver/libraries/httplib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								httpserver/libraries/httplib.h
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										45
									
								
								math/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								math/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| # math library | ||||
|  | ||||
| This library adds extra math functions to Ground. | ||||
|  | ||||
| ## Functions | ||||
|  | ||||
| ### fun -double !sinVal -double &input | ||||
|  | ||||
| Gets the sin of input. | ||||
|  | ||||
| ### fun -double !cosVal -double &input | ||||
|  | ||||
| Gets the cos of input. | ||||
|  | ||||
| ### fun -double !tanVal -double &input | ||||
|  | ||||
| Gets the tan of input. | ||||
|  | ||||
| ### fun -double !sqrtVal -double &input | ||||
|  | ||||
| Gets the square root of input. | ||||
|  | ||||
| ### fun -int !modVal -int &a -int &b | ||||
|  | ||||
| Gets the remainder of a divided by b. | ||||
|  | ||||
| ### fun -double !floorVal -double &input | ||||
|  | ||||
| Gets the floor of input. | ||||
|  | ||||
| ### fun -double !ceilVal -double &input | ||||
|  | ||||
| Gets the ceil of input. | ||||
|  | ||||
| ### fun -double !roundVal -double &input | ||||
|  | ||||
| Rounds the input to the nearest integer. | ||||
|  | ||||
| ### fun -int !randomInt -int &min -int &max | ||||
|  | ||||
| Gets a random integer between min and max (inclusive). | ||||
|  | ||||
| ### fun -double !randomDouble -double &min -double &max | ||||
|  | ||||
| Gets a random double between min and max (inclusive). | ||||
							
								
								
									
										193
									
								
								math/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								math/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| #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 | ||||
							
								
								
									
										79
									
								
								math/math.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								math/math.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| #include "ground_lib.h" | ||||
| #include <cmath> | ||||
| #include <random> | ||||
|  | ||||
| // Math functions | ||||
| GroundValue sinVal(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||
|     return GROUND_DOUBLE_VAL(sin(GET_DOUBLE(args[0]))); | ||||
| } | ||||
|  | ||||
| GroundValue cosVal(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||
|     return GROUND_DOUBLE_VAL(cos(GET_DOUBLE(args[0]))); | ||||
| } | ||||
|  | ||||
| GroundValue tanVal(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||
|     return GROUND_DOUBLE_VAL(tan(GET_DOUBLE(args[0]))); | ||||
| } | ||||
|  | ||||
| GroundValue sqrtVal(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||
|     return GROUND_DOUBLE_VAL(sqrt(GET_DOUBLE(args[0]))); | ||||
| } | ||||
|  | ||||
| GroundValue modVal(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_2(GROUND_INT, GROUND_INT); | ||||
|     return GROUND_INT_VAL(GET_INT(args[0]) % GET_INT(args[1])); | ||||
| } | ||||
|  | ||||
| GroundValue floorVal(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||
|     return GROUND_DOUBLE_VAL(floor(GET_DOUBLE(args[0]))); | ||||
| } | ||||
|  | ||||
| GroundValue ceilVal(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||
|     return GROUND_DOUBLE_VAL(ceil(GET_DOUBLE(args[0]))); | ||||
| } | ||||
|  | ||||
| GroundValue roundVal(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||
|     return GROUND_DOUBLE_VAL(round(GET_DOUBLE(args[0]))); | ||||
| } | ||||
|  | ||||
| GroundValue randomInt(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_2(GROUND_INT, GROUND_INT); | ||||
|     std::random_device rd; | ||||
|     std::mt19937 gen(rd()); | ||||
|     std::uniform_int_distribution<> distrib(GET_INT(args[0]), GET_INT(args[1])); | ||||
|     return GROUND_INT_VAL(distrib(gen)); | ||||
| } | ||||
|  | ||||
| GroundValue randomDouble(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_2(GROUND_DOUBLE, GROUND_DOUBLE); | ||||
|     std::random_device rd; | ||||
|     std::mt19937 gen(rd()); | ||||
|     std::uniform_real_distribution<> distrib(GET_DOUBLE(args[0]), GET_DOUBLE(args[1])); | ||||
|     return GROUND_DOUBLE_VAL(distrib(gen)); | ||||
| } | ||||
|  | ||||
| // Library setup | ||||
| GROUND_LIBRARY_INTERFACE() | ||||
|  | ||||
| GROUND_LIBRARY_INIT() | ||||
|     REGISTER_GROUND_FUNCTION(sinVal); | ||||
|     REGISTER_GROUND_FUNCTION(cosVal); | ||||
|     REGISTER_GROUND_FUNCTION(tanVal); | ||||
|     REGISTER_GROUND_FUNCTION(sqrtVal); | ||||
|     REGISTER_GROUND_FUNCTION(modVal); | ||||
|     REGISTER_GROUND_FUNCTION(floorVal); | ||||
|     REGISTER_GROUND_FUNCTION(ceilVal); | ||||
|     REGISTER_GROUND_FUNCTION(roundVal); | ||||
|     REGISTER_GROUND_FUNCTION(randomInt); | ||||
|     REGISTER_GROUND_FUNCTION(randomDouble); | ||||
| GROUND_LIBRARY_INIT_END() | ||||
|  | ||||
| GROUND_LIBRARY_CLEANUP() | ||||
| GROUND_LIBRARY_CLEANUP_END() | ||||
							
								
								
									
										
											BIN
										
									
								
								request.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								request.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										13
									
								
								request/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								request/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| # request library | ||||
|  | ||||
| This library allows various web requests from within Ground. | ||||
|  | ||||
| ## Functions | ||||
|  | ||||
| ### fun -string !simpleRequest -string &url | ||||
|  | ||||
| Makes a web request to a URL, and returns the contents. If the request is not successful, returns a response beginning with "Error code", and prints it to the console. | ||||
|  | ||||
| ### fun -bool !saveContents -string &url -string &location | ||||
|  | ||||
| Makes a web request to a URL, and saves the contents to a file. If successful, returns true. If not, returns false. | ||||
							
								
								
									
										193
									
								
								request/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								request/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| #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 | ||||
							
								
								
									
										52
									
								
								request/request.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								request/request.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| #include "ground_lib.h" | ||||
|  | ||||
| #include <cpr/cpr.h> | ||||
| #include <cpr/interface.h> | ||||
| #include <fstream> | ||||
|  | ||||
| void error(std::string status) { | ||||
|     std::cout << "Request error: " << status << std::endl; | ||||
| } | ||||
|  | ||||
| GroundValue simpleRequest(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_1(GROUND_STRING); | ||||
|  | ||||
|     cpr::Response r = cpr::Get(cpr::Url(GET_STRING(args[0]))); | ||||
|  | ||||
|     if (!(r.status_code >= 200 && r.status_code < 300)) { | ||||
|         error("Non zero HTTP code " + std::to_string(r.status_code)); | ||||
|         return ground_string_val("Error code " + std::to_string(r.status_code));     | ||||
|     } | ||||
|      | ||||
|     return ground_string_val(r.text); | ||||
| } | ||||
|  | ||||
| GroundValue saveContents(GroundValue* args, int arg_count) { | ||||
|     VALIDATE_ARGS_2(GROUND_STRING, GROUND_STRING); | ||||
|  | ||||
|     std::ofstream file(GET_STRING(args[1]), std::ios::binary); | ||||
|  | ||||
|     if (file.good()) { | ||||
|         cpr::Response r = cpr::Download(file, cpr::Url{GET_STRING(args[0])}); | ||||
|  | ||||
|         if (!(r.status_code >= 200 && r.status_code < 300)) { | ||||
|             error("Non zero HTTP code " + std::to_string(r.status_code)); | ||||
|             return GROUND_BOOL_VAL(false); | ||||
|         } | ||||
|     } else { | ||||
|         error(std::string("Cannot open file ") + GET_STRING(args[1]) + " for writing"); | ||||
|         return GROUND_BOOL_VAL(false); | ||||
|     } | ||||
|  | ||||
|     return GROUND_BOOL_VAL(true); | ||||
| } | ||||
|  | ||||
| GROUND_LIBRARY_INTERFACE() | ||||
|  | ||||
| GROUND_LIBRARY_INIT() | ||||
|     REGISTER_GROUND_FUNCTION(simpleRequest); | ||||
|     REGISTER_GROUND_FUNCTION(saveContents); | ||||
| GROUND_LIBRARY_INIT_END() | ||||
|  | ||||
| GROUND_LIBRARY_CLEANUP() | ||||
| GROUND_LIBRARY_CLEANUP_END() | ||||
		Reference in New Issue
	
	Block a user