DVX_GUI/dvxbasic/compiler/symtab.h

129 lines
4 KiB
C

// 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 <stdint.h>
#include <stdbool.h>
// ============================================================
// 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
} BasScopeE;
// ============================================================
// Symbol entry
// ============================================================
#define BAS_MAX_SYMBOL_NAME 64
#define BAS_MAX_PARAMS 16
#define BAS_MAX_CALL_PATCHES 32
#define BAS_MAX_UDT_FIELDS 32
// 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
bool isDefined; // false = forward-declared
bool isArray;
bool isShared;
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)
// 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[BAS_MAX_CALL_PATCHES];
int32_t patchCount;
// For CONST: the constant value
union {
int32_t constInt;
double constDbl;
};
char constStr[256];
// For TYPE_DEF: field definitions
BasFieldDefT fields[BAS_MAX_UDT_FIELDS];
int32_t fieldCount;
} BasSymbolT;
// ============================================================
// Symbol table
// ============================================================
#define BAS_MAX_SYMBOLS 512
typedef struct {
BasSymbolT symbols[BAS_MAX_SYMBOLS];
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
} 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 or local depending on scope).
int32_t basSymTabAllocSlot(BasSymTabT *tab);
#endif // DVXBASIC_SYMTAB_H