feat(bytecode): +DupFrom

This commit is contained in:
Alain Zscheile 2022-10-22 20:45:19 +02:00
parent b889f626ab
commit 550c25340d
3 changed files with 22 additions and 5 deletions

View file

@ -13,10 +13,11 @@ pub enum OpType {
Return = 0x52, /* R */
// stack operations
Push = 0x50, /* P */
Pop = 0x51, /* Q */
Dup = 0x44, /* D */
Swap = 0x53, /* S */
Push = 0x50, /* P */
Pop = 0x51, /* Q */
Dup = 0x44, /* D */
Swap = 0x53, /* S */
DupFrom = 0x46, /* F */
// extensions
Shift = 0x73, /* s */

View file

@ -47,6 +47,12 @@ pub enum Instr {
/// shifts the top stack value by $0 ($0 is a signed integer)
Shift(i8),
// indirect stack operations
/// duplicates the top-(*top) stack value, pushing it to the top of the stack
/// this does not change the stack height
/// (the top value is replaced by the value it points to)
DupFrom,
/// basic math operations (on integers and atoms)
DoMath1(MathUnOp),
@ -69,6 +75,7 @@ impl Instr {
Instr::Dup(_) => OpType::Dup,
Instr::Swap(_) => OpType::Swap,
Instr::Shift(_) => OpType::Shift,
Instr::DupFrom => OpType::DupFrom,
Instr::DoMath1(_) => OpType::DoMath1,
Instr::DoMath2(_) => OpType::DoMath2,
}
@ -115,6 +122,7 @@ impl<'a> crate::Parse<'a> for Instr {
OpType::Label => Ok((inp, Instr::Label)),
OpType::CallRemote => Ok((inp, Instr::CallRemote)),
OpType::Return => Ok((inp, Instr::Return)),
OpType::DupFrom => Ok((inp, Instr::DupFrom)),
}
.map_err(|()| ParseError)
}
@ -136,7 +144,7 @@ impl Instr {
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(()),
Instr::Label | Instr::CallRemote | Instr::Return | Instr::DupFrom => Ok(()),
}
}
}

View file

@ -190,6 +190,14 @@ impl Process<'_> {
*x >>= (shdelta as u8) + 1;
}
}
Instr::DupFrom => {
let x: u64 = self.stack.pop().ok_or(Error::NotEnoughStacked)?;
let y: u64 = *self
.stack
.get(usize::try_from(x).map_err(|_| Error::NotEnoughStacked)?)
.ok_or(Error::NotEnoughStacked)?;
self.stack.push(y);
}
Instr::DoMath1(ubo) => {
use consts::MathUnOp as U;
let x = self.stpop()?;