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.
variable_scope: Vec<HashMap<String, i32>>,
function_locations: HashMap<String, usize>,
devices: HashMap<String, String>,
output: &'a mut BufWriter<Box<dyn Write>>,
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;
}

View File

@@ -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<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> {
let identifier = extract_token_data!(
token_from_option!(self.current_token),

View File

@@ -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<Expression>),
ReturnExpression(Box<Expression>),
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),
}
}
}

View File

@@ -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!() => {

View File

@@ -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