From 548d82607884b7a839c9390107c0da8fbb90ac96 Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Fri, 29 Nov 2024 19:57:44 -0700 Subject: [PATCH] Add support for device declaration expressions --- src/compiler/mod.rs | 10 +++++++++- src/parser/mod.rs | 35 +++++++++++++++++++++++++++++++++++ src/parser/tree_node.rs | 16 ++++++++++++++++ src/tokenizer/mod.rs | 1 + src/tokenizer/token.rs | 2 ++ tests/file.stlg | 2 ++ 6 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 292eb61..28a3b3a 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -35,6 +35,7 @@ pub struct Compiler<'a> { /// Max stack size for the program is by default 512. variable_scope: Vec>, function_locations: HashMap, + devices: HashMap, output: &'a mut BufWriter>, current_line: usize, declared_main: bool, @@ -46,6 +47,7 @@ impl<'a> Compiler<'a> { parser, variable_scope: Vec::new(), function_locations: HashMap::new(), + devices: HashMap::new(), output: writer, current_line: 0, declared_main: false, @@ -122,6 +124,12 @@ impl<'a> Compiler<'a> { Expression::DeclarationExpression(var_name, expr) => { self.declaration_expression(&var_name, *expr)? } + Expression::DeviceDeclarationExpression(DeviceDeclarationExpression { + name, + device, + }) => { + self.devices.insert(name, device); + } _ => todo!("{:?}", expression), }; @@ -250,7 +258,7 @@ impl<'a> Compiler<'a> { } _ => todo!("something is up with the arguments"), } - self.push_stack(&format!("{function_name}{iter_index}"))?; + self.push_stack(&format!("{function_name}Invocation{iter_index}"))?; iter_index += 1; } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0ecc701..32522d9 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -180,6 +180,10 @@ impl Parser { // match declarations with a `let` keyword TokenType::Keyword(Keyword::Let) => self.declaration()?, + TokenType::Keyword(Keyword::Device) => { + Expression::DeviceDeclarationExpression(self.device()?) + } + // match functions with a `fn` keyword TokenType::Keyword(Keyword::Fn) => Expression::FunctionExpression(self.function()?), @@ -258,6 +262,37 @@ impl Parser { } } + fn device(&mut self) -> Result { + // sanity check, make sure current token is a `device` keyword + + let current_token = token_from_option!(self.current_token); + if !self_matches_current!(self, TokenType::Keyword(Keyword::Device)) { + return Err(ParseError::UnexpectedToken(current_token.clone())); + } + + let identifier = extract_token_data!( + token_from_option!(self.get_next()?), + TokenType::Identifier(ref id), + id.clone() + ); + + let current_token = token_from_option!(self.get_next()?).clone(); + if !token_matches!(current_token, TokenType::Symbol(Symbol::Assign)) { + return Err(ParseError::UnexpectedToken(current_token)); + } + + let device = extract_token_data!( + token_from_option!(self.get_next()?), + TokenType::String(ref id), + id.clone() + ); + + Ok(DeviceDeclarationExpression { + name: identifier, + device, + }) + } + fn assignment(&mut self) -> Result { let identifier = extract_token_data!( token_from_option!(self.current_token), diff --git a/src/parser/tree_node.rs b/src/parser/tree_node.rs index 3296803..a1f448d 100644 --- a/src/parser/tree_node.rs +++ b/src/parser/tree_node.rs @@ -144,6 +144,20 @@ pub enum LiteralOrVariable { Variable(String), } +#[derive(Debug, PartialEq, Eq)] +pub struct DeviceDeclarationExpression { + /// any variable-like name + pub name: String, + /// The device port, ex. (db, d0, d1, d2, d3, d4, d5) + pub device: String, +} + +impl std::fmt::Display for DeviceDeclarationExpression { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "(device {} = {})", self.name, self.device) + } +} + #[derive(Debug, PartialEq, Eq)] pub enum Expression { @@ -159,6 +173,7 @@ pub enum Expression { PriorityExpression(Box), ReturnExpression(Box), Variable(String), + DeviceDeclarationExpression(DeviceDeclarationExpression), } impl std::fmt::Display for Expression { @@ -176,6 +191,7 @@ impl std::fmt::Display for Expression { Expression::Variable(id) => write!(f, "{}", id), Expression::PriorityExpression(e) => write!(f, "({})", e), Expression::ReturnExpression(e) => write!(f, "(return {})", e), + Expression::DeviceDeclarationExpression(e) => write!(f, "{}", e), } } } diff --git a/src/tokenizer/mod.rs b/src/tokenizer/mod.rs index 64c10d3..a9d3414 100644 --- a/src/tokenizer/mod.rs +++ b/src/tokenizer/mod.rs @@ -406,6 +406,7 @@ impl Tokenizer { "enum" if next_ws!() => keyword!(Enum), "import" if next_ws!() => keyword!(Import), "export" if next_ws!() => keyword!(Export), + "device" if next_ws!() => keyword!(Device), // boolean literals "true" if next_ws!() => { diff --git a/src/tokenizer/token.rs b/src/tokenizer/token.rs index e966395..e507186 100644 --- a/src/tokenizer/token.rs +++ b/src/tokenizer/token.rs @@ -164,6 +164,8 @@ pub enum Keyword { Fn, /// Represents the `if` keyword If, + /// Represents the `device` keyword. Useful for defining a device at a specific address (ex. d0, d1, d2, etc.) + Device, /// Represents the `else` keyword Else, /// Represents the `return` keyword diff --git a/tests/file.stlg b/tests/file.stlg index 1036d0e..82e1567 100644 --- a/tests/file.stlg +++ b/tests/file.stlg @@ -1,3 +1,5 @@ +device self = "db"; + fn doStuff(x, y, z) { let i = x + y + z; };