diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-03-18 12:06:17 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-03-18 13:24:20 +1300 |
commit | 0925bd156ae2e34ad259d40aaf870eb5f7cfcfb9 (patch) | |
tree | abd0a35a995f53b10e81b66cdfd4571f93748343 /src/compiler.rs | |
parent | f25bc47f5c6b7e52304b1e9c9adb4310f2e77ee7 (diff) | |
download | torque-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.rs | 250 |
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); -} |