|
|
@ -10,6 +10,7 @@ use crate::defs::StackOp; |
|
|
|
use crsn::sexp::Sexp; |
|
|
|
use crsn::sexp::Sexp; |
|
|
|
use crsn::sexp; |
|
|
|
use crsn::sexp; |
|
|
|
use crsn::utils::A; |
|
|
|
use crsn::utils::A; |
|
|
|
|
|
|
|
use crsn::asm::data::{RdObj, Rd, Wr}; |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Default)] |
|
|
|
#[derive(Debug, Default)] |
|
|
|
struct Stacks { |
|
|
|
struct Stacks { |
|
|
@ -28,16 +29,57 @@ impl OpTrait for StackOp { |
|
|
|
state.write(*dst, id)?; |
|
|
|
state.write(*dst, id)?; |
|
|
|
} |
|
|
|
} |
|
|
|
StackOp::Push { obj, src } => { |
|
|
|
StackOp::Push { obj, src } => { |
|
|
|
|
|
|
|
prepare_push(state, obj, src, |
|
|
|
|
|
|
|
|stack, val| stack.push_back(val))?; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
StackOp::ReversePush { obj, src } => { |
|
|
|
|
|
|
|
prepare_push(state, obj, src, |
|
|
|
|
|
|
|
|stack, val| stack.push_front(val))?; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
StackOp::Pop { dst, obj } => { |
|
|
|
|
|
|
|
prepare_pop(state, dst, obj, |
|
|
|
|
|
|
|
|stack| stack.pop_back())?; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
StackOp::ReversePop { dst, obj } => { |
|
|
|
|
|
|
|
prepare_pop(state, dst, obj, |
|
|
|
|
|
|
|
|stack| stack.pop_front())?; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(eres) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn to_sexp(&self) -> Sexp { |
|
|
|
|
|
|
|
match self { |
|
|
|
|
|
|
|
StackOp::NewStack { dst } => sexp::list(&[A("stack"), A(dst)]), |
|
|
|
|
|
|
|
StackOp::Push { obj, src } => sexp::list(&[A("push"), A(obj), A(src)]), |
|
|
|
|
|
|
|
StackOp::Pop { dst, obj } => sexp::list(&[A("pop"), A(dst), A(obj)]), |
|
|
|
|
|
|
|
StackOp::ReversePush { obj, src } => sexp::list(&[A("rpush"), A(obj), A(src)]), |
|
|
|
|
|
|
|
StackOp::ReversePop { dst, obj } => sexp::list(&[A("rpop"), A(dst), A(obj)]), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn drop_obj(state: &mut RunState, handle: Value) -> Result<Option<()>, Fault> { |
|
|
|
|
|
|
|
let stacks: &mut Stacks = state.ext_mut(); |
|
|
|
|
|
|
|
Ok(stacks.store.remove(&handle).map(|_| ())) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn prepare_push(mut state: &mut RunState, obj: &RdObj, src: &Rd, pushfn : impl FnOnce(&mut VecDeque<Value>, Value) -> ()) -> Result<(), Fault> { |
|
|
|
state.clear_status(); |
|
|
|
state.clear_status(); |
|
|
|
let handle = state.read_obj(*obj)?; |
|
|
|
let handle = state.read_obj(*obj)?; |
|
|
|
let val = state.read(*src)?; |
|
|
|
let val = state.read(*src)?; |
|
|
|
|
|
|
|
|
|
|
|
let stacks: &mut Stacks = state.ext_mut(); |
|
|
|
let stacks: &mut Stacks = state.ext_mut(); |
|
|
|
stacks.store.get_mut(&handle) |
|
|
|
let mutable = stacks.store.get_mut(&handle) |
|
|
|
.ok_or_else(|| Fault::ObjectNotExist(handle))? |
|
|
|
.ok_or_else(|| Fault::ObjectNotExist(handle))?; |
|
|
|
.push_back(val); |
|
|
|
|
|
|
|
} |
|
|
|
pushfn(mutable, val); |
|
|
|
StackOp::Pop { dst, obj } => { |
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn prepare_pop(state: &mut RunState, dst: &Wr, obj: &RdObj, popfn : impl FnOnce(&mut VecDeque<Value>) -> Option<Value>) -> Result<(), Fault> { |
|
|
|
state.clear_status(); |
|
|
|
state.clear_status(); |
|
|
|
let handle = state.read_obj(*obj)?; |
|
|
|
let handle = state.read_obj(*obj)?; |
|
|
|
|
|
|
|
|
|
|
@ -45,7 +87,7 @@ impl OpTrait for StackOp { |
|
|
|
let stack = stacks.store.get_mut(&handle) |
|
|
|
let stack = stacks.store.get_mut(&handle) |
|
|
|
.ok_or_else(|| Fault::ObjectNotExist(handle))?; |
|
|
|
.ok_or_else(|| Fault::ObjectNotExist(handle))?; |
|
|
|
|
|
|
|
|
|
|
|
let val = stack.pop_back(); |
|
|
|
let val = popfn(stack); |
|
|
|
|
|
|
|
|
|
|
|
if stack.is_empty() { |
|
|
|
if stack.is_empty() { |
|
|
|
state.set_flag(Cond::Zero, true); |
|
|
|
state.set_flag(Cond::Zero, true); |
|
|
@ -62,22 +104,5 @@ impl OpTrait for StackOp { |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
state.write(*dst, val)?; |
|
|
|
state.write(*dst, val)?; |
|
|
|
} |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(eres) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn to_sexp(&self) -> Sexp { |
|
|
|
|
|
|
|
match self { |
|
|
|
|
|
|
|
StackOp::NewStack { dst } => sexp::list(&[A("stack"), A(dst)]), |
|
|
|
|
|
|
|
StackOp::Push { obj, src } => sexp::list(&[A("push"), A(obj), A(src)]), |
|
|
|
|
|
|
|
StackOp::Pop { dst, obj } => sexp::list(&[A("pop"), A(dst), A(obj)]), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn drop_obj(state: &mut RunState, handle: Value) -> Result<Option<()>, Fault> { |
|
|
|
|
|
|
|
let stacks: &mut Stacks = state.ext_mut(); |
|
|
|
|
|
|
|
Ok(stacks.store.remove(&handle).map(|_| ())) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|