add user_error stream (#917)

This commit is contained in:
Mark Thom
2021-04-30 21:58:03 -06:00
parent bba836dc31
commit d0b25de554
10 changed files with 228 additions and 223 deletions

View File

@@ -6,7 +6,11 @@ fn main() {
let handler = signal::SigHandler::Handler(handle_sigint); let handler = signal::SigHandler::Handler(handle_sigint);
unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap(); unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap();
let mut wam = machine::Machine::new(readline::input_stream(), machine::Stream::stdout()); let mut wam = machine::Machine::new(
readline::input_stream(),
machine::Stream::stdout(),
machine::Stream::stderr(),
);
wam.run_top_level(); wam.run_top_level();
} }

View File

@@ -1331,7 +1331,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.print_atom(alias); self.print_atom(alias);
} else { } else {
if self.format_struct(iter, max_depth, 1, clause_name!("$stream")) { if self.format_struct(iter, max_depth, 1, clause_name!("$stream")) {
let atom = if stream.is_stdout() || stream.is_stdin() { let atom = if stream.is_stdout() || stream.is_stdin() || stream.is_stderr() {
TokenOrRedirect::Atom(clause_name!("user")) TokenOrRedirect::Atom(clause_name!("user"))
} else { } else {
TokenOrRedirect::RawPtr(stream.as_ptr()) TokenOrRedirect::RawPtr(stream.as_ptr())

View File

@@ -14,13 +14,15 @@ fn capture_offset(line: &Line, index: usize, stack: &mut Vec<usize>) -> bool {
stack.push(index + offset); stack.push(index + offset);
} }
&Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(offset))) &Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(offset)))
if offset > 0 => { if offset > 0 =>
stack.push(index + offset); {
} stack.push(index + offset);
}
&Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(offset))) &Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(offset)))
if offset > 0 => { if offset > 0 =>
stack.push(index + offset); {
} stack.push(index + offset);
}
&Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => { &Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
stack.push(index + offset); stack.push(index + offset);
} }

View File

@@ -310,49 +310,55 @@ pub(crate) struct MachineState {
impl fmt::Debug for MachineState { impl fmt::Debug for MachineState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("MachineState") f.debug_struct("MachineState")
.field("atom_tbl", &self.atom_tbl) .field("atom_tbl", &self.atom_tbl)
.field("s", &self.s) .field("s", &self.s)
.field("p", &self.p) .field("p", &self.p)
.field("b", &self.b) .field("b", &self.b)
.field("b0", &self.b0) .field("b0", &self.b0)
.field("e", &self.e) .field("e", &self.e)
.field("num_of_args", &self.num_of_args) .field("num_of_args", &self.num_of_args)
.field("cp", &self.cp) .field("cp", &self.cp)
.field("attr_var_init", &self.attr_var_init) .field("attr_var_init", &self.attr_var_init)
.field("fail", &self.fail) .field("fail", &self.fail)
.field("heap", &self.heap) .field("heap", &self.heap)
.field("mode", &self.mode) .field("mode", &self.mode)
.field("stack", &self.stack) .field("stack", &self.stack)
.field("registers", &self.registers) .field("registers", &self.registers)
.field("trail", &self.trail) .field("trail", &self.trail)
.field("tr", &self.tr) .field("tr", &self.tr)
.field("hb", &self.hb) .field("hb", &self.hb)
.field("block", &self.block) .field("block", &self.block)
.field("ball", &self.ball) .field("ball", &self.ball)
.field("lifted_heap", &self.lifted_heap) .field("lifted_heap", &self.lifted_heap)
.field("interms", &self.interms) .field("interms", &self.interms)
.field("last_call", &self.last_call) .field("last_call", &self.last_call)
.field("flags", &self.flags) .field("flags", &self.flags)
.field("cc", &self.cc) .field("cc", &self.cc)
.field("global_clock", &self.global_clock) .field("global_clock", &self.global_clock)
.field("dynamic_mode", &self.dynamic_mode) .field("dynamic_mode", &self.dynamic_mode)
.field("unify_fn", .field(
"unify_fn",
if self.unify_fn as usize == MachineState::unify as usize { if self.unify_fn as usize == MachineState::unify as usize {
&"MachineState::unify" &"MachineState::unify"
} else if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize { } else if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize {
&"MachineState::unify_with_occurs_check" &"MachineState::unify_with_occurs_check"
} else { } else {
&"MachineState::unify_with_occurs_check_with_error" &"MachineState::unify_with_occurs_check_with_error"
}) },
.field("bind_fn", )
.field(
"bind_fn",
if self.bind_fn as usize == MachineState::bind as usize { if self.bind_fn as usize == MachineState::bind as usize {
&"MachineState::bind" &"MachineState::bind"
} else if self.bind_fn as usize == MachineState::bind_with_occurs_check_wrapper as usize { } else if self.bind_fn as usize
== MachineState::bind_with_occurs_check_wrapper as usize
{
&"MachineState::bind_with_occurs_check" &"MachineState::bind_with_occurs_check"
} else { } else {
&"MachineState::bind_with_occurs_check_with_error_wrapper" &"MachineState::bind_with_occurs_check_with_error_wrapper"
}) },
.finish() )
.finish()
} }
} }

View File

@@ -222,7 +222,7 @@ impl MachineState {
&mut self, &mut self,
a1: Addr, a1: Addr,
a2: Addr, a2: Addr,
mut occurs_trigger: impl FnMut() mut occurs_trigger: impl FnMut(),
) { ) {
let mut pdl = vec![a1, a2]; let mut pdl = vec![a1, a2];
let mut tabu_list: IndexSet<(Addr, Addr)> = IndexSet::new(); let mut tabu_list: IndexSet<(Addr, Addr)> = IndexSet::new();
@@ -1241,7 +1241,8 @@ impl MachineState {
let h = self.heap.h(); let h = self.heap.h();
self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1))); self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec())); self.heap
.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
self.bind(addr.as_var().unwrap(), Addr::HeapCell(h)); self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
@@ -1380,7 +1381,7 @@ impl MachineState {
_ => {} _ => {}
} }
match &code[p-1] { match &code[p - 1] {
&Line::Choice(ChoiceInstruction::DynamicInternalElse(birth, death, _)) => { &Line::Choice(ChoiceInstruction::DynamicInternalElse(birth, death, _)) => {
if birth < machine_st.cc && Death::Finite(machine_st.cc) <= death { if birth < machine_st.cc && Death::Finite(machine_st.cc) <= death {
return true; return true;
@@ -1411,9 +1412,7 @@ impl MachineState {
Addr::LoadStatePayload(_) | Addr::Stream(_) | Addr::TcpListener(_) => { Addr::LoadStatePayload(_) | Addr::Stream(_) | Addr::TcpListener(_) => {
IndexingCodePtr::Fail IndexingCodePtr::Fail
} }
Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => { Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => v,
v
}
Addr::PStrLocation(..) => l, Addr::PStrLocation(..) => l,
Addr::Char(_) Addr::Char(_)
| Addr::Con(_) | Addr::Con(_)
@@ -3203,15 +3202,11 @@ impl MachineState {
match code_repo.find_living_dynamic(p, self.cc) { match code_repo.find_living_dynamic(p, self.cc) {
Some((offset, oi, ii, is_next_clause)) => { Some((offset, oi, ii, is_next_clause)) => {
self.p = CodePtr::Local(LocalCodePtr::IndexingBuf( self.p = CodePtr::Local(LocalCodePtr::IndexingBuf(p.abs_loc(), oi, ii));
p.abs_loc(), oi, ii,
));
match self.dynamic_mode { match self.dynamic_mode {
FirstOrNext::First if !is_next_clause => { FirstOrNext::First if !is_next_clause => {
self.p = CodePtr::Local(LocalCodePtr::DirEntry( self.p = CodePtr::Local(LocalCodePtr::DirEntry(p.abs_loc() + offset));
p.abs_loc() + offset,
));
} }
FirstOrNext::First => { FirstOrNext::First => {
// there's a leading DynamicElse that sets self.cc. // there's a leading DynamicElse that sets self.cc.
@@ -3234,9 +3229,8 @@ impl MachineState {
self.num_of_args -= 1; self.num_of_args -= 1;
} }
None => { None => {
self.p = CodePtr::Local(LocalCodePtr::DirEntry( self.p =
p.abs_loc() + offset, CodePtr::Local(LocalCodePtr::DirEntry(p.abs_loc() + offset));
));
} }
} }
} }
@@ -3261,33 +3255,18 @@ impl MachineState {
Some(_) => { Some(_) => {
try_or_fail!( try_or_fail!(
self, self,
call_policy.retry( call_policy.retry(self, offset, global_variables,)
self,
offset,
global_variables,
)
) )
} }
None => { None => {
try_or_fail!( try_or_fail!(
self, self,
call_policy.trust( call_policy.trust(self, offset, global_variables,)
self,
offset,
global_variables,
)
) )
} }
} }
} else { } else {
try_or_fail!( try_or_fail!(self, call_policy.trust(self, offset, global_variables,))
self,
call_policy.trust(
self,
offset,
global_variables,
)
)
} }
} }
} }
@@ -3297,7 +3276,7 @@ impl MachineState {
None => { None => {
self.fail = true; self.fail = true;
} }
} }
} }
pub(super) fn execute_indexed_choice_instr( pub(super) fn execute_indexed_choice_instr(
@@ -3415,20 +3394,14 @@ impl MachineState {
None => { None => {
try_or_fail!( try_or_fail!(
self, self,
call_policy.trust_me( call_policy.trust_me(self, global_variables,)
self,
global_variables,
)
) )
} }
} }
} else { } else {
try_or_fail!( try_or_fail!(
self, self,
call_policy.trust_me( call_policy.trust_me(self, global_variables,)
self,
global_variables,
)
) )
} }
} }
@@ -3500,20 +3473,14 @@ impl MachineState {
None => { None => {
try_or_fail!( try_or_fail!(
self, self,
call_policy.trust_me( call_policy.trust_me(self, global_variables,)
self,
global_variables,
)
) )
} }
} }
} else { } else {
try_or_fail!( try_or_fail!(
self, self,
call_policy.trust_me( call_policy.trust_me(self, global_variables,)
self,
global_variables,
)
) )
} }
} }

View File

@@ -115,6 +115,7 @@ pub struct Machine {
pub(super) code_repo: CodeRepo, pub(super) code_repo: CodeRepo,
pub(super) user_input: Stream, pub(super) user_input: Stream,
pub(super) user_output: Stream, pub(super) user_output: Stream,
pub(super) user_error: Stream,
pub(super) load_contexts: Vec<LoadContext>, pub(super) load_contexts: Vec<LoadContext>,
} }
@@ -274,7 +275,7 @@ impl Machine {
} }
} }
pub fn new(user_input: Stream, user_output: Stream) -> Self { pub fn new(user_input: Stream, user_output: Stream, user_error: Stream) -> Self {
use ref_thread_local::RefThreadLocal; use ref_thread_local::RefThreadLocal;
let mut wam = Machine { let mut wam = Machine {
@@ -285,6 +286,7 @@ impl Machine {
code_repo: CodeRepo::new(), code_repo: CodeRepo::new(),
user_input, user_input,
user_output, user_output,
user_error,
load_contexts: vec![], load_contexts: vec![],
}; };
@@ -367,6 +369,12 @@ impl Machine {
.stream_aliases .stream_aliases
.insert(clause_name!("user_output"), self.user_output.clone()); .insert(clause_name!("user_output"), self.user_output.clone());
self.user_error.options_mut().alias = Some(clause_name!("user_error"));
self.indices
.stream_aliases
.insert(clause_name!("user_error"), self.user_error.clone());
self.indices.streams.insert(self.user_output.clone()); self.indices.streams.insert(self.user_output.clone());
} }
@@ -528,14 +536,12 @@ impl MachineState {
) { ) {
match instr { match instr {
&Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr), &Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr),
&Line::Choice(ref choice_instr) => { &Line::Choice(ref choice_instr) => self.execute_choice_instr(
self.execute_choice_instr( choice_instr,
choice_instr, code_repo,
code_repo, &mut policies.call_policy,
&mut policies.call_policy, &mut indices.global_variables,
&mut indices.global_variables, ),
)
}
&Line::Cut(ref cut_instr) => { &Line::Cut(ref cut_instr) => {
self.execute_cut_instr(cut_instr, &mut policies.cut_policy) self.execute_cut_instr(cut_instr, &mut policies.cut_policy)
} }
@@ -553,25 +559,18 @@ impl MachineState {
self.p += 1; self.p += 1;
} }
&Line::IndexingCode(ref indexing_lines) => { &Line::IndexingCode(ref indexing_lines) => {
self.execute_indexing_instr( self.execute_indexing_instr(indexing_lines, code_repo)
indexing_lines,
code_repo,
)
}
&Line::IndexedChoice(ref choice_instr) => {
self.execute_indexed_choice_instr(
choice_instr,
&mut policies.call_policy,
&mut indices.global_variables,
)
}
&Line::DynamicIndexedChoice(_) => {
self.execute_dynamic_indexed_choice_instr(
code_repo,
&mut policies.call_policy,
&mut indices.global_variables,
)
} }
&Line::IndexedChoice(ref choice_instr) => self.execute_indexed_choice_instr(
choice_instr,
&mut policies.call_policy,
&mut indices.global_variables,
),
&Line::DynamicIndexedChoice(_) => self.execute_dynamic_indexed_choice_instr(
code_repo,
&mut policies.call_policy,
&mut indices.global_variables,
),
&Line::Query(ref query_instr) => { &Line::Query(ref query_instr) => {
self.execute_query_instr(&query_instr); self.execute_query_instr(&query_instr);
self.p += 1; self.p += 1;

View File

@@ -409,13 +409,11 @@ pub(super) fn compare_pstr_prefixes<'a>(
let machine_st = i1.machine_st; let machine_st = i1.machine_st;
let check_focuses = || { let check_focuses = || match (i1.focus(), i2.focus()) {
match (i1.focus(), i2.focus()) { (Addr::EmptyList, Addr::EmptyList) => Some(Ordering::Equal),
(Addr::EmptyList, Addr::EmptyList) => Some(Ordering::Equal), (Addr::EmptyList, _) => Some(Ordering::Less),
(Addr::EmptyList, _) => Some(Ordering::Less), (_, Addr::EmptyList) => Some(Ordering::Greater),
(_, Addr::EmptyList) => Some(Ordering::Greater), _ => None,
_ => None,
}
}; };
return match r1 { return match r1 {
@@ -430,12 +428,8 @@ pub(super) fn compare_pstr_prefixes<'a>(
unreachable!() unreachable!()
} }
} }
Some(PStrIteratee::Char(_)) => { Some(PStrIteratee::Char(_)) => Some(ordering),
Some(ordering) None => check_focuses(),
}
None => {
check_focuses()
}
}; };
} }
} }

View File

@@ -23,12 +23,13 @@ pub(crate) struct RawBlock<T: RawBlockTraits> {
} }
impl<T: RawBlockTraits> RawBlock<T> { impl<T: RawBlockTraits> RawBlock<T> {
pub(crate) pub(crate) fn new() -> Self {
fn new() -> Self { let mut block = RawBlock {
let mut block = RawBlock { size: 0, size: 0,
base: ptr::null(), base: ptr::null(),
top: ptr::null(), top: ptr::null(),
_marker: PhantomData }; _marker: PhantomData,
};
unsafe { unsafe {
block.grow(); block.grow();
@@ -46,45 +47,47 @@ impl<T: RawBlockTraits> RawBlock<T> {
self.top = T::base_offset(self.base); self.top = T::base_offset(self.base);
} }
pub(super) pub(super) unsafe fn grow(&mut self) {
unsafe fn grow(&mut self) {
if self.size == 0 { if self.size == 0 {
self.init_at_size(T::init_size()); self.init_at_size(T::init_size());
} else { } else {
let layout = alloc::Layout::from_size_align_unchecked(T::init_size(), T::align()); let layout = alloc::Layout::from_size_align_unchecked(T::init_size(), T::align());
let top_dist = self.top as usize - self.base as usize; let top_dist = self.top as usize - self.base as usize;
self.base = alloc::realloc(self.base as *mut _, layout, self.size*2) as *const _; self.base = alloc::realloc(self.base as *mut _, layout, self.size * 2) as *const _;
self.top = (self.base as usize + top_dist) as *const _; self.top = (self.base as usize + top_dist) as *const _;
self.size *= 2; self.size *= 2;
} }
} }
fn empty_block() -> Self { fn empty_block() -> Self {
RawBlock { size: 0, RawBlock {
base: ptr::null(), size: 0,
top: ptr::null(), base: ptr::null(),
_marker: PhantomData } top: ptr::null(),
_marker: PhantomData,
}
} }
#[inline] #[inline]
pub(crate) pub(crate) fn take(&mut self) -> Self {
fn take(&mut self) -> Self {
mem::replace(self, Self::empty_block()) mem::replace(self, Self::empty_block())
} }
#[inline] #[inline]
fn free_space(&self) -> usize { fn free_space(&self) -> usize {
debug_assert!(self.top >= self.base, debug_assert!(
"self.top = {:?} < {:?} = self.base", self.top >= self.base,
self.top, self.base); "self.top = {:?} < {:?} = self.base",
self.top,
self.base
);
self.size - (self.top as usize - self.base as usize) self.size - (self.top as usize - self.base as usize)
} }
#[inline] #[inline]
pub(crate) pub(crate) unsafe fn new_block(&mut self, size: usize) -> *const u8 {
unsafe fn new_block(&mut self, size: usize) -> *const u8 {
loop { loop {
if self.free_space() >= size { if self.free_space() >= size {
return (self.top as usize + size) as *const _; return (self.top as usize + size) as *const _;
@@ -94,14 +97,13 @@ impl<T: RawBlockTraits> RawBlock<T> {
} }
} }
pub(crate) pub(crate) fn deallocate(&mut self) {
fn deallocate(&mut self) {
unsafe { unsafe {
let layout = alloc::Layout::from_size_align_unchecked(self.size, T::align()); let layout = alloc::Layout::from_size_align_unchecked(self.size, T::align());
alloc::dealloc(self.base as *mut u8, layout); alloc::dealloc(self.base as *mut u8, layout);
self.top = ptr::null(); self.top = ptr::null();
self.base = ptr::null(); self.base = ptr::null();
self.size = 0; self.size = 0;
} }

View File

@@ -14,7 +14,7 @@ use std::fmt;
use std::fs::File; use std::fs::File;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::io; use std::io;
use std::io::{stdout, Cursor, ErrorKind, Read, Seek, SeekFrom, Write}; use std::io::{stderr, stdout, Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
use std::mem; use std::mem;
use std::net::{Shutdown, TcpStream}; use std::net::{Shutdown, TcpStream};
use std::ops::DerefMut; use std::ops::DerefMut;
@@ -114,6 +114,7 @@ enum StreamInstance {
PausedPrologStream(Vec<u8>, Box<StreamInstance>), PausedPrologStream(Vec<u8>, Box<StreamInstance>),
ReadlineStream(ReadlineStream), ReadlineStream(ReadlineStream),
StaticStr(Cursor<&'static str>), StaticStr(Cursor<&'static str>),
Stderr,
Stdout, Stdout,
TcpStream(ClauseName, TcpStream), TcpStream(ClauseName, TcpStream),
TlsStream(ClauseName, TlsStream<TcpStream>), TlsStream(ClauseName, TlsStream<TcpStream>),
@@ -148,12 +149,13 @@ impl StreamInstance {
StreamInstance::ReadlineStream(ref mut rl_stream) => rl_stream.read(buf), StreamInstance::ReadlineStream(ref mut rl_stream) => rl_stream.read(buf),
StreamInstance::StaticStr(ref mut src) => src.read(buf), StreamInstance::StaticStr(ref mut src) => src.read(buf),
StreamInstance::Bytes(ref mut cursor) => cursor.read(buf), StreamInstance::Bytes(ref mut cursor) => cursor.read(buf),
StreamInstance::OutputFile(..) | StreamInstance::Stdout | StreamInstance::Null => { StreamInstance::OutputFile(..)
Err(std::io::Error::new( | StreamInstance::Stderr
ErrorKind::PermissionDenied, | StreamInstance::Stdout
StreamError::ReadFromOutputStream, | StreamInstance::Null => Err(std::io::Error::new(
)) ErrorKind::PermissionDenied,
} StreamError::ReadFromOutputStream,
)),
} }
} }
} }
@@ -186,6 +188,7 @@ impl fmt::Debug for StreamInstance {
&StreamInstance::ReadlineStream(ref readline_stream) => { &StreamInstance::ReadlineStream(ref readline_stream) => {
write!(fmt, "ReadlineStream({:?})", readline_stream) write!(fmt, "ReadlineStream({:?})", readline_stream)
} }
&StreamInstance::Stderr => write!(fmt, "Stderr"),
&StreamInstance::Stdout => write!(fmt, "Stdout"), &StreamInstance::Stdout => write!(fmt, "Stdout"),
&StreamInstance::TcpStream(_, ref tcp_stream) => { &StreamInstance::TcpStream(_, ref tcp_stream) => {
write!(fmt, "TcpStream({:?})", tcp_stream) write!(fmt, "TcpStream({:?})", tcp_stream)
@@ -521,7 +524,9 @@ impl Stream {
| StreamInstance::InputFile(..) => "read", | StreamInstance::InputFile(..) => "read",
StreamInstance::TcpStream(..) | StreamInstance::TlsStream(..) => "read_append", StreamInstance::TcpStream(..) | StreamInstance::TlsStream(..) => "read_append",
StreamInstance::OutputFile(_, _, true) => "append", StreamInstance::OutputFile(_, _, true) => "append",
StreamInstance::Stdout | StreamInstance::OutputFile(_, _, false) => "write", StreamInstance::Stderr
| StreamInstance::Stdout
| StreamInstance::OutputFile(_, _, false) => "write",
StreamInstance::Null => "", StreamInstance::Null => "",
} }
} }
@@ -538,6 +543,11 @@ impl Stream {
Stream::from_inst(StreamInstance::Stdout) Stream::from_inst(StreamInstance::Stdout)
} }
#[inline]
pub fn stderr() -> Self {
Stream::from_inst(StreamInstance::Stderr)
}
#[inline] #[inline]
pub(crate) fn from_tcp_stream(address: ClauseName, tcp_stream: TcpStream) -> Self { pub(crate) fn from_tcp_stream(address: ClauseName, tcp_stream: TcpStream) -> Self {
tcp_stream.set_read_timeout(None).unwrap(); tcp_stream.set_read_timeout(None).unwrap();
@@ -561,6 +571,14 @@ impl Stream {
Stream::from_inst(StreamInstance::InputFile(name, file)) Stream::from_inst(StreamInstance::InputFile(name, file))
} }
#[inline]
pub(crate) fn is_stderr(&self) -> bool {
match self.stream_inst.0.borrow().stream_inst {
StreamInstance::Stderr => true,
_ => false,
}
}
#[inline] #[inline]
pub(crate) fn is_stdout(&self) -> bool { pub(crate) fn is_stdout(&self) -> bool {
match self.stream_inst.0.borrow().stream_inst { match self.stream_inst.0.borrow().stream_inst {
@@ -608,7 +626,8 @@ impl Stream {
#[inline] #[inline]
pub(crate) fn is_output_stream(&self) -> bool { pub(crate) fn is_output_stream(&self) -> bool {
match self.stream_inst.0.borrow().stream_inst { match self.stream_inst.0.borrow().stream_inst {
StreamInstance::Stdout StreamInstance::Stderr
| StreamInstance::Stdout
| StreamInstance::TcpStream(..) | StreamInstance::TcpStream(..)
| StreamInstance::TlsStream(..) | StreamInstance::TlsStream(..)
| StreamInstance::Bytes(_) | StreamInstance::Bytes(_)
@@ -1110,6 +1129,7 @@ impl Write for Stream {
StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.write(buf), StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.write(buf),
StreamInstance::Bytes(ref mut cursor) => cursor.write(buf), StreamInstance::Bytes(ref mut cursor) => cursor.write(buf),
StreamInstance::Stdout => stdout().write(buf), StreamInstance::Stdout => stdout().write(buf),
StreamInstance::Stderr => stderr().write(buf),
StreamInstance::PausedPrologStream(..) StreamInstance::PausedPrologStream(..)
| StreamInstance::StaticStr(_) | StreamInstance::StaticStr(_)
| StreamInstance::ReadlineStream(_) | StreamInstance::ReadlineStream(_)
@@ -1127,6 +1147,7 @@ impl Write for Stream {
StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.flush(), StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.flush(),
StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.flush(), StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.flush(),
StreamInstance::Bytes(ref mut cursor) => cursor.flush(), StreamInstance::Bytes(ref mut cursor) => cursor.flush(),
StreamInstance::Stderr => stderr().flush(),
StreamInstance::Stdout => stdout().flush(), StreamInstance::Stdout => stdout().flush(),
StreamInstance::PausedPrologStream(..) StreamInstance::PausedPrologStream(..)
| StreamInstance::StaticStr(_) | StreamInstance::StaticStr(_)

View File

@@ -1852,26 +1852,24 @@ impl MachineState {
let addr = self[temp_v!(2)]; let addr = self[temp_v!(2)];
match indices.global_variables.get_mut(&key) { match indices.global_variables.get_mut(&key) {
Some((ref ball, ref mut loc)) => { Some((ref ball, ref mut loc)) => match loc {
match loc { Some(ref value_addr) => {
Some(ref value_addr) => { (self.unify_fn)(self, addr, *value_addr);
(self.unify_fn)(self, addr, *value_addr);
}
loc @ None if !ball.stub.is_empty() => {
let h = self.heap.h();
let stub = ball.copy_and_align(h);
self.heap.extend(stub.into_iter());
(self.unify_fn)(self, addr, Addr::HeapCell(h));
if !self.fail {
*loc = Some(Addr::HeapCell(h));
self.trail(TrailRef::BlackboardEntry(key_h));
}
}
_ => self.fail = true,
} }
} loc @ None if !ball.stub.is_empty() => {
let h = self.heap.h();
let stub = ball.copy_and_align(h);
self.heap.extend(stub.into_iter());
(self.unify_fn)(self, addr, Addr::HeapCell(h));
if !self.fail {
*loc = Some(Addr::HeapCell(h));
self.trail(TrailRef::BlackboardEntry(key_h));
}
}
_ => self.fail = true,
},
None => self.fail = true, None => self.fail = true,
}; };
} }
@@ -2617,7 +2615,7 @@ impl MachineState {
indices.streams.insert(current_output_stream.clone()); indices.streams.insert(current_output_stream.clone());
} }
if !stream.is_stdin() && !stream.is_stdout() { if !stream.is_stdin() && !stream.is_stdout() && !stream.is_stderr() {
stream.close(); stream.close();
if let Some(ref alias) = stream.options().alias { if let Some(ref alias) = stream.options().alias {
@@ -3472,17 +3470,22 @@ impl MachineState {
self.fail = match self.store(self.deref(self[temp_v!(2)])) { self.fail = match self.store(self.deref(self[temp_v!(2)])) {
Addr::Str(s) => match &self.heap[s] { Addr::Str(s) => match &self.heap[s] {
&HeapCellValue::NamedStr(arity, ref name, ref spec) => { &HeapCellValue::NamedStr(arity, ref name, ref spec) => {
if CLAUSE_TYPE_FORMS.borrow().get(&(name.as_str(), arity)).is_some() { if CLAUSE_TYPE_FORMS
.borrow()
.get(&(name.as_str(), arity))
.is_some()
{
true true
} else { } else {
let index = indices.get_predicate_code_index( let index = indices
name.clone(), .get_predicate_code_index(
arity, name.clone(),
module_name, arity,
spec.clone(), module_name,
) spec.clone(),
.map(|index| index.get()) )
.unwrap_or(IndexPtr::DynamicUndefined); .map(|index| index.get())
.unwrap_or(IndexPtr::DynamicUndefined);
match index { match index {
IndexPtr::DynamicUndefined => false, IndexPtr::DynamicUndefined => false,
@@ -3499,17 +3502,22 @@ impl MachineState {
let spec = let spec =
fetch_atom_op_spec(name.clone(), spec.clone(), &indices.op_dir); fetch_atom_op_spec(name.clone(), spec.clone(), &indices.op_dir);
if CLAUSE_TYPE_FORMS.borrow().get(&(name.as_str(), 0)).is_some() { if CLAUSE_TYPE_FORMS
.borrow()
.get(&(name.as_str(), 0))
.is_some()
{
true true
} else { } else {
let index = indices.get_predicate_code_index( let index = indices
name.clone(), .get_predicate_code_index(
0, name.clone(),
module_name, 0,
spec.clone(), module_name,
) spec.clone(),
.map(|index| index.get()) )
.unwrap_or(IndexPtr::DynamicUndefined); .map(|index| index.get())
.unwrap_or(IndexPtr::DynamicUndefined);
match index { match index {
IndexPtr::DynamicUndefined => false, IndexPtr::DynamicUndefined => false,
@@ -4482,22 +4490,22 @@ impl MachineState {
let new_value = self.store(self.deref(self[temp_v!(2)])); let new_value = self.store(self.deref(self[temp_v!(2)]));
match indices.global_variables.get_mut(&key) { match indices.global_variables.get_mut(&key) {
Some((_, ref mut loc)) => { Some((_, ref mut loc)) => match loc {
match loc { Some(ref mut value) => {
Some(ref mut value) => { let old_value_loc = self.heap.push(HeapCellValue::Addr(*value));
let old_value_loc = self.heap.push(HeapCellValue::Addr(*value)); self.trail(TrailRef::BlackboardOffset(key_h, old_value_loc));
self.trail(TrailRef::BlackboardOffset(key_h, old_value_loc)); *value = new_value;
*value = new_value;
}
loc @ None => {
self.trail(TrailRef::BlackboardEntry(key_h));
*loc = Some(new_value);
}
} }
} loc @ None => {
self.trail(TrailRef::BlackboardEntry(key_h));
*loc = Some(new_value);
}
},
None => { None => {
self.trail(TrailRef::BlackboardEntry(key_h)); self.trail(TrailRef::BlackboardEntry(key_h));
indices.global_variables.insert(key, (Ball::new(), Some(new_value))); indices
.global_variables
.insert(key, (Ball::new(), Some(new_value)));
} }
} }
} }
@@ -5361,21 +5369,23 @@ impl MachineState {
} }
&SystemClauseType::IsSTOEnabled => { &SystemClauseType::IsSTOEnabled => {
if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize { if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize {
let value = self.heap.to_unifiable( let value = self
HeapCellValue::Atom(clause_name!("true"), None), .heap
); .to_unifiable(HeapCellValue::Atom(clause_name!("true"), None));
(self.unify_fn)(self, self[temp_v!(1)], value); (self.unify_fn)(self, self[temp_v!(1)], value);
} else if self.unify_fn as usize == MachineState::unify_with_occurs_check_with_error as usize { } else if self.unify_fn as usize
let value = self.heap.to_unifiable( == MachineState::unify_with_occurs_check_with_error as usize
HeapCellValue::Atom(clause_name!("error"), None), {
); let value = self
.heap
.to_unifiable(HeapCellValue::Atom(clause_name!("error"), None));
(self.unify_fn)(self, self[temp_v!(1)], value); (self.unify_fn)(self, self[temp_v!(1)], value);
} else { } else {
let value = self.heap.to_unifiable( let value = self
HeapCellValue::Atom(clause_name!("false"), None), .heap
); .to_unifiable(HeapCellValue::Atom(clause_name!("false"), None));
(self.unify_fn)(self, self[temp_v!(1)], value); (self.unify_fn)(self, self[temp_v!(1)], value);
} }