[[package]]
name = "prolog_parser"
-version = "0.8.44"
+version = "0.8.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "prolog_parser 0.8.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "prolog_parser 0.8.47 (registry+https://github.com/rust-lang/crates.io-index)",
"ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustyline 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
-"checksum prolog_parser 0.8.44 (registry+https://github.com/rust-lang/crates.io-index)" = "c113cce59b3e97ff141e933d09eb1618e44b11cad9fa2ce6eb53ef832c38dc5c"
+"checksum prolog_parser 0.8.47 (registry+https://github.com/rust-lang/crates.io-index)" = "2cf575fc8b91b2d9a9487f13655cffb6f697a5294b74de9b24b6a5fbe987e229"
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
nix = "0.15.0"
num-rug-adapter = { optional = true, version = "0.1.1" }
ordered-float = "0.5.0"
-prolog_parser = { version = "0.8.44", default-features = false }
+prolog_parser = { version = "0.8.47", default-features = false }
ref_thread_local = "0.0.0"
rug = { version = "1.4.0", optional = true }
rustyline = "6.0.0"
mod prolog;
use crate::prolog::machine::*;
+use crate::prolog::machine::streams::*;
use crate::prolog::read::*;
use std::sync::atomic::Ordering;
let handler = signal::SigHandler::Handler(handle_sigint);
unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap();
- let mut wam = Machine::new(readline::input_stream());
+ let mut wam = Machine::new(readline::input_stream(), Stream::stdout());
wam.run_top_level();
}
CopyToLiftedHeap,
CreatePartialString,
CurrentInput,
+ CurrentOutput,
DeleteAttribute,
DeleteHeadAttribute,
DynamicModuleResolution(usize),
&SystemClauseType::CopyTermWithoutAttrVars => clause_name!("$copy_term_without_attr_vars"),
&SystemClauseType::CreatePartialString => clause_name!("$create_partial_string"),
&SystemClauseType::CurrentInput => clause_name!("$current_input"),
+ &SystemClauseType::CurrentOutput => clause_name!("$current_output"),
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)),
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
("$current_input", 1) => Some(SystemClauseType::CurrentInput),
+ ("$current_output", 1) => Some(SystemClauseType::CurrentOutput),
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
("$get_next_db_ref", 2) => Some(SystemClauseType::GetNextDBRef),
self.push_list();
}
}
+ HeapCellValue::Addr(Addr::Stream(stream)) => {
+ if let Some(alias) = &stream.options.alias {
+ self.print_atom(alias);
+ } else {
+ if stream.is_stdout() || stream.is_stdin() {
+ self.append_str("user");
+ } else {
+ self.append_str(&format!(
+ "'$stream'(0x{:x})",
+ stream.as_ptr() as usize,
+ ));
+ }
+ }
+ }
HeapCellValue::Addr(addr) => {
if let Some(offset_str) = self.offset_as_string(iter, addr) {
push_space_if_amb!(self, &offset_str, {
abolish/1, asserta/1, assertz/1, atom_chars/2,
atom_codes/2, atom_concat/3, atom_length/2,
bagof/3, catch/3, char_code/2, clause/2,
- current_input/1, current_op/3, current_predicate/1,
- current_prolog_flag/2, expand_goal/2,
- expand_term/2, fail/0, false/0, findall/3,
- findall/4, get_char/1, halt/0, max_arity/1,
- number_chars/2, number_codes/2, once/1, op/3,
- read_term/2, repeat/0, retract/1,
+ current_input/1, current_output/1, current_op/3,
+ current_predicate/1, current_prolog_flag/2,
+ expand_goal/2, expand_term/2, fail/0, false/0,
+ findall/3, findall/4, get_char/1, halt/0,
+ max_arity/1, number_chars/2, number_codes/2,
+ once/1, op/3, read_term/2, repeat/0, retract/1,
set_prolog_flag/2, setof/3, sub_atom/5,
subsumes_term/2, term_variables/2, throw/1,
true/0, unify_with_occurs_check/2, write/1,
unify_with_occurs_check(X, Y) :- '$unify_with_occurs_check'(X, Y).
current_input(S) :- '$current_input'(S).
+
+current_output(S) :- '$current_output'(S).
}
pub(crate) type ModuleStubDir = IndexMap<ClauseName, ModuleStub>;
+pub(crate) type StreamAliasDir = IndexMap<ClauseName, Stream>;
pub struct IndexStore {
pub(super) atom_tbl: TabledData<Atom>,
pub(super) code_dir: CodeDir,
- pub(super) module_dir: ModuleDir,
pub(super) dynamic_code_dir: DynamicCodeDir,
pub(super) global_variables: GlobalVarDir,
pub(super) in_situ_code_dir: InSituCodeDir,
pub(super) in_situ_module_dir: ModuleStubDir,
+ pub(super) module_dir: ModuleDir,
pub(super) modules: ModuleDir,
pub(super) op_dir: OpDir,
+ pub(super) stream_aliases: StreamAliasDir,
}
impl IndexStore {
in_situ_module_dir: ModuleStubDir::new(),
op_dir: default_op_dir(),
modules: ModuleDir::new(),
+ stream_aliases: StreamAliasDir::new(),
}
}
use downcast::Any;
use std::cmp::Ordering;
-use std::io::{stdout, Write};
+use std::io::Write;
use std::mem;
use std::ops::{Index, IndexMut};
use std::rc::Rc;
ct: &BuiltInClauseType,
indices: &mut IndexStore,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) -> CallResult {
match ct {
&BuiltInClauseType::AcyclicTerm => {
machine_st.compare_term(qt);
return_from_clause!(machine_st.last_call, machine_st)
}
- &BuiltInClauseType::Nl => {
- let mut stdout = stdout();
-
- write!(stdout, "\n").unwrap();
- stdout.flush().unwrap();
+ &BuiltInClauseType::Nl => {
+ write!(current_output_stream, "\n").unwrap();
+ current_output_stream.flush().unwrap();
+
return_from_clause!(machine_st.last_call, machine_st)
}
&BuiltInClauseType::Read => {
arity: usize,
indices: &mut IndexStore,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) -> CallResult {
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
match ClauseType::from(name.clone(), arity, None) {
ClauseType::BuiltIn(built_in) => {
machine_st.setup_built_in_call(built_in.clone());
- self.call_builtin(machine_st, &built_in, indices, current_input_stream)?;
+ self.call_builtin(
+ machine_st,
+ &built_in,
+ indices,
+ current_input_stream,
+ current_output_stream,
+ )?;
}
ClauseType::CallN => {
machine_st.handle_internal_call_n(arity);
ct: &BuiltInClauseType,
indices: &mut IndexStore,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) -> CallResult {
- self.prev_policy
- .call_builtin(machine_st, ct, indices, current_input_stream)?;
+ self.prev_policy.call_builtin(
+ machine_st,
+ ct,
+ indices,
+ current_input_stream,
+ current_output_stream
+ )?;
+
self.increment(machine_st)
}
arity: usize,
indices: &mut IndexStore,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) -> CallResult {
- self.prev_policy
- .call_n(machine_st, arity, indices, current_input_stream)?;
+ self.prev_policy.call_n(
+ machine_st,
+ arity,
+ indices,
+ current_input_stream,
+ current_output_stream,
+ )?;
+
self.increment(machine_st)
}
}
call_policy: &mut Box<dyn CallPolicy>,
cut_policy: &mut Box<dyn CutPolicy>,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
ct: &ClauseType,
arity: usize,
lco: bool,
match ct {
&ClauseType::BuiltIn(ref ct) => try_or_fail!(
self,
- call_policy.call_builtin(self, ct, indices, current_input_stream)
+ call_policy.call_builtin(
+ self,
+ ct,
+ indices,
+ current_input_stream,
+ current_output_stream,
+ )
),
&ClauseType::CallN => try_or_fail!(
self,
- call_policy.call_n(self, arity, indices, current_input_stream)
+ call_policy.call_n(self, arity, indices, current_input_stream, current_output_stream)
),
&ClauseType::Hook(ref hook) => try_or_fail!(self, call_policy.compile_hook(self, hook)),
&ClauseType::Inlined(ref ct) => {
call_policy,
cut_policy,
current_input_stream,
+ current_output_stream,
)
),
};
call_policy: &mut Box<dyn CallPolicy>,
cut_policy: &mut Box<dyn CutPolicy>,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
instr: &ControlInstruction,
) {
match instr {
call_policy,
cut_policy,
current_input_stream,
+ current_output_stream,
ct,
arity,
lco,
mod partial_string;
mod raw_block;
mod stack;
-pub(super) mod streams;
+pub(crate) mod streams;
pub(super) mod term_expansion;
pub mod toplevel;
pub(super) code_repo: CodeRepo,
pub(super) toplevel_idx: usize,
pub(super) current_input_stream: Stream,
+ pub(super) current_output_stream: Stream,
}
impl Index<LocalCodePtr> for CodeRepo {
self.run_query();
}
- pub fn new(current_input_stream: Stream) -> Self
+ pub fn new(current_input_stream: Stream, current_output_stream: Stream) -> Self
{
let mut wam = Machine {
machine_st: MachineState::new(),
code_repo: CodeRepo::new(),
toplevel_idx: 0,
current_input_stream,
+ current_output_stream,
};
let atom_tbl = wam.indices.atom_tbl.clone();
&mut self.policies,
&mut self.code_repo,
&mut self.current_input_stream,
+ &mut self.current_output_stream,
);
match self.machine_st.p {
policies: &mut MachinePolicies,
code_repo: &CodeRepo,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) {
match instr {
&Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr),
&mut policies.call_policy,
&mut policies.cut_policy,
current_input_stream,
+ current_output_stream,
control_instr,
),
&Line::Fact(ref fact_instr) => {
policies: &mut MachinePolicies,
code_repo: &CodeRepo,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) {
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
Some(instr) => instr,
policies,
code_repo,
current_input_stream,
+ current_output_stream,
);
}
policies: &mut MachinePolicies,
code_repo: &mut CodeRepo,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) -> bool {
loop {
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
indices,
policies,
code_repo,
- current_input_stream
+ current_input_stream,
+ current_output_stream,
);
if self.fail {
policies: &mut MachinePolicies,
code_repo: &mut CodeRepo,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) {
loop {
- self.execute_instr(indices, policies, code_repo, current_input_stream);
+ self.execute_instr(
+ indices,
+ policies,
+ code_repo,
+ current_input_stream,
+ current_output_stream,
+ );
if self.fail {
self.backtrack();
if !instigating_instr.as_ref().is_head_instr() {
let cp = self.p.local();
self.run_verify_attr_interrupt(cp);
- } else if !self.verify_attr_stepper(indices, policies, code_repo, current_input_stream) {
+ } else if !self.verify_attr_stepper(
+ indices,
+ policies,
+ code_repo,
+ current_input_stream,
+ current_output_stream,
+ ) {
if self.fail {
break;
}
use std::error::Error;
use std::fmt;
use std::fs::File;
-use std::io::{Cursor, ErrorKind, Read, Write};
+use std::io::{stdin, stdout, Cursor, ErrorKind, Read, Write};
use std::hash::{Hash, Hasher};
use std::net::TcpStream;
use std::rc::Rc;
DynReadSource(Box<dyn Read>),
File(File),
ReadlineStream(ReadlineStream),
+ Stdin,
+ Stdout,
TcpStream(TcpStream),
}
ptr
}
+
+ #[inline]
+ pub(crate)
+ fn stdout() -> Self {
+ Stream {
+ options: StreamOptions::default(),
+ stream_inst: WrappedStreamInstance::new(
+ StreamInstance::Stdout
+ ),
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn stdin() -> Self {
+ Stream {
+ options: StreamOptions::default(),
+ stream_inst: WrappedStreamInstance::new(
+ StreamInstance::Stdin
+ ),
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn is_stdout(&self) -> bool {
+ match *self.stream_inst.0.borrow() {
+ StreamInstance::Stdout => {
+ true
+ }
+ _ => {
+ false
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn is_stdin(&self) -> bool {
+ match *self.stream_inst.0.borrow() {
+ StreamInstance::Stdin | StreamInstance::ReadlineStream(_) => {
+ true
+ }
+ _ => {
+ false
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn is_input_stream(&self) -> bool {
+ match *self.stream_inst.0.borrow() {
+ StreamInstance::Stdin
+ | StreamInstance::TcpStream(_)
+ | StreamInstance::Bytes(_)
+ | StreamInstance::ReadlineStream(_)
+ | StreamInstance::DynReadSource(_)
+ | StreamInstance::File(_) => {
+ true
+ }
+ _ => {
+ false
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn is_output_stream(&self) -> bool {
+ match *self.stream_inst.0.borrow() {
+ StreamInstance::Stdout
+ | StreamInstance::TcpStream(_)
+ | StreamInstance::Bytes(_)
+ | StreamInstance::File(_) => {
+ true
+ }
+ _ => {
+ false
+ }
+ }
+ }
}
impl Read for Stream {
StreamInstance::Bytes(ref mut cursor) => {
cursor.read(buf)
}
+ StreamInstance::Stdin => {
+ stdin().read(buf)
+ }
+ StreamInstance::Stdout => {
+ Err(std::io::Error::new(
+ ErrorKind::PermissionDenied,
+ StreamError::ReadFromOutputStream,
+ ))
+ }
}
}
}
StreamInstance::Bytes(ref mut cursor) => {
cursor.write(buf)
}
+ StreamInstance::Stdout => {
+ stdout().write(buf)
+ }
_ => {
Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamInstance::Bytes(ref mut cursor) => {
cursor.flush()
}
+ StreamInstance::Stdout => {
+ stdout().flush()
+ }
_ => {
Err(std::io::Error::new(
ErrorKind::PermissionDenied,
call_policy: &mut Box<dyn CallPolicy>,
cut_policy: &mut Box<dyn CutPolicy>,
current_input_stream: &mut Stream,
+ current_output_stream: &mut Stream,
) -> CallResult {
match ct {
&SystemClauseType::AbolishClause => {
}
}
}
+ &SystemClauseType::CurrentOutput => {
+ let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let stream = current_output_stream.clone();
+
+ match addr {
+ addr if addr.is_ref() => {
+ self.unify(Addr::Stream(stream), addr);
+ }
+ Addr::Stream(other_stream) => {
+ self.fail = stream != other_stream;
+ }
+ addr => {
+ let stub = MachineError::functor_stub(
+ clause_name!("current_input"),
+ 1,
+ );
+
+ let err = MachineError::domain_error(
+ DomainError::Stream,
+ addr,
+ );
+
+ return Err(self.error_form(err, stub));
+ }
+ }
+ }
&SystemClauseType::AtEndOfExpansion => {
if self.cp == LocalCodePtr::TopLevel(0, 0) {
self.at_end_of_expansion = true;
&mut wam.policies,
&mut wam.code_repo,
&mut readline::input_stream(),
+ &mut Stream::stdout(),
);
if self.fail || self.at_end_of_expansion {
in_situ_code_dir: InSituCodeDir::new(),
in_situ_module_dir: ModuleStubDir::new(),
op_dir: $op_dir,
- modules: $modules,
+ modules: $modules,
+ stream_aliases: StreamAliasDir::new(),
}
};
}