fix(_): fix misc stuff

This commit is contained in:
Alain Zscheile 2022-09-28 15:44:05 +02:00
parent 5f77e04826
commit 18a7c524e6
2 changed files with 73 additions and 25 deletions

View file

@ -51,5 +51,8 @@ pub enum MathBinOp {
Add = 0x2b, /* + */
Sub = 0x2d, /* - */
Div = 0x2f, /* / */
// signed arithmetic operations
Srem = 0x24, /* $ */
}
impl Sealed for MathBinOp {}

View file

@ -3,7 +3,7 @@
extern crate alloc;
use alloc::{format, string::String, sync::Arc, vec::Vec};
use alloc::{sync::Arc, vec::Vec};
use core::fmt;
use fogtix_bytecode::{consts, Instr, Parse, Pointer};
@ -26,6 +26,20 @@ pub struct InstrPtr {
pub pos: usize,
}
impl fmt::Display for InstrPtr {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "@{:p}:{:x}", self.m, self.pos)
}
}
impl fmt::Debug for InstrPtr {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as fmt::Display>::fmt(self, f)
}
}
fn next_instr(m: &Module, pos: usize) -> Option<Result<(usize, Instr), &[u8]>> {
m.as_slice()
.get(pos..)
@ -51,7 +65,11 @@ pub type StackEntValue = u128;
#[derive(Clone, Debug)]
pub enum Error {
InvalidJumpTarget(&'static str, String, usize),
InvalidJumpTarget {
invoked_by: &'static str,
from: InstrPtr,
to: InstrPtr,
},
InstrpOutOfBounds,
UnparsableInstruction(Vec<u8>),
OutOfFuel,
@ -63,8 +81,16 @@ pub enum Error {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidJumpTarget(a, b, c) => {
write!(f, "`{}` arrived at non-jump target `{}` @ {}", a, b, c)
Self::InvalidJumpTarget {
invoked_by,
from,
to,
} => {
write!(
f,
"`{}` arrived from `{}` => at non-jump target `{}`",
invoked_by, from, to
)
}
Self::InstrpOutOfBounds => write!(f, "instruction pointer out-of-bounds"),
Self::UnparsableInstruction(x) => write!(f, "reached unparsable instruction: {:x?}", x),
@ -83,28 +109,26 @@ pub struct Process {
}
fn verify_jumptarget_explicit(
previptr: usize,
jinstr: &'static str,
jtip: &InstrPtr,
from: &InstrPtr,
to: &InstrPtr,
) -> Result<(), Error> {
if jtip.pos == 0 {
return Ok(());
if to.pos == 0 {
Ok(())
} else if let Some(Ok((_, Instr::Label))) = to.next_instr() {
Ok(())
} else {
Err(Error::InvalidJumpTarget {
invoked_by: jinstr,
from: from.clone(),
to: to.clone(),
})
}
if let Some(Ok((_, trgi))) = jtip.next_instr() {
if trgi != Instr::Label {
return Err(Error::InvalidJumpTarget(
jinstr,
format!("{:?}", trgi),
previptr,
));
}
}
Ok(())
}
impl Process {
fn verify_jumptarget(&self, previptr: usize, jinstr: &'static str) -> Result<(), Error> {
verify_jumptarget_explicit(previptr, jinstr, &self.instrp)
fn verify_jumptarget(&self, jinstr: &'static str, from: &InstrPtr) -> Result<(), Error> {
verify_jumptarget_explicit(jinstr, from, &self.instrp)
}
fn stpop(&mut self) -> Result<StackEntValue, Error> {
@ -143,7 +167,13 @@ impl Process {
Ok(y) => y,
Err(_) => return Err(Error::InstrpOutOfBounds),
};
self.verify_jumptarget(previptr, "call-l")?;
self.verify_jumptarget(
"call-l",
&InstrPtr {
m: self.instrp.m.clone(),
pos: previptr,
},
)?;
}
Instr::CallLDefer(x) => match x.try_into() {
Ok(pos) => {
@ -151,7 +181,14 @@ impl Process {
m: self.instrp.m.clone(),
pos,
};
verify_jumptarget_explicit(previptr, "call-l-defer", &jtip)?;
verify_jumptarget_explicit(
"call-l-defer",
&InstrPtr {
m: self.instrp.m.clone(),
pos: previptr,
},
&jtip,
)?;
if self.instrp.is_call2jump() {
self.instrp = jtip;
} else {
@ -167,7 +204,13 @@ impl Process {
};
if self.stpop()? != 0 {
self.instrp.pos = x;
self.verify_jumptarget(previptr, "jump-cond")?;
self.verify_jumptarget(
"jump-cond",
&InstrPtr {
m: self.instrp.m.clone(),
pos: previptr,
},
)?;
}
}
Instr::Return => match self.callstack.pop() {
@ -221,8 +264,10 @@ impl Process {
let a = self.stpop()?;
use consts::MathBinOp as B;
self.stack.push(match mbo {
B::Lt => if a < b { 1 } else { 0 },
B::Eq => if a < b { 1 } else { 0 },
B::Lt if a < b => 1,
B::Lt => 0,
B::Eq if a == b => 1,
B::Eq => 0,
B::And => a & b,
B::Or => a | b,
B::Xor => a ^ b,