diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-07-04 21:39:00 +1200 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-07-04 21:39:03 +1200 |
commit | ad276fffb31c77135d802db6f460e1e78aeef974 (patch) | |
tree | 4e8ec8b8c4e0a9670dc37606018b6be87be90a07 | |
parent | 99ad972395af9953e433b4a7c11bcfd6c4daad3f (diff) | |
download | bedrock-asm-ad276fffb31c77135d802db6f460e1e78aeef974.zip |
Raise error if an instruction name is redefined
-rw-r--r-- | src/stages/semantic.rs | 15 | ||||
-rw-r--r-- | src/stages/semantic_tokens.rs | 3 |
2 files changed, 17 insertions, 1 deletions
diff --git a/src/stages/semantic.rs b/src/stages/semantic.rs index 909659d..dc9709e 100644 --- a/src/stages/semantic.rs +++ b/src/stages/semantic.rs @@ -1,15 +1,24 @@ use crate::*; +use std::str::FromStr; + use indexmap::{IndexMap, IndexSet}; pub fn parse_semantic(syntactic: Vec<Tracked<SyntacticToken>>) -> Result<Program, Vec<Tracked<SemanticError>>> { + let mut errors = Vec::new(); + // Record all label definitions and macro names up front. let mut definitions = IndexMap::new(); let mut macro_names = IndexSet::new(); for token in &syntactic { match &token.value { SyntacticToken::LabelDefinition(name) => { + // Check if identifier is reserved. + if Instruction::from_str(&name).is_ok() { + let error = SemanticError::ReservedIdentifier(name.to_string()); + errors.push(Tracked::from(error, token.source.clone())); + } // Use a fake index for now. let definition = Definition::new(0, DefinitionVariant::LabelDefinition); let tracked = Tracked::from(definition, token.source.clone()); @@ -19,6 +28,11 @@ pub fn parse_semantic(syntactic: Vec<Tracked<SyntacticToken>>) -> Result<Program } SyntacticToken::MacroDefinition(definition) => { let name = &definition.name; + // Check if identifier is reserved. + if Instruction::from_str(&name).is_ok() { + let error = SemanticError::ReservedIdentifier(name.to_string()); + errors.push(Tracked::from(error, name.source.clone())); + } if !macro_names.insert(name.clone()) { unreachable!("Uncaught duplicate macro definition '{name}'") } @@ -29,7 +43,6 @@ pub fn parse_semantic(syntactic: Vec<Tracked<SyntacticToken>>) -> Result<Program // Convert syntactic tokens to semantic tokens. let mut tokens: Vec<Tracked<SemanticToken>> = Vec::new(); - let mut errors = Vec::new(); let mut stack = Vec::new(); for syn_token in syntactic { diff --git a/src/stages/semantic_tokens.rs b/src/stages/semantic_tokens.rs index fc454be..c735828 100644 --- a/src/stages/semantic_tokens.rs +++ b/src/stages/semantic_tokens.rs @@ -49,6 +49,7 @@ pub enum SemanticToken { pub enum SemanticError { InvocationBeforeDefinition, + ReservedIdentifier(String), } @@ -64,6 +65,8 @@ fn report_semantic_error(error: &Tracked<SemanticError>, source_code: &str) { let message = match &error.value { SemanticError::InvocationBeforeDefinition => "Macro cannot be invoked before it has been defined", + SemanticError::ReservedIdentifier(name) => + &format!("Identifier '{name}' is reserved for a built-in instruction"), }; report_source_issue(LogLevel::Error, &context, message); } |