Added directfs
Added a very rudimentary file I/O system suitable for experimenting with the language further. A better one will be designed when we have sensible error management.
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
use super::flow::IOCmdHandlePack;
|
||||
use super::instances::{
|
||||
BRead, ReadCmd, SRead, SinkHandle, SourceHandle, WriteCmd,
|
||||
BRead, ReadCmd, SRead, WriteCmd, Sink, Source,
|
||||
};
|
||||
use crate::foreign::cps_box::init_cps;
|
||||
use crate::foreign::{Atom, Atomic};
|
||||
use crate::representations::OrcString;
|
||||
use crate::systems::scheduler::SharedHandle;
|
||||
use crate::systems::stl::Binary;
|
||||
use crate::systems::RuntimeError;
|
||||
use crate::{ast, define_fn, ConstTree, Interner, Primitive};
|
||||
@@ -22,17 +23,13 @@ define_fn! {
|
||||
cmd: ReadCmd::RBytes(BRead::All),
|
||||
handle: x.downcast()?
|
||||
}));
|
||||
ReadBytes {
|
||||
stream: SourceHandle,
|
||||
n: u64
|
||||
} => Ok(init_cps(3, IOCmdHandlePack{
|
||||
cmd: ReadCmd::RBytes(BRead::N(n.try_into().unwrap())),
|
||||
handle: stream.clone()
|
||||
}));
|
||||
ReadUntil {
|
||||
stream: SourceHandle,
|
||||
pattern: u64
|
||||
} => {
|
||||
ReadBytes { stream: SharedHandle<Source>, n: u64 } => {
|
||||
Ok(init_cps(3, IOCmdHandlePack{
|
||||
cmd: ReadCmd::RBytes(BRead::N(n.try_into().unwrap())),
|
||||
handle: stream.clone()
|
||||
}))
|
||||
};
|
||||
ReadUntil { stream: SharedHandle<Source>, pattern: u64 } => {
|
||||
let delim = pattern.try_into().map_err(|_| RuntimeError::ext(
|
||||
"greater than 255".to_string(),
|
||||
"converting number to byte"
|
||||
@@ -42,20 +39,18 @@ define_fn! {
|
||||
handle: stream
|
||||
}))
|
||||
};
|
||||
WriteStr {
|
||||
stream: SinkHandle,
|
||||
string: OrcString
|
||||
} => Ok(init_cps(3, IOCmdHandlePack {
|
||||
cmd: WriteCmd::WStr(string.get_string()),
|
||||
handle: stream.clone(),
|
||||
}));
|
||||
WriteBin {
|
||||
stream: SinkHandle,
|
||||
bytes: Binary
|
||||
} => Ok(init_cps(3, IOCmdHandlePack {
|
||||
cmd: WriteCmd::WBytes(bytes),
|
||||
handle: stream.clone(),
|
||||
}));
|
||||
WriteStr { stream: SharedHandle<Sink>, string: OrcString } => {
|
||||
Ok(init_cps(3, IOCmdHandlePack {
|
||||
cmd: WriteCmd::WStr(string.get_string()),
|
||||
handle: stream.clone(),
|
||||
}))
|
||||
};
|
||||
WriteBin { stream: SharedHandle<Sink>, bytes: Binary } => {
|
||||
Ok(init_cps(3, IOCmdHandlePack {
|
||||
cmd: WriteCmd::WBytes(bytes),
|
||||
handle: stream.clone(),
|
||||
}))
|
||||
};
|
||||
Flush = |x| Ok(init_cps(3, IOCmdHandlePack {
|
||||
cmd: WriteCmd::Flush,
|
||||
handle: x.downcast()?
|
||||
|
||||
@@ -9,12 +9,11 @@ use crate::systems::scheduler::{Canceller, SharedHandle};
|
||||
use crate::systems::stl::Binary;
|
||||
use crate::Literal;
|
||||
|
||||
/// Any type that we can read controlled amounts of data from
|
||||
pub type Source = BufReader<Box<dyn Read + Send>>;
|
||||
/// Any type that we can write data to
|
||||
pub type Sink = Box<dyn Write + Send>;
|
||||
|
||||
pub type SourceHandle = SharedHandle<Source>;
|
||||
pub type SinkHandle = SharedHandle<Sink>;
|
||||
|
||||
/// String reading command
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum SRead {
|
||||
@@ -39,7 +38,7 @@ pub enum ReadCmd {
|
||||
impl IOCmd for ReadCmd {
|
||||
type Stream = Source;
|
||||
type Result = ReadResult;
|
||||
type Handle = SourceHandle;
|
||||
type Handle = SharedHandle<Source>;
|
||||
|
||||
// This is a buggy rule, check manually
|
||||
#[allow(clippy::read_zero_byte_vec)]
|
||||
@@ -82,22 +81,21 @@ impl ReadResult {
|
||||
pub fn dispatch(self, succ: ExprInst, fail: ExprInst) -> Vec<ExprInst> {
|
||||
match self {
|
||||
ReadResult::RBin(_, Err(e)) | ReadResult::RStr(_, Err(e)) => {
|
||||
vec![call(fail, vec![wrap_io_error(e)]).wrap()]
|
||||
vec![call(fail, [wrap_io_error(e)]).wrap()]
|
||||
},
|
||||
ReadResult::RBin(_, Ok(bytes)) => {
|
||||
let arg = Binary(Arc::new(bytes)).atom_cls().wrap();
|
||||
vec![call(succ, vec![arg]).wrap()]
|
||||
vec![call(succ, [arg]).wrap()]
|
||||
},
|
||||
ReadResult::RStr(_, Ok(text)) => {
|
||||
vec![call(succ, vec![Literal::Str(text.into()).into()]).wrap()]
|
||||
vec![call(succ, [Literal::Str(text.into()).into()]).wrap()]
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Placeholder function for an eventual conversion from [io::Error] to Orchid
|
||||
/// data
|
||||
fn wrap_io_error(_e: io::Error) -> ExprInst { Literal::Uint(0u64).into() }
|
||||
/// Function to convert [io::Error] to Orchid data
|
||||
pub fn wrap_io_error(_e: io::Error) -> ExprInst { Literal::Uint(0u64).into() }
|
||||
|
||||
/// Writing command (string or binary)
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@@ -109,7 +107,7 @@ pub enum WriteCmd {
|
||||
|
||||
impl IOCmd for WriteCmd {
|
||||
type Stream = Sink;
|
||||
type Handle = SinkHandle;
|
||||
type Handle = SharedHandle<Sink>;
|
||||
type Result = WriteResult;
|
||||
|
||||
fn execute(
|
||||
|
||||
@@ -9,3 +9,4 @@ mod service;
|
||||
|
||||
// pub use facade::{io_system, IOStream, IOSystem};
|
||||
pub use service::{Service, Stream, StreamTable};
|
||||
pub use instances::{wrap_io_error, Source, Sink};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#[allow(unused)] // for doc
|
||||
use std::io::{BufReader, Read, Write};
|
||||
|
||||
use itertools::Itertools;
|
||||
use rust_embed::RustEmbed;
|
||||
use trait_set::trait_set;
|
||||
|
||||
@@ -69,8 +70,8 @@ impl<'a, ST: IntoIterator<Item = (&'a str, Stream)>> IntoSystem<'static>
|
||||
|stream| (stream, Vec::new()),
|
||||
);
|
||||
match result {
|
||||
Ok(cancel) => Ok(call(tail, vec![init_cps(1, cancel).wrap()]).wrap()),
|
||||
Err(e) => Ok(call(fail, vec![e.atom_exi()]).wrap()),
|
||||
Ok(cancel) => Ok(call(tail, [init_cps(1, cancel).wrap()]).wrap()),
|
||||
Err(e) => Ok(call(fail, [e.atom_exi()]).wrap()),
|
||||
}
|
||||
});
|
||||
let scheduler = self.scheduler.clone();
|
||||
@@ -87,8 +88,8 @@ impl<'a, ST: IntoIterator<Item = (&'a str, Stream)>> IntoSystem<'static>
|
||||
|stream| (stream, Vec::new()),
|
||||
);
|
||||
match result {
|
||||
Ok(cancel) => Ok(call(tail, vec![init_cps(1, cancel).wrap()]).wrap()),
|
||||
Err(e) => Ok(call(fail, vec![e.atom_exi()]).wrap()),
|
||||
Ok(cancel) => Ok(call(tail, [init_cps(1, cancel).wrap()]).wrap()),
|
||||
Err(e) => Ok(call(fail, [e.atom_exi()]).wrap()),
|
||||
}
|
||||
});
|
||||
let streams = self.global_streams.into_iter().map(|(n, stream)| {
|
||||
@@ -101,7 +102,7 @@ impl<'a, ST: IntoIterator<Item = (&'a str, Stream)>> IntoSystem<'static>
|
||||
});
|
||||
System {
|
||||
handlers,
|
||||
name: vec!["system".to_string(), "io".to_string()],
|
||||
name: ["system", "io"].into_iter().map_into().collect(),
|
||||
constants: io_bindings(i, streams).unwrap_tree(),
|
||||
code: embed_to_map::<IOEmbed>(".orc", i),
|
||||
prelude: vec![FileEntry {
|
||||
|
||||
Reference in New Issue
Block a user