write_term_to_chars(_, Options, _) :-
var(Options), instantiation_error(write_term_to_chars/3).
write_term_to_chars(Term, Options, Chars) :-
- '$skip_max_list'(_, -1, Options, Options0),
- ( var(Options0) ->
- instantiation_error(write_term_to_chars/3)
- ; nonvar(Chars) ->
+ builtins:parse_write_options(Options,
+ [IgnoreOps, MaxDepth, NumberVars, Quoted, VNNames],
+ write_term_to_chars/3),
+ ( nonvar(Chars) ->
throw(error(uninstantiation_error(Chars), write_term_to_chars/3))
- ; Options0 == [] ->
- true
;
- type_error(list, Options, write_term_to_chars/3)
+ true
),
- builtins:inst_member_or(Options, ignore_ops(IgnoreOps), ignore_ops(false)),
- builtins:inst_member_or(Options, numbervars(NumberVars), numbervars(false)),
- builtins:inst_member_or(Options, quoted(Quoted), quoted(false)),
- builtins:inst_member_or(Options, variable_names(VarNames), variable_names([])),
- builtins:inst_member_or(Options, max_depth(MaxDepth), max_depth(0)),
term_variables(Term, Vars),
extend_var_list(Vars, VarNames, NewVarNames, numbervars),
- '$write_term_to_chars'(Term, IgnoreOps, NumberVars, Quoted, NewVarNames, MaxDepth, Chars).
+ '$write_term_to_chars'(Chars, Term, IgnoreOps, NumberVars, Quoted, NewVarNames, MaxDepth).
stream: Stream,
indices: &mut IndexStore,
) -> CallResult {
+ let mut orig_stream = stream.clone();
let mut stream = self.open_parsing_stream(stream, "read_term", 3)?;
- match self.read(
- &mut stream,
- indices.atom_tbl.clone(),
- &indices.op_dir,
- ) {
- Ok(term_write_result) => {
- let term = self[temp_v!(2)];
- self.unify(Addr::HeapCell(term_write_result.heap_loc), term);
-
- if self.fail {
- return Ok(());
- }
+ loop {
+ match self.read(
+ &mut stream,
+ indices.atom_tbl.clone(),
+ &indices.op_dir,
+ ) {
+ Ok(term_write_result) => {
+ let term = self[temp_v!(2)];
+ self.unify(Addr::HeapCell(term_write_result.heap_loc), term);
+
+ if self.fail {
+ return Ok(());
+ }
- let mut list_of_var_eqs = vec![];
+ let mut list_of_var_eqs = vec![];
- for (var, binding) in term_write_result.var_dict.into_iter() {
- let var_atom = clause_name!(var.to_string(), indices.atom_tbl);
+ for (var, binding) in term_write_result.var_dict.into_iter() {
+ let var_atom = clause_name!(var.to_string(), indices.atom_tbl);
- let h = self.heap.h();
- let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
+ let h = self.heap.h();
+ let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
- self.heap.push(HeapCellValue::NamedStr(2, clause_name!("="), spec));
- self.heap.push(HeapCellValue::Atom(var_atom, None));
- self.heap.push(HeapCellValue::Addr(binding));
+ self.heap.push(HeapCellValue::NamedStr(2, clause_name!("="), spec));
+ self.heap.push(HeapCellValue::Atom(var_atom, None));
+ self.heap.push(HeapCellValue::Addr(binding));
- list_of_var_eqs.push(Addr::Str(h));
- }
+ list_of_var_eqs.push(Addr::Str(h));
+ }
- let mut var_set: IndexMap<Ref, bool> = IndexMap::new();
+ let mut var_set: IndexMap<Ref, bool> = IndexMap::new();
- for addr in self.acyclic_pre_order_iter(term) {
- if let Some(var) = addr.as_var() {
- if !var_set.contains_key(&var) {
- var_set.insert(var, true);
- } else {
- var_set.insert(var, false);
+ for addr in self.acyclic_pre_order_iter(term) {
+ if let Some(var) = addr.as_var() {
+ if !var_set.contains_key(&var) {
+ var_set.insert(var, true);
+ } else {
+ var_set.insert(var, false);
+ }
}
}
- }
- let mut var_list = vec![];
- let mut singleton_var_list = vec![];
+ let mut var_list = vec![];
+ let mut singleton_var_list = vec![];
- for addr in self.acyclic_pre_order_iter(term) {
- if let Some(var) = addr.as_var() {
- if var_set.get(&var) == Some(&true) {
- singleton_var_list.push(var.as_addr());
- }
+ for addr in self.acyclic_pre_order_iter(term) {
+ if let Some(var) = addr.as_var() {
+ if var_set.get(&var) == Some(&true) {
+ singleton_var_list.push(var.as_addr());
+ }
- var_list.push(var.as_addr());
+ var_list.push(var.as_addr());
+ }
}
- }
- let singleton_addr = self[temp_v!(3)];
- let singletons_offset =
- Addr::HeapCell(self.heap.to_list(singleton_var_list.into_iter()));
+ let singleton_addr = self[temp_v!(3)];
+ let singletons_offset =
+ Addr::HeapCell(self.heap.to_list(singleton_var_list.into_iter()));
- self.unify(singletons_offset, singleton_addr);
+ self.unify(singletons_offset, singleton_addr);
- if self.fail {
- return Ok(());
- }
+ if self.fail {
+ return Ok(());
+ }
- let vars_addr = self[temp_v!(4)];
- let vars_offset =
- Addr::HeapCell(self.heap.to_list(var_list.into_iter()));
+ let vars_addr = self[temp_v!(4)];
+ let vars_offset =
+ Addr::HeapCell(self.heap.to_list(var_list.into_iter()));
- self.unify(vars_offset, vars_addr);
+ self.unify(vars_offset, vars_addr);
- if self.fail {
- return Ok(());
- }
+ if self.fail {
+ return Ok(());
+ }
- let var_names_addr = self[temp_v!(5)];
- let var_names_offset =
- Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter()));
+ let var_names_addr = self[temp_v!(5)];
+ let var_names_offset =
+ Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter()));
- Ok(self.unify(var_names_offset, var_names_addr))
- }
- Err(err) => {
- if let ParserError::UnexpectedEOF = err {
- std::process::exit(0);
+ return Ok(self.unify(var_names_offset, var_names_addr));
}
+ Err(err) => {
+ if let ParserError::UnexpectedEOF = err {
+ self.eof_action(
+ self[temp_v!(2)],
+ &mut orig_stream,
+ clause_name!("read_term"),
+ 3
+ )?;
+
+ if orig_stream.options.eof_action == EOFAction::Reset {
+ if self.fail == false {
+ continue;
+ } else {
+ return Ok(());
+ }
+ }
+ }
- // reset the input stream after an input failure.
- //*stream = readline::input_stream();
-
- let h = self.heap.h();
- let syntax_error = MachineError::syntax_error(h, err);
- let stub = MachineError::functor_stub(clause_name!("read_term"), 2);
-
- Err(self.error_form(syntax_error, stub))
+ return Ok(());
+ }
}
}
}
var_names.insert(var, atom);
}
- _ => unreachable!(),
+ _ => {
+ }
},
- _ => unreachable!(),
+ _ => {
+ }
}
}
use crate::prolog_parser::ast::*;
+use crate::prolog::read::PrologStream;
use crate::prolog::read::readline::*;
use crate::prolog::machine::machine_errors::*;
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::*;
-use crate::prolog::read::PrologStream;
use std::cell::RefCell;
use std::error::Error;
use std::fmt;
use std::fs::File;
-use std::io::{stdout, Cursor, ErrorKind, Read, Write};
+use std::io::{stdout, Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
use std::hash::{Hash, Hasher};
use std::net::TcpStream;
use std::rc::Rc;
impl From<TcpStream> for Stream {
fn from(tcp_stream: TcpStream) -> Self {
+ tcp_stream.set_read_timeout(None).unwrap();
+ tcp_stream.set_write_timeout(None).unwrap();
+
Stream {
options: StreamOptions::default(),
stream_inst: WrappedStreamInstance::new(
}
}
}
+
+ // returns true on success.
+ #[inline]
+ fn reset(&mut self) -> bool {
+ match *self.stream_inst.0.borrow_mut() {
+ StreamInstance::Bytes(ref mut cursor) => {
+ cursor.set_position(0);
+ true
+ }
+ StreamInstance::InputFile(ref mut file) => {
+ file.seek(SeekFrom::Start(0)).unwrap();
+ true
+ }
+ StreamInstance::ReadlineStream(ref mut stream) => {
+ *stream = ReadlineStream::new(String::new());
+ true
+ }
+ _ => {
+ false
+ }
+ }
+ }
}
impl MachineState {
+ #[inline]
+ pub(crate)
+ fn eof_action(
+ &mut self,
+ result: Addr,
+ stream: &mut Stream,
+ caller: ClauseName,
+ arity: usize,
+ ) -> CallResult {
+ match stream.options.eof_action {
+ EOFAction::Error => {
+ let stub = MachineError::functor_stub(caller, arity);
+
+ let stream = vec![
+ HeapCellValue::Stream(stream.clone())
+ ];
+
+ let err = MachineError::permission_error(
+ self.heap.h(),
+ Permission::InputStream,
+ "past_end_of_stream",
+ stream,
+ );
+
+ Err(self.error_form(err, stub))
+ }
+ EOFAction::EOFCode => {
+ let end_of_stream = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!("end_of_stream"), None)
+ );
+
+ Ok(self.unify(result, end_of_stream))
+ }
+ EOFAction::Reset => {
+ Ok(self.fail = !stream.reset())
+ }
+ }
+ }
+
pub(crate)
fn to_stream_options(
&self,
}
None => {
let stub = MachineError::functor_stub(clause_name!(caller), arity);
- let h = self.heap.h();
let addr = self.heap.to_unifiable(
HeapCellValue::Atom(atom.clone(), spec.clone())
);
return Err(self.error_form(
- MachineError::existence_error(h + 1, ExistenceError::Stream(addr)),
+ MachineError::existence_error(self.heap.h(), ExistenceError::Stream(addr)),
stub,
));
}
stub_name: &'static str,
stub_arity: usize,
) -> Result<PrologStream, MachineStub> {
- match parsing_stream(stream) {
- Ok(stream) => {
- Ok(stream)
+ match parsing_stream(stream.clone()) {
+ Ok(parsing_stream) => {
+ Ok(parsing_stream)
}
Err(e) => {
let stub = MachineError::functor_stub(clause_name!(stub_name), stub_arity);
stream.flush().unwrap();
}
&SystemClauseType::WriteTermToChars => {
- let addr = self[temp_v!(1)];
+ let addr = self[temp_v!(2)];
let printer =
match self.write_term(&indices.op_dir)? {
let result = printer.print(addr).result();
let chars = self.heap.put_complete_string(&result);
- let result_addr = self.store(self.deref(self[temp_v!(7)]));
+ let result_addr = self.store(self.deref(self[temp_v!(1)]));
if let Some(var) = result_addr.as_var() {
self.bind(var, chars);
}
impl ReadlineStream {
+ pub fn new(pending_input: String) -> Self {
+ let rl = Editor::<()>::new();
+ ReadlineStream { rl, pending_input: Cursor::new(pending_input) }
+ }
+
pub fn input_stream(pending_input: String) -> Stream {
let mut rl = Editor::<()>::new();
rl.bind_sequence(KeyPress::Tab, Cmd::Insert(1, "\t".to_string()));