DVX_GUI/src/apps/kpunch/dvxbasic/runtime/values.h

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