Organisation, documentation, mathlib

This commit is contained in:
2025-08-28 11:11:59 +10:00
parent a9bfc1b0e3
commit 6596bfcc85
13 changed files with 948 additions and 1 deletions

45
extlibs/math/README.md Normal file
View 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
extlibs/math/ground_lib.h Normal file
View 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
extlibs/math/math.cpp Normal file
View 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()