AMAZING NEW FEATURES ldn, bfio

This commit is contained in:
2020-10-11 01:35:19 +02:00
parent 74e3716ce4
commit 4062ff4d09
17 changed files with 400 additions and 109 deletions
+28
View File
@@ -1,4 +1,6 @@
use crsn::asm::data::{Rd, RdObj, Wr};
use crsn::asm::data::literal::Value;
use crate::parse::{BUF_IOMODE_QUEUE, BUF_IOMODE_REVERSE_QUEUE, BUF_IOMODE_STACK, BUF_IOMODE_REVERSE_STACK};
#[derive(Clone, Debug, PartialEq)]
pub enum BufValue {
@@ -7,9 +9,35 @@ pub enum BufValue {
Chars(String),
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BufIoMode {
Queue,
ReverseQueue,
Stack,
ReverseStack,
}
impl BufIoMode {
pub fn to_value(self) -> Value {
match self {
BufIoMode::Queue => BUF_IOMODE_QUEUE,
BufIoMode::ReverseQueue => BUF_IOMODE_REVERSE_QUEUE,
BufIoMode::Stack => BUF_IOMODE_STACK,
BufIoMode::ReverseStack => BUF_IOMODE_REVERSE_STACK,
}
}
}
impl Default for BufIoMode {
fn default() -> Self {
Self::Queue
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum BufOps {
New { dst: Wr, value: BufValue },
SetIoMode { obj: RdObj, mode: BufIoMode },
// Elementary ops
Read { dst: Wr, obj: RdObj, idx: Rd },
+122 -53
View File
@@ -1,19 +1,25 @@
use std::collections::{HashMap, VecDeque};
use crsn::asm::data::literal::Value;
use crsn::asm::instr::cond::Flag;
use crsn::module::{EvalRes, OpTrait};
use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crsn::sexp;
use crsn::sexp::{Sexp, atom_qs};
use crsn::sexp::{atom_qs, Sexp};
use crsn::utils::A;
use crate::defs::{BufOps, BufValue};
use crsn::asm::instr::cond::Flag;
use crate::defs::{BufIoMode, BufOps, BufValue};
#[derive(Debug, Default, Clone)]
struct Buffer {
data: VecDeque<Value>,
iomode: BufIoMode,
}
#[derive(Debug, Default)]
struct ExtData {
store: HashMap<Value, VecDeque<Value>>,
buffers: HashMap<Value, Buffer>,
}
// TODO optimize and DRY
@@ -49,26 +55,38 @@ impl OpTrait for BufOps {
};
let data: &mut ExtData = state.ext_mut();
data.store.insert(id, que);
data.buffers.insert(id, Buffer {
data: que,
iomode: Default::default()
});
state.write(dst, id)?;
}
BufOps::SetIoMode { obj, mode } => {
state.clear_status();
let handle = state.read_obj(obj)?;
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
buf.iomode = *mode;
}
BufOps::Push { obj, src } => {
state.clear_status();
let val = state.read(src)?;
let handle = state.read_obj(obj)?;
let stacks: &mut ExtData = state.ext_mut();
let stack = stacks.store.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
stack.push_back(val);
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
buf.data.push_back(val);
}
BufOps::Pop { dst, obj } => {
state.clear_status();
let handle = state.read_obj(obj)?;
let stacks: &mut ExtData = state.ext_mut();
let stack = stacks.store.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if let Some(val) = stack.pop_back() {
let empty = stack.is_empty();
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if let Some(val) = buf.data.pop_back() {
let empty = buf.data.is_empty();
state.write(dst, val)?;
state.update_status(val);
state.set_flag(Flag::Empty, empty);
@@ -82,9 +100,9 @@ impl OpTrait for BufOps {
state.clear_status();
let handle = state.read_obj(obj)?;
let idx = state.read(idx)?;
let stacks: &mut ExtData = state.ext_mut();
let stack = stacks.store.get(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if let Some(val) = stack.get(idx as usize) {
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if let Some(val) = buf.data.get(idx as usize) {
let val = *val;
state.update_status(val);
state.write(dst, val)?;
@@ -96,9 +114,9 @@ impl OpTrait for BufOps {
BufOps::GetLen { dst, obj } => {
state.clear_status();
let handle = state.read_obj(obj)?;
let stacks: &mut ExtData = state.ext_mut();
let stack = stacks.store.get(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
let val = stack.len() as Value;
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
let val = buf.data.len() as Value;
state.write(dst, val)?;
state.update_status(val);
}
@@ -108,12 +126,12 @@ impl OpTrait for BufOps {
let handle = state.read_obj(obj)?;
let val = state.read(value)?;
let idx = state.read(idx)? as usize;
let stacks: &mut ExtData = state.ext_mut();
let stack = stacks.store.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if idx < stack.len() {
stack[idx] = val;
} else if idx == stack.len() {
stack.push_back(val);
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if idx < buf.data.len() {
buf.data[idx] = val;
} else if idx == buf.data.len() {
buf.data.push_back(val);
} else {
state.set_flag(Flag::Overflow, true);
}
@@ -124,12 +142,12 @@ impl OpTrait for BufOps {
let handle = state.read_obj(obj)?;
let val = state.read(value)?;
let idx = state.read(idx)? as usize;
let stacks: &mut ExtData = state.ext_mut();
let stack = stacks.store.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if idx < stack.len() {
stack.insert(idx, val);
} else if idx == stack.len() {
stack.push_back(val);
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if idx < buf.data.len() {
buf.data.insert(idx, val);
} else if idx == buf.data.len() {
buf.data.push_back(val);
} else {
state.set_flag(Flag::Overflow, true);
}
@@ -139,11 +157,11 @@ impl OpTrait for BufOps {
state.clear_status();
let handle = state.read_obj(obj)?;
let idx = state.read(idx)? as usize;
let stacks: &mut ExtData = state.ext_mut();
let stack = stacks.store.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if idx < stack.len() {
let val = stack.remove(idx).unwrap();
let empty = stack.is_empty();
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
if idx < buf.data.len() {
let val = buf.data.remove(idx).unwrap();
let empty = buf.data.is_empty();
state.update_status(val);
state.write(dst, val)?;
state.set_flag(Flag::Empty, empty);
@@ -155,21 +173,21 @@ impl OpTrait for BufOps {
BufOps::Resize { obj, len } => {
let handle = state.read_obj(obj)?;
let len = state.read(len)? as usize;
let stacks: &mut ExtData = state.ext_mut();
let stack = stacks.store.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
stack.resize(len, 0);
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
buf.data.resize(len, 0);
}
BufOps::Reverse { obj } => {
let handle = state.read_obj(obj)?;
let stacks: &mut ExtData = state.ext_mut();
let stack = stacks.store.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
let len = stack.len();
let store: &mut ExtData = state.ext_mut();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
let len = buf.data.len();
if len > 1 {
let mut start = 0;
let mut end = len - 1;
while start < end {
stack.swap(start, end);
buf.data.swap(start, end);
start += 1;
end -= 1;
}
@@ -179,20 +197,22 @@ impl OpTrait for BufOps {
BufOps::AppendBuf { obj, obj2 } => {
let handle = state.read_obj(obj)?;
let handle2 = state.read_obj(obj2)?;
let stacks: &mut ExtData = state.ext_mut();
let stack2 = stacks.store.get(&handle2).ok_or_else(|| Fault::ObjectNotExist(handle))?.clone();
let stack = stacks.store.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
stack.extend(stack2);
let store: &mut ExtData = state.ext_mut();
// TODO figure out how to avoid cloning
let buf2 = store.buffers.get(&handle2).ok_or_else(|| Fault::ObjectNotExist(handle))?.data.clone();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
buf.data.extend(buf2);
}
BufOps::PrependBuf { obj, obj2 } => {
let handle = state.read_obj(obj)?;
let handle2 = state.read_obj(obj2)?;
let stacks: &mut ExtData = state.ext_mut();
let stack2 = stacks.store.get(&handle2).ok_or_else(|| Fault::ObjectNotExist(handle))?.clone();
let stack = stacks.store.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
for v in stack2.into_iter().rev() {
stack.push_front(v);
let store: &mut ExtData = state.ext_mut();
// TODO figure out how to avoid cloning
let buf2 = store.buffers.get(&handle2).ok_or_else(|| Fault::ObjectNotExist(handle))?.data.clone();
let buf = store.buffers.get_mut(&handle).ok_or_else(|| Fault::ObjectNotExist(handle))?;
for v in buf2.into_iter().rev() {
buf.data.push_front(v);
}
}
}
@@ -257,12 +277,61 @@ impl OpTrait for BufOps {
BufOps::PrependBuf { obj, obj2 } => {
sexp::list(&[A("bfprep"), A(obj), A(obj2)])
}
BufOps::SetIoMode { obj, mode } => {
sexp::list(&[A("bfio"), A(obj), A(mode.to_value())])
}
}
}
}
pub(crate) fn drop_obj(state: &mut RunState, handle: Value) -> Result<Option<()>, Fault> {
let stacks: &mut ExtData = state.ext_mut();
Ok(stacks.store.remove(&handle).map(|_| ()))
let store: &mut ExtData = state.ext_mut();
Ok(store.buffers.remove(&handle).map(|_| ()))
}
/// Run-time method called to read an object (using the object handle syntax)
pub(crate) fn read_obj(state: &mut RunState, handle: Value)
-> Result<Option<Value>, Fault>
{
let store: &mut ExtData = state.ext_mut();
if let Some(buf) = store.buffers.get_mut(&handle) {
match match buf.iomode {
BufIoMode::Queue => buf.data.pop_front(),
BufIoMode::ReverseQueue => buf.data.pop_back(),
BufIoMode::Stack => buf.data.pop_back(),
BufIoMode::ReverseStack => buf.data.pop_front()
} {
None => {
state.set_flag(Flag::Overflow, true);
state.set_flag(Flag::Empty, true);
Ok(Some(0))
}
Some(val) => {
let em = buf.data.is_empty();
state.set_flag(Flag::Empty, em);
Ok(Some(val))
}
}
} else {
Ok(None)
}
}
/// Run-time method called to write an object (using the object handle syntax)
pub(crate) fn write_obj(state: &mut RunState, handle: Value, value: Value) -> Result<Option<()>, Fault>
{
let store: &mut ExtData = state.ext_mut();
if let Some(buf) = store.buffers.get_mut(&handle) {
match buf.iomode {
BufIoMode::Queue => buf.data.push_back(value),
BufIoMode::ReverseQueue => buf.data.push_front(value),
BufIoMode::Stack => buf.data.push_back(value),
BufIoMode::ReverseStack => buf.data.push_front(value)
}
Ok(Some(()))
} else {
Ok(None)
}
}
+27
View File
@@ -6,6 +6,7 @@ use crsn::module::{CrsnExtension, ParseRes};
use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{RunState, ThreadInfo};
use crsn::sexp::SourcePosition;
use crate::parse::{BUF_IOMODE_STACK, BUF_IOMODE_REVERSE_STACK, BUF_IOMODE_QUEUE, BUF_IOMODE_REVERSE_QUEUE};
mod defs;
mod parse;
@@ -32,4 +33,30 @@ impl CrsnExtension for BufOps {
fn drop_obj(&self, _ti: &ThreadInfo, state: &mut RunState, handle: Value) -> Result<Option<()>, Fault> {
exec::drop_obj(state, handle)
}
/// Run-time method called to read an object (using the object handle syntax)
fn read_obj(&self, state: &mut RunState, handle: Value)
-> Result<Option<Value>, Fault>
{
exec::read_obj(state, handle)
}
/// Run-time method called to write an object (using the object handle syntax)
fn write_obj(&self, state: &mut RunState, handle: Value, value: Value) -> Result<Option<()>, Fault>
{
exec::write_obj(state, handle, value)
}
/// Get value of an extension-provided constant.
/// This constant may be an object handle, or a constant value used as argument in some other instruction.
fn get_constant_value<'a>(&self, name: &str) -> Option<Value>
{
match name {
"BFIO_STACK" => Some(BUF_IOMODE_STACK),
"BFIO_RSTACK" => Some(BUF_IOMODE_REVERSE_STACK),
"BFIO_QUEUE" => Some(BUF_IOMODE_QUEUE),
"BFIO_RQUEUE" => Some(BUF_IOMODE_REVERSE_QUEUE),
_ => None
}
}
}
+22 -1
View File
@@ -4,9 +4,15 @@ use crsn::asm::parse::arg_parser::TokenParser;
use crsn::module::ParseRes;
use crsn::sexp::{SourcePosition, Sexp, Atom};
use crate::defs::{BufOps, BufValue};
use crate::defs::{BufOps, BufValue, BufIoMode};
use crsn::asm::data::Rd;
use crsn::asm::parse::parse_data::parse_rd;
use crsn::asm::data::literal::Value;
pub const BUF_IOMODE_STACK : Value = 1;
pub const BUF_IOMODE_REVERSE_STACK : Value = 2;
pub const BUF_IOMODE_QUEUE : Value = 3;
pub const BUF_IOMODE_REVERSE_QUEUE : Value = 4;
pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
Ok(ParseRes::ext(match keyword {
@@ -40,6 +46,21 @@ pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenPar
BufOps::New { dst, value }
}
"bfio" => {
let obj = args.next_rdobj()?;
let (mode, modepos) = args.next_value()?;
BufOps::SetIoMode {
obj,
mode: match mode {
BUF_IOMODE_STACK => BufIoMode::Stack,
BUF_IOMODE_REVERSE_STACK => BufIoMode::ReverseStack,
BUF_IOMODE_QUEUE => BufIoMode::Queue,
BUF_IOMODE_REVERSE_QUEUE => BufIoMode::ReverseQueue,
_ => return Err(CrsnError::Parse("Bad buffer iomode".into(), modepos))
}
}
}
"bfrd" => {
let dst = args.next_wr()?;
let obj = args.next_rdobj()?;