183 lines
6.2 KiB
C
183 lines
6.2 KiB
C
// 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 <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
|
|
// ============================================================
|
|
// 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)
|
|
void *objVal; // BAS_TYPE_OBJECT (opaque host pointer)
|
|
BasValueT *refVal; // BAS_TYPE_REF (ByRef pointer to variable slot)
|
|
};
|
|
};
|
|
|
|
// 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);
|
|
BasValueT basValObject(void *obj);
|
|
|
|
// 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
|