Skip to content

Commit 2006523

Browse files
committed
interpreter: (in)equality comparisons
1 parent 3b9ce0e commit 2006523

2 files changed

Lines changed: 41 additions & 8 deletions

File tree

interpreter/src/types.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::{
1010
use ahash::RandomState;
1111
use hashbrown::HashMap;
1212

13-
#[derive(Debug, Clone, PartialEq)]
13+
#[derive(Debug, Clone)]
1414
pub enum Value<'a> {
1515
Float(f64),
1616
String(Cow<'a, [u8]>),
@@ -119,6 +119,37 @@ impl<'a> Div for &'_ Value<'a> {
119119
}
120120
}
121121

122+
impl PartialEq for Value<'_> {
123+
fn eq(&self, other: &Self) -> bool {
124+
match (self, other) {
125+
// Numeric comparisons
126+
(&Self::Float(lhs), &Self::Float(rhs)) => lhs == rhs,
127+
(&Self::Bool(lhs), &Self::Bool(rhs)) => lhs == rhs,
128+
(&Self::Float(f), &Self::Bool(b)) | (&Self::Bool(b), &Self::Float(f)) => b && f == 1.,
129+
// String-based comparisons
130+
(Self::String(lhs) | Self::Regex(lhs), Self::String(rhs) | Self::Regex(rhs)) => {
131+
lhs == rhs
132+
}
133+
(&Self::Float(f), Self::String(s) | Self::Regex(s))
134+
| (Self::String(s) | Self::Regex(s), &Self::Float(f)) => {
135+
f.to_string().as_bytes() == s.as_ref()
136+
}
137+
(&Self::Bool(b), Self::String(s) | Self::Regex(s))
138+
| (Self::String(s) | Self::Regex(s), &Self::Bool(b)) => {
139+
(if b { b"1" } else { b"0" }) == s.as_ref()
140+
}
141+
// True on empty string value.
142+
(Self::Untyped | Self::Unassigned, Self::String(s) | Self::Regex(s))
143+
| (Self::String(s) | Self::Regex(s), Self::Untyped | Self::Unassigned) => s.is_empty(),
144+
(Self::Untyped | Self::Unassigned, Self::Untyped | Self::Unassigned) => true,
145+
(Self::Untyped | Self::Unassigned, _) | (_, Self::Untyped | Self::Unassigned) => false,
146+
(Self::Array(_), _) | (_, Self::Array(_)) => {
147+
panic!("Attempted to use array in scalar context!")
148+
}
149+
}
150+
}
151+
}
152+
122153
impl Eq for Value<'_> {}
123154
impl Hash for Value<'_> {
124155
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {

interpreter/src/vm.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use parser::Identifier;
1212

1313
use crate::{
1414
ir::{
15-
NonLocal, OpCode, Reg,
15+
Label, NonLocal, OpCode, Reg,
1616
lower::{Bytecode, Code, ValueContext},
1717
},
1818
types::Value,
@@ -127,6 +127,9 @@ impl Interpreter<'_> {
127127
OpCode::Subtract => lhs - rhs,
128128
OpCode::Multiply => lhs * rhs,
129129
OpCode::Divide => lhs / rhs,
130+
// Float values on boolean cmps are intentional.
131+
OpCode::Eq => Value::Float((lhs == rhs) as usize as _),
132+
OpCode::NEq => Value::Float((lhs != rhs) as usize as _),
130133
OpCode::Concat => {
131134
let mut buf = StdVec::with_capacity(
132135
lhs.string_size_hint() + rhs.string_size_hint(),
@@ -154,18 +157,17 @@ impl Interpreter<'_> {
154157
}
155158
_ => todo!(),
156159
},
157-
ix if let Some((cond, true_to, false_to)) = ix.get_branch() => {
160+
ix if let Some((cond, Label(true_to), Label(false_to))) = ix.get_branch() => {
158161
let label = if self.registers.get(*cond).to_bool() {
159-
true_to.0
162+
*true_to
160163
} else {
161-
false_to.0
164+
*false_to
162165
};
163166
self.program_counter = label as _;
164-
165167
continue;
166168
}
167-
ix if let Some(label) = ix.get_jump() => {
168-
self.program_counter = label.0 as _;
169+
ix if let Some(&Label(label)) = ix.get_jump() => {
170+
self.program_counter = label as _;
169171
continue;
170172
}
171173
ix => todo!("{ix:?}"),

0 commit comments

Comments
 (0)