Use section numbers when resolving local labels

This changes the semantics of local labels. Previously, local labels
were just shorthand for writing out `name.local`, which meant if there
were multiple sections named "name", there could potentially be name
collisions.

This commit adds a unique numeric suffix to each section's ID string.
This guarantees that locals in one section won't interfere with those in
a different section.
This commit is contained in:
2025-06-21 21:58:55 -07:00
parent 34f808e042
commit 84cec642a3
3 changed files with 76 additions and 3 deletions
+5 -3
View File
@@ -43,7 +43,8 @@ pub fn process_labels(board: &mut Board) {
/// Resolve ".local" labels to "name.local" form. /// Resolve ".local" labels to "name.local" form.
fn resolve_local_labels(stats: &mut [ParsedStat]) { fn resolve_local_labels(stats: &mut [ParsedStat]) {
for stat in stats.iter_mut() { for stat in stats.iter_mut() {
let mut section = CompactString::const_new(""); let mut section_counter = 0;
let mut section = CompactString::const_new("$0");
for chunk in stat.iter_mut() { for chunk in stat.iter_mut() {
match chunk { match chunk {
Chunk::Label { Chunk::Label {
@@ -57,12 +58,13 @@ fn resolve_local_labels(stats: &mut [ParsedStat]) {
if label.name.is_empty() { if label.name.is_empty() {
// Expand :.local to :name.local // Expand :.local to :name.local
assert!(label.local.is_some()); assert!(label.local.is_some());
label.name = section.clone() label.name = section.clone();
} else if label.local.is_none() { } else if label.local.is_none() {
// Interpret label :name as start of new section. // Interpret label :name as start of new section.
// Only label definitions do this; label references have no effect. // Only label definitions do this; label references have no effect.
if !*is_ref { if !*is_ref {
section = label.name.clone(); section_counter += 1;
section = format!("{}${}", &label.name, section_counter).into();
} }
} }
} }
@@ -18,3 +18,38 @@ expression: board_to_text(board)
' '
:stop :stop
#walk i #walk i
---
'Using locals before any globals are defined
:_loop1
#take gems 1 _break
#_loop1
:_break
---
'Multiple sections with the same name
#end
:touch
Trying to sell you some ammo...
#take gems 10 _skip
#give ammo 10
:_skip
#zap touch
#end
:touch
Trying to sell you some torches...
#take gems 15 _skip0
#give torches 5
:_skip0
#restore touch
---
'Multiple locals with the same name
#end
:repeat3
:_z
:_z
:_z
#take gems 1 _skip1
#give score 1
:_skip1
#zap _z
#_z
:_z
+36
View File
@@ -14,3 +14,39 @@
' '
:stop :stop
#walk i #walk i
---
'Using locals before any globals are defined
:.loop
#take gems 1 .break
#.loop
:.break
---
'Multiple sections with the same name
#end
:touch
Trying to sell you some ammo...
#take gems 10 .skip
#give ammo 10
:.skip
#zap touch
#end
:touch
Trying to sell you some torches...
#take gems 15 .skip
#give torches 5
:.skip
#restore touch
---
'Multiple locals with the same name
#end
:repeat3
:.z
:.z
:.z
#take gems 1 .skip
#give score 1
:.skip
#zap .z
#.z
:.z