// symtab.c -- DVX BASIC symbol table implementation #include "symtab.h" #include #include // ============================================================ // Case-insensitive name comparison // ============================================================ static bool namesEqual(const char *a, const char *b) { while (*a && *b) { char ca = *a >= 'a' && *a <= 'z' ? *a - 32 : *a; char cb = *b >= 'a' && *b <= 'z' ? *b - 32 : *b; if (ca != cb) { return false; } a++; b++; } return *a == *b; } // ============================================================ // basSymTabAdd // ============================================================ BasSymbolT *basSymTabAdd(BasSymTabT *tab, const char *name, BasSymKindE kind, uint8_t dataType) { if (tab->count >= BAS_MAX_SYMBOLS) { return NULL; } // Check for duplicate in current scope BasScopeE scope = tab->inLocalScope ? SCOPE_LOCAL : SCOPE_GLOBAL; for (int32_t i = 0; i < tab->count; i++) { if (tab->symbols[i].scope == scope && namesEqual(tab->symbols[i].name, name)) { return NULL; // duplicate } } BasSymbolT *sym = &tab->symbols[tab->count++]; memset(sym, 0, sizeof(*sym)); strncpy(sym->name, name, BAS_MAX_SYMBOL_NAME - 1); sym->name[BAS_MAX_SYMBOL_NAME - 1] = '\0'; sym->kind = kind; sym->scope = scope; sym->dataType = dataType; sym->isDefined = true; return sym; } // ============================================================ // basSymTabAllocSlot // ============================================================ int32_t basSymTabAllocSlot(BasSymTabT *tab) { if (tab->inLocalScope) { return tab->nextLocalIdx++; } return tab->nextGlobalIdx++; } // ============================================================ // basSymTabEnterLocal // ============================================================ void basSymTabEnterLocal(BasSymTabT *tab) { tab->inLocalScope = true; tab->nextLocalIdx = 0; } // ============================================================ // basSymTabFind // ============================================================ BasSymbolT *basSymTabFind(BasSymTabT *tab, const char *name) { // Search local scope first if (tab->inLocalScope) { for (int32_t i = tab->count - 1; i >= 0; i--) { if (tab->symbols[i].scope == SCOPE_LOCAL && namesEqual(tab->symbols[i].name, name)) { return &tab->symbols[i]; } } } // Search global scope return basSymTabFindGlobal(tab, name); } // ============================================================ // basSymTabFindGlobal // ============================================================ BasSymbolT *basSymTabFindGlobal(BasSymTabT *tab, const char *name) { for (int32_t i = 0; i < tab->count; i++) { if (tab->symbols[i].scope == SCOPE_GLOBAL && namesEqual(tab->symbols[i].name, name)) { return &tab->symbols[i]; } } return NULL; } // ============================================================ // basSymTabInit // ============================================================ void basSymTabInit(BasSymTabT *tab) { memset(tab, 0, sizeof(*tab)); } // ============================================================ // basSymTabLeaveLocal // ============================================================ void basSymTabLeaveLocal(BasSymTabT *tab) { // Remove all local symbols int32_t newCount = 0; for (int32_t i = 0; i < tab->count; i++) { if (tab->symbols[i].scope != SCOPE_LOCAL) { if (i != newCount) { tab->symbols[newCount] = tab->symbols[i]; } newCount++; } } tab->count = newCount; tab->inLocalScope = false; tab->nextLocalIdx = 0; }