emit negated declarations
This commit is contained in:
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user