Configure streams separately
This commit is contained in:
@@ -7,22 +7,83 @@ use rand::{rngs::StdRng, SeedableRng};
|
|||||||
use crate::Machine;
|
use crate::Machine;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
bootstrapping_compile, current_dir, import_builtin_impls, libraries, load_module, Atom,
|
bootstrapping_compile, current_dir, import_builtin_impls, libraries, load_module, Arena, Atom,
|
||||||
Callback, CompilationTarget, IndexStore, ListingSource, MachineArgs, MachineState, Stream,
|
Callback, CompilationTarget, IndexStore, ListingSource, MachineArgs, MachineState, Stream,
|
||||||
StreamOptions,
|
StreamOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Describes how the streams of a [`Machine`](crate::Machine) will be handled.
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
enum OutputStreamConfig {
|
||||||
|
#[default]
|
||||||
|
Null,
|
||||||
|
Memory,
|
||||||
|
Stdout,
|
||||||
|
Stderr,
|
||||||
|
Callback(Callback),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for OutputStreamConfig {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Null => write!(f, "Null"),
|
||||||
|
Self::Memory => write!(f, "Memory"),
|
||||||
|
Self::Stdout => write!(f, "Stdout"),
|
||||||
|
Self::Stderr => write!(f, "Stderr"),
|
||||||
|
Self::Callback(_) => f.debug_tuple("Callback").field(&"<callback>").finish(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputStreamConfig {
|
||||||
|
fn into_stream(self, arena: &mut Arena) -> Stream {
|
||||||
|
match self {
|
||||||
|
OutputStreamConfig::Null => Stream::Null(StreamOptions::default()),
|
||||||
|
OutputStreamConfig::Memory => Stream::from_owned_string("".to_owned(), arena),
|
||||||
|
OutputStreamConfig::Stdout => Stream::stdout(arena),
|
||||||
|
OutputStreamConfig::Stderr => Stream::stderr(arena),
|
||||||
|
OutputStreamConfig::Callback(callback) => Stream::from_callback(callback, arena),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
enum InputStreamConfig {
|
||||||
|
#[default]
|
||||||
|
Null,
|
||||||
|
Stdin,
|
||||||
|
Channel(Receiver<Vec<u8>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputStreamConfig {
|
||||||
|
fn into_stream(self, arena: &mut Arena, add_history: bool) -> Stream {
|
||||||
|
match self {
|
||||||
|
InputStreamConfig::Null => Stream::Null(StreamOptions::default()),
|
||||||
|
InputStreamConfig::Stdin => Stream::stdin(arena, add_history),
|
||||||
|
InputStreamConfig::Channel(channel) => Stream::input_channel(channel, arena),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Describes how the streams of a [`Machine`](crate::Machine) will be handled.
|
||||||
pub struct StreamConfig {
|
pub struct StreamConfig {
|
||||||
inner: StreamConfigInner,
|
stdin: InputStreamConfig,
|
||||||
|
stdout: OutputStreamConfig,
|
||||||
|
stderr: OutputStreamConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StreamConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::in_memory()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StreamConfig {
|
impl StreamConfig {
|
||||||
/// Binds the input, output and error streams to stdin, stdout and stderr.
|
/// Binds the input, output and error streams to stdin, stdout and stderr.
|
||||||
pub fn stdio() -> Self {
|
pub fn stdio() -> Self {
|
||||||
StreamConfig {
|
StreamConfig {
|
||||||
inner: StreamConfigInner::Stdio,
|
stdin: InputStreamConfig::Stdin,
|
||||||
|
stdout: OutputStreamConfig::Stdout,
|
||||||
|
stderr: OutputStreamConfig::Stderr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +92,9 @@ impl StreamConfig {
|
|||||||
/// The input stream is ignored.
|
/// The input stream is ignored.
|
||||||
pub fn in_memory() -> Self {
|
pub fn in_memory() -> Self {
|
||||||
StreamConfig {
|
StreamConfig {
|
||||||
inner: StreamConfigInner::Memory,
|
stdin: InputStreamConfig::Null,
|
||||||
|
stdout: OutputStreamConfig::Memory,
|
||||||
|
stderr: OutputStreamConfig::Stderr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,14 +106,24 @@ impl StreamConfig {
|
|||||||
(
|
(
|
||||||
UserInput { inner: sender },
|
UserInput { inner: sender },
|
||||||
StreamConfig {
|
StreamConfig {
|
||||||
inner: StreamConfigInner::Callbacks {
|
stdin: InputStreamConfig::Channel(receiver),
|
||||||
stdin: receiver,
|
stdout: stdout.map_or(OutputStreamConfig::Null, |x| {
|
||||||
stdout,
|
OutputStreamConfig::Callback(x)
|
||||||
stderr,
|
}),
|
||||||
},
|
stderr: stderr.map_or(OutputStreamConfig::Null, |x| {
|
||||||
|
OutputStreamConfig::Callback(x)
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn into_streams(self, arena: &mut Arena, add_history: bool) -> (Stream, Stream, Stream) {
|
||||||
|
(
|
||||||
|
self.stdin.into_stream(arena, add_history),
|
||||||
|
self.stdout.into_stream(arena),
|
||||||
|
self.stderr.into_stream(arena),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A handler for the stdin of the [`Machine`](crate::Machine).
|
/// A handler for the stdin of the [`Machine`](crate::Machine).
|
||||||
@@ -72,18 +145,6 @@ impl Write for UserInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
enum StreamConfigInner {
|
|
||||||
Stdio,
|
|
||||||
#[default]
|
|
||||||
Memory,
|
|
||||||
Callbacks {
|
|
||||||
stdin: Receiver<Vec<u8>>,
|
|
||||||
stdout: Option<Callback>,
|
|
||||||
stderr: Option<Callback>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes how a [`Machine`](crate::Machine) will be configured.
|
/// Describes how a [`Machine`](crate::Machine) will be configured.
|
||||||
pub struct MachineBuilder {
|
pub struct MachineBuilder {
|
||||||
pub(crate) streams: StreamConfig,
|
pub(crate) streams: StreamConfig,
|
||||||
@@ -123,33 +184,9 @@ impl MachineBuilder {
|
|||||||
let args = MachineArgs::new();
|
let args = MachineArgs::new();
|
||||||
let mut machine_st = MachineState::new();
|
let mut machine_st = MachineState::new();
|
||||||
|
|
||||||
let (user_input, user_output, user_error) = match self.streams.inner {
|
let (user_input, user_output, user_error) = self
|
||||||
StreamConfigInner::Stdio => (
|
.streams
|
||||||
Stream::stdin(&mut machine_st.arena, args.add_history),
|
.into_streams(&mut machine_st.arena, args.add_history);
|
||||||
Stream::stdout(&mut machine_st.arena),
|
|
||||||
Stream::stderr(&mut machine_st.arena),
|
|
||||||
),
|
|
||||||
StreamConfigInner::Memory => (
|
|
||||||
Stream::Null(StreamOptions::default()),
|
|
||||||
Stream::from_owned_string("".to_owned(), &mut machine_st.arena),
|
|
||||||
Stream::stderr(&mut machine_st.arena),
|
|
||||||
),
|
|
||||||
StreamConfigInner::Callbacks {
|
|
||||||
stdin,
|
|
||||||
stdout,
|
|
||||||
stderr,
|
|
||||||
} => (
|
|
||||||
Stream::input_channel(stdin, &mut machine_st.arena),
|
|
||||||
stdout.map_or_else(
|
|
||||||
|| Stream::Null(StreamOptions::default()),
|
|
||||||
|x| Stream::from_callback(x, &mut machine_st.arena),
|
|
||||||
),
|
|
||||||
stderr.map_or_else(
|
|
||||||
|| Stream::Null(StreamOptions::default()),
|
|
||||||
|x| Stream::from_callback(x, &mut machine_st.arena),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut wam = Machine {
|
let mut wam = Machine {
|
||||||
machine_st,
|
machine_st,
|
||||||
|
|||||||
Reference in New Issue
Block a user