hence/hence/src/arg.rs

370 lines
14 KiB
Rust

use anyhow::{bail, Result};
use parse_int;
use rand;
use std::cmp::Ordering;
use std::fmt;
use unescape::unescape;
use crate::arg;
use crate::assembler;
use crate::lexer;
pub fn unescape_string(string: &str) -> String {
match unescape(string) {
Some(x) => x,
None => "".to_string(),
}
}
#[derive(Debug, Clone)]
pub enum Arg {
Char(char),
String(String),
Number(u16),
Variable(String),
BinaryExpression {
left: Box<Self>,
right: Box<Self>,
op: BinaryExpressionOperator,
},
}
impl fmt::Display for Arg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Arg::Char(x) => write!(f, "'{}'", x.escape_default()),
Arg::String(x) => write!(f, "\"{}\"", x.escape_default()),
Arg::Number(x) => write!(f, "{}", x),
Arg::Variable(x) => write!(f, "{}", x.clone()),
Arg::BinaryExpression { left, right, op } => {
write!(f, "({} {} {})", left, op, right)
}
}
}
}
impl assembler::ToCode for Arg {}
impl assembler::ByteResolvable<assembler::Assembler> for Arg {
fn resolve_number(&self, data: &mut assembler::Assembler) -> Result<u16> {
match self {
Arg::Char(x) => Ok(*x as u16),
Arg::String(x) => {
let y = unescape_string(x);
if y.len() == 1 {
Ok(y.as_bytes()[0] as u16)
} else {
let bytes = y.as_bytes();
Ok(((bytes[0] as u16) << 8) | bytes[1] as u16)
}
}
Arg::Number(x) => Ok(*x),
Arg::Variable(x) => {
let mut name = x.clone();
let mut arg: Option<arg::Arg>;
loop {
arg = data.constants.get(&name).cloned();
match arg {
Some(a) => {
match a {
arg::Arg::Variable(n) => {
name = n;
}
_ => break Ok(a.resolve_number(data)?),
};
}
_ => bail!("Variable does not exist: {}", name),
}
}
}
Arg::BinaryExpression { left, right, op } => {
let left_val = left.resolve_number(data)?;
let right_val = right.resolve_number(data)?;
Ok(match op {
BinaryExpressionOperator::Not => !left_val,
BinaryExpressionOperator::And => left_val & right_val,
BinaryExpressionOperator::Nand => !(left_val & right_val),
BinaryExpressionOperator::Or => left_val | right_val,
BinaryExpressionOperator::Nor => !(left_val | right_val),
BinaryExpressionOperator::Xor => left_val ^ right_val,
BinaryExpressionOperator::Xnor => !(left_val ^ right_val),
BinaryExpressionOperator::Lsh => left_val << right_val,
BinaryExpressionOperator::Rsh => left_val >> right_val,
BinaryExpressionOperator::Add => left_val.wrapping_add(right_val),
BinaryExpressionOperator::Sub => left_val.wrapping_sub(right_val),
BinaryExpressionOperator::Mul => left_val.wrapping_mul(right_val),
BinaryExpressionOperator::Div => left_val.wrapping_div(right_val),
BinaryExpressionOperator::Pow => left_val.wrapping_pow(right_val as u32),
BinaryExpressionOperator::Cmp => match left_val.cmp(&right_val) {
Ordering::Equal => 0,
Ordering::Less => 1,
Ordering::Greater => 2,
},
BinaryExpressionOperator::Eq => (left_val == right_val) as u16,
BinaryExpressionOperator::Neq => (left_val != right_val) as u16,
BinaryExpressionOperator::Lt => (left_val < right_val) as u16,
BinaryExpressionOperator::Gt => (left_val > right_val) as u16,
BinaryExpressionOperator::Leq => (left_val <= right_val) as u16,
BinaryExpressionOperator::Geq => (left_val >= right_val) as u16,
BinaryExpressionOperator::Bol => (left_val & 1 == 1) as u16,
BinaryExpressionOperator::Inv => (left_val & 1 != 1) as u16,
BinaryExpressionOperator::Rnd => rand::random(),
})
}
}
}
fn resolve_bytes(&self, data: &mut assembler::Assembler) -> Result<Vec<u8>> {
match self {
Arg::Char(x) => Ok(vec![*x as u8]),
Arg::String(x) => Ok(unescape_string(x).bytes().collect()),
Arg::Number(x) => Ok(vec![(*x >> 8) as u8, *x as u8]),
Arg::Variable(x) => {
let mut name = x.clone();
let mut arg: Option<arg::Arg>;
loop {
arg = data.constants.get(&name).cloned();
match arg {
Some(a) => {
match a {
arg::Arg::Variable(n) => {
name = n;
}
_ => break Ok(a.resolve_bytes(data)?),
};
}
_ => bail!("Variable could not be resolved: {}", name),
}
}
}
Arg::BinaryExpression {
left: _,
right: _,
op: _,
} => {
let x = self.resolve_number(data)?;
Ok(vec![(x >> 8) as u8, x as u8])
}
}
}
fn resolve_string(&self, data: &mut assembler::Assembler) -> Result<String> {
match self {
Arg::Char(x) => Ok(x.to_string()),
Arg::String(x) => Ok(x.clone()),
Arg::Number(_) => bail!("Number cannot be resolved as string"),
Arg::Variable(_) => self.resolve_string(data),
Arg::BinaryExpression {
left: _,
right: _,
op: _,
} => bail!("Binary expression cannot be resolved as string"),
}
}
}
#[derive(Debug, Clone)]
pub enum BinaryExpressionOperator {
Not,
And,
Nand,
Or,
Nor,
Xor,
Xnor,
Lsh,
Rsh,
Add,
Sub,
Mul,
Div,
Pow,
Cmp,
Eq,
Neq,
Lt,
Gt,
Leq,
Geq,
Bol,
Inv,
Rnd,
}
impl fmt::Display for BinaryExpressionOperator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BinaryExpressionOperator::Not => write!(f, "~"),
BinaryExpressionOperator::And => write!(f, "&"),
BinaryExpressionOperator::Nand => write!(f, "~&"),
BinaryExpressionOperator::Or => write!(f, "|"),
BinaryExpressionOperator::Nor => write!(f, "~|"),
BinaryExpressionOperator::Xor => write!(f, "^"),
BinaryExpressionOperator::Xnor => write!(f, "~^"),
BinaryExpressionOperator::Lsh => write!(f, "<<"),
BinaryExpressionOperator::Rsh => write!(f, ">>"),
BinaryExpressionOperator::Add => write!(f, "+"),
BinaryExpressionOperator::Sub => write!(f, "-"),
BinaryExpressionOperator::Mul => write!(f, "*"),
BinaryExpressionOperator::Div => write!(f, "/"),
BinaryExpressionOperator::Pow => write!(f, "**"),
BinaryExpressionOperator::Cmp => write!(f, "<=>"),
BinaryExpressionOperator::Eq => write!(f, "=="),
BinaryExpressionOperator::Neq => write!(f, "!="),
BinaryExpressionOperator::Lt => write!(f, "<"),
BinaryExpressionOperator::Gt => write!(f, ">"),
BinaryExpressionOperator::Leq => write!(f, "<="),
BinaryExpressionOperator::Geq => write!(f, ">="),
BinaryExpressionOperator::Bol => write!(f, "!!"),
BinaryExpressionOperator::Inv => write!(f, "!"),
BinaryExpressionOperator::Rnd => write!(f, "?"),
}
}
}
impl assembler::ToCode for BinaryExpressionOperator {}
pub fn parse_binary_operation(token: &lexer::Token) -> Result<BinaryExpressionOperator> {
match token {
lexer::Token::Not => Ok(BinaryExpressionOperator::Not),
lexer::Token::And => Ok(BinaryExpressionOperator::And),
lexer::Token::Nand => Ok(BinaryExpressionOperator::Nand),
lexer::Token::Or => Ok(BinaryExpressionOperator::Or),
lexer::Token::Nor => Ok(BinaryExpressionOperator::Nor),
lexer::Token::Xor => Ok(BinaryExpressionOperator::Xor),
lexer::Token::Xnor => Ok(BinaryExpressionOperator::Xnor),
lexer::Token::Lsh => Ok(BinaryExpressionOperator::Lsh),
lexer::Token::Rsh => Ok(BinaryExpressionOperator::Rsh),
lexer::Token::Add => Ok(BinaryExpressionOperator::Add),
lexer::Token::Sub => Ok(BinaryExpressionOperator::Sub),
lexer::Token::Mul => Ok(BinaryExpressionOperator::Mul),
lexer::Token::Div => Ok(BinaryExpressionOperator::Div),
lexer::Token::Pow => Ok(BinaryExpressionOperator::Pow),
lexer::Token::Cmp => Ok(BinaryExpressionOperator::Cmp),
lexer::Token::Eq => Ok(BinaryExpressionOperator::Eq),
lexer::Token::Neq => Ok(BinaryExpressionOperator::Neq),
lexer::Token::Lt => Ok(BinaryExpressionOperator::Lt),
lexer::Token::Gt => Ok(BinaryExpressionOperator::Gt),
lexer::Token::Leq => Ok(BinaryExpressionOperator::Leq),
lexer::Token::Geq => Ok(BinaryExpressionOperator::Geq),
lexer::Token::Bol => Ok(BinaryExpressionOperator::Bol),
lexer::Token::Inv => Ok(BinaryExpressionOperator::Inv),
lexer::Token::Rnd => Ok(BinaryExpressionOperator::Rnd),
_ => bail!("Invalid binary expression operator"),
}
}
pub fn parse_binary_expression_arg(tokens: &mut Vec<&lexer::Token>) -> Result<Arg> {
if tokens.is_empty() {
bail!("Malformed binary expression");
}
let mut args: Vec<_> = tokens.drain(..3).collect();
let mut bin_expr = Arg::BinaryExpression {
left: Box::new(parse_args(vec![args[0]])?[0].clone()),
right: Box::new(parse_args(vec![args[2]])?[0].clone()),
op: parse_binary_operation(args[1])?,
};
while !tokens.is_empty() {
args = tokens.drain(..2).collect();
bin_expr = Arg::BinaryExpression {
left: Box::new(bin_expr),
right: Box::new(parse_args(vec![args[1]])?[0].clone()),
op: parse_binary_operation(args[0])?,
}
}
Ok(bin_expr)
}
pub fn parse_args(tokens: Vec<&lexer::Token>) -> Result<Vec<Arg>> {
let mut iter = tokens.into_iter();
let mut args: Vec<Arg> = vec![];
let mut last_was_comma = true;
while let Some(token) = iter.next() {
match token {
lexer::Token::Comma => {
last_was_comma = true;
}
_ => {
if !last_was_comma {
bail!("Invalid argument separation");
}
match token {
lexer::Token::Comment(_) => {}
lexer::Token::CharLiteral(x) => {
let y = unescape_string(x);
if y.len() > 1 {
bail!("Char cannot hold string")
} else if let Some(c) = y.chars().next() {
args.push(Arg::Char(c));
} else {
bail!("Char cannot be empty");
}
}
lexer::Token::StringLiteral(x) => {
args.push(Arg::String(x.clone()));
}
lexer::Token::Literal(x) => {
args.push(Arg::Variable(x.clone()));
}
lexer::Token::Number(x) => {
args.push(Arg::Number(if x.starts_with('-') {
-parse_int::parse::<i16>(&x[1..])? as u16
} else {
parse_int::parse(x)?
}));
}
lexer::Token::LParen => {
let mut depth: usize = 1;
args.push(parse_binary_expression_arg(
&mut iter
.by_ref()
.take_while(|t| match t {
lexer::Token::LParen => {
depth += 1;
true
}
lexer::Token::RParen => {
depth -= 1;
depth != 0
}
_ => true,
})
.collect(),
)?);
}
_ => bail!("Unexpected token for argument"),
}
last_was_comma = false;
}
}
}
Ok(args)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_unescape_string() {
assert_eq!(unescape_string("\\n test"), "\n test".to_string());
assert_eq!(unescape_string(""), "".to_string());
}
}