1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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})"),
}
}
|