diff --git a/rust_compiler/libs/compiler/src/v1.rs b/rust_compiler/libs/compiler/src/v1.rs index 56b32ca..a5a2672 100644 --- a/rust_compiler/libs/compiler/src/v1.rs +++ b/rust_compiler/libs/compiler/src/v1.rs @@ -5,7 +5,7 @@ use parser::{ tree_node::{ AssignmentExpression, BinaryExpression, BlockExpression, DeviceDeclarationExpression, Expression, FunctionExpression, IfExpression, InvocationExpression, Literal, - LiteralOrVariable, LogicalExpression, LoopExpression, WhileExpression, + LiteralOrVariable, LogicalExpression, LoopExpression, Span, Spanned, WhileExpression, }, }; use quick_error::quick_error; @@ -22,6 +22,14 @@ macro_rules! debug { "".into() } }; + + ($self: expr, $debug_value: expr, $args: expr) => { + if $self.config.debug { + format!($debug_value, $args) + } else { + "".into() + } + }; } quick_error! { @@ -36,19 +44,19 @@ quick_error! { ScopeError(error: variable_manager::Error) { from() } - DuplicateIdentifier(func_name: String) { + DuplicateIdentifier(func_name: String, span: Span) { display("`{func_name}` has already been defined") } - UnknownIdentifier(ident: String) { + UnknownIdentifier(ident: String, span: Span) { display("`{ident}` is not found in the current scope.") } - InvalidDevice(device: String) { + InvalidDevice(device: String, span: Span) { display("`{device}` is not valid") } - AgrumentMismatch(func_name: String) { + AgrumentMismatch(func_name: String, span: Span) { display("Incorrect number of arguments passed into `{func_name}`") } - Unknown(reason: String) { + Unknown(reason: String, span: Option) { display("{reason}") } } @@ -173,7 +181,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { Ok(None) } Expression::Declaration(var_name, expr) => { - self.expression_declaration(var_name, *expr, scope) + self.expression_declaration(var_name.node, *expr, scope) } Expression::Assignment(assign_expr) => { self.expression_assignment(assign_expr, scope)?; @@ -223,7 +231,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { })) } Expression::Variable(name) => { - let loc = scope.get_location_of(&name)?; + let loc = scope.get_location_of(&name.node)?; Ok(Some(CompilationResult { location: loc, temp_name: None, // User variable, do not free @@ -368,7 +376,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { (var_loc, None) } Expression::Variable(name) => { - let src_loc = scope.get_location_of(&name)?; + let src_loc = scope.get_location_of(&name.node)?; let var_loc = scope.add_variable(&var_name, LocationRequest::Persist)?; // Handle loading from stack if necessary @@ -417,11 +425,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { expression, } = expr; - let location = scope.get_location_of(&identifier)?; + let location = scope.get_location_of(&identifier.node)?; let (val_str, cleanup) = self.compile_operand(*expression, scope)?; let debug_tag = if self.config.debug { - format!(" #{}", identifier) + format!(" #{}", identifier.node) } else { String::new() }; @@ -456,16 +464,16 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { invoke_expr: InvocationExpression, stack: &mut VariableScope, ) -> Result<(), Error> { - if !self.function_locations.contains_key(&invoke_expr.name) { - return Err(Error::UnknownIdentifier(invoke_expr.name)); + if !self.function_locations.contains_key(&invoke_expr.name.node) { + return Err(Error::UnknownIdentifier(invoke_expr.name.node)); } - let Some(args) = self.function_metadata.get(&invoke_expr.name) else { - return Err(Error::UnknownIdentifier(invoke_expr.name)); + let Some(args) = self.function_metadata.get(&invoke_expr.name.node) else { + return Err(Error::UnknownIdentifier(invoke_expr.name.node)); }; if args.len() != invoke_expr.arguments.len() { - return Err(Error::AgrumentMismatch(invoke_expr.name)); + return Err(Error::AgrumentMismatch(invoke_expr.name.node)); } // backup all used registers to the stack @@ -484,7 +492,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { let val = if b { "1" } else { "0" }; self.write_output(format!("push {val}"))?; } - Expression::Variable(var_name) => match stack.get_location_of(var_name)? { + Expression::Variable(var_name) => match stack.get_location_of(var_name.node)? { VariableLocation::Persistant(reg) | VariableLocation::Temporary(reg) => { self.write_output(format!("push r{reg}"))?; } @@ -524,14 +532,14 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { _ => { return Err(Error::Unknown(format!( "Attempted to call `{}` with an unsupported argument type", - invoke_expr.name + invoke_expr.name.node ))); } } } // jump to the function and store current line in ra - self.write_output(format!("jal {}", invoke_expr.name))?; + self.write_output(format!("jal {}", invoke_expr.name.node))?; for register in active_registers { let VariableLocation::Stack(stack_offset) = @@ -557,10 +565,10 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { } fn expression_device(&mut self, expr: DeviceDeclarationExpression) -> Result<(), Error> { - if self.devices.contains_key(&expr.name) { - return Err(Error::DuplicateIdentifier(expr.name)); + if self.devices.contains_key(&expr.name.node) { + return Err(Error::DuplicateIdentifier(expr.name.node)); } - self.devices.insert(expr.name, expr.device); + self.devices.insert(expr.name.node, expr.device); Ok(()) } @@ -589,7 +597,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { // Compile Body // Scope variables in body are ephemeral to the block, handled by expression_block - self.expression_block(expr.body, scope)?; + self.expression_block(expr.body.node, scope)?; // If we have an else branch, we need to jump over it after the 'if' body if expr.else_branch.is_some() { @@ -597,8 +605,8 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { self.write_output(format!("{else_label}:"))?; match *expr.else_branch.unwrap() { - Expression::Block(block) => self.expression_block(block, scope)?, - Expression::If(if_expr) => self.expression_if(if_expr, scope)?, + Expression::Block(block) => self.expression_block(block.node, scope)?, + Expression::If(if_expr) => self.expression_if(if_expr.node, scope)?, _ => unreachable!("Parser ensures else branch is Block or If"), } } @@ -623,7 +631,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { self.write_output(format!("{start_label}:"))?; // Compile Body - self.expression_block(expr.body, scope)?; + self.expression_block(expr.body.node, scope)?; // Jump back to start self.write_output(format!("j {start_label}"))?; @@ -887,9 +895,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { ) -> Result<(), Error> { // First, sort the expressions to ensure functions are hoisted expr.0.sort_by(|a, b| { - if matches!(b, Expression::Function(_)) && matches!(a, Expression::Function(_)) { + if matches!(b.node, Expression::Function(_)) + && matches!(a.node, Expression::Function(_)) + { std::cmp::Ordering::Equal - } else if matches!(a, Expression::Function(_)) { + } else if matches!(a.node, Expression::Function(_)) { std::cmp::Ordering::Less } else { std::cmp::Ordering::Greater @@ -898,19 +908,19 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { for expr in expr.0 { if !self.declared_main - && !matches!(expr, Expression::Function(_)) + && !matches!(expr.node, Expression::Function(_)) && !scope.has_parent() { self.write_output("main:")?; self.declared_main = true; } - match expr { + match expr.node { Expression::Return(ret_expr) => { self.expression_return(*ret_expr, scope)?; } _ => { - let result = self.expression(expr, scope)?; + let result = self.expression(expr.node, scope)?; // If the expression was a statement that returned a temp result (e.g. `1 + 2;` line), // we must free it to avoid leaking registers. if let Some(comp_res) = result @@ -940,7 +950,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { }; match expr { - Expression::Variable(var_name) => match scope.get_location_of(var_name)? { + Expression::Variable(var_name) => match scope.get_location_of(var_name.node)? { VariableLocation::Temporary(reg) | VariableLocation::Persistant(reg) => { self.write_output(format!( "move r{} r{reg} {}", @@ -1055,8 +1065,8 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { )); }; - let Some(device) = self.devices.get(&device) else { - return Err(Error::InvalidDevice(device)); + let Some(device) = self.devices.get(&device.node) else { + return Err(Error::InvalidDevice(device.node)); }; let Literal::String(logic_type) = logic_type else { @@ -1102,8 +1112,8 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { )); }; - let Some(device) = self.devices.get(&device) else { - return Err(Error::InvalidDevice(device)); + let Some(device) = self.devices.get(&device.node) else { + return Err(Error::InvalidDevice(device.node)); }; let Literal::String(logic_type) = logic_type else { @@ -1133,27 +1143,29 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { /// Calees are responsible for backing up any registers they wish to use. fn expression_function<'v>( &mut self, - expr: FunctionExpression, + expr: Spanned, scope: &mut VariableScope<'v>, ) -> Result<(), Error> { let FunctionExpression { name, arguments, body, - } = expr; + } = *expr; - if self.function_locations.contains_key(&name) { - return Err(Error::DuplicateIdentifier(name)); + if self.function_locations.contains_key(&name.node) { + return Err(Error::DuplicateIdentifier(name.node)); } - self.function_metadata - .insert(name.clone(), arguments.clone()); + self.function_metadata.insert( + name.node.clone(), + arguments.iter().map(|a| a.node.clone()).collect(), + ); // Declare the function as a line identifier - self.write_output(format!("{}:", name))?; + self.write_output(format!("{}:", name.node))?; self.function_locations - .insert(name.clone(), self.current_line); + .insert(name.node.clone(), self.current_line); // Create a new block scope for the function body let mut block_scope = VariableScope::scoped(scope); @@ -1166,13 +1178,16 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { .rev() .take(VariableScope::PERSIST_REGISTER_COUNT as usize) { - let loc = block_scope.add_variable(var_name, LocationRequest::Persist)?; + let loc = block_scope.add_variable(var_name.node.clone(), LocationRequest::Persist)?; // we don't need to imcrement the stack offset as it's already on the stack from the // previous scope match loc { VariableLocation::Persistant(loc) => { - self.write_output(format!("pop r{loc} {}", debug!(self, "#{var_name}")))?; + self.write_output(format!( + "pop r{loc} {}", + debug!(self, "#{}", var_name.node) + ))?; } VariableLocation::Stack(_) => { return Err(Error::Unknown( @@ -1194,19 +1209,19 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { // anything as they already exist on the stack, but we DO need to let our block_scope be // aware that the variables exist on the stack (left to right) for var_name in arguments.iter().take(arguments.len() - saved_variables) { - block_scope.add_variable(var_name, LocationRequest::Stack)?; + block_scope.add_variable(var_name.node.clone(), LocationRequest::Stack)?; } self.write_output("push ra")?; - block_scope.add_variable(format!("{name}_ra"), LocationRequest::Stack)?; + block_scope.add_variable(format!("{}_ra", name.node), LocationRequest::Stack)?; for expr in body.0 { - match expr { + match expr.node { Expression::Return(ret_expr) => { self.expression_return(*ret_expr, &mut block_scope)?; } _ => { - let result = self.expression(expr, &mut block_scope)?; + let result = self.expression(expr.node, &mut block_scope)?; // Free unused statement results if let Some(comp_res) = result && let Some(name) = comp_res.temp_name @@ -1219,7 +1234,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> { // Get the saved return address and save it back into `ra` let VariableLocation::Stack(ra_stack_offset) = - block_scope.get_location_of(format!("{name}_ra"))? + block_scope.get_location_of(format!("{}_ra", name.node))? else { return Err(Error::Unknown( "Stored return address not in stack as expected".into(), diff --git a/rust_compiler/libs/parser/src/lib.rs b/rust_compiler/libs/parser/src/lib.rs index 2b89b23..dd73f82 100644 --- a/rust_compiler/libs/parser/src/lib.rs +++ b/rust_compiler/libs/parser/src/lib.rs @@ -544,6 +544,7 @@ impl<'a> Parser<'a> { } let identifier_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; + let identifier_span = Self::token_to_span(identifier_token); let identifier = match identifier_token.token_type { TokenType::Identifier(ref id) => id.clone(), _ => { @@ -574,13 +575,18 @@ impl<'a> Parser<'a> { }; Ok(DeviceDeclarationExpression { - name: identifier, + name: Spanned { + span: identifier_span, + node: identifier, + }, device, }) } fn assignment(&mut self) -> Result { - let identifier = match self.current_token.as_ref().unwrap().token_type { + let identifier_token = self.current_token.as_ref().unwrap(); + let identifier_span = Self::token_to_span(identifier_token); + let identifier = match identifier_token.token_type { TokenType::Identifier(ref id) => id.clone(), _ => { return Err(Error::UnexpectedToken( @@ -602,7 +608,10 @@ impl<'a> Parser<'a> { let expression = self.expression()?.ok_or(Error::UnexpectedEOF)?; Ok(AssignmentExpression { - identifier, + identifier: Spanned { + span: identifier_span, + node: identifier, + }, expression: boxed!(expression), }) } @@ -905,7 +914,9 @@ impl<'a> Parser<'a> { } fn invocation(&mut self) -> Result { - let identifier = match self.current_token.as_ref().unwrap().token_type { + let identifier_token = self.current_token.as_ref().unwrap(); + let identifier_span = Self::token_to_span(identifier_token); + let identifier = match identifier_token.token_type { TokenType::Identifier(ref id) => id.clone(), _ => { return Err(Error::UnexpectedToken( @@ -956,7 +967,10 @@ impl<'a> Parser<'a> { } Ok(InvocationExpression { - name: identifier, + name: Spanned { + span: identifier_span, + node: identifier, + }, arguments, }) } @@ -1022,13 +1036,6 @@ impl<'a> Parser<'a> { } fn declaration(&mut self) -> Result { - // "let" consumed by unary before calling spanned(declaration). - // But spanned() peeks start. Unary did NOT consume let inside unary match... - // Wait, Unary DOES match on current_token. It is `Let`. - // Then Unary calls `self.spanned(|p| p.declaration())`. - // `declaration()` checks `self.current_token` is `Let`. - // So `declaration` expects `Let` to be current. - let current_token = self.current_token.as_ref().ok_or(Error::UnexpectedEOF)?; if !self_matches_current!(self, TokenType::Keyword(Keyword::Let)) { return Err(Error::UnexpectedToken( @@ -1037,6 +1044,7 @@ impl<'a> Parser<'a> { )); } let identifier_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; + let identifier_span = Self::token_to_span(identifier_token); let identifier = match identifier_token.token_type { TokenType::Identifier(ref id) => id.clone(), _ => { @@ -1068,7 +1076,10 @@ impl<'a> Parser<'a> { } Ok(Expression::Declaration( - identifier, + Spanned { + span: identifier_span, + node: identifier, + }, boxed!(assignment_expression), )) } @@ -1210,6 +1221,7 @@ impl<'a> Parser<'a> { fn function(&mut self) -> Result { // 'fn' is current let fn_ident_token = self.get_next()?.ok_or(Error::UnexpectedEOF)?; + let fn_ident_span = Self::token_to_span(fn_ident_token); let fn_ident = match fn_ident_token.token_type { TokenType::Identifier(ref id) => id.clone(), _ => { @@ -1228,13 +1240,14 @@ impl<'a> Parser<'a> { )); } - let mut arguments = Vec::::new(); + let mut arguments = Vec::>::new(); while !token_matches!( self.get_next()?.ok_or(Error::UnexpectedEOF)?, TokenType::Symbol(Symbol::RParen) ) { let current_token = self.current_token.as_ref().unwrap(); + let arg_span = Self::token_to_span(current_token); let argument = match current_token.token_type { TokenType::Identifier(ref id) => id.clone(), _ => { @@ -1245,14 +1258,19 @@ impl<'a> Parser<'a> { } }; - if arguments.contains(&argument) { + let spanned_arg = Spanned { + span: arg_span, + node: argument, + }; + + if arguments.contains(&spanned_arg) { return Err(Error::DuplicateIdentifier( Self::token_to_span(current_token), current_token.clone(), )); } - arguments.push(argument); + arguments.push(spanned_arg); if !self_matches_peek!(self, TokenType::Symbol(Symbol::Comma)) && !self_matches_peek!(self, TokenType::Symbol(Symbol::RParen)) @@ -1278,7 +1296,10 @@ impl<'a> Parser<'a> { }; Ok(FunctionExpression { - name: fn_ident, + name: Spanned { + span: fn_ident_span, + node: fn_ident, + }, arguments, body: self.block()?, }) @@ -1305,9 +1326,7 @@ impl<'a> Parser<'a> { Some(Expression::Literal(literal)) => { LiteralOrVariable::Literal(literal.node.clone()) } - Some(Expression::Variable(ident)) => { - LiteralOrVariable::Variable(ident.node.clone()) - } + Some(Expression::Variable(ident)) => LiteralOrVariable::Variable(ident), _ => { return Err(Error::UnexpectedToken( self.current_span(), @@ -1334,7 +1353,7 @@ impl<'a> Parser<'a> { let invocation = self.invocation()?; - match invocation.name.as_str() { + match invocation.name.node.as_str() { "yield" => { check_length(self, &invocation.arguments, 0)?; Ok(SysCall::System(sys_call::System::Yield)) @@ -1420,3 +1439,4 @@ impl<'a> Parser<'a> { } } } + diff --git a/rust_compiler/libs/parser/src/tree_node.rs b/rust_compiler/libs/parser/src/tree_node.rs index 21588d2..78af175 100644 --- a/rust_compiler/libs/parser/src/tree_node.rs +++ b/rust_compiler/libs/parser/src/tree_node.rs @@ -74,7 +74,7 @@ impl std::fmt::Display for LogicalExpression { #[derive(Debug, PartialEq, Eq)] pub struct AssignmentExpression { - pub identifier: String, + pub identifier: Spanned, pub expression: Box>, } @@ -86,8 +86,8 @@ impl std::fmt::Display for AssignmentExpression { #[derive(Debug, PartialEq, Eq)] pub struct FunctionExpression { - pub name: String, - pub arguments: Vec, + pub name: Spanned, + pub arguments: Vec>, pub body: BlockExpression, } @@ -97,7 +97,11 @@ impl std::fmt::Display for FunctionExpression { f, "(fn {}({}) {{ {} }})", self.name, - self.arguments.to_vec().join(", "), + self.arguments + .iter() + .map(|e| e.to_string()) + .collect::>() + .join(", "), self.body ) } @@ -122,7 +126,7 @@ impl std::fmt::Display for BlockExpression { #[derive(Debug, PartialEq, Eq)] pub struct InvocationExpression { - pub name: String, + pub name: Spanned, pub arguments: Vec, } @@ -144,7 +148,7 @@ impl std::fmt::Display for InvocationExpression { #[derive(Debug, PartialEq, Eq)] pub enum LiteralOrVariable { Literal(Literal), - Variable(String), + Variable(Spanned), } impl std::fmt::Display for LiteralOrVariable { @@ -159,7 +163,7 @@ impl std::fmt::Display for LiteralOrVariable { #[derive(Debug, PartialEq, Eq)] pub struct DeviceDeclarationExpression { /// any variable-like name - pub name: String, + pub name: Spanned, /// The device port, ex. (db, d0, d1, d2, d3, d4, d5) pub device: String, } @@ -218,7 +222,7 @@ pub struct Span { pub end_col: usize, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Spanned { pub span: Span, pub node: T, @@ -248,7 +252,7 @@ pub enum Expression { Block(Spanned), Break(Span), Continue(Span), - Declaration(String, Box>), + Declaration(Spanned, Box>), DeviceDeclaration(Spanned), Function(Spanned), If(Spanned), @@ -289,3 +293,4 @@ impl std::fmt::Display for Expression { } } } +