emit negated declarations

This commit is contained in:
2025-11-22 22:44:25 -07:00
parent 1706698ffa
commit 17089b53e1
6 changed files with 560 additions and 27 deletions

View File

@@ -62,3 +62,26 @@ fn variable_declaration_numeric_literal_stack_spillover() -> anyhow::Result<()>
Ok(())
}
#[test]
fn variable_declaration_negative() -> anyhow::Result<()> {
let compiled = compile! {
debug
"
let i = -1;
"
};
assert_eq!(
compiled,
indoc! {
"
j main
main:
move r8 -1 #i
"
}
);
Ok(())
}

View File

@@ -2,8 +2,8 @@ use crate::variable_manager::{self, LocationRequest, VariableLocation, VariableS
use parser::{
Parser as ASTParser,
tree_node::{
BlockExpression, DeviceDeclarationExpression, Expression, FunctionExpression,
InvocationExpression, Literal,
BinaryExpression, BlockExpression, DeviceDeclarationExpression, Expression,
FunctionExpression, InvocationExpression, Literal,
},
};
use quick_error::quick_error;
@@ -124,46 +124,61 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
Ok(())
}
fn emit_variable_assignment(
&mut self,
var_name: &str,
location: VariableLocation,
source_value: impl Into<String>,
) -> Result<(), Error> {
let debug_tag = if self.config.debug {
format!(" #{var_name}")
} else {
String::new()
};
match location {
VariableLocation::Temporary(reg) | VariableLocation::Persistant(reg) => {
self.write_output(format!("move r{reg} {}{debug_tag}", source_value.into()))?;
}
VariableLocation::Stack(_) => {
self.write_output(format!("push {}{debug_tag}", source_value.into()))?;
}
}
Ok(())
}
fn expression_declaration<'v>(
&mut self,
var_name: String,
expr: Expression,
scope: &mut VariableScope<'v>,
) -> Result<(), Error> {
// optimization. Check for a negated numeric literal
if let Expression::Negation(box_expr) = &expr
&& let Expression::Literal(Literal::Number(neg_num)) = &**box_expr
{
let loc = scope.add_variable(&var_name, LocationRequest::Persist)?;
self.emit_variable_assignment(&var_name, loc, format!("-{neg_num}"))?;
return Ok(());
}
match expr {
Expression::Literal(Literal::Number(num)) => {
let var_location =
scope.add_variable(var_name.clone(), LocationRequest::Persist)?;
let num_str = num.to_string();
if let VariableLocation::Temporary(reg) | VariableLocation::Persistant(reg) =
var_location
{
self.write_output(format!(
"move r{reg} {num_str} {}",
debug!(self, "#{var_name}")
))?;
} else {
self.write_output(format!("push {num_str} {}", debug!(self, "#{var_name}")))?;
}
self.emit_variable_assignment(&var_name, var_location, num)?;
}
Expression::Invocation(invoke_expr) => {
self.expression_function_invocation(invoke_expr, scope)?;
// Return value _should_ be in VariableScope::RETURN_REGISTER
match scope.add_variable(var_name.clone(), LocationRequest::Persist)? {
VariableLocation::Temporary(reg) | VariableLocation::Persistant(reg) => self
.write_output(format!(
"move r{reg} r{} {}",
VariableScope::RETURN_REGISTER,
debug!(self, "#{var_name}")
))?,
VariableLocation::Stack(_) => self.write_output(format!(
"push r{} {}",
VariableScope::RETURN_REGISTER,
debug!(self, "#{var_name}")
))?,
}
let loc = scope.add_variable(&var_name, LocationRequest::Persist)?;
self.emit_variable_assignment(
&var_name,
loc,
format!("r{}", VariableScope::RETURN_REGISTER),
)?;
}
_ => {
return Err(Error::Unknown(
@@ -267,6 +282,14 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
Ok(())
}
fn expression_binary<'v>(
&mut self,
expr: BinaryExpression,
scope: &mut VariableScope<'v>,
) -> Result<(), Error> {
Ok(())
}
fn expression_block<'v>(
&mut self,
mut expr: BlockExpression,

View File

@@ -37,8 +37,11 @@ pub enum LocationRequest {
#[derive(Clone)]
pub enum VariableLocation {
/// Represents a temporary register (r1 - r7)
Temporary(u8),
/// Represents a persistant register (r8 - r14)
Persistant(u8),
/// Represents a a stack offset (current stack - offset = variable loc)
Stack(u16),
}

View File

@@ -214,6 +214,14 @@ impl Parser {
// match priority expressions with a left parenthesis
TokenType::Symbol(Symbol::LParen) => Expression::Priority(self.priority()?),
// match minus symbols to handle negative numbers or negated expressions
TokenType::Symbol(Symbol::Minus) => {
self.assign_next()?; // consume the `-` symbol
let inner_expr = self.expression()?.ok_or(Error::UnexpectedEOF)?;
Expression::Negation(boxed!(inner_expr))
}
_ => {
return Err(Error::UnexpectedToken(current_token.clone()));
}

View File

@@ -111,6 +111,12 @@ impl std::fmt::Display for Number {
}
}
impl std::convert::From<Number> for String {
fn from(value: Number) -> Self {
value.to_string()
}
}
#[derive(Debug, PartialEq, Hash, Eq, Clone, Copy)]
pub enum Symbol {
// Single Character Symbols