~: function calls should be restricted in input arity
This commit is contained in:
parent
94117e5817
commit
17efdff6f5
|
@ -10,7 +10,8 @@ pub enum Instr<'a> {
|
|||
|
||||
/// pops the descriptor table pointer from the stack,
|
||||
/// then tries to call the $0 on it.
|
||||
Call(Atom),
|
||||
/// $1 is the amount of arguments (arity) extracted from the stack after the pointer
|
||||
Call(Atom, u8),
|
||||
|
||||
/// jumps to the destination $0 inside of the current module
|
||||
Jump(u64),
|
||||
|
@ -43,7 +44,7 @@ impl Instr<'_> {
|
|||
pub fn typ(&self) -> OpType {
|
||||
match self {
|
||||
Instr::Label => OpType::Label,
|
||||
Instr::Call(_) => OpType::Call,
|
||||
Instr::Call(_, _) => OpType::Call,
|
||||
Instr::Jump(_) => OpType::Jump,
|
||||
Instr::Return => OpType::Return,
|
||||
Instr::Push(_) => OpType::Push,
|
||||
|
@ -89,7 +90,11 @@ impl<'a> crate::Parse<'a> for Instr<'a> {
|
|||
}
|
||||
let (inp, otyp) = OpType::parse(inp)?;
|
||||
match otyp {
|
||||
OpType::Call => Atom::parse(inp).map(|(inp, val)| (inp, Instr::Call(val))),
|
||||
OpType::Call => {
|
||||
let (inp, val) = Atom::parse(inp)?;
|
||||
let (inp, arity) = u8::parse(inp)?;
|
||||
Ok((inp, Instr::Call(val, arity)))
|
||||
}
|
||||
OpType::Jump => u64::parse(inp).map(|(inp, val)| (inp, Instr::Jump(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))),
|
||||
|
@ -110,7 +115,10 @@ impl Instr<'_> {
|
|||
use int_enum::IntEnum;
|
||||
writer.write_all(&self.typ().int_value().to_be_bytes())?;
|
||||
match self {
|
||||
Instr::Call(val) => val.write_to(writer)?,
|
||||
Instr::Call(val, arity) => {
|
||||
val.write_to(&mut writer)?;
|
||||
writer.write_all(&[*arity])?;
|
||||
}
|
||||
Instr::Jump(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())?,
|
||||
|
|
|
@ -11,7 +11,7 @@ struct Module {
|
|||
type InstrPtr = (Arc<Module>, usize);
|
||||
|
||||
trait Origin: Send + Sync + core::fmt::Debug {
|
||||
fn call(&self, p: &Pointer, a: &Atom) -> InstrPtr;
|
||||
fn call(&self, p: &Pointer, a: &Atom, stack: &mut Vec<StackEntValue>) -> InstrPtr;
|
||||
fn incr_refcount(&self, p: &Pointer);
|
||||
fn decr_refcount(&self, p: &Pointer);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ static NOOP_MODULE: Lazy<Arc<Module>> = Lazy::new(|| {
|
|||
#[derive(Debug)]
|
||||
struct NoopOrigin;
|
||||
impl Origin for NoopOrigin {
|
||||
fn call(&self, p: &Pointer, a: &Atom) -> InstrPtr {
|
||||
fn call(&self, p: &Pointer, a: &Atom, _stack: &mut Vec<StackEntValue>) -> InstrPtr {
|
||||
eprintln!(
|
||||
"WARN: tried to invoke pointer {:?}({:?}) without valid context",
|
||||
p, a
|
||||
|
@ -113,7 +113,7 @@ impl Process {
|
|||
self.instrp.1 += nxtiptr.len() - nxti_arr.len();
|
||||
match nxti {
|
||||
Instr::Label => {}
|
||||
Instr::Call(atom) => {
|
||||
Instr::Call(atom, arity) => {
|
||||
let mut call2jump = false;
|
||||
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
|
||||
if let Ok((_, Instr::Return)) = Instr::parse(n2xti_arr) {
|
||||
|
@ -130,7 +130,10 @@ impl Process {
|
|||
break;
|
||||
}
|
||||
Some(StackEntValue::Pointer(wp)) => {
|
||||
self.instrp = wp.orig.call(&wp.p, &atom);
|
||||
let ssl = self.stack.len();
|
||||
let mut args = self.stack.drain(ssl - usize::from(arity)..).collect();
|
||||
self.instrp = wp.orig.call(&wp.p, &atom, &mut args);
|
||||
self.stack.extend(args);
|
||||
}
|
||||
Some(x) => {
|
||||
eprintln!(
|
||||
|
|
Loading…
Reference in a new issue