# The MIT License (MIT) # # Copyright (C) 2026 Scott Duensing # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. .section Libraries .topic lib.basrt .title BASIC Runtime Library .toc 0 BASIC Runtime Library .index BASIC Runtime .index BasVmT .index BasValueT .index BasStringT .index BasArrayT .index BasModuleT .h1 BASIC Runtime Library Stack-based p-code virtual machine and value system for DVX BASIC. Embeddable: the host provides I/O and UI callbacks. No DVX GUI dependencies in the core runtime. Headers: apps/dvxbasic/runtime/vm.h, apps/dvxbasic/runtime/values.h .link lib.basrt.values Value System (values.h) .link lib.basrt.vm Virtual Machine (vm.h) .topic lib.basrt.values .title Value System .toc 1 Value System .index BasValueT .index BasStringT .index BasArrayT .index BasUdtT .index basStringNew .index basArrayNew .index basValCopy .index basValRelease .h1 Value System Tagged union value type for the VM evaluation stack, variables, and array elements. Strings, arrays, and UDT instances are reference-counted for automatic memory management without a garbage collector. Header: apps/dvxbasic/runtime/values.h .h2 Type Tags .table Constant Value C Union Field Description -------- ----- ------------- ----------- BAS_TYPE_INTEGER 0 intVal 16-bit signed integer. BAS_TYPE_LONG 1 longVal 32-bit signed integer. BAS_TYPE_SINGLE 2 sngVal 32-bit float. BAS_TYPE_DOUBLE 3 dblVal 64-bit float. BAS_TYPE_STRING 4 strVal Reference-counted dynamic string. BAS_TYPE_BOOLEAN 5 boolVal True (-1) or False (0). BAS_TYPE_ARRAY 6 arrVal Reference-counted array. BAS_TYPE_UDT 7 udtVal Reference-counted user-defined type. BAS_TYPE_OBJECT 8 objVal Opaque host pointer (form, control). BAS_TYPE_REF 9 refVal ByRef pointer to a BasValueT slot. .endtable .h2 BasValueT Tagged union holding any BASIC value. .code struct BasValueTag { uint8_t type; // BAS_TYPE_* union { int16_t intVal; int32_t longVal; float sngVal; double dblVal; BasStringT *strVal; int16_t boolVal; BasArrayT *arrVal; BasUdtT *udtVal; void *objVal; BasValueT *refVal; }; }; .endcode .h2 Value Constructors .code 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); .endcode Each returns a BasValueT with the appropriate type tag set. basValString increments the string's reference count. .h2 Value Lifetime .code BasValueT basValCopy(BasValueT v); void basValRelease(BasValueT *v); .endcode .table Function Description -------- ----------- basValCopy Copy a value. Increments reference count for strings, arrays, and UDTs. basValRelease Release a value. Decrements reference count and frees if it reaches zero. .endtable .h2 Type Conversion .code BasValueT basValToInteger(BasValueT v); BasValueT basValToLong(BasValueT v); BasValueT basValToSingle(BasValueT v); BasValueT basValToDouble(BasValueT v); BasValueT basValToString(BasValueT v); BasValueT basValToBool(BasValueT v); .endcode Each returns a new value of the target type. The original is not released; the caller manages both lifetimes. .h2 Value Utilities .table Function Description -------- ----------- basValToNumber(v) Convert any numeric value to double. basValFormatString(v) Return a new ref-counted string representation of v. basValIsTruthy(v) True if non-zero number or non-empty string. basValCompare(a, b) Compare two values. Returns -1, 0, or 1. basValCompareCI(a, b) Case-insensitive comparison (OPTION COMPARE TEXT). basValPromoteType(a, b) Determine common type for binary ops (e.g. Integer + Single -> Single). .endtable .h2 BasStringT Reference-counted string with flexible array member for inline storage. .code typedef struct { int32_t refCount; int32_t len; int32_t cap; char data[]; } BasStringT; .endcode .h3 String Functions .table Function Description -------- ----------- basStringNew(text, len) Allocate from a C string. refCount starts at 1. basStringAlloc(cap) Allocate an empty string with given capacity. basStringRef(s) Increment reference count. Returns s. basStringUnref(s) Decrement reference count. Frees when it reaches zero. basStringConcat(a, b) Concatenate two strings. Returns a new string (refCount 1). basStringSub(s, start, len) Extract a substring. Returns a new string (refCount 1). basStringCompare(a, b) Compare. Returns <0, 0, >0 (like strcmp). basStringCompareCI(a, b) Case-insensitive compare. basStringSystemInit() Initialize the string system and empty string singleton. basStringSystemShutdown() Shut down the string system. .endtable The global basEmptyString is a singleton that is never freed. .h2 BasArrayT Reference-counted multi-dimensional array (up to BAS_ARRAY_MAX_DIMS = 8 dimensions). .code typedef struct { int32_t refCount; uint8_t elementType; int32_t dims; int32_t lbound[BAS_ARRAY_MAX_DIMS]; int32_t ubound[BAS_ARRAY_MAX_DIMS]; int32_t totalElements; BasValueT *elements; } BasArrayT; .endcode .h3 Array Functions .table Function Description -------- ----------- basArrayNew(dims, lbounds, ubounds, type) Allocate an array. refCount starts at 1. basArrayFree(arr) Free all elements and release the array. basArrayRef(arr) Increment reference count. basArrayUnref(arr) Decrement reference count. Frees at zero. basArrayIndex(arr, indices, ndims) Compute flat index from multi-dimensional indices. Returns -1 if out of bounds. .endtable .h2 BasUdtT Reference-counted user-defined type instance. .code typedef struct { int32_t refCount; int32_t typeId; int32_t fieldCount; BasValueT *fields; } BasUdtT; .endcode .h3 UDT Functions .table Function Description -------- ----------- basUdtNew(typeId, fieldCount) Allocate a UDT instance. refCount starts at 1. basUdtFree(udt) Free all fields and release. basUdtRef(udt) Increment reference count. basUdtUnref(udt) Decrement reference count. Frees at zero. .endtable .topic lib.basrt.vm .title Virtual Machine .toc 1 Virtual Machine .index BasVmT .index BasModuleT .index BasVmResultE .index basVmCreate .index basVmRun .index basVmStep .index basVmDestroy .index basVmCallSub .h1 Virtual Machine Stack-based p-code interpreter. Executes compiled BASIC bytecode modules. The host provides I/O, UI, SQL, and external library callbacks. The VM has no DVX dependencies; it can be embedded in any C program. Header: apps/dvxbasic/runtime/vm.h .h2 VM Limits .table Constant Value Description -------- ----- ----------- BAS_VM_STACK_SIZE 256 Evaluation stack depth. BAS_VM_CALL_STACK_SIZE 64 Maximum call nesting depth. BAS_VM_MAX_GLOBALS 512 Global variable slots. BAS_VM_MAX_LOCALS 64 Local variables per stack frame. BAS_VM_MAX_FOR_DEPTH 32 Maximum nested FOR loop depth. BAS_VM_MAX_FILES 16 Open file channels (1-based). .endtable .h2 BasVmResultE Result codes returned by basVmRun and basVmStep. .table Code Value Description ---- ----- ----------- BAS_VM_OK 0 Program completed normally. BAS_VM_HALTED 1 HALT instruction reached. BAS_VM_YIELDED 2 DoEvents yielded control. BAS_VM_ERROR 3 Runtime error. BAS_VM_STACK_OVERFLOW 4 Evaluation stack overflow. BAS_VM_STACK_UNDERFLOW 5 Evaluation stack underflow. BAS_VM_CALL_OVERFLOW 6 Call stack overflow. BAS_VM_DIV_BY_ZERO 7 Division by zero. BAS_VM_TYPE_MISMATCH 8 Type mismatch in operation. BAS_VM_OUT_OF_MEMORY 9 Memory allocation failed. BAS_VM_BAD_OPCODE 10 Unknown opcode encountered. BAS_VM_FILE_ERROR 11 File I/O error. BAS_VM_SUBSCRIPT_RANGE 12 Array subscript out of range. BAS_VM_USER_ERROR 13 ON ERROR raised by program. BAS_VM_STEP_LIMIT 14 Step limit reached (not an error). BAS_VM_BREAKPOINT 15 Breakpoint or step completed (not an error). .endtable .h2 Lifecycle .code BasVmT *basVmCreate(void); void basVmDestroy(BasVmT *vm); void basVmLoadModule(BasVmT *vm, BasModuleT *module); void basVmReset(BasVmT *vm); .endcode .table Function Description -------- ----------- basVmCreate Allocate and initialize a new VM instance. basVmDestroy Destroy the VM and free all resources. basVmLoadModule Load a compiled module (BasModuleT) into the VM. basVmReset Reset to initial state (clear stack, globals, PC). .endtable .h2 Execution .code BasVmResultE basVmRun(BasVmT *vm); BasVmResultE basVmStep(BasVmT *vm); void basVmSetStepLimit(BasVmT *vm, int32_t limit); .endcode .table Function Description -------- ----------- basVmRun Execute the loaded module until it ends, halts, yields, errors, or hits a breakpoint/step limit. basVmStep Execute a single instruction and return. Useful for debugger stepping. basVmSetStepLimit Set maximum instructions per basVmRun call. 0 = unlimited (default). Returns BAS_VM_STEP_LIMIT when reached. .endtable .h2 I/O Callbacks The host provides these callbacks for PRINT, INPUT, and DoEvents statements. .code void basVmSetPrintCallback(BasVmT *vm, BasPrintFnT fn, void *ctx); void basVmSetInputCallback(BasVmT *vm, BasInputFnT fn, void *ctx); void basVmSetDoEventsCallback(BasVmT *vm, BasDoEventsFnT fn, void *ctx); .endcode .h3 Callback Types .code typedef void (*BasPrintFnT)(void *ctx, const char *text, bool newline); typedef bool (*BasInputFnT)(void *ctx, const char *prompt, char *buf, int32_t bufSize); typedef bool (*BasDoEventsFnT)(void *ctx); .endcode .table Type Description ---- ----------- BasPrintFnT Called for PRINT output. text is null-terminated. newline indicates line advance. BasInputFnT Called for INPUT. Fill buf (up to bufSize-1 chars). Return true on success, false on cancel. BasDoEventsFnT Called for DoEvents. Process pending events and return. Return false to stop the program. .endtable .h2 UI Callbacks For form and control integration. The VM resolves all UI operations through these callbacks, keeping it independent of any specific GUI toolkit. .code void basVmSetUiCallbacks(BasVmT *vm, const BasUiCallbacksT *ui); .endcode .h3 BasUiCallbacksT .table Field Signature Description ----- --------- ----------- getProp BasValueT (*)(ctx, ctrlRef, propName) Get a control property value. setProp void (*)(ctx, ctrlRef, propName, value) Set a control property. callMethod BasValueT (*)(ctx, ctrlRef, methodName, args, argc) Call a method on a control. createCtrl void *(*)(ctx, formRef, typeName, ctrlName) Create a control on a form. findCtrl void *(*)(ctx, formRef, ctrlName) Find a control by name. findCtrlIdx void *(*)(ctx, formRef, ctrlName, index) Find a control array element. loadForm void *(*)(ctx, formName) Load a form by name. unloadForm void (*)(ctx, formRef) Unload a form. showForm void (*)(ctx, formRef, modal) Show a form (modal or modeless). hideForm void (*)(ctx, formRef) Hide a form (keep in memory). msgBox int32_t (*)(ctx, message, flags) Display a message box. inputBox BasStringT *(*)(ctx, prompt, title, defaultText) Display an input box. ctx void * User pointer passed to all callbacks. .endtable .h2 SQL Callbacks For database integration. .code void basVmSetSqlCallbacks(BasVmT *vm, const BasSqlCallbacksT *sql); .endcode .h3 BasSqlCallbacksT .table Field Signature Description ----- --------- ----------- sqlOpen int32_t (*)(path) Open a database. Returns handle. sqlClose void (*)(db) Close a database. sqlExec bool (*)(db, sql) Execute a non-query SQL statement. sqlError const char *(*)(db) Get last error message. sqlQuery int32_t (*)(db, sql) Execute a query. Returns result set handle. sqlNext bool (*)(rs) Advance to next row. sqlEof bool (*)(rs) Check if at end of result set. sqlFieldCount int32_t (*)(rs) Get number of columns. sqlFieldName const char *(*)(rs, col) Get column name by index. sqlFieldText const char *(*)(rs, col) Get column value as text by index. sqlFieldByName const char *(*)(rs, name) Get column value as text by name. sqlFieldInt int32_t (*)(rs, col) Get column value as integer. sqlFieldDbl double (*)(rs, col) Get column value as double. sqlFreeResult void (*)(rs) Free a result set. sqlAffectedRows int32_t (*)(db) Get number of rows affected by last statement. .endtable .h2 External Library Callbacks For DECLARE LIBRARY support. The VM resolves external functions at runtime via the host. .code void basVmSetExternCallbacks(BasVmT *vm, const BasExternCallbacksT *ext); .endcode .h3 BasExternCallbacksT .table Field Signature Description ----- --------- ----------- resolveExtern void *(*)(ctx, libName, funcName) Resolve a native function by library and symbol name. Cached after first call. callExtern BasValueT (*)(ctx, funcPtr, funcName, args, argc, retType) Call a resolved native function, marshalling arguments and return value. ctx void * User pointer passed to both callbacks. .endtable .h2 Form Context Set the active form context during event dispatch. .code void basVmSetCurrentForm(BasVmT *vm, void *formRef); void basVmSetCurrentFormVars(BasVmT *vm, BasValueT *vars, int32_t count); .endcode .h2 Stack Access Push and pop values on the evaluation stack for host integration. .code bool basVmPush(BasVmT *vm, BasValueT val); bool basVmPop(BasVmT *vm, BasValueT *val); .endcode Both return true on success, false on stack overflow/underflow. .h2 Error Reporting .code const char *basVmGetError(const BasVmT *vm); .endcode Returns the current error message string. Valid after basVmRun returns BAS_VM_ERROR. .h2 Sub/Function Calls from Host Call a SUB or FUNCTION by its code address from host code. .code bool basVmCallSub(BasVmT *vm, int32_t codeAddr); bool basVmCallSubWithArgs(BasVmT *vm, int32_t codeAddr, const BasValueT *args, int32_t argCount); bool basVmCallSubWithArgsOut(BasVmT *vm, int32_t codeAddr, const BasValueT *args, int32_t argCount, BasValueT *outArgs, int32_t outCount); .endcode .table Function Description -------- ----------- basVmCallSub Call a SUB with no arguments. basVmCallSubWithArgs Call a SUB with arguments pushed onto the stack frame. basVmCallSubWithArgsOut Call a SUB and read back modified argument values after it returns. .endtable All three push a call frame, execute until the SUB returns, then restore the previous execution state. Return true on normal completion, false on error or if the VM is not idle. .h2 Debugger API .code void basVmSetBreakpoints(BasVmT *vm, int32_t *lines, int32_t count); void basVmStepInto(BasVmT *vm); void basVmStepOver(BasVmT *vm); void basVmStepOut(BasVmT *vm); void basVmRunToCursor(BasVmT *vm, int32_t line); int32_t basVmGetCurrentLine(const BasVmT *vm); .endcode .table Function Description -------- ----------- basVmSetBreakpoints Set the breakpoint list (sorted array of source line numbers, host-owned memory). basVmStepInto Break at the next OP_LINE instruction. basVmStepOver Break when call depth returns to the current level. basVmStepOut Break when call depth drops below the current level. basVmRunToCursor Break when execution reaches the specified source line. basVmGetCurrentLine Get the current source line number (from the last OP_LINE instruction). .endtable The breakpoint callback notifies the host when a breakpoint fires during nested sub calls: .code typedef void (*BasBreakpointFnT)(void *ctx, int32_t line); .endcode .h2 BasModuleT Compiled module produced by the BASIC compiler and loaded into the VM. .code typedef struct { uint8_t *code; int32_t codeLen; BasStringT **constants; int32_t constCount; int32_t globalCount; int32_t entryPoint; BasValueT *dataPool; int32_t dataCount; BasProcEntryT *procs; int32_t procCount; BasFormVarInfoT *formVarInfo; int32_t formVarInfoCount; BasDebugVarT *debugVars; int32_t debugVarCount; BasDebugUdtDefT *debugUdtDefs; int32_t debugUdtDefCount; } BasModuleT; .endcode .table Field Description ----- ----------- code P-code bytecode array. codeLen Length of bytecode in bytes. constants String constant pool. constCount Number of string constants. globalCount Number of global variable slots needed. entryPoint PC of the first instruction (module-level code). dataPool DATA statement value pool (for READ). dataCount Number of values in the data pool. procs Procedure table (SUBs and FUNCTIONs). procCount Number of procedures. formVarInfo Per-form variable counts and init code addresses. formVarInfoCount Number of forms with form-scoped variables. debugVars Variable names and metadata for the debugger. debugVarCount Number of debug variable entries. debugUdtDefs UDT type definitions for the debugger. debugUdtDefCount Number of debug UDT definitions. .endtable