forked from MightyPork/crsn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
6.0 KiB
229 lines
6.0 KiB
use std::fmt::{self, Display, Formatter};
|
|
use std::ops::Not;
|
|
|
|
use sexp::SourcePosition;
|
|
|
|
use crate::asm::error::CrsnError;
|
|
|
|
/// Condition flag
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
|
pub enum Flag {
|
|
/// Equality
|
|
Equal,
|
|
/// Equal to zero
|
|
Zero,
|
|
/// A < B
|
|
Lower,
|
|
/// A > B
|
|
Greater,
|
|
/// A > 0
|
|
Positive,
|
|
/// A < 0
|
|
Negative,
|
|
/// Arithmetic operation caused an integer operand to overflow
|
|
Overflow,
|
|
/// Arithmetic (or other) operation was invalid.
|
|
/// Example: division by zero
|
|
Invalid,
|
|
/// Arithmetic carry
|
|
Carry,
|
|
// Full
|
|
Full,
|
|
// Empty
|
|
Empty,
|
|
// Empty
|
|
Eof,
|
|
}
|
|
|
|
impl From<Flag> for Cond {
|
|
fn from(flag: Flag) -> Self {
|
|
match flag {
|
|
Flag::Equal => Cond::Equal,
|
|
Flag::Zero => Cond::Zero,
|
|
Flag::Lower => Cond::Lower,
|
|
Flag::Greater => Cond::Greater,
|
|
Flag::Positive => Cond::Positive,
|
|
Flag::Negative => Cond::Negative,
|
|
Flag::Overflow => Cond::Overflow,
|
|
Flag::Invalid => Cond::Invalid,
|
|
Flag::Carry => Cond::Carry,
|
|
Flag::Full => Cond::Full,
|
|
Flag::Empty => Cond::Empty,
|
|
Flag::Eof => Cond::Eof,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Condition flag
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
|
pub enum Cond {
|
|
/// Equality
|
|
Equal,
|
|
/// Inequality
|
|
NotEqual,
|
|
/// Equal to zero
|
|
Zero,
|
|
/// Not equal zero
|
|
NotZero,
|
|
/// A < B
|
|
Lower,
|
|
/// A <= B
|
|
LowerOrEqual,
|
|
/// A > B
|
|
Greater,
|
|
/// A >= B
|
|
GreaterOrEqual,
|
|
/// A > 0
|
|
Positive,
|
|
/// A <= 0
|
|
NonPositive,
|
|
/// A < 0
|
|
Negative,
|
|
/// A >= 0
|
|
NonNegative,
|
|
/// Arithmetic operation caused an integer operand to overflow
|
|
Overflow,
|
|
/// No overflow
|
|
NotOverflow,
|
|
/// Arithmetic (or other) operation was invalid.
|
|
/// Example: division by zero
|
|
Invalid,
|
|
/// Operation was valid
|
|
Valid,
|
|
/// Arithmetic carry
|
|
Carry,
|
|
/// Carry not set
|
|
NotCarry,
|
|
// Full
|
|
Full,
|
|
/// Not full
|
|
NotFull,
|
|
// Empty
|
|
Empty,
|
|
/// Not empty
|
|
NotEmpty,
|
|
// Empty
|
|
Eof,
|
|
/// Not empty
|
|
NotEof,
|
|
// Always true, for eg. (else? ...)
|
|
True,
|
|
/// Always false
|
|
False,
|
|
}
|
|
|
|
pub fn parse_cond(text: &str, pos: &SourcePosition) -> Result<Cond, CrsnError> {
|
|
Ok(match text.trim_end_matches('?') {
|
|
"eq" | "=" | "==" => Cond::Equal,
|
|
"ne" | "<>" | "!=" | "≠" => Cond::NotEqual,
|
|
"z" | "0" => Cond::Zero,
|
|
"nz" | "<>0" | "!0" => Cond::NotZero,
|
|
"lt" | "<" => Cond::Lower,
|
|
"le" | "<=" | "≤" => Cond::LowerOrEqual,
|
|
"gt" | ">" => Cond::Greater,
|
|
"ge" | ">=" | "≥" => Cond::GreaterOrEqual,
|
|
"pos" | "+" | ">0" => Cond::Positive,
|
|
"neg" | "-" | "<0" => Cond::Negative,
|
|
"npos" | "0-" | "<=0" | "≤0" => Cond::NonPositive,
|
|
"nneg" | "0+" | ">=0" | "≥0" => Cond::NonNegative,
|
|
"c" => Cond::Carry,
|
|
"nc" => Cond::NotCarry,
|
|
"em" | "empty" => Cond::Empty,
|
|
"nem" | "nempty" => Cond::NotEmpty,
|
|
"f" | "full" => Cond::Full,
|
|
"nf" | "nfull" => Cond::NotFull,
|
|
"ok" | "val" | "valid" => Cond::Valid,
|
|
"inval" | "invalid" | "nval" | "nok" => Cond::Invalid,
|
|
"eof" => Cond::Eof,
|
|
"neof" => Cond::NotEof,
|
|
"ov" => Cond::Overflow,
|
|
"nov" => Cond::NotOverflow,
|
|
"else" => Cond::True,
|
|
_ => {
|
|
return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into(), pos.clone()));
|
|
}
|
|
})
|
|
}
|
|
|
|
impl Display for Flag {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
let cond : Cond = (*self).into();
|
|
write!(f, "{}", cond)
|
|
}
|
|
}
|
|
|
|
impl Display for Cond {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
f.write_str(match self {
|
|
Cond::Equal => "eq",
|
|
Cond::NotEqual => "ne",
|
|
Cond::Zero => "z",
|
|
Cond::NotZero => "nz",
|
|
Cond::Empty => "emp",
|
|
Cond::NotEmpty => "nemp",
|
|
Cond::Full => "full",
|
|
Cond::NotFull => "nfull",
|
|
Cond::Lower => "lt",
|
|
Cond::LowerOrEqual => "le",
|
|
Cond::Greater => "gt",
|
|
Cond::GreaterOrEqual => "ge",
|
|
Cond::Positive => "pos",
|
|
Cond::Negative => "neg",
|
|
Cond::NonPositive => "npos",
|
|
Cond::NonNegative => "nneg",
|
|
Cond::Overflow => "ov",
|
|
Cond::NotOverflow => "nov",
|
|
Cond::Carry => "c",
|
|
Cond::NotCarry => "nc",
|
|
Cond::Invalid => "inval",
|
|
Cond::Valid => "valid",
|
|
Cond::Eof => "eof",
|
|
Cond::NotEof => "neof",
|
|
Cond::True => "else",
|
|
Cond::False => "never",
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Not for Cond {
|
|
type Output = Cond;
|
|
|
|
fn not(self) -> Self::Output {
|
|
match self {
|
|
Cond::Equal => Cond::NotEqual,
|
|
Cond::Zero => Cond::NotZero,
|
|
Cond::Overflow => Cond::NotOverflow,
|
|
Cond::Carry => Cond::NotCarry,
|
|
|
|
Cond::Empty => Cond::NotEmpty,
|
|
Cond::NotEmpty => Cond::Empty,
|
|
|
|
Cond::Full => Cond::NotFull,
|
|
Cond::NotFull => Cond::Full,
|
|
|
|
Cond::Positive => Cond::NonPositive,
|
|
Cond::Negative => Cond::NonNegative,
|
|
Cond::NonPositive => Cond::Positive,
|
|
Cond::NonNegative => Cond::Negative,
|
|
|
|
Cond::NotEqual => Cond::Equal,
|
|
Cond::NotZero => Cond::Zero,
|
|
Cond::NotOverflow => Cond::Overflow,
|
|
Cond::NotCarry => Cond::Carry,
|
|
|
|
Cond::Lower => Cond::GreaterOrEqual,
|
|
Cond::Greater => Cond::LowerOrEqual,
|
|
Cond::LowerOrEqual => Cond::Greater,
|
|
Cond::GreaterOrEqual => Cond::Lower,
|
|
|
|
Cond::Invalid => Cond::Valid,
|
|
Cond::Valid => Cond::Invalid,
|
|
|
|
Cond::NotEof => Cond::Eof,
|
|
Cond::Eof => Cond::NotEof,
|
|
|
|
Cond::True => Cond::False,
|
|
Cond::False => Cond::True,
|
|
}
|
|
}
|
|
}
|
|
|