|
|
@ -1,28 +1,75 @@ |
|
|
|
use std::fmt::{self, Display, Formatter}; |
|
|
|
use std::fmt::{self, Display, Formatter}; |
|
|
|
use std::ops::Not; |
|
|
|
use std::ops::Not; |
|
|
|
|
|
|
|
use crate::error::Error; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Condition flag
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] |
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] |
|
|
|
pub enum Cond { |
|
|
|
pub enum Cond { |
|
|
|
|
|
|
|
/// Equality
|
|
|
|
Equal, |
|
|
|
Equal, |
|
|
|
|
|
|
|
/// Inequality
|
|
|
|
NotEqual, |
|
|
|
NotEqual, |
|
|
|
|
|
|
|
/// Equal to zero
|
|
|
|
Zero, |
|
|
|
Zero, |
|
|
|
|
|
|
|
/// Not equal zero
|
|
|
|
NotZero, |
|
|
|
NotZero, |
|
|
|
|
|
|
|
/// A < B
|
|
|
|
Lower, |
|
|
|
Lower, |
|
|
|
|
|
|
|
/// A <= B
|
|
|
|
LowerOrEqual, |
|
|
|
LowerOrEqual, |
|
|
|
|
|
|
|
/// A > B
|
|
|
|
Greater, |
|
|
|
Greater, |
|
|
|
|
|
|
|
/// A >= B
|
|
|
|
GreaterOrEqual, |
|
|
|
GreaterOrEqual, |
|
|
|
|
|
|
|
/// A > 0
|
|
|
|
Positive, |
|
|
|
Positive, |
|
|
|
|
|
|
|
/// A <= 0
|
|
|
|
NonPositive, |
|
|
|
NonPositive, |
|
|
|
|
|
|
|
/// A < 0
|
|
|
|
Negative, |
|
|
|
Negative, |
|
|
|
|
|
|
|
/// A >= 0
|
|
|
|
NonNegative, |
|
|
|
NonNegative, |
|
|
|
|
|
|
|
/// Arithmetic operation caused an integer operand to overflow
|
|
|
|
Overflow, |
|
|
|
Overflow, |
|
|
|
|
|
|
|
/// No overflow
|
|
|
|
NotOverflow, |
|
|
|
NotOverflow, |
|
|
|
|
|
|
|
/// Arithmetic (or other) operation was invalid.
|
|
|
|
|
|
|
|
/// Example: division by zero
|
|
|
|
Invalid, |
|
|
|
Invalid, |
|
|
|
|
|
|
|
/// Operation was valid
|
|
|
|
Valid, |
|
|
|
Valid, |
|
|
|
|
|
|
|
/// Arithmetic carry
|
|
|
|
Carry, |
|
|
|
Carry, |
|
|
|
|
|
|
|
/// Carry not set
|
|
|
|
NotCarry, |
|
|
|
NotCarry, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn parse_cond(text: &str) -> Result<Cond, Error> { |
|
|
|
|
|
|
|
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" | "!c" => Cond::NotCarry, |
|
|
|
|
|
|
|
"valid" => Cond::Valid, |
|
|
|
|
|
|
|
"inval" => Cond::Invalid, |
|
|
|
|
|
|
|
"ov" | "^" => Cond::Overflow, |
|
|
|
|
|
|
|
"nov" | "!ov" | "!^" => Cond::NotOverflow, |
|
|
|
|
|
|
|
_ => { |
|
|
|
|
|
|
|
return Err(Error::Parse(format!("Unknown cond: {}", text).into())); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Display for Cond { |
|
|
|
impl Display for Cond { |
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
|
|
|
f.write_str(match self { |
|
|
|
f.write_str(match self { |
|
|
@ -43,7 +90,7 @@ impl Display for Cond { |
|
|
|
Cond::Carry => "c", |
|
|
|
Cond::Carry => "c", |
|
|
|
Cond::NotCarry => "nc", |
|
|
|
Cond::NotCarry => "nc", |
|
|
|
Cond::Invalid => "inval", |
|
|
|
Cond::Invalid => "inval", |
|
|
|
Cond::Valid => "ok", |
|
|
|
Cond::Valid => "valid", |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|