]> Repositorios git - scryer-prolog.git/commitdiff
adapt write_term family, add handling for EOF actions.
authorMark Thom <[email protected]>
Tue, 5 May 2020 03:17:06 +0000 (21:17 -0600)
committerMark Thom <[email protected]>
Tue, 5 May 2020 03:17:06 +0000 (21:17 -0600)
src/prolog/lib/charsio.pl
src/prolog/machine/machine_state.rs
src/prolog/machine/streams.rs
src/prolog/machine/system_calls.rs
src/prolog/read.rs

index 69a364308cd60d82d419c3323cf1b04d2e5b35f9..e929dc816bd063179bea3829d934022f2ca17ea7 100644 (file)
@@ -124,21 +124,14 @@ read_term_from_chars(Chars, Term) :-
 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).
index b86496b36c5041da2696c1bb8493ea23d66621a4..691d1374213d6f4acccb31262a91e2994af027d1 100644 (file)
@@ -619,100 +619,109 @@ impl MachineState {
         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(());
+                }
             }
         }
     }
@@ -809,9 +818,11 @@ impl MachineState {
 
                                 var_names.insert(var, atom);
                             }
-                            _ => unreachable!(),
+                            _ => {
+                            }
                         },
-                        _ => unreachable!(),
+                        _ => {
+                        }
                     }
                 }
 
index 8cd7cbf0f29854c34431f4269ec7630bf8c97f7e..1dbb753263957c03e4d32a31fbe1b1a8bc716e5e 100644 (file)
@@ -1,16 +1,16 @@
 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;
@@ -148,6 +148,9 @@ pub struct Stream {
 
 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(
@@ -322,9 +325,70 @@ impl Stream {
             }
         }
     }
+
+    // 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,
@@ -426,14 +490,13 @@ impl MachineState {
                         }
                         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,
                             ));
                         }
@@ -474,9 +537,9 @@ impl MachineState {
         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);
index a0e10b25745d19cf21d9c22e6ab0a39e45d2c2ae..83d4eb48c44b4366529f392919e6539eeab2f470 100644 (file)
@@ -3949,7 +3949,7 @@ impl MachineState {
                 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)? {
@@ -3965,7 +3965,7 @@ impl MachineState {
                 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);
index 28d35358e0040f9aefdb5a7b7135362989c7879a..9ed6c6cbcc97430a5657c615c4b569eac1247ab1 100644 (file)
@@ -42,6 +42,11 @@ pub mod readline {
     }
 
     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()));