diff --git a/rust_compiler/Cargo.toml b/rust_compiler/Cargo.toml index 4b0e4c3..2269c18 100644 --- a/rust_compiler/Cargo.toml +++ b/rust_compiler/Cargo.toml @@ -43,6 +43,6 @@ parser = { path = "libs/parser" } compiler = { path = "libs/compiler" } helpers = { path = "libs/helpers" } safer-ffi = { workspace = true } +anyhow = { version = "^1.0", features = ["backtrace"] } [dev-dependencies] -anyhow = { version = "^1.0", features = ["backtrace"] } diff --git a/rust_compiler/libs/compiler/src/v1.rs b/rust_compiler/libs/compiler/src/v1.rs index 482a1d7..ac3acf2 100644 --- a/rust_compiler/libs/compiler/src/v1.rs +++ b/rust_compiler/libs/compiler/src/v1.rs @@ -152,12 +152,12 @@ struct CompilationResult<'a> { temp_name: Option>, } -pub struct Compiler<'a, W: std::io::Write> { +pub struct Compiler<'a, 'w, W: std::io::Write> { pub parser: ASTParser<'a>, function_locations: HashMap, usize>, function_metadata: HashMap, Vec>>, devices: HashMap, Cow<'a, str>>, - output: &'a mut BufWriter, + output: &'w mut BufWriter, current_line: usize, declared_main: bool, config: CompilerConfig, @@ -167,10 +167,10 @@ pub struct Compiler<'a, W: std::io::Write> { pub errors: Vec>, } -impl<'a, W: std::io::Write> Compiler<'a, W> { +impl<'a, 'w, W: std::io::Write> Compiler<'a, 'w, W> { pub fn new( parser: ASTParser<'a>, - writer: &'a mut BufWriter, + writer: &'w mut BufWriter, config: Option, ) -> Self { Self { @@ -258,7 +258,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression( &mut self, expr: Spanned>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result>, Error<'a>> { match expr.node { Expression::Function(expr_func) => { @@ -459,7 +459,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn resolve_device( &mut self, expr: Spanned>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result<(Cow<'a, str>, Option>), Error<'a>> { // If it's a direct variable reference, check if it's a known device alias first if let Expression::Variable(ref name) = expr.node @@ -516,7 +516,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { &mut self, var_name: Spanned>, expr: Spanned>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result>, Error<'a>> { let name_str = var_name.node; let name_span = var_name.span; @@ -599,8 +599,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { )); }; - let loc = - scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?; + let loc = scope.add_variable( + name_str.clone(), + LocationRequest::Persist, + Some(name_span), + )?; self.emit_variable_assignment( name_str, &loc, @@ -612,8 +615,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { // Support assigning binary expressions to variables directly Expression::Binary(bin_expr) => { let result = self.expression_binary(bin_expr, scope)?; - let var_loc = - scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?; + let var_loc = scope.add_variable( + name_str.clone(), + LocationRequest::Persist, + Some(name_span), + )?; if let CompilationResult { location: VariableLocation::Constant(Literal::Number(num)), @@ -636,8 +642,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { } Expression::Logical(log_expr) => { let result = self.expression_logical(log_expr, scope)?; - let var_loc = - scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?; + let var_loc = scope.add_variable( + name_str.clone(), + LocationRequest::Persist, + Some(name_span), + )?; // Move result from temp to new persistent variable let result_reg = self.resolve_register(&result.location)?; @@ -661,8 +670,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { } }; - let var_loc = - scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?; + let var_loc = scope.add_variable( + name_str.clone(), + LocationRequest::Persist, + Some(name_span), + )?; // Handle loading from stack if necessary let src_str = match src_loc { @@ -713,8 +725,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { )); }; - let var_loc = - scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?; + let var_loc = scope.add_variable( + name_str.clone(), + LocationRequest::Persist, + Some(name_span), + )?; let result_reg = self.resolve_register(&comp_res.location)?; self.emit_variable_assignment(name_str, &var_loc, result_reg)?; @@ -742,7 +757,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_const_declaration( &mut self, expr: ConstDeclarationExpression<'a>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result, Error<'a>> { let ConstDeclarationExpression { name: const_name, @@ -777,7 +792,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_assignment( &mut self, expr: AssignmentExpression<'a>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result<(), Error<'a>> { let AssignmentExpression { assignee, @@ -865,7 +880,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_function_invocation( &mut self, invoke_expr: Spanned>, - stack: &mut VariableScope<'a>, + stack: &mut VariableScope<'a, '_>, ) -> Result<(), Error<'a>> { let InvocationExpression { name, arguments } = invoke_expr.node; @@ -1062,7 +1077,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_if( &mut self, expr: IfExpression<'a>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result<(), Error<'a>> { let end_label = self.next_label_name(); let else_label = if expr.else_branch.is_some() { @@ -1109,7 +1124,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_loop( &mut self, expr: LoopExpression<'a>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result<(), Error<'a>> { let start_label = self.next_label_name(); let end_label = self.next_label_name(); @@ -1135,7 +1150,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_while( &mut self, expr: WhileExpression<'a>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result<(), Error<'a>> { let start_label = self.next_label_name(); let end_label = self.next_label_name(); @@ -1222,7 +1237,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn compile_operand( &mut self, expr: Spanned>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result<(Cow<'a, str>, Option>), Error<'a>> { // Optimization for literals if let Expression::Literal(spanned_lit) = &expr.node { @@ -1293,7 +1308,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn compile_literal_or_variable( &mut self, val: LiteralOrVariable<'a>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result<(Cow<'a, str>, Option>), Error<'a>> { let dummy_span = Span { start_line: 0, @@ -1321,7 +1336,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_binary( &mut self, expr: Spanned>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result, Error<'a>> { fn fold_binary_expression<'a>(expr: &BinaryExpression<'a>) -> Option { let (lhs, rhs) = match &expr { @@ -1414,7 +1429,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_logical( &mut self, expr: Spanned>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result, Error<'a>> { match expr.node { LogicalExpression::Not(inner) => { @@ -1480,10 +1495,10 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { } } - fn expression_block( + fn expression_block<'v>( &mut self, mut expr: BlockExpression<'a>, - parent_scope: &mut VariableScope<'a>, + parent_scope: &'v mut VariableScope<'a, '_>, ) -> Result<(), Error<'a>> { // First, sort the expressions to ensure functions are hoisted expr.0.sort_by(|a, b| { @@ -1549,7 +1564,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_return( &mut self, expr: Spanned>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result, Error<'a>> { if let Expression::Negation(neg_expr) = &expr.node && let Expression::Literal(spanned_lit) = &neg_expr.node @@ -1686,7 +1701,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { &mut self, expr: System<'a>, span: Span, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result>, Error<'a>> { macro_rules! cleanup { ($($to_clean:expr),*) => { @@ -1943,7 +1958,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_syscall_math( &mut self, expr: Math<'a>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result>, Error<'a>> { macro_rules! cleanup { ($($to_clean:expr),*) => { @@ -2139,7 +2154,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { fn expression_function( &mut self, expr: Spanned>, - scope: &mut VariableScope<'a>, + scope: &mut VariableScope<'a, '_>, ) -> Result<(), Error<'a>> { let FunctionExpression { name, @@ -2222,7 +2237,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { self.write_output("push ra")?; block_scope.add_variable( - format!("{}_ra", name.node), + Cow::from(format!("{}_ra", name.node)), LocationRequest::Stack, Some(name.span), )?; @@ -2249,7 +2264,8 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { } // Get the saved return address and save it back into `ra` - let ra_res = block_scope.get_location_of(format!("{}_ra", name.node), Some(name.span)); + let ra_res = + block_scope.get_location_of(&Cow::from(format!("{}_ra", name.node)), Some(name.span)); let ra_stack_offset = match ra_res { Ok(VariableLocation::Stack(offset)) => offset, diff --git a/rust_compiler/libs/compiler/src/variable_manager.rs b/rust_compiler/libs/compiler/src/variable_manager.rs index fd2e463..77a5c24 100644 --- a/rust_compiler/libs/compiler/src/variable_manager.rs +++ b/rust_compiler/libs/compiler/src/variable_manager.rs @@ -66,15 +66,17 @@ pub enum VariableLocation<'a> { Device(Cow<'a, str>), } -pub struct VariableScope<'a> { +// FIX: Added 'b lifetime for the parent reference +pub struct VariableScope<'a, 'b> { temporary_vars: VecDeque, persistant_vars: VecDeque, var_lookup_table: HashMap, VariableLocation<'a>>, stack_offset: u16, - parent: Option<&'a VariableScope<'a>>, + parent: Option<&'b VariableScope<'a, 'b>>, } -impl<'a> Default for VariableScope<'a> { +// FIX: Updated Default impl to include 'b +impl<'a, 'b> Default for VariableScope<'a, 'b> { fn default() -> Self { Self { parent: None, @@ -86,7 +88,8 @@ impl<'a> Default for VariableScope<'a> { } } -impl<'a> VariableScope<'a> { +// FIX: Updated impl block to include 'b +impl<'a, 'b> VariableScope<'a, 'b> { #[allow(dead_code)] pub const TEMP_REGISTER_COUNT: u8 = 7; pub const PERSIST_REGISTER_COUNT: u8 = 7; @@ -109,7 +112,8 @@ impl<'a> VariableScope<'a> { }) } - pub fn scoped(parent: &'a VariableScope<'a>) -> Self { + // FIX: parent is now &'b VariableScope<'a, 'b> + pub fn scoped(parent: &'b VariableScope<'a, 'b>) -> Self { Self { parent: Option::Some(parent), temporary_vars: parent.temporary_vars.clone(), @@ -206,7 +210,7 @@ impl<'a> VariableScope<'a> { return Ok(loc); } - Err(Error::UnknownVariable(Cow::from(var_name.to_owned()), span)) + Err(Error::UnknownVariable(var_name.clone(), span)) } pub fn has_parent(&self) -> bool { diff --git a/rust_compiler/src/main.rs b/rust_compiler/src/main.rs index bff25c9..040f07f 100644 --- a/rust_compiler/src/main.rs +++ b/rust_compiler/src/main.rs @@ -12,20 +12,38 @@ use thiserror::Error; use tokenizer::{self, Tokenizer}; #[derive(Error, Debug)] -enum StationlangError { +enum Error<'a> { #[error(transparent)] - Tokenizer(#[from] tokenizer::Error), + Tokenizer(tokenizer::Error), #[error(transparent)] - Parser(#[from] parser::Error), + Parser(parser::Error<'a>), #[error(transparent)] - Compile(#[from] compiler::Error), + Compile(compiler::Error<'a>), #[error(transparent)] IO(#[from] std::io::Error), } +impl<'a> From> for Error<'a> { + fn from(value: parser::Error<'a>) -> Self { + Self::Parser(value) + } +} + +impl<'a> From> for Error<'a> { + fn from(value: compiler::Error<'a>) -> Self { + Self::Compile(value) + } +} + +impl<'a> From for Error<'a> { + fn from(value: tokenizer::Error) -> Self { + Self::Tokenizer(value) + } +} + #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Args { @@ -37,7 +55,7 @@ struct Args { output_file: Option, } -fn run_logic() -> Result<(), StationlangError> { +fn run_logic<'a>() -> Result<(), Error<'a>> { let args = Args::parse(); let input_file = args.input_file; @@ -63,7 +81,6 @@ fn run_logic() -> Result<(), StationlangError> { }; let tokenizer = Tokenizer::from(input_string.as_str()); - let parser = ASTParser::new(tokenizer); let mut writer: BufWriter> = match args.output_file { @@ -73,20 +90,17 @@ fn run_logic() -> Result<(), StationlangError> { let compiler = Compiler::new(parser, &mut writer, None); - let mut errors = compiler.compile(); + let errors = compiler.compile(); if !errors.is_empty() { let mut std_error = stderr(); - let last = errors.pop(); - let errors = errors.into_iter().map(StationlangError::from); + let errors = errors.into_iter().map(Error::from); std_error.write_all(b"Compilation error:\n")?; for err in errors { std_error.write_all(format!("{}\n", err).as_bytes())?; } - - return Err(StationlangError::from(last.unwrap())); } writer.flush()?; @@ -94,7 +108,7 @@ fn run_logic() -> Result<(), StationlangError> { Ok(()) } -fn main() -> Result<(), StationlangError> { +fn main() -> anyhow::Result<()> { run_logic()?; Ok(())