feat(vm): basic comparison operators
This commit is contained in:
parent
7602e9f7b9
commit
b67f42b773
|
@ -50,6 +50,10 @@ impl Sealed for MathUnOp {}
|
|||
pub enum MathBinOp {
|
||||
Concat = 0x2e, /* . */
|
||||
|
||||
// comparison operations
|
||||
Lt = 0x3c, /* < */
|
||||
Eq = 0x3d, /* = */
|
||||
|
||||
// bit operations
|
||||
And = 0x26, /* & */
|
||||
Or = 0x7c, /* | */
|
||||
|
|
|
@ -50,6 +50,8 @@ pub enum Instr<'a> {
|
|||
|
||||
/// basic math operations (on integers and atoms)
|
||||
DoMath1(MathUnOp),
|
||||
|
||||
/// binary math operations, stack top is like: `... lhs rhs $`
|
||||
DoMath2(MathBinOp),
|
||||
}
|
||||
|
||||
|
|
|
@ -120,15 +120,17 @@ fn verify_jumptarget_explicit(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn u128_binmath(a: u128, b: u128, mbo: consts::MathBinOp) -> Result<u128, Error> {
|
||||
fn u128_binmath(a: u128, b: u128, mbo: consts::MathBinOp) -> Result<StackEntValue, Error> {
|
||||
use consts::MathBinOp as B;
|
||||
Ok(match mbo {
|
||||
Ok(StackEntValue::Atom(Atom::from(match mbo {
|
||||
B::Concat => {
|
||||
return Err(Error::StackedInvalidType {
|
||||
expected: "bytes,bytes",
|
||||
got: "[int|atom, int|atom]".to_string(),
|
||||
})
|
||||
}
|
||||
B::Lt => return Ok(StackEntValue::Int(if a < b { 1 } else { 0 })),
|
||||
B::Eq => return Ok(StackEntValue::Int(if a < b { 1 } else { 0 })),
|
||||
B::And => a & b,
|
||||
B::Or => a | b,
|
||||
B::Xor => a ^ b,
|
||||
|
@ -143,7 +145,7 @@ fn u128_binmath(a: u128, b: u128, mbo: consts::MathBinOp) -> Result<u128, Error>
|
|||
Some(x) => x,
|
||||
None => return Err(Error::DivisionByZero),
|
||||
},
|
||||
})
|
||||
})))
|
||||
}
|
||||
|
||||
impl Process {
|
||||
|
@ -341,6 +343,8 @@ impl Process {
|
|||
self.stack.push(match (a, b) {
|
||||
(V::Int(a), V::Int(b)) => match mbo {
|
||||
B::Concat => V::Atom(Atom::from((a, b))),
|
||||
B::Lt => V::Int(if a < b { 1 } else { 0 }),
|
||||
B::Eq => V::Int(if a == b { 1 } else { 0 }),
|
||||
B::And => V::Int(a & b),
|
||||
B::Or => V::Int(a | b),
|
||||
B::Xor => V::Int(a ^ b),
|
||||
|
@ -359,21 +363,18 @@ impl Process {
|
|||
}),
|
||||
},
|
||||
(V::Atom(a), V::Atom(b)) => {
|
||||
V::Atom(Atom::from(u128_binmath(u128::from(a), u128::from(b), mbo)?))
|
||||
u128_binmath(u128::from(a), u128::from(b), mbo)?
|
||||
}
|
||||
(V::Int(a), V::Atom(b)) => {
|
||||
V::Atom(Atom::from(u128_binmath(u128::from(a), u128::from(b), mbo)?))
|
||||
}
|
||||
(V::Atom(a), V::Int(b)) => {
|
||||
V::Atom(Atom::from(u128_binmath(u128::from(a), u128::from(b), mbo)?))
|
||||
}
|
||||
(V::Bytes(a), V::Bytes(b)) => V::Bytes(match mbo {
|
||||
(V::Int(a), V::Atom(b)) => u128_binmath(u128::from(a), u128::from(b), mbo)?,
|
||||
(V::Atom(a), V::Int(b)) => u128_binmath(u128::from(a), u128::from(b), mbo)?,
|
||||
(V::Bytes(a), V::Bytes(b)) => match mbo {
|
||||
B::Concat => {
|
||||
let mut x = Vec::with_capacity(a.len() + b.len());
|
||||
x.extend_from_slice(&a);
|
||||
x.extend_from_slice(&b);
|
||||
x
|
||||
V::Bytes(x)
|
||||
}
|
||||
B::Eq => V::Int(if a == b { 1 } else { 0 }),
|
||||
B::And => {
|
||||
let mut x: Vec<_> =
|
||||
a.iter().zip(b.iter()).map(|(w, v)| w & v).collect();
|
||||
|
@ -381,7 +382,7 @@ impl Process {
|
|||
x.extend_from_slice(
|
||||
&(if a.len() < b.len() { b } else { a })[minp..],
|
||||
);
|
||||
x
|
||||
V::Bytes(x)
|
||||
}
|
||||
B::Or => {
|
||||
let mut x: Vec<_> =
|
||||
|
@ -390,7 +391,7 @@ impl Process {
|
|||
x.extend_from_slice(
|
||||
&(if a.len() < b.len() { b } else { a })[minp..],
|
||||
);
|
||||
x
|
||||
V::Bytes(x)
|
||||
}
|
||||
B::Xor => {
|
||||
let mut x: Vec<_> =
|
||||
|
@ -399,7 +400,7 @@ impl Process {
|
|||
x.extend_from_slice(
|
||||
&(if a.len() < b.len() { b } else { a })[minp..],
|
||||
);
|
||||
x
|
||||
V::Bytes(x)
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::StackedInvalidType {
|
||||
|
@ -407,7 +408,8 @@ impl Process {
|
|||
got: "[bytes, bytes]".to_string(),
|
||||
})
|
||||
}
|
||||
}),
|
||||
},
|
||||
_ if mbo == B::Eq => V::Int(0),
|
||||
(a, b) => {
|
||||
return Err(Error::StackedInvalidType {
|
||||
expected: "[int|atom, int|atom] | [bytes,bytes]",
|
||||
|
@ -431,7 +433,7 @@ mod tests {
|
|||
}
|
||||
|
||||
proptest::proptest! {
|
||||
#![proptest_config(proptest::prelude::ProptestConfig::with_cases(4096))]
|
||||
#![proptest_config(proptest::prelude::ProptestConfig::with_cases(8192))]
|
||||
|
||||
#[test]
|
||||
fn doesnt_crash(inp in proptest::collection::vec(0..=u8::MAX, 0..1024)) {
|
||||
|
@ -449,7 +451,7 @@ mod tests {
|
|||
pos: 0,
|
||||
},
|
||||
};
|
||||
let _ = futures_lite::future::block_on(p.run(Some(&mut 1024)));
|
||||
let _ = futures_lite::future::block_on(p.run(Some(&mut 2048)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue