Add support for device declaration expressions

This commit is contained in:
2024-11-29 19:57:44 -07:00
parent 1e0f986cf1
commit 548d826078
6 changed files with 65 additions and 1 deletions

View File

@@ -35,6 +35,7 @@ pub struct Compiler<'a> {
/// Max stack size for the program is by default 512. /// Max stack size for the program is by default 512.
variable_scope: Vec<HashMap<String, i32>>, variable_scope: Vec<HashMap<String, i32>>,
function_locations: HashMap<String, usize>, function_locations: HashMap<String, usize>,
devices: HashMap<String, String>,
output: &'a mut BufWriter<Box<dyn Write>>, output: &'a mut BufWriter<Box<dyn Write>>,
current_line: usize, current_line: usize,
declared_main: bool, declared_main: bool,
@@ -46,6 +47,7 @@ impl<'a> Compiler<'a> {
parser, parser,
variable_scope: Vec::new(), variable_scope: Vec::new(),
function_locations: HashMap::new(), function_locations: HashMap::new(),
devices: HashMap::new(),
output: writer, output: writer,
current_line: 0, current_line: 0,
declared_main: false, declared_main: false,
@@ -122,6 +124,12 @@ impl<'a> Compiler<'a> {
Expression::DeclarationExpression(var_name, expr) => { Expression::DeclarationExpression(var_name, expr) => {
self.declaration_expression(&var_name, *expr)? self.declaration_expression(&var_name, *expr)?
} }
Expression::DeviceDeclarationExpression(DeviceDeclarationExpression {
name,
device,
}) => {
self.devices.insert(name, device);
}
_ => todo!("{:?}", expression), _ => todo!("{:?}", expression),
}; };
@@ -250,7 +258,7 @@ impl<'a> Compiler<'a> {
} }
_ => todo!("something is up with the arguments"), _ => 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; iter_index += 1;
} }

View File

@@ -180,6 +180,10 @@ impl Parser {
// match declarations with a `let` keyword // match declarations with a `let` keyword
TokenType::Keyword(Keyword::Let) => self.declaration()?, TokenType::Keyword(Keyword::Let) => self.declaration()?,
TokenType::Keyword(Keyword::Device) => {
Expression::DeviceDeclarationExpression(self.device()?)
}
// match functions with a `fn` keyword // match functions with a `fn` keyword
TokenType::Keyword(Keyword::Fn) => Expression::FunctionExpression(self.function()?), TokenType::Keyword(Keyword::Fn) => Expression::FunctionExpression(self.function()?),
@@ -258,6 +262,37 @@ impl Parser {
} }
} }
fn device(&mut self) -> Result<DeviceDeclarationExpression, ParseError> {
// 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<AssignmentExpression, ParseError> { fn assignment(&mut self) -> Result<AssignmentExpression, ParseError> {
let identifier = extract_token_data!( let identifier = extract_token_data!(
token_from_option!(self.current_token), token_from_option!(self.current_token),

View File

@@ -144,6 +144,20 @@ pub enum LiteralOrVariable {
Variable(String), 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)] #[derive(Debug, PartialEq, Eq)]
pub enum Expression { pub enum Expression {
@@ -159,6 +173,7 @@ pub enum Expression {
PriorityExpression(Box<Expression>), PriorityExpression(Box<Expression>),
ReturnExpression(Box<Expression>), ReturnExpression(Box<Expression>),
Variable(String), Variable(String),
DeviceDeclarationExpression(DeviceDeclarationExpression),
} }
impl std::fmt::Display for Expression { impl std::fmt::Display for Expression {
@@ -176,6 +191,7 @@ impl std::fmt::Display for Expression {
Expression::Variable(id) => write!(f, "{}", id), Expression::Variable(id) => write!(f, "{}", id),
Expression::PriorityExpression(e) => write!(f, "({})", e), Expression::PriorityExpression(e) => write!(f, "({})", e),
Expression::ReturnExpression(e) => write!(f, "(return {})", e), Expression::ReturnExpression(e) => write!(f, "(return {})", e),
Expression::DeviceDeclarationExpression(e) => write!(f, "{}", e),
} }
} }
} }

View File

@@ -406,6 +406,7 @@ impl Tokenizer {
"enum" if next_ws!() => keyword!(Enum), "enum" if next_ws!() => keyword!(Enum),
"import" if next_ws!() => keyword!(Import), "import" if next_ws!() => keyword!(Import),
"export" if next_ws!() => keyword!(Export), "export" if next_ws!() => keyword!(Export),
"device" if next_ws!() => keyword!(Device),
// boolean literals // boolean literals
"true" if next_ws!() => { "true" if next_ws!() => {

View File

@@ -164,6 +164,8 @@ pub enum Keyword {
Fn, Fn,
/// Represents the `if` keyword /// Represents the `if` keyword
If, If,
/// Represents the `device` keyword. Useful for defining a device at a specific address (ex. d0, d1, d2, etc.)
Device,
/// Represents the `else` keyword /// Represents the `else` keyword
Else, Else,
/// Represents the `return` keyword /// Represents the `return` keyword

View File

@@ -1,3 +1,5 @@
device self = "db";
fn doStuff(x, y, z) { fn doStuff(x, y, z) {
let i = x + y + z; let i = x + y + z;
}; };