From f4ced467e4859bfe9c83c1a5f355dc81baae7b26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Tue, 6 Oct 2020 12:18:07 +0200 Subject: [PATCH] add rpush and rpop stack instructions --- crsn_stacks/src/defs.rs | 2 + crsn_stacks/src/exec.rs | 89 +++++++++++++++++++++++++--------------- crsn_stacks/src/parse.rs | 14 +++++++ examples/stacks.csn | 22 ++++++++++ 4 files changed, 95 insertions(+), 32 deletions(-) diff --git a/crsn_stacks/src/defs.rs b/crsn_stacks/src/defs.rs index c85ad4f..ddef1db 100644 --- a/crsn_stacks/src/defs.rs +++ b/crsn_stacks/src/defs.rs @@ -5,4 +5,6 @@ pub enum StackOp { NewStack { dst: Wr }, Push { obj: RdObj, src: Rd }, Pop { dst: Wr, obj: RdObj }, + ReversePush { obj: RdObj, src: Rd }, + ReversePop { dst: Wr, obj: RdObj }, } diff --git a/crsn_stacks/src/exec.rs b/crsn_stacks/src/exec.rs index b574306..1d29106 100644 --- a/crsn_stacks/src/exec.rs +++ b/crsn_stacks/src/exec.rs @@ -10,6 +10,7 @@ use crate::defs::StackOp; use crsn::sexp::Sexp; use crsn::sexp; use crsn::utils::A; +use crsn::asm::data::{RdObj, Rd, Wr}; #[derive(Debug, Default)] struct Stacks { @@ -28,40 +29,20 @@ impl OpTrait for StackOp { state.write(*dst, id)?; } StackOp::Push { obj, src } => { - state.clear_status(); - let handle = state.read_obj(*obj)?; - let val = state.read(*src)?; - - let stacks: &mut Stacks = state.ext_mut(); - stacks.store.get_mut(&handle) - .ok_or_else(|| Fault::ObjectNotExist(handle))? - .push_back(val); + 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 } => { - state.clear_status(); - let handle = state.read_obj(*obj)?; - - let stacks: &mut Stacks = state.ext_mut(); - let stack = stacks.store.get_mut(&handle) - .ok_or_else(|| Fault::ObjectNotExist(handle))?; - - let val = stack.pop_back(); - - if stack.is_empty() { - state.set_flag(Cond::Zero, true); - } - - let val = match val { - None => { - state.set_flag(Cond::Overflow, true); - 0 - } - Some(val) => { - val - } - }; - - state.write(*dst, val)?; + prepare_pop(state, dst, obj, + |stack| stack.pop_back())?; + } + StackOp::ReversePop { dst, obj } => { + prepare_pop(state, dst, obj, + |stack| stack.pop_front())?; } } @@ -73,11 +54,55 @@ impl OpTrait for StackOp { 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, 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) -> ()) -> Result<(), Fault> { + state.clear_status(); + let handle = state.read_obj(*obj)?; + let val = state.read(*src)?; + + let stacks: &mut Stacks = state.ext_mut(); + let mutable = stacks.store.get_mut(&handle) + .ok_or_else(|| Fault::ObjectNotExist(handle))?; + + pushfn(mutable, val); + Ok(()) +} + +fn prepare_pop(state: &mut RunState, dst: &Wr, obj: &RdObj, popfn : impl FnOnce(&mut VecDeque) -> Option) -> Result<(), Fault> { + state.clear_status(); + let handle = state.read_obj(*obj)?; + + let stacks: &mut Stacks = state.ext_mut(); + let stack = stacks.store.get_mut(&handle) + .ok_or_else(|| Fault::ObjectNotExist(handle))?; + + let val = popfn(stack); + + if stack.is_empty() { + state.set_flag(Cond::Zero, true); + } + + let val = match val { + None => { + state.set_flag(Cond::Overflow, true); + 0 + } + Some(val) => { + val + } + }; + + state.write(*dst, val)?; + Ok(()) +} diff --git a/crsn_stacks/src/parse.rs b/crsn_stacks/src/parse.rs index 55da319..b1206e3 100644 --- a/crsn_stacks/src/parse.rs +++ b/crsn_stacks/src/parse.rs @@ -27,6 +27,20 @@ pub(crate) fn parse<'a>(keyword: &str, mut args: TokenParser<'a>) -> Result { + StackOp::ReversePush { + obj: args.next_rdobj()?, + src: args.next_rd()?, + } + } + + "rpop" => { + StackOp::ReversePop { + dst: args.next_wr()?, + obj: args.next_rdobj()?, + } + } + _other => { return Ok(ParseRes::Unknown(args)); } diff --git a/examples/stacks.csn b/examples/stacks.csn index 9c37a9b..a828235 100644 --- a/examples/stacks.csn +++ b/examples/stacks.csn @@ -10,5 +10,27 @@ (pop r1 @r0) (cmp r1 1 (ne? (fault))) + ; test reverse push + (push @r0 1) + (push @r0 7) + (rpush @r0 8) + + (pop r1 @r0) + (cmp r1 7 (ne? (fault))) + + (pop r1 @r0) + (cmp r1 1 (ne? (fault))) + + (pop r1 @r0) + (cmp r1 8 (ne? (fault))) + + ; test reverse pop + + (push @r0 1000) + (push @r0 2000) + + (rpop r1 @r0) + (cmp r1 1000 (ne? (fault))) + (drop @r0) )