From 3ff40241ee6fe129267401f306fed1bd34fdc04d Mon Sep 17 00:00:00 2001 From: Chris Mounce Date: Sat, 5 Jul 2025 23:49:57 -0700 Subject: [PATCH] Add more error messages for local/anonymous labels --- src/labels/parse.rs | 22 +++++++++ src/labels/process.rs | 13 +++-- ...m__labels__process__test__diagnostics.snap | 47 +++++++++++++++++++ tests/labels/diagnostics.txt | 13 +++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/labels/parse.rs b/src/labels/parse.rs index 190151e..a0cae52 100644 --- a/src/labels/parse.rs +++ b/src/labels/parse.rs @@ -52,6 +52,28 @@ pub fn parse_stat_labels(stat: &Stat, ctx: &Context) -> ParsedStat { Tag::Reference => { let label = cap.children().find(|c| c.kind() == Tag::Label).unwrap(); label_captures.push((Tag::Reference, label)); + + // Detect invalid recipients. + // This should probably happen later in processing, but + // we'd need an AST that can track spans for message recipients. + let mut recipient = None; + let (mut anon, mut local) = (false, false); + for child in cap.walk_children() { + match child.kind() { + Tag::Anon => anon = true, + Tag::Local => local = true, + Tag::Recipient => recipient = Some(child), + _ => {} + } + } + if let Some(recipient) = recipient { + let ctx = ctx.with_span(recipient.span()); + if anon { + ctx.error("message targets not allowed for anonymous labels"); + } else if local { + ctx.error("message targets not supported for local labels"); + } + } } _ => {} } diff --git a/src/labels/process.rs b/src/labels/process.rs index 6cd07c8..1fe866f 100644 --- a/src/labels/process.rs +++ b/src/labels/process.rs @@ -20,7 +20,7 @@ pub fn process_labels(board: &Board, ctx: &Context) -> Board { .collect(); let mut registry = Registry::new(); - resolve_local_labels(&mut stats); + resolve_local_labels(&mut stats, ctx); assign_named_labels(&mut stats, &mut registry); // Assign names to anonymous labels @@ -47,8 +47,10 @@ pub fn process_labels(board: &Board, ctx: &Context) -> Board { } /// Resolve ".local" labels to "name.local" form. -fn resolve_local_labels(stats: &mut [ParsedStat]) { - for stat in stats.iter_mut() { +fn resolve_local_labels(stats: &mut [ParsedStat], ctx: &Context) { + for (i, stat) in stats.iter_mut().enumerate() { + let ctx = ctx.with_stat(i); + // Helper: Generate unique section strings like "touch$0" let mut i = 0; let mut make_section_id = |label_name: &str| -> CompactString { @@ -89,6 +91,11 @@ fn resolve_local_labels(stats: &mut [ParsedStat]) { namespace_to_section .insert(label.namespace.clone(), make_section_id(&label.name)); } + } else { + // User specified both a section name and a local name ("name.local"). + // This isn't allowed because of issues around resolving the section ID. + ctx.with_span(label.span.clone()) + .error("local labels with section names not supported"); } } _ => {} diff --git a/src/labels/snapshots/zasm__labels__process__test__diagnostics.snap b/src/labels/snapshots/zasm__labels__process__test__diagnostics.snap index 557308b..4af7276 100644 --- a/src/labels/snapshots/zasm__labels__process__test__diagnostics.snap +++ b/src/labels/snapshots/zasm__labels__process__test__diagnostics.snap @@ -44,3 +44,50 @@ error: backward reference needs an anonymous label 2 | #send @f 3 | #send @b | ^^ + +error: message targets not allowed for anonymous labels + => test.zzt -> Title screen -> @Disallowed targets (1,1) -> line 3:2 + | + 1 | @Disallowed targets + 2 | :@ + 3 | #self:@b + | ^^^^ + 4 | #others:@f + 5 | #all:.local + 6 | :@ + | + +error: message targets not allowed for anonymous labels + => test.zzt -> Title screen -> @Disallowed targets (1,1) -> line 4:2 + | + 1 | @Disallowed targets + 2 | :@ + 3 | #self:@b + 4 | #others:@f + | ^^^^^^ + 5 | #all:.local + 6 | :@ + 7 | :.local + | + +error: message targets not supported for local labels + => test.zzt -> Title screen -> @Disallowed targets (1,1) -> line 5:2 + | + 2 | :@ + 3 | #self:@b + 4 | #others:@f + 5 | #all:.local + | ^^^ + 6 | :@ + 7 | :.local + | + +error: local labels with section names not supported + => test.zzt -> Title screen -> @Locals with section names (1,1) -> line 3:2 + | + 1 | @Locals with section names + 2 | :touch + 3 | #touch.skip + | ^^^^^^^^^^ + 4 | :.skip + | diff --git a/tests/labels/diagnostics.txt b/tests/labels/diagnostics.txt index 6899f40..9038b8b 100644 --- a/tests/labels/diagnostics.txt +++ b/tests/labels/diagnostics.txt @@ -14,3 +14,16 @@ @Errors in sorted order #send @f #send @b +--- +@Disallowed targets +:@ +#self:@b +#others:@f +#all:.local +:@ +:.local +--- +@Locals with section names +:touch +#touch.skip +:.skip