summaryrefslogtreecommitdiff
path: root/src/stages/compiler.rs
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-10-13 19:22:36 +1300
committerBen Bridle <ben@derelict.engineering>2025-10-14 16:54:44 +1300
commitd95f62157bc17ee8aad12aa8887315766207c326 (patch)
tree6f496de46b0e42be984dc12c9f80a65c32e87554 /src/stages/compiler.rs
parent0f32d50293ffb1a990acf9eec128415ba54a9561 (diff)
downloadtorque-asm-d95f62157bc17ee8aad12aa8887315766207c326.zip
Track more information with SymbolParser
To be able to re-use the symbol parser code in the intermediate stage in order to quickly find all symbol definitions and invocations in the program (in particular now that macro definitions are indistinguishable from label definitions, since they can both follow references), the symbol parser now tracks additional information about each symbol (argument count, torque-specific role, and parent macro definition).
Diffstat (limited to 'src/stages/compiler.rs')
-rw-r--r--src/stages/compiler.rs77
1 files changed, 57 insertions, 20 deletions
diff --git a/src/stages/compiler.rs b/src/stages/compiler.rs
index 7dfebd0..1476ec8 100644
--- a/src/stages/compiler.rs
+++ b/src/stages/compiler.rs
@@ -1,8 +1,6 @@
use crate::*;
use assembler::{Symbol, SymbolRole, DefinitionType};
-use SymbolRole::*;
-use DefinitionType::*;
use std::path::Path;
@@ -22,7 +20,27 @@ pub fn parse_symbols(source_code: &str, path: Option<&Path>) -> Option<Vec<Symbo
Ok(semantic) => semantic,
Err(_errors) => return None,
};
- Some(SymbolParser::new().parse(&semantic))
+ // Convert symbols to the format required by the assembler library.
+ let parsed = SymbolParser::new().parse(&semantic);
+ let mut symbols = Vec::new();
+ for symbol in parsed {
+ let name = format!("{}::{}", symbol.name, symbol.arg_count);
+ let namespace = match symbol.macro_name {
+ Some(macro_name) => vec![macro_name],
+ None => vec![],
+ };
+ let source = symbol.source;
+ let role = match symbol.role {
+ SymbolRoleDetailed::MacroDefinition =>
+ SymbolRole::Definition(DefinitionType::CanFollowReference),
+ SymbolRoleDetailed::LabelDefinition =>
+ SymbolRole::Definition(DefinitionType::CanFollowReference),
+ SymbolRoleDetailed::Invocation =>
+ SymbolRole::Reference,
+ };
+ symbols.push(Symbol { name, namespace, source, role });
+ }
+ Some(symbols)
}
/// Push source code to a source compilation string.
@@ -43,10 +61,27 @@ pub fn push_code(compilation: &mut String, source_file: &SourceFile) {
}
-// Extract symbol definitions from a list of semantic tokens.
+// Track additional information for each symbol.
+pub struct SymbolDetailed {
+ pub name: String,
+ pub macro_name: Option<String>,
+ pub arg_count: usize,
+ pub role: SymbolRoleDetailed,
+ pub source: SourceSpan,
+}
+
+pub enum SymbolRoleDetailed {
+ MacroDefinition,
+ LabelDefinition,
+ Invocation,
+}
+
+
+// Extract symbol definitions and invocations from a list of semantic tokens.
pub struct SymbolParser {
+ /// Current macro definition name.
pub macro_name: Option<String>,
- pub symbols: Vec<Symbol>,
+ pub symbols: Vec<SymbolDetailed>,
}
impl SymbolParser {
@@ -57,18 +92,19 @@ impl SymbolParser {
}
}
- fn record_symbol(&mut self, name: &str, arg_count: usize, source: &SourceSpan, role: SymbolRole) {
- let name = format!("{name}:{arg_count}");
- let namespace = match &self.macro_name {
- Some(macro_name) => vec![macro_name.to_owned()],
- None => vec![],
- };
- let source = source.to_owned();
- self.symbols.push(Symbol { name, namespace, source, role });
-
+ fn record_symbol(&mut self, name: &str, arg_count: usize, source: &SourceSpan, role: SymbolRoleDetailed) {
+ self.symbols.push(
+ SymbolDetailed {
+ name: name.to_string(),
+ macro_name: self.macro_name.clone(),
+ arg_count,
+ role,
+ source: source.clone(),
+ }
+ );
}
- pub fn parse(mut self, semantic: &[Tracked<SemanticToken>]) -> Vec<Symbol> {
+ pub fn parse(mut self, semantic: &[Tracked<SemanticToken>]) -> Vec<SymbolDetailed> {
for token in semantic {
let source = &token.source;
match &token.value {
@@ -78,8 +114,9 @@ impl SymbolParser {
&definition.name,
definition.arguments.len(),
&definition.name.source,
- Definition(CanFollowReference),
+ SymbolRoleDetailed::MacroDefinition,
);
+ // Track that we're currently inside a macro definition.
self.macro_name = Some(definition.name.to_string());
for argument in &definition.arguments {
@@ -87,7 +124,7 @@ impl SymbolParser {
&argument.name,
0,
&argument.source,
- Definition(MustPrecedeReference),
+ SymbolRoleDetailed::MacroDefinition,
);
}
match &definition.body {
@@ -139,7 +176,7 @@ impl SymbolParser {
&invocation.name,
invocation.arguments.len(),
&source,
- Reference,
+ SymbolRoleDetailed::Invocation,
);
for argument in &invocation.arguments {
@@ -168,7 +205,7 @@ impl SymbolParser {
&name,
0,
&source,
- Definition(CanFollowReference),
+ SymbolRoleDetailed::LabelDefinition,
);
}
BlockToken::PinnedAddress(integer) => {
@@ -184,7 +221,7 @@ impl SymbolParser {
&field.name.to_string(),
0,
&field.source,
- Reference,
+ SymbolRoleDetailed::Invocation,
);
}
}