let handler = signal::SigHandler::Handler(handle_sigint);
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();
}
self.print_atom(alias);
} else {
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"))
} else {
TokenOrRedirect::RawPtr(stream.as_ptr())
stack.push(index + offset);
}
&Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(offset)))
- if offset > 0 => {
- stack.push(index + offset);
- }
+ if offset > 0 =>
+ {
+ stack.push(index + offset);
+ }
&Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(offset)))
- if offset > 0 => {
- stack.push(index + offset);
- }
+ if offset > 0 =>
+ {
+ stack.push(index + offset);
+ }
&Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
stack.push(index + offset);
}
impl fmt::Debug for MachineState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("MachineState")
- .field("atom_tbl", &self.atom_tbl)
- .field("s", &self.s)
- .field("p", &self.p)
- .field("b", &self.b)
- .field("b0", &self.b0)
- .field("e", &self.e)
- .field("num_of_args", &self.num_of_args)
- .field("cp", &self.cp)
- .field("attr_var_init", &self.attr_var_init)
- .field("fail", &self.fail)
- .field("heap", &self.heap)
- .field("mode", &self.mode)
- .field("stack", &self.stack)
- .field("registers", &self.registers)
- .field("trail", &self.trail)
- .field("tr", &self.tr)
- .field("hb", &self.hb)
- .field("block", &self.block)
- .field("ball", &self.ball)
- .field("lifted_heap", &self.lifted_heap)
- .field("interms", &self.interms)
- .field("last_call", &self.last_call)
- .field("flags", &self.flags)
- .field("cc", &self.cc)
- .field("global_clock", &self.global_clock)
- .field("dynamic_mode", &self.dynamic_mode)
- .field("unify_fn",
+ .field("atom_tbl", &self.atom_tbl)
+ .field("s", &self.s)
+ .field("p", &self.p)
+ .field("b", &self.b)
+ .field("b0", &self.b0)
+ .field("e", &self.e)
+ .field("num_of_args", &self.num_of_args)
+ .field("cp", &self.cp)
+ .field("attr_var_init", &self.attr_var_init)
+ .field("fail", &self.fail)
+ .field("heap", &self.heap)
+ .field("mode", &self.mode)
+ .field("stack", &self.stack)
+ .field("registers", &self.registers)
+ .field("trail", &self.trail)
+ .field("tr", &self.tr)
+ .field("hb", &self.hb)
+ .field("block", &self.block)
+ .field("ball", &self.ball)
+ .field("lifted_heap", &self.lifted_heap)
+ .field("interms", &self.interms)
+ .field("last_call", &self.last_call)
+ .field("flags", &self.flags)
+ .field("cc", &self.cc)
+ .field("global_clock", &self.global_clock)
+ .field("dynamic_mode", &self.dynamic_mode)
+ .field(
+ "unify_fn",
if self.unify_fn as usize == MachineState::unify as usize {
&"MachineState::unify"
} else if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize {
&"MachineState::unify_with_occurs_check"
} else {
&"MachineState::unify_with_occurs_check_with_error"
- })
- .field("bind_fn",
+ },
+ )
+ .field(
+ "bind_fn",
if self.bind_fn as usize == MachineState::bind as usize {
&"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"
} else {
&"MachineState::bind_with_occurs_check_with_error_wrapper"
- })
- .finish()
+ },
+ )
+ .finish()
}
}
&mut self,
a1: Addr,
a2: Addr,
- mut occurs_trigger: impl FnMut()
+ mut occurs_trigger: impl FnMut(),
) {
let mut pdl = vec![a1, a2];
let mut tabu_list: IndexSet<(Addr, Addr)> = IndexSet::new();
let h = self.heap.h();
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));
_ => {}
}
- match &code[p-1] {
+ match &code[p - 1] {
&Line::Choice(ChoiceInstruction::DynamicInternalElse(birth, death, _)) => {
if birth < machine_st.cc && Death::Finite(machine_st.cc) <= death {
return true;
Addr::LoadStatePayload(_) | Addr::Stream(_) | Addr::TcpListener(_) => {
IndexingCodePtr::Fail
}
- Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => {
- v
- }
+ Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => v,
Addr::PStrLocation(..) => l,
Addr::Char(_)
| Addr::Con(_)
match code_repo.find_living_dynamic(p, self.cc) {
Some((offset, oi, ii, is_next_clause)) => {
- self.p = CodePtr::Local(LocalCodePtr::IndexingBuf(
- p.abs_loc(), oi, ii,
- ));
+ self.p = CodePtr::Local(LocalCodePtr::IndexingBuf(p.abs_loc(), oi, ii));
match self.dynamic_mode {
FirstOrNext::First if !is_next_clause => {
- self.p = CodePtr::Local(LocalCodePtr::DirEntry(
- p.abs_loc() + offset,
- ));
+ self.p = CodePtr::Local(LocalCodePtr::DirEntry(p.abs_loc() + offset));
}
FirstOrNext::First => {
// there's a leading DynamicElse that sets self.cc.
self.num_of_args -= 1;
}
None => {
- self.p = CodePtr::Local(LocalCodePtr::DirEntry(
- p.abs_loc() + offset,
- ));
+ self.p =
+ CodePtr::Local(LocalCodePtr::DirEntry(p.abs_loc() + offset));
}
}
}
Some(_) => {
try_or_fail!(
self,
- call_policy.retry(
- self,
- offset,
- global_variables,
- )
+ call_policy.retry(self, offset, global_variables,)
)
}
None => {
try_or_fail!(
self,
- call_policy.trust(
- self,
- offset,
- global_variables,
- )
+ call_policy.trust(self, offset, global_variables,)
)
}
}
} else {
- try_or_fail!(
- self,
- call_policy.trust(
- self,
- offset,
- global_variables,
- )
- )
+ try_or_fail!(self, call_policy.trust(self, offset, global_variables,))
}
}
}
None => {
self.fail = true;
}
- }
+ }
}
pub(super) fn execute_indexed_choice_instr(
None => {
try_or_fail!(
self,
- call_policy.trust_me(
- self,
- global_variables,
- )
+ call_policy.trust_me(self, global_variables,)
)
}
}
} else {
try_or_fail!(
self,
- call_policy.trust_me(
- self,
- global_variables,
- )
+ call_policy.trust_me(self, global_variables,)
)
}
}
None => {
try_or_fail!(
self,
- call_policy.trust_me(
- self,
- global_variables,
- )
+ call_policy.trust_me(self, global_variables,)
)
}
}
} else {
try_or_fail!(
self,
- call_policy.trust_me(
- self,
- global_variables,
- )
+ call_policy.trust_me(self, global_variables,)
)
}
}
pub(super) code_repo: CodeRepo,
pub(super) user_input: Stream,
pub(super) user_output: Stream,
+ pub(super) user_error: Stream,
pub(super) load_contexts: Vec<LoadContext>,
}
}
}
- 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;
let mut wam = Machine {
code_repo: CodeRepo::new(),
user_input,
user_output,
+ user_error,
load_contexts: vec![],
};
.stream_aliases
.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());
}
) {
match instr {
&Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr),
- &Line::Choice(ref choice_instr) => {
- self.execute_choice_instr(
- choice_instr,
- code_repo,
- &mut policies.call_policy,
- &mut indices.global_variables,
- )
- }
+ &Line::Choice(ref choice_instr) => self.execute_choice_instr(
+ choice_instr,
+ code_repo,
+ &mut policies.call_policy,
+ &mut indices.global_variables,
+ ),
&Line::Cut(ref cut_instr) => {
self.execute_cut_instr(cut_instr, &mut policies.cut_policy)
}
self.p += 1;
}
&Line::IndexingCode(ref indexing_lines) => {
- self.execute_indexing_instr(
- 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,
- )
+ self.execute_indexing_instr(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::Query(ref query_instr) => {
self.execute_query_instr(&query_instr);
self.p += 1;
let machine_st = i1.machine_st;
- let check_focuses = || {
- match (i1.focus(), i2.focus()) {
- (Addr::EmptyList, Addr::EmptyList) => Some(Ordering::Equal),
- (Addr::EmptyList, _) => Some(Ordering::Less),
- (_, Addr::EmptyList) => Some(Ordering::Greater),
- _ => None,
- }
+ let check_focuses = || match (i1.focus(), i2.focus()) {
+ (Addr::EmptyList, Addr::EmptyList) => Some(Ordering::Equal),
+ (Addr::EmptyList, _) => Some(Ordering::Less),
+ (_, Addr::EmptyList) => Some(Ordering::Greater),
+ _ => None,
};
return match r1 {
unreachable!()
}
}
- Some(PStrIteratee::Char(_)) => {
- Some(ordering)
- }
- None => {
- check_focuses()
- }
+ Some(PStrIteratee::Char(_)) => Some(ordering),
+ None => check_focuses(),
};
}
}
}
impl<T: RawBlockTraits> RawBlock<T> {
- pub(crate)
- fn new() -> Self {
- let mut block = RawBlock { size: 0,
- base: ptr::null(),
- top: ptr::null(),
- _marker: PhantomData };
+ pub(crate) fn new() -> Self {
+ let mut block = RawBlock {
+ size: 0,
+ base: ptr::null(),
+ top: ptr::null(),
+ _marker: PhantomData,
+ };
unsafe {
block.grow();
self.top = T::base_offset(self.base);
}
- pub(super)
- unsafe fn grow(&mut self) {
+ pub(super) unsafe fn grow(&mut self) {
if self.size == 0 {
self.init_at_size(T::init_size());
} else {
let layout = alloc::Layout::from_size_align_unchecked(T::init_size(), T::align());
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.size *= 2;
}
}
fn empty_block() -> Self {
- RawBlock { size: 0,
- base: ptr::null(),
- top: ptr::null(),
- _marker: PhantomData }
+ RawBlock {
+ size: 0,
+ base: ptr::null(),
+ top: ptr::null(),
+ _marker: PhantomData,
+ }
}
#[inline]
- pub(crate)
- fn take(&mut self) -> Self {
+ pub(crate) fn take(&mut self) -> Self {
mem::replace(self, Self::empty_block())
}
#[inline]
fn free_space(&self) -> usize {
- debug_assert!(self.top >= self.base,
- "self.top = {:?} < {:?} = self.base",
- self.top, self.base);
+ debug_assert!(
+ self.top >= self.base,
+ "self.top = {:?} < {:?} = self.base",
+ self.top,
+ self.base
+ );
self.size - (self.top as usize - self.base as usize)
}
#[inline]
- pub(crate)
- unsafe fn new_block(&mut self, size: usize) -> *const u8 {
+ pub(crate) unsafe fn new_block(&mut self, size: usize) -> *const u8 {
loop {
if self.free_space() >= size {
return (self.top as usize + size) as *const _;
}
}
- pub(crate)
- fn deallocate(&mut self) {
+ pub(crate) fn deallocate(&mut self) {
unsafe {
let layout = alloc::Layout::from_size_align_unchecked(self.size, T::align());
alloc::dealloc(self.base as *mut u8, layout);
- self.top = ptr::null();
+ self.top = ptr::null();
self.base = ptr::null();
self.size = 0;
}
use std::fs::File;
use std::hash::{Hash, Hasher};
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::net::{Shutdown, TcpStream};
use std::ops::DerefMut;
PausedPrologStream(Vec<u8>, Box<StreamInstance>),
ReadlineStream(ReadlineStream),
StaticStr(Cursor<&'static str>),
+ Stderr,
Stdout,
TcpStream(ClauseName, TcpStream),
TlsStream(ClauseName, TlsStream<TcpStream>),
StreamInstance::ReadlineStream(ref mut rl_stream) => rl_stream.read(buf),
StreamInstance::StaticStr(ref mut src) => src.read(buf),
StreamInstance::Bytes(ref mut cursor) => cursor.read(buf),
- StreamInstance::OutputFile(..) | StreamInstance::Stdout | StreamInstance::Null => {
- Err(std::io::Error::new(
- ErrorKind::PermissionDenied,
- StreamError::ReadFromOutputStream,
- ))
- }
+ StreamInstance::OutputFile(..)
+ | StreamInstance::Stderr
+ | StreamInstance::Stdout
+ | StreamInstance::Null => Err(std::io::Error::new(
+ ErrorKind::PermissionDenied,
+ StreamError::ReadFromOutputStream,
+ )),
}
}
}
&StreamInstance::ReadlineStream(ref readline_stream) => {
write!(fmt, "ReadlineStream({:?})", readline_stream)
}
+ &StreamInstance::Stderr => write!(fmt, "Stderr"),
&StreamInstance::Stdout => write!(fmt, "Stdout"),
&StreamInstance::TcpStream(_, ref tcp_stream) => {
write!(fmt, "TcpStream({:?})", tcp_stream)
| StreamInstance::InputFile(..) => "read",
StreamInstance::TcpStream(..) | StreamInstance::TlsStream(..) => "read_append",
StreamInstance::OutputFile(_, _, true) => "append",
- StreamInstance::Stdout | StreamInstance::OutputFile(_, _, false) => "write",
+ StreamInstance::Stderr
+ | StreamInstance::Stdout
+ | StreamInstance::OutputFile(_, _, false) => "write",
StreamInstance::Null => "",
}
}
Stream::from_inst(StreamInstance::Stdout)
}
+ #[inline]
+ pub fn stderr() -> Self {
+ Stream::from_inst(StreamInstance::Stderr)
+ }
+
#[inline]
pub(crate) fn from_tcp_stream(address: ClauseName, tcp_stream: TcpStream) -> Self {
tcp_stream.set_read_timeout(None).unwrap();
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]
pub(crate) fn is_stdout(&self) -> bool {
match self.stream_inst.0.borrow().stream_inst {
#[inline]
pub(crate) fn is_output_stream(&self) -> bool {
match self.stream_inst.0.borrow().stream_inst {
- StreamInstance::Stdout
+ StreamInstance::Stderr
+ | StreamInstance::Stdout
| StreamInstance::TcpStream(..)
| StreamInstance::TlsStream(..)
| StreamInstance::Bytes(_)
StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.write(buf),
StreamInstance::Bytes(ref mut cursor) => cursor.write(buf),
StreamInstance::Stdout => stdout().write(buf),
+ StreamInstance::Stderr => stderr().write(buf),
StreamInstance::PausedPrologStream(..)
| StreamInstance::StaticStr(_)
| StreamInstance::ReadlineStream(_)
StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.flush(),
StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.flush(),
StreamInstance::Bytes(ref mut cursor) => cursor.flush(),
+ StreamInstance::Stderr => stderr().flush(),
StreamInstance::Stdout => stdout().flush(),
StreamInstance::PausedPrologStream(..)
| StreamInstance::StaticStr(_)
let addr = self[temp_v!(2)];
match indices.global_variables.get_mut(&key) {
- Some((ref ball, ref mut loc)) => {
- match loc {
- Some(ref 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);
+ Some((ref ball, ref mut loc)) => match loc {
+ Some(ref 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));
+ 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));
- }
+ if !self.fail {
+ *loc = Some(Addr::HeapCell(h));
+ self.trail(TrailRef::BlackboardEntry(key_h));
}
- _ => self.fail = true,
}
- }
+ _ => self.fail = true,
+ },
None => self.fail = true,
};
}
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();
if let Some(ref alias) = stream.options().alias {
self.fail = match self.store(self.deref(self[temp_v!(2)])) {
Addr::Str(s) => match &self.heap[s] {
&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
} else {
- let index = indices.get_predicate_code_index(
- name.clone(),
- arity,
- module_name,
- spec.clone(),
- )
- .map(|index| index.get())
- .unwrap_or(IndexPtr::DynamicUndefined);
+ let index = indices
+ .get_predicate_code_index(
+ name.clone(),
+ arity,
+ module_name,
+ spec.clone(),
+ )
+ .map(|index| index.get())
+ .unwrap_or(IndexPtr::DynamicUndefined);
match index {
IndexPtr::DynamicUndefined => false,
let spec =
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
} else {
- let index = indices.get_predicate_code_index(
- name.clone(),
- 0,
- module_name,
- spec.clone(),
- )
- .map(|index| index.get())
- .unwrap_or(IndexPtr::DynamicUndefined);
+ let index = indices
+ .get_predicate_code_index(
+ name.clone(),
+ 0,
+ module_name,
+ spec.clone(),
+ )
+ .map(|index| index.get())
+ .unwrap_or(IndexPtr::DynamicUndefined);
match index {
IndexPtr::DynamicUndefined => false,
let new_value = self.store(self.deref(self[temp_v!(2)]));
match indices.global_variables.get_mut(&key) {
- Some((_, ref mut loc)) => {
- match loc {
- Some(ref mut value) => {
- let old_value_loc = self.heap.push(HeapCellValue::Addr(*value));
- self.trail(TrailRef::BlackboardOffset(key_h, old_value_loc));
- *value = new_value;
- }
- loc @ None => {
- self.trail(TrailRef::BlackboardEntry(key_h));
- *loc = Some(new_value);
- }
+ Some((_, ref mut loc)) => match loc {
+ Some(ref mut value) => {
+ let old_value_loc = self.heap.push(HeapCellValue::Addr(*value));
+ self.trail(TrailRef::BlackboardOffset(key_h, old_value_loc));
+ *value = new_value;
}
- }
+ loc @ None => {
+ self.trail(TrailRef::BlackboardEntry(key_h));
+ *loc = Some(new_value);
+ }
+ },
None => {
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)));
}
}
}
}
&SystemClauseType::IsSTOEnabled => {
if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize {
- let value = self.heap.to_unifiable(
- HeapCellValue::Atom(clause_name!("true"), None),
- );
+ let value = self
+ .heap
+ .to_unifiable(HeapCellValue::Atom(clause_name!("true"), None));
(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 {
- let value = self.heap.to_unifiable(
- HeapCellValue::Atom(clause_name!("error"), None),
- );
+ } else if self.unify_fn as usize
+ == MachineState::unify_with_occurs_check_with_error as usize
+ {
+ let value = self
+ .heap
+ .to_unifiable(HeapCellValue::Atom(clause_name!("error"), None));
(self.unify_fn)(self, self[temp_v!(1)], value);
} else {
- let value = self.heap.to_unifiable(
- HeapCellValue::Atom(clause_name!("false"), None),
- );
+ let value = self
+ .heap
+ .to_unifiable(HeapCellValue::Atom(clause_name!("false"), None));
(self.unify_fn)(self, self[temp_v!(1)], value);
}