Consistently handle auto-scoping of local symbols

This commit is contained in:
Rangi42
2024-09-09 11:31:42 -04:00
committed by Eldred Habert
parent cff05435ad
commit 6e83a14143
14 changed files with 60 additions and 57 deletions

View File

@@ -120,22 +120,42 @@ static Symbol &createSymbol(std::string const &symName) {
return sym;
}
static bool isAutoScoped(std::string const &symName) {
// `labelScope` should be global if it's defined
assume(!labelScope || labelScope->name.find('.') == std::string::npos);
size_t dotPos = symName.find('.');
// If there are no dots, it's not a local label
if (dotPos == std::string::npos)
return false;
// Check for nothing after the dot
if (dotPos == symName.length() - 1)
fatalerror("'%s' is a nonsensical reference to an empty local label\n", symName.c_str());
// Check for more than one dot
if (symName.find('.', dotPos + 1) != std::string::npos)
fatalerror("'%s' is a nonsensical reference to a nested local label\n", symName.c_str());
// Check for already-qualified local label
if (dotPos > 0)
return false;
// Check for unqualifiable local label
if (!labelScope)
fatalerror("Unqualified local label '%s' in main scope\n", symName.c_str());
return true;
}
Symbol *sym_FindExactSymbol(std::string const &symName) {
auto search = symbols.find(symName);
return search != symbols.end() ? &search->second : nullptr;
}
Symbol *sym_FindScopedSymbol(std::string const &symName) {
if (size_t dotPos = symName.find('.'); dotPos != std::string::npos) {
if (symName.find('.', dotPos + 1) != std::string::npos)
fatalerror(
"'%s' is a nonsensical reference to a nested local symbol\n", symName.c_str()
);
// If auto-scoped local label, expand the name
if (dotPos == 0 && labelScope)
return sym_FindExactSymbol(labelScope->name + symName);
}
return sym_FindExactSymbol(symName);
return sym_FindExactSymbol(isAutoScoped(symName) ? labelScope->name + symName : symName);
}
Symbol *sym_FindScopedValidSymbol(std::string const &symName) {
@@ -186,15 +206,7 @@ bool sym_IsPurgedExact(std::string const &symName) {
}
bool sym_IsPurgedScoped(std::string const &symName) {
if (size_t dotPos = symName.find('.'); dotPos != std::string::npos) {
// Check for a nonsensical reference to a nested scoped symbol
if (symName.find('.', dotPos + 1) != std::string::npos)
return false;
// If auto-scoped local label, expand the name
if (dotPos == 0 && labelScope)
return sym_IsPurgedExact(labelScope->name + symName);
}
return sym_IsPurgedExact(symName);
return sym_IsPurgedExact(isAutoScoped(symName) ? labelScope->name + symName : symName);
}
int32_t sym_GetRSValue() {
@@ -353,7 +365,9 @@ Symbol *sym_AddVar(std::string const &symName, int32_t value) {
}
static Symbol *addLabel(std::string const &symName) {
assume(!symName.starts_with('.')); // The symbol name must have been expanded prior
// The symbol name should have been expanded already
assume(!symName.starts_with('.'));
Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) {
@@ -380,29 +394,10 @@ static Symbol *addLabel(std::string const &symName) {
}
Symbol *sym_AddLocalLabel(std::string const &symName) {
// Assuming no dots in `labelScope` if defined
assume(!labelScope || labelScope->name.find('.') == std::string::npos);
// The symbol name should be local, qualified or not
assume(symName.find('.') != std::string::npos);
size_t dotPos = symName.find('.');
assume(dotPos != std::string::npos); // There should be at least one dot in `symName`
// Check for something after the dot
if (dotPos == symName.length() - 1) {
fatalerror("'%s' is a nonsensical reference to an empty local label\n", symName.c_str());
}
// Check for more than one dot
if (symName.find('.', dotPos + 1) != std::string::npos)
fatalerror("'%s' is a nonsensical reference to a nested local label\n", symName.c_str());
if (dotPos == 0) {
if (!labelScope) {
error("Unqualified local label '%s' in main scope\n", symName.c_str());
return nullptr;
}
return addLabel(labelScope->name + symName);
}
return addLabel(symName);
return addLabel(isAutoScoped(symName) ? labelScope->name + symName : symName);
}
Symbol *sym_AddLabel(std::string const &symName) {
@@ -496,14 +491,7 @@ Symbol *sym_Ref(std::string const &symName) {
Symbol *sym = sym_FindScopedSymbol(symName);
if (!sym) {
if (symName.starts_with('.')) {
if (!labelScope)
fatalerror("Local label reference '%s' in main scope\n", symName.c_str());
sym = &createSymbol(labelScope->name + symName);
} else {
sym = &createSymbol(symName);
}
sym = &createSymbol(isAutoScoped(symName) ? labelScope->name + symName : symName);
sym->type = SYM_REF;
}

View File

@@ -0,0 +1,3 @@
SECTION "Test", ROM0
PURGE .test

View File

@@ -0,0 +1,2 @@
FATAL: empty-local-purged.asm(3):
Unqualified local label '.test' in main scope

View File

@@ -0,0 +1,3 @@
SECTION "Test", ROM0
dw Referenced.

View File

@@ -0,0 +1,2 @@
FATAL: empty-local-referenced.asm(3):
'Referenced.' is a nonsensical reference to an empty local label

View File

@@ -0,0 +1,4 @@
SECTION "Test", ROM0
Label:
dw Label.

View File

@@ -0,0 +1,2 @@
FATAL: empty-local-used.asm(4):
'Label.' is a nonsensical reference to an empty local label

View File

@@ -1,4 +1,3 @@
SECTION "Test", ROM0
Label:

View File

@@ -1,2 +1,2 @@
FATAL: empty-local.asm(5):
FATAL: empty-local.asm(4):
'Label.' is a nonsensical reference to an empty local label

View File

@@ -1,3 +1,3 @@
SECTION "sec", ROM0
SECTION "Test", ROM0
dw .test

View File

@@ -1,2 +1,2 @@
FATAL: local-ref-without-parent.asm(3):
Local label reference '.test' in main scope
Unqualified local label '.test' in main scope

View File

@@ -1,2 +1,3 @@
SECTION "Test", ROM0
.test:

View File

@@ -1,3 +1,2 @@
error: local-without-parent.asm(2):
FATAL: local-without-parent.asm(3):
Unqualified local label '.test' in main scope
error: Assembly aborted (1 error)!

View File

@@ -1,2 +1,2 @@
FATAL: nested-local-reference.asm(8):
'Parent.child.grandchild' is a nonsensical reference to a nested local symbol
'Parent.child.grandchild' is a nonsensical reference to a nested local label