diff options
Diffstat (limited to 'src/stages/semantic_tokens.rs')
-rw-r--r-- | src/stages/semantic_tokens.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/stages/semantic_tokens.rs b/src/stages/semantic_tokens.rs new file mode 100644 index 0000000..ca5b27a --- /dev/null +++ b/src/stages/semantic_tokens.rs @@ -0,0 +1,101 @@ +use crate::*; + +use std::collections::HashMap; + + +pub struct Program { + pub definitions: HashMap<String, Tracked<Definition>>, + pub tokens: Vec<Tracked<SemanticToken>>, +} + +pub struct Definition { + pub kind: DefinitionKind, + pub definition: usize, + pub references: Vec<usize>, + pub deep_references: Vec<(usize, usize)>, +} + +impl Definition { + pub fn new(i: usize, kind: DefinitionKind) -> Self { + Self { + kind, + definition: i, + references: Vec::new(), + deep_references: Vec::new(), + } + } +} + +pub enum DefinitionKind { + MacroDefinition(Vec<Tracked<SemanticToken>>), + LabelDefinition, +} + +pub enum SemanticToken { + Comment(String), + + LabelDefinition(String), + MacroDefinition(Tracked<String>), + + RawValue(Value), + Instruction(Instruction), + Invocation(String), + + Padding(Value), + String(Vec<u8>), + + BlockOpen(usize), + BlockClose(usize), +} + +pub enum SemanticError { + InvocationBeforeDefinition, +} + + +pub fn report_semantic_errors(errors: &[Tracked<SemanticError>], source_code: &str) { + for error in errors { + report_semantic_error(error, source_code); + } +} + +fn report_semantic_error(error: &Tracked<SemanticError>, source_code: &str) { + let context = Context { source_code: &source_code, source: &error.source }; + let message = match &error.value { + SemanticError::InvocationBeforeDefinition => + "Invocation before definition", + }; + + report_source_issue(LogLevel::Error, &context, message); +} + + +pub fn print_semantic_token(i: usize, token: &SemanticToken, definitions: &HashMap<String, Tracked<Definition>>) { + match token { + SemanticToken::Comment(_) => + indent!(i, "Comment"), + + SemanticToken::LabelDefinition(name) => + indent!(i, "LabelDefinition({name})"), + SemanticToken::MacroDefinition(name) => { + indent!(i, "MacroDefinition({name})"); + if let Some(definition) = definitions.get(name.as_str()) { + if let DefinitionKind::MacroDefinition(body) = &definition.kind { + for token in body { + print_semantic_token(i+1, token, definitions); + } + } + } + } + + SemanticToken::RawValue(value) => indent!(i, "RawValue({value})"), + SemanticToken::Instruction(instruction) => indent!(i, "Instruction({instruction})"), + SemanticToken::Invocation(name) => indent!(i, "Invocation({name})"), + + SemanticToken::Padding(value) => indent!(i, "Padding({value})"), + SemanticToken::String(bytes) => indent!(i, "String({})", String::from_utf8_lossy(bytes)), + + SemanticToken::BlockOpen(pointer) => indent!(i, "BlockOpen(*{pointer})"), + SemanticToken::BlockClose(pointer) => indent!(i, "BlockOpen(*{pointer})"), + } +} |