fix(_): fix misc stuff
This commit is contained in:
parent
5f77e04826
commit
18a7c524e6
|
@ -51,5 +51,8 @@ pub enum MathBinOp {
|
|||
Add = 0x2b, /* + */
|
||||
Sub = 0x2d, /* - */
|
||||
Div = 0x2f, /* / */
|
||||
|
||||
// signed arithmetic operations
|
||||
Srem = 0x24, /* $ */
|
||||
}
|
||||
impl Sealed for MathBinOp {}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue