feat(bytecode): pop and dup should take 16bit values
This commit is contained in:
parent
de02eba3dc
commit
b1ea85cf3e
|
@ -31,10 +31,10 @@ pub enum Instr<'a> {
|
|||
Push(Value<'a>),
|
||||
|
||||
/// pops the top $0+1 values from the stack
|
||||
Pop(u32),
|
||||
Pop(u16),
|
||||
|
||||
/// duplicates the top stack value
|
||||
Dup,
|
||||
/// duplicates the top-$0 stack value, pushing it to the top of the stack
|
||||
Dup(u16),
|
||||
|
||||
/// swaps the 2 top-most stack values
|
||||
Swap,
|
||||
|
@ -59,7 +59,7 @@ impl Instr<'_> {
|
|||
Instr::Return => OpType::Return,
|
||||
Instr::Push(_) => OpType::Push,
|
||||
Instr::Pop(_) => OpType::Pop,
|
||||
Instr::Dup => OpType::Dup,
|
||||
Instr::Dup(_) => OpType::Dup,
|
||||
Instr::Swap => OpType::Swap,
|
||||
Instr::ABuild => OpType::ABuild,
|
||||
Instr::ADecon => OpType::ADecon,
|
||||
|
@ -110,11 +110,11 @@ impl<'a> crate::Parse<'a> for Instr<'a> {
|
|||
OpType::Jump => u64::parse(inp).map(|(inp, val)| (inp, Instr::Jump(val))),
|
||||
OpType::JumpCond => u64::parse(inp).map(|(inp, val)| (inp, Instr::JumpCond(val))),
|
||||
OpType::Push => Ok(Value::parse(inp).map(|(inp, val)| (inp, Instr::Push(val)))?),
|
||||
OpType::Pop => u32::parse(inp).map(|(inp, val)| (inp, Instr::Pop(val))),
|
||||
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::DoMath2 => MathBinOp::parse(inp).map(|(inp, val)| (inp, Instr::DoMath2(val))),
|
||||
OpType::Label => Ok((inp, Instr::Label)),
|
||||
OpType::Return => Ok((inp, Instr::Return)),
|
||||
OpType::Dup => Ok((inp, Instr::Dup)),
|
||||
OpType::Swap => Ok((inp, Instr::Swap)),
|
||||
OpType::ABuild => Ok((inp, Instr::ABuild)),
|
||||
OpType::ADecon => Ok((inp, Instr::ADecon)),
|
||||
|
@ -138,13 +138,9 @@ impl Instr<'_> {
|
|||
Instr::JumpCond(val) => writer.write_all(&val.to_be_bytes())?,
|
||||
Instr::Push(val) => val.write_to(writer)?,
|
||||
Instr::Pop(val) => writer.write_all(&val.to_be_bytes())?,
|
||||
Instr::Dup(val) => writer.write_all(&val.to_be_bytes())?,
|
||||
Instr::DoMath2(val) => writer.write_all(&val.int_value().to_be_bytes())?,
|
||||
Instr::Label
|
||||
| Instr::Return
|
||||
| Instr::Dup
|
||||
| Instr::Swap
|
||||
| Instr::ABuild
|
||||
| Instr::ADecon => {}
|
||||
Instr::Label | Instr::Return | Instr::Swap | Instr::ABuild | Instr::ADecon => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -242,24 +242,21 @@ impl Process {
|
|||
}
|
||||
Instr::Pop(cnt) => {
|
||||
let ssl = self.stack.len() - 1;
|
||||
match usize::try_from(cnt) {
|
||||
Ok(cnt) => {
|
||||
if cnt >= ssl {
|
||||
self.stack = Vec::new();
|
||||
} else {
|
||||
self.stack.truncate(ssl - cnt - 1);
|
||||
}
|
||||
}
|
||||
Err(_) => self.stack = Vec::new(),
|
||||
let cnt = usize::from(cnt);
|
||||
if cnt >= ssl {
|
||||
self.stack = Vec::new();
|
||||
} else {
|
||||
self.stack.truncate(ssl - cnt - 1);
|
||||
}
|
||||
}
|
||||
Instr::Dup => {
|
||||
let x = match self.stack.last() {
|
||||
Instr::Dup(delta) => {
|
||||
let x = match self.stack.len().checked_sub(usize::from(delta) + 1) {
|
||||
None => {
|
||||
tracing::error!("dup on empty stack @ {}", previptr);
|
||||
tracing::error!("dup on too small stack @ {}", previptr);
|
||||
break;
|
||||
}
|
||||
Some(x) => x.clone(),
|
||||
// SAFETY: the value x is always smaller than the stack height
|
||||
Some(x) => self.stack[x].clone(),
|
||||
};
|
||||
self.stack.push(x);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue