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:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user