// symtab.h -- DVX BASIC symbol table // // Tracks variables, constants, subroutines, functions, and labels // during compilation. Supports nested scopes (global + one local // scope per SUB/FUNCTION). // // Embeddable: no DVX dependencies, pure C. #ifndef DVXBASIC_SYMTAB_H #define DVXBASIC_SYMTAB_H #include "../compiler/opcodes.h" #include #include // ============================================================ // Symbol kinds // ============================================================ typedef enum { SYM_VARIABLE, SYM_CONST, SYM_SUB, SYM_FUNCTION, SYM_LABEL, SYM_TYPE_DEF // user-defined TYPE } BasSymKindE; // ============================================================ // Symbol scope // ============================================================ typedef enum { SCOPE_GLOBAL, SCOPE_LOCAL, SCOPE_FORM // per-form variable (persists while form is loaded) } BasScopeE; // ============================================================ // Symbol entry // ============================================================ #define BAS_MAX_SYMBOL_NAME 64 #define BAS_MAX_PARAMS 16 // UDT field definition typedef struct { char name[BAS_MAX_SYMBOL_NAME]; uint8_t dataType; // BAS_TYPE_* int32_t udtTypeId; // if dataType == BAS_TYPE_UDT, index of the TYPE_DEF symbol } BasFieldDefT; typedef struct { char name[BAS_MAX_SYMBOL_NAME]; BasSymKindE kind; BasScopeE scope; uint8_t dataType; // BAS_TYPE_* for variables/functions int32_t index; // slot index (local or global) int32_t codeAddr; // PC address for SUB/FUNCTION/LABEL int32_t localCount; // number of local variables (for SUB/FUNCTION, set on leave) bool isDefined; // false = forward-declared bool isArray; bool isShared; bool isExtern; // true = external library function (DECLARE LIBRARY) bool formScopeEnded; // true = form scope ended, invisible to lookups int32_t udtTypeId; // for variables of BAS_TYPE_UDT: index of TYPE_DEF symbol int32_t fixedLen; // for STRING * n: fixed length (0 = variable-length) uint16_t externLibIdx; // constant pool index for library name (if isExtern) uint16_t externFuncIdx; // constant pool index for function name (if isExtern) // For SUB/FUNCTION: parameter info int32_t paramCount; uint8_t paramTypes[BAS_MAX_PARAMS]; bool paramByVal[BAS_MAX_PARAMS]; // Forward-reference backpatch list (code addresses to patch when defined) int32_t *patchAddrs; // stb_ds dynamic array int32_t patchCount; // For CONST: the constant value union { int32_t constInt; double constDbl; }; char constStr[256]; // For TYPE_DEF: field definitions BasFieldDefT *fields; // stb_ds dynamic array int32_t fieldCount; } BasSymbolT; // ============================================================ // Symbol table // ============================================================ typedef struct { BasSymbolT *symbols; // stb_ds dynamic array int32_t count; int32_t nextGlobalIdx; // next global variable slot int32_t nextLocalIdx; // next local variable slot (reset per SUB/FUNCTION) bool inLocalScope; // true when inside SUB/FUNCTION bool inFormScope; // true inside BEGINFORM...ENDFORM char formScopeName[BAS_MAX_SYMBOL_NAME]; // current form name int32_t nextFormVarIdx; // next form-level variable slot int32_t formScopeSymStart; // symbol count at BEGINFORM (for marking ended) } BasSymTabT; // ============================================================ // API // ============================================================ void basSymTabInit(BasSymTabT *tab); // Add a symbol. Returns the symbol pointer, or NULL if the table is full // or the name already exists in the current scope. BasSymbolT *basSymTabAdd(BasSymTabT *tab, const char *name, BasSymKindE kind, uint8_t dataType); // Look up a symbol by name. Searches local scope first, then global. // Case-insensitive. BasSymbolT *basSymTabFind(BasSymTabT *tab, const char *name); // Look up a symbol in the global scope only. BasSymbolT *basSymTabFindGlobal(BasSymTabT *tab, const char *name); // Enter local scope (called at SUB/FUNCTION start). void basSymTabEnterLocal(BasSymTabT *tab); // Leave local scope (called at END SUB/FUNCTION). Removes local symbols. void basSymTabLeaveLocal(BasSymTabT *tab); // Allocate the next variable slot (global, local, or form depending on scope). int32_t basSymTabAllocSlot(BasSymTabT *tab); // Enter form scope (called at BEGINFORM). Form-level DIMs create SCOPE_FORM variables. void basSymTabEnterFormScope(BasSymTabT *tab, const char *formName); // Leave form scope (called at ENDFORM). Marks form-scope symbols as ended. // Returns the number of form variables allocated. int32_t basSymTabLeaveFormScope(BasSymTabT *tab); #endif // DVXBASIC_SYMTAB_H