// values.h -- DVX BASIC value representation and string heap // // Tagged union value type for the VM's evaluation stack, variables, // and array elements. Strings are reference-counted for automatic // memory management without a garbage collector. // // Embeddable: no DVX dependencies, pure C. #ifndef DVXBASIC_VALUES_H #define DVXBASIC_VALUES_H #include #include #include // ============================================================ // Reference-counted string // ============================================================ typedef struct { int32_t refCount; int32_t len; int32_t cap; // allocated capacity (>= len + 1) char data[]; // flexible array member, null-terminated } BasStringT; // Allocate a new string from a C string. refCount starts at 1. BasStringT *basStringNew(const char *text, int32_t len); // Allocate an empty string with a given capacity. BasStringT *basStringAlloc(int32_t cap); // Increment reference count. BasStringT *basStringRef(BasStringT *s); // Decrement reference count. Frees if count reaches zero. void basStringUnref(BasStringT *s); // Concatenate two strings. Returns a new string (refCount 1). BasStringT *basStringConcat(const BasStringT *a, const BasStringT *b); // Substring. Returns a new string (refCount 1). BasStringT *basStringSub(const BasStringT *s, int32_t start, int32_t len); // Compare two strings. Returns <0, 0, >0 like strcmp. int32_t basStringCompare(const BasStringT *a, const BasStringT *b); // Compare two strings case-insensitively. Returns <0, 0, >0. int32_t basStringCompareCI(const BasStringT *a, const BasStringT *b); // The empty string singleton (never freed). extern BasStringT *basEmptyString; // Initialize/shutdown the string system. void basStringSystemInit(void); void basStringSystemShutdown(void); // ============================================================ // Forward declarations // ============================================================ typedef struct BasValueTag BasValueT; // ============================================================ // Reference-counted array // ============================================================ #define BAS_ARRAY_MAX_DIMS 8 typedef struct { int32_t refCount; uint8_t elementType; // BAS_TYPE_* int32_t dims; // number of dimensions int32_t lbound[BAS_ARRAY_MAX_DIMS]; // lower bound per dimension int32_t ubound[BAS_ARRAY_MAX_DIMS]; // upper bound per dimension int32_t totalElements; BasValueT *elements; // flat array of values } BasArrayT; // Allocate a new array. refCount starts at 1. BasArrayT *basArrayNew(int32_t dims, int32_t *lbounds, int32_t *ubounds, uint8_t elementType); // Free all elements and release the array. void basArrayFree(BasArrayT *arr); // Increment reference count. BasArrayT *basArrayRef(BasArrayT *arr); // Decrement reference count. Frees if count reaches zero. void basArrayUnref(BasArrayT *arr); // Compute flat index from multi-dimensional indices. Returns -1 if out of bounds. int32_t basArrayIndex(BasArrayT *arr, int32_t *indices, int32_t ndims); // ============================================================ // Reference-counted user-defined type instance // ============================================================ typedef struct { int32_t refCount; int32_t typeId; // index into type definition table int32_t fieldCount; BasValueT *fields; // array of field values } BasUdtT; // Allocate a new UDT instance. refCount starts at 1. BasUdtT *basUdtNew(int32_t typeId, int32_t fieldCount); // Free all fields and release the UDT. void basUdtFree(BasUdtT *udt); // Increment reference count. BasUdtT *basUdtRef(BasUdtT *udt); // Decrement reference count. Frees if count reaches zero. void basUdtUnref(BasUdtT *udt); // ============================================================ // Tagged value // ============================================================ struct BasValueTag { uint8_t type; // BAS_TYPE_* union { int16_t intVal; // BAS_TYPE_INTEGER int32_t longVal; // BAS_TYPE_LONG float sngVal; // BAS_TYPE_SINGLE double dblVal; // BAS_TYPE_DOUBLE BasStringT *strVal; // BAS_TYPE_STRING (ref-counted) int16_t boolVal; // BAS_TYPE_BOOLEAN (True=-1, False=0) BasArrayT *arrVal; // BAS_TYPE_ARRAY (ref-counted) BasUdtT *udtVal; // BAS_TYPE_UDT (ref-counted) }; }; // Create values BasValueT basValInteger(int16_t v); BasValueT basValLong(int32_t v); BasValueT basValSingle(float v); BasValueT basValDouble(double v); BasValueT basValString(BasStringT *s); BasValueT basValStringFromC(const char *text); BasValueT basValBool(bool v); // Copy a value (increments string refcount if applicable). BasValueT basValCopy(BasValueT v); // Release a value (decrements string refcount if applicable). void basValRelease(BasValueT *v); // Convert a value to a specific type. Returns the converted value. // The original is NOT released -- caller manages lifetime. BasValueT basValToInteger(BasValueT v); BasValueT basValToLong(BasValueT v); BasValueT basValToSingle(BasValueT v); BasValueT basValToDouble(BasValueT v); BasValueT basValToString(BasValueT v); BasValueT basValToBool(BasValueT v); // Get the numeric value as a double (for mixed-type arithmetic). double basValToNumber(BasValueT v); // Get the string representation. Returns a new ref-counted string. BasStringT *basValFormatString(BasValueT v); // Check if a value is truthy (non-zero number, non-empty string). bool basValIsTruthy(BasValueT v); // Compare two values. Returns -1, 0, or 1. // Numeric types are compared numerically. Strings lexicographically. int32_t basValCompare(BasValueT a, BasValueT b); // Compare two values case-insensitively (for OPTION COMPARE TEXT). int32_t basValCompareCI(BasValueT a, BasValueT b); // Determine the common type for a binary operation (type promotion). // Integer + Single -> Single, etc. uint8_t basValPromoteType(uint8_t a, uint8_t b); #endif // DVXBASIC_VALUES_H