summaryrefslogtreecommitdiff
path: root/src/compiler.rs
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-03-18 12:06:17 +1300
committerBen Bridle <ben@derelict.engineering>2025-03-18 13:24:20 +1300
commit0925bd156ae2e34ad259d40aaf870eb5f7cfcfb9 (patch)
treeabd0a35a995f53b10e81b66cdfd4571f93748343 /src/compiler.rs
parentf25bc47f5c6b7e52304b1e9c9adb4310f2e77ee7 (diff)
downloadtorque-asm-0925bd156ae2e34ad259d40aaf870eb5f7cfcfb9.zip
Update assembler dependency
torque-asm now uses the Compiler type provided by the assembler library.
Diffstat (limited to 'src/compiler.rs')
-rw-r--r--src/compiler.rs250
1 files changed, 0 insertions, 250 deletions
diff --git a/src/compiler.rs b/src/compiler.rs
deleted file mode 100644
index c0caae0..0000000
--- a/src/compiler.rs
+++ /dev/null
@@ -1,250 +0,0 @@
-use crate::*;
-
-use assembler::*;
-use assembler::DefinitionType::*;
-use assembler::SymbolRole::*;
-
-
-/// Compiles multiple source code files into one.
-pub struct Compiler {
- pub source_path: PathBuf,
- pub resolver: Resolver,
-}
-
-impl Compiler {
- pub fn from_string<P: AsRef<Path>>(source_code: String, path: P) -> Self {
- let source_unit = SourceUnit::from_string(source_code, &path, parse_symbols);
- Self {
- source_path: path.as_ref().to_path_buf(),
- resolver: Resolver::new(source_unit)
- }
- }
-
- pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, FileError> {
- let source_unit = SourceUnit::from_path(&path, None, parse_symbols)?;
- Ok(Self {
- source_path: path.as_ref().to_path_buf(),
- resolver: Resolver::new(source_unit)
- })
- }
-
- /// Find library files descending from the parent directory.
- pub fn include_libs_from_parent(&mut self, ext: &str) {
- if let Some(parent_path) = self.source_path.parent() {
- let parent_path = parent_path.to_owned();
- self.include_libs_from_path(&parent_path, ext);
- }
- }
-
- /// Find library files at or descending from a path.
- pub fn include_libs_from_path(&mut self, path: &Path, ext: &str) {
- let libraries = gather_from_path(path, Some(ext), parse_symbols);
- self.resolver.add_library_source_units(libraries);
- self.resolver.resolve();
- }
-
- /// Find library files from a PATH-style environment variable.
- pub fn include_libs_from_path_variable(&mut self, name: &str, ext: &str) {
- let libraries = gather_from_path_variable(name, Some(ext), parse_symbols);
- self.resolver.add_library_source_units(libraries);
- self.resolver.resolve();
- }
-
- pub fn error(&self) -> Option<ResolverError> {
- self.resolver.error()
- }
-
- pub fn get_compiled_source(&mut self) -> Result<String, MergeError> {
- self.resolver.calculate_hierarchy();
- self.resolver.get_merged_source_code(push_source_code)
- }
-}
-
-
-/// Parse all symbols from a source code string.
-fn parse_symbols(source_code: &str, path: Option<&Path>) -> Option<Vec<Symbol>> {
- let syntactic = match parse_syntactic(source_code, path) {
- Ok(syntactic) => syntactic,
- Err(_errors) => return None,
- };
- let semantic = match parse_semantic(syntactic) {
- Ok(semantic) => semantic,
- Err(_errors) => return None,
- };
- Some(SymbolParser::new().parse(&semantic))
-}
-
-
-// Extract symbol definitions from a list of semantic tokens.
-pub struct SymbolParser {
- pub macro_name: Option<String>,
- pub symbols: Vec<Symbol>,
-}
-
-impl SymbolParser {
- pub fn new() -> Self {
- Self {
- macro_name: None,
- symbols: Vec::new(),
- }
- }
-
- fn record_symbol(&mut self, name: &str, source: &SourceSpan, role: SymbolRole) {
- let name = name.to_string();
- 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 });
-
- }
-
- pub fn parse(mut self, semantic: &[Tracked<SemanticToken>]) -> Vec<Symbol> {
- for token in semantic {
- let source = &token.source;
- match &token.value {
- SemanticToken::MacroDefinition(definition) => {
- // Record macro definition.
- self.record_symbol(
- &definition.name,
- &definition.name.source,
- Definition(MustPrecedeReference),
- );
- self.macro_name = Some(definition.name.to_string());
-
- for argument in &definition.arguments {
- self.record_symbol(
- &argument.name,
- &argument.source,
- Definition(MustPrecedeReference),
- );
- }
- match &definition.body {
- MacroDefinitionBody::Integer(integer) => {
- self.parse_integer_token(&integer, &integer.source)
- }
- MacroDefinitionBody::Invocation(invocation) => {
- self.parse_invocation(&invocation, &invocation.source)
- }
- MacroDefinitionBody::Block(tokens) => {
- for token in tokens {
- self.parse_block_token(&token, &token.source);
- }
- }
- }
- self.macro_name = None;
- }
- SemanticToken::BlockToken(token) => {
- self.parse_block_token(token, &source);
- }
- }
- }
- return self.symbols;
- }
-
- fn parse_expression(&mut self, expression: &Expression, _source: &SourceSpan) {
- for token in &expression.tokens {
- let source = &token.source;
- match &token.value {
- ExpressionToken::IntegerToken(integer) => {
- self.parse_integer_token(integer, source);
- }
- ExpressionToken::Invocation(invocation) => {
- self.parse_invocation(invocation, source);
- }
- ExpressionToken::Operator(_) => (),
- }
- }
- }
-
- fn parse_invocation(&mut self, invocation: &Invocation, source: &SourceSpan) {
- self.record_symbol(
- &invocation.name,
- &source,
- Reference,
- );
-
- for argument in &invocation.arguments {
- let source = &argument.source;
- match &argument.value {
- InvocationArgument::IntegerToken(integer) => {
- self.parse_integer_token(integer, &source);
- }
- InvocationArgument::BlockToken(block) => {
- self.parse_block_token(block, &source);
- }
- InvocationArgument::Invocation(invocation) => {
- self.parse_invocation(invocation, &source);
- }
- InvocationArgument::String(_) => (),
- }
- }
- }
-
- fn parse_block_token(&mut self, token: &BlockToken, source: &SourceSpan) {
- match token {
- BlockToken::LabelDefinition(name) => {
- self.record_symbol(
- &name,
- &source,
- Definition(CanFollowReference),
- );
- }
- BlockToken::PinnedAddress(integer) => {
- self.parse_integer_token(integer, &integer.source);
- }
- BlockToken::ConditionalBlock(condition) => {
- self.parse_integer_token(&condition.predicate, &condition.predicate.source);
- self.parse_block_token(&condition.body, &condition.body.source);
- }
- BlockToken::WordTemplate(word_template) => {
- for field in &word_template.fields {
- self.record_symbol(
- &field.name.to_string(),
- &field.source,
- Reference,
- );
- }
- }
- BlockToken::Block(tokens) => {
- for token in tokens {
- self.parse_block_token(token, &token.source);
- }
- }
- BlockToken::Invocation(invocation) => {
- self.parse_invocation(invocation, source);
- }
- }
- }
-
- fn parse_integer_token(&mut self, token: &IntegerToken, source: &SourceSpan) {
- match &token {
- IntegerToken::Expression(expression) => {
- self.parse_expression(&expression, source)
- }
- IntegerToken::Invocation(invocation) => {
- self.parse_invocation(&invocation, source)
- }
- IntegerToken::IntegerLiteral(_) => (),
- }
- }
-}
-
-
-/// Push source code to a source compilation string.
-fn push_source_code(compilation: &mut String, source_file: &SourceFile) {
- // Skip blank files.
- let source_code = &source_file.source_code;
- if source_code.chars().all(|c| c.is_whitespace()) { return; }
- // Ensure that the previous section is followed by two newline characters.
- if !compilation.is_empty() {
- if !compilation.ends_with('\n') { compilation.push('\n'); }
- if !compilation.ends_with("\n\n") { compilation.push('\n'); }
- }
- // Push a path comment and the source code.
- let path_str = source_file.path.as_os_str().to_string_lossy();
- let path_comment = format!("(: {path_str} )\n");
- compilation.push_str(&path_comment);
- compilation.push_str(&source_code);
-}