feat(bytecode): add bitshift operation

This commit is contained in:
Alain Zscheile 2022-09-28 15:07:03 +02:00
parent 3cccbc31b8
commit 14c7cbb08b
4 changed files with 17 additions and 2 deletions

View file

@ -19,6 +19,7 @@ pub enum OpType {
Swap = 0x53, /* S */
// extensions
Shift = 0x73, /* s */
DoMath1 = 0x6d, /* m */
DoMath2 = 0x4d, /* M */
}

View file

@ -44,6 +44,9 @@ pub enum Instr {
/// (`Swap(0)` swaps the two top-most stack values)
Swap(u16),
/// shifts the top stack value by $0 ($0 is a signed integer)
Shift(i8),
/// basic math operations (on integers and atoms)
DoMath1(MathUnOp),
@ -65,6 +68,7 @@ impl Instr {
Instr::Pop(_) => OpType::Pop,
Instr::Dup(_) => OpType::Dup,
Instr::Swap(_) => OpType::Swap,
Instr::Shift(_) => OpType::Shift,
Instr::DoMath1(_) => OpType::DoMath1,
Instr::DoMath2(_) => OpType::DoMath2,
}
@ -105,6 +109,7 @@ impl<'a> crate::Parse<'a> for Instr {
OpType::Pop => u16::parse(inp).map(|(inp, val)| (inp, Instr::Pop(val))),
OpType::Dup => u16::parse(inp).map(|(inp, val)| (inp, Instr::Dup(val))),
OpType::Swap => u16::parse(inp).map(|(inp, val)| (inp, Instr::Swap(val))),
OpType::Shift => i8::parse(inp).map(|(inp, shv)| (inp, Instr::Shift(shv))),
OpType::DoMath1 => MathUnOp::parse(inp).map(|(inp, val)| (inp, Instr::DoMath1(val))),
OpType::DoMath2 => MathBinOp::parse(inp).map(|(inp, val)| (inp, Instr::DoMath2(val))),
OpType::Label => Ok((inp, Instr::Label)),
@ -128,6 +133,7 @@ impl Instr {
Instr::Pop(val) | Instr::Dup(val) | Instr::Swap(val) => {
writer.write_all(&val.to_be_bytes())
}
Instr::Shift(shv) => writer.write_all(&shv.to_be_bytes()),
Instr::DoMath1(val) => writer.write_all(&val.int_value().to_be_bytes()),
Instr::DoMath2(val) => writer.write_all(&val.int_value().to_be_bytes()),
Instr::Label | Instr::CallRemote | Instr::Return => Ok(()),

View file

@ -36,7 +36,7 @@ macro_rules! parse_number {
}
}
parse_number!(u16, u32, u64, u128);
parse_number!(i8, u16, u32, u64, u128);
impl<'a, T: int_enum::IntEnum + intern::Sealed> Parse<'a> for T
where

View file

@ -189,7 +189,7 @@ impl Process {
let x = match self.stack.len().checked_sub(usize::from(delta) + 1) {
None => return Err(Error::NotEnoughStacked),
// SAFETY: the value x is always smaller than the stack height
Some(x) => self.stack[x].clone(),
Some(x) => self.stack[x],
};
self.stack.push(x);
}
@ -201,6 +201,14 @@ impl Process {
};
core::mem::swap(&mut y[0], &mut z[0]);
}
Instr::Shift(shdelta) => {
let x = self.stack.last_mut().ok_or(Error::NotEnoughStacked)?;
if shdelta < 0 {
*x <<= (-shdelta) as u8;
} else {
*x >>= (shdelta as u8) + 1;
}
}
Instr::DoMath1(ubo) => {
use consts::MathUnOp as U;
let x = self.stpop()?;