mirror of
https://github.com/uutils/awk.git
synced 2026-06-10 16:15:04 -07:00
interpreter: ordered boolean comparisons
This commit is contained in:
@@ -42,7 +42,6 @@ pub enum OpCode {
|
||||
Negation,
|
||||
ToInt,
|
||||
Negative,
|
||||
Concat,
|
||||
|
||||
// Binary operations
|
||||
Eq,
|
||||
@@ -61,6 +60,7 @@ pub enum OpCode {
|
||||
Divide,
|
||||
Raise,
|
||||
Modulo,
|
||||
Concat,
|
||||
|
||||
// Intrinsic operations
|
||||
LoadUser,
|
||||
|
||||
@@ -65,6 +65,10 @@ impl Value<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn b2f(b: bool) -> Self {
|
||||
Self::Float(b as usize as f64)
|
||||
}
|
||||
|
||||
pub fn write_string(&self, f: &mut Vec<u8>) {
|
||||
match self {
|
||||
Self::String(s) | Self::Regex(s) => f.extend_from_slice(s),
|
||||
@@ -171,6 +175,55 @@ impl PartialEq for Value<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Value<'_> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
match (self, other) {
|
||||
// Numeric comparisons
|
||||
(&Self::Float(lhs), Self::Float(rhs)) => lhs.partial_cmp(rhs),
|
||||
(&Self::Bool(lhs), Self::Bool(rhs)) => lhs.partial_cmp(rhs),
|
||||
(&Self::Float(f), &Self::Bool(b)) => f.partial_cmp(&(b as usize as _)),
|
||||
(&Self::Bool(b), Self::Float(f)) => (b as usize as f64).partial_cmp(f),
|
||||
// String-based comparisons
|
||||
(Self::String(lhs) | Self::Regex(lhs), Self::String(rhs) | Self::Regex(rhs)) => {
|
||||
lhs.as_ref().partial_cmp(rhs)
|
||||
}
|
||||
(&Self::Float(f), Self::String(s) | Self::Regex(s)) => {
|
||||
f.to_string().as_bytes().partial_cmp(s)
|
||||
}
|
||||
(Self::String(s) | Self::Regex(s), &Self::Float(f)) => {
|
||||
s.as_ref().partial_cmp(f.to_string().as_bytes())
|
||||
}
|
||||
(&Self::Bool(b), Self::String(s) | Self::Regex(s)) => {
|
||||
(if b { b"1" } else { b"0" }).as_ref().partial_cmp(s)
|
||||
}
|
||||
(Self::String(s) | Self::Regex(s), &Self::Bool(b)) => {
|
||||
s.as_ref().partial_cmp(if b { b"1" } else { b"0" })
|
||||
}
|
||||
(Self::Untyped | Self::Unassigned, Self::String(s) | Self::Regex(s)) => {
|
||||
b"".as_ref().partial_cmp(s)
|
||||
}
|
||||
(Self::String(s) | Self::Regex(s), Self::Untyped | Self::Unassigned) => {
|
||||
s.as_ref().partial_cmp(b"")
|
||||
}
|
||||
(Self::Array(_), _) | (_, Self::Array(_)) => {
|
||||
panic!("Attempted to use array in scalar context!")
|
||||
}
|
||||
(Self::Untyped | Self::Unassigned, Self::Untyped | Self::Unassigned) => {
|
||||
b"".partial_cmp(b"")
|
||||
}
|
||||
// Copyful comparisons
|
||||
(lhs, rhs) => {
|
||||
let mut str_buf: Vec<u8> = Vec::new();
|
||||
str_buf.reserve_exact(lhs.string_size_hint() + rhs.string_size_hint());
|
||||
lhs.write_string(&mut str_buf);
|
||||
let midpoint = str_buf.len();
|
||||
rhs.write_string(&mut str_buf);
|
||||
str_buf[0..midpoint].partial_cmp(&str_buf[midpoint..])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Value<'_> {}
|
||||
impl Hash for Value<'_> {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
|
||||
+11
-3
@@ -130,8 +130,16 @@ impl Interpreter<'_> {
|
||||
OpCode::Raise => lhs ^ rhs,
|
||||
OpCode::Modulo => lhs % rhs,
|
||||
// Float values on boolean cmps are intentional.
|
||||
OpCode::Eq => Value::Float((lhs == rhs) as usize as _),
|
||||
OpCode::NEq => Value::Float((lhs != rhs) as usize as _),
|
||||
OpCode::Eq => Value::b2f(lhs == rhs),
|
||||
OpCode::NEq => Value::b2f(lhs != rhs),
|
||||
OpCode::Gt => Value::b2f(lhs > rhs),
|
||||
OpCode::Lt => Value::b2f(lhs < rhs),
|
||||
OpCode::GtE => Value::b2f(lhs >= rhs),
|
||||
OpCode::LtE => Value::b2f(lhs <= rhs),
|
||||
OpCode::And => todo!(),
|
||||
OpCode::Or => todo!(),
|
||||
OpCode::Matches => todo!(),
|
||||
OpCode::MatchesNot => todo!(),
|
||||
OpCode::Concat => {
|
||||
let mut buf = StdVec::with_capacity(
|
||||
lhs.string_size_hint() + rhs.string_size_hint(),
|
||||
@@ -140,7 +148,7 @@ impl Interpreter<'_> {
|
||||
rhs.write_string(&mut buf);
|
||||
Value::String(buf.into())
|
||||
}
|
||||
_ => todo!(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.registers.write(dest, val);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user