add more sensible API for object handles, add drop instruction
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
use crsn::asm::data::{Rd, Wr};
|
||||
use crsn::asm::data::{Rd, Wr, RdObj};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum StackOp {
|
||||
Push { num: Rd, src: Rd },
|
||||
Pop { dst: Wr, num: Rd },
|
||||
NewStack { dst: Wr },
|
||||
Push { obj: RdObj, src: Rd },
|
||||
Pop { dst: Wr, obj: RdObj },
|
||||
}
|
||||
|
||||
+43
-42
@@ -1,69 +1,65 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::collections::{VecDeque, HashMap};
|
||||
|
||||
use crsn::asm::data::literal::Value;
|
||||
use crsn::asm::instr::Cond;
|
||||
use crsn::module::{EvalRes, OpTrait};
|
||||
use crsn::module::{EvalRes, OpTrait, CrsnExtension};
|
||||
use crsn::runtime::fault::Fault;
|
||||
use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
|
||||
|
||||
use crate::defs::StackOp;
|
||||
use crate::StackOps;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Stacks {
|
||||
stacks: Vec<VecDeque<Value>>,
|
||||
}
|
||||
|
||||
impl Default for Stacks {
|
||||
fn default() -> Self {
|
||||
Stacks {
|
||||
stacks: vec![VecDeque::default(); 8],
|
||||
}
|
||||
}
|
||||
store: HashMap<Value, VecDeque<Value>>,
|
||||
}
|
||||
|
||||
impl OpTrait for StackOp {
|
||||
fn execute(&self, _ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
|
||||
fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
|
||||
let eres = EvalRes::default();
|
||||
match self {
|
||||
StackOp::Push { num, src } => {
|
||||
StackOp::NewStack { dst } => {
|
||||
let id = info.uniq();
|
||||
let stacks: &mut Stacks = state.ext_mut();
|
||||
stacks.store.insert(id, VecDeque::new());
|
||||
|
||||
state.write(*dst, id)?;
|
||||
}
|
||||
StackOp::Push { obj, src } => {
|
||||
state.clear_status();
|
||||
let stack_num = state.read(*num)?;
|
||||
let handle = state.read_obj(*obj)?;
|
||||
let val = state.read(*src)?;
|
||||
|
||||
if stack_num > 8 {
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
} else {
|
||||
let obj: &mut Stacks = state.ext_mut();
|
||||
obj.stacks[stack_num as usize].push_back(val);
|
||||
}
|
||||
let stacks: &mut Stacks = state.ext_mut();
|
||||
stacks.store.get_mut(&handle)
|
||||
.ok_or_else(|| Fault::ObjectNotExist(handle))?
|
||||
.push_back(val);
|
||||
}
|
||||
StackOp::Pop { dst, num } => {
|
||||
StackOp::Pop { dst, obj } => {
|
||||
state.clear_status();
|
||||
let stack_num = state.read(*num)?;
|
||||
let handle = state.read_obj(*obj)?;
|
||||
|
||||
if stack_num > 8 {
|
||||
state.set_flag(Cond::Invalid, true);
|
||||
} else {
|
||||
let obj: &mut Stacks = state.ext_mut();
|
||||
let val = obj.stacks[stack_num as usize].pop_back();
|
||||
let stacks: &mut Stacks = state.ext_mut();
|
||||
let stack = stacks.store.get_mut(&handle)
|
||||
.ok_or_else(|| Fault::ObjectNotExist(handle))?;
|
||||
|
||||
if obj.stacks[stack_num as usize].is_empty() {
|
||||
state.set_flag(Cond::Zero, true);
|
||||
}
|
||||
let val = stack.pop_back();
|
||||
|
||||
let val = match val {
|
||||
None => {
|
||||
state.set_flag(Cond::Overflow, true);
|
||||
0
|
||||
}
|
||||
Some(val) => {
|
||||
val
|
||||
}
|
||||
};
|
||||
|
||||
state.write(*dst, val)?;
|
||||
if stack.is_empty() {
|
||||
state.set_flag(Cond::Zero, true);
|
||||
}
|
||||
|
||||
// TODO
|
||||
let val = match val {
|
||||
None => {
|
||||
state.set_flag(Cond::Overflow, true);
|
||||
0
|
||||
}
|
||||
Some(val) => {
|
||||
val
|
||||
}
|
||||
};
|
||||
|
||||
state.write(*dst, val)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,3 +67,8 @@ impl OpTrait for StackOp {
|
||||
}
|
||||
//
|
||||
}
|
||||
|
||||
pub(crate) fn drop_stack(state: &mut RunState, handle : Value) -> Result<Option<()>, Fault> {
|
||||
let stacks: &mut Stacks = state.ext_mut();
|
||||
Ok(stacks.store.remove(&handle).map(|_| ()))
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use crsn::asm::error::Error;
|
||||
use crsn::asm::instr::Op;
|
||||
use crsn::asm::parse::arg_parser::ArgParser;
|
||||
use crsn::module::{AsmModule, ParseOpRes};
|
||||
use crsn::module::{CrsnExtension, ParseOpRes};
|
||||
|
||||
use crate::defs::StackOp;
|
||||
use crsn::runtime::run_thread::{ThreadInfo, RunState};
|
||||
use crsn::asm::data::literal::Value;
|
||||
use crsn::runtime::fault::Fault;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StackOps {
|
||||
@@ -11,23 +14,29 @@ pub struct StackOps {
|
||||
}
|
||||
|
||||
impl StackOps {
|
||||
pub fn new() -> Box<dyn AsmModule> {
|
||||
pub fn new() -> Box<dyn CrsnExtension> {
|
||||
Box::new(Self {
|
||||
_internal: ()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AsmModule for StackOps {
|
||||
impl CrsnExtension for StackOps {
|
||||
fn name(&self) -> &'static str {
|
||||
"stacks"
|
||||
}
|
||||
|
||||
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes, Error> {
|
||||
Ok(ParseOpRes::Parsed(Op::Ext(Box::new(match keyword {
|
||||
"stack" => {
|
||||
StackOp::NewStack {
|
||||
dst: args.next_wr()?,
|
||||
}
|
||||
}
|
||||
|
||||
"push" => {
|
||||
StackOp::Push {
|
||||
num: args.next_rd()?,
|
||||
obj: args.next_rdobj()?,
|
||||
src: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
@@ -35,7 +44,7 @@ impl AsmModule for StackOps {
|
||||
"pop" => {
|
||||
StackOp::Pop {
|
||||
dst: args.next_wr()?,
|
||||
num: args.next_rd()?,
|
||||
obj: args.next_rdobj()?,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,4 +53,9 @@ impl AsmModule for StackOps {
|
||||
}
|
||||
}))))
|
||||
}
|
||||
|
||||
fn drop_obj(&self, _ti: &ThreadInfo, state: &mut RunState, handle : Value) -> Result<Option<()>, Fault>
|
||||
{
|
||||
crate::exec::drop_stack(state, handle)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user