feat(bytecode): add bitshift operation
This commit is contained in:
parent
3cccbc31b8
commit
14c7cbb08b
|
@ -19,6 +19,7 @@ pub enum OpType {
|
|||
Swap = 0x53, /* S */
|
||||
|
||||
// extensions
|
||||
Shift = 0x73, /* s */
|
||||
DoMath1 = 0x6d, /* m */
|
||||
DoMath2 = 0x4d, /* M */
|
||||
}
|
||||
|
|
|
@ -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(()),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()?;
|
||||
|
|
Loading…
Reference in a new issue