]> Repositorios git - scryer-prolog.git/commitdiff
provide read_term_from_chars/2 (#334)
authorMark Thom <[email protected]>
Sun, 12 Apr 2020 23:26:11 +0000 (17:26 -0600)
committerMark Thom <[email protected]>
Sun, 12 Apr 2020 23:26:11 +0000 (17:26 -0600)
src/prolog/clause_types.rs
src/prolog/lib/charsio.pl
src/prolog/machine/machine_errors.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/system_calls.rs
src/prolog/read.rs

index 485928dc1350cc04c4b800768c2d9fddce0ae1f4..7100855e238591dbc582c0617256b07877fa3076 100644 (file)
@@ -242,6 +242,7 @@ pub enum SystemClauseType {
     Maybe,
     QuotedToken,
     RawInputReadChar,
+    ReadTermFromChars,
     ResetBlock,
     ReturnFromVerifyAttr,
     SetBall,
@@ -388,6 +389,7 @@ impl SystemClauseType {
             &SystemClauseType::NextEP => clause_name!("$nextEP"),
             &SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"),
             &SystemClauseType::ReadTerm => clause_name!("$read_term"),
+            &SystemClauseType::ReadTermFromChars => clause_name!("$read_term_from_chars"),
             &SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
             &SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
             &SystemClauseType::RetractClause => clause_name!("$retract_clause"),
@@ -508,6 +510,7 @@ impl SystemClauseType {
             ("$nextEP", 3) => Some(SystemClauseType::NextEP),
             ("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
             ("$read_term", 2) => Some(SystemClauseType::ReadTerm),
+            ("$read_term_from_chars", 2) => Some(SystemClauseType::ReadTermFromChars),
             ("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
             ("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
             ("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
index f6b2eb2edbbd8b7812466b84b3a6d31de0afe1df..f11ef287e17b2bf70a21074087c7017dbf1409d5 100644 (file)
@@ -1,4 +1,22 @@
-:- module(charsio, [write_term_to_chars/3]).
+:- module(charsio, [read_term_from_chars/2,
+                    write_term_to_chars/3]).
+
+:- use_module(library(iso_ext)).
+
+read_term_from_chars(Chars, Term) :-
+    (  var(Chars) ->
+       throw(error(instantiation_error, read_term_from_chars/2))
+    ;  nonvar(Term) ->
+       throw(error(uninstantiation_error(Term), read_term_from_chars/2))
+    ;  '$skip_max_list'(_, -1, Chars, Chars0),
+       Chars0 == [],
+       partial_string(Chars) ->
+       true
+    ;
+       throw(error(type_error(complete_string, Chars), read_term_from_chars/2))
+    ),
+    '$read_term_from_chars'(Chars, Term).
+
 
 write_term_to_chars(_, Options, _) :-
     var(Options), throw(error(instantiation_error, write_term_to_chars/3)).
index f57c169aa03056452379bb5d24be2848a58ac029..3e366322590dcaaaaf8341558416a67a1b9c1b5d 100644 (file)
@@ -145,7 +145,8 @@ impl DomainError for Number {
 }
 
 impl MachineError {
-    pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
+    pub(super)
+    fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
         functor!(
             "/",
             SharedOpDesc::new(400, YFX),
@@ -153,7 +154,8 @@ impl MachineError {
         )
     }
 
-    pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
+    pub(super)
+    fn evaluation_error(eval_error: EvalError) -> Self {
         let stub = functor!("evaluation_error", [atom(eval_error.as_str())]);
 
         MachineError {
@@ -313,6 +315,20 @@ impl MachineError {
         }
     }
 
+    pub(super)
+    fn uninstantiation_error(culprit: Addr) -> Self {
+        let stub = functor!(
+            "uninstantiation_error",
+            [addr(culprit)]
+        );
+
+        MachineError {
+            stub,
+            location: None,
+            from: ErrorProvenance::Received,
+        }
+    }
+
     pub(super)
     fn session_error(h: usize, err: SessionError) -> Self {
         match err {
index e94b039bdb15303a560da2f914779f1c735e7483..9f50f530d0b8f20cbce2cded0f66c2a929c0881c 100644 (file)
@@ -1,4 +1,5 @@
 use prolog_parser::ast::*;
+use prolog_parser::tabled_rc::*;
 
 use crate::prolog::clause_types::*;
 use crate::prolog::forms::*;
@@ -11,6 +12,7 @@ use crate::prolog::machine::machine_indices::*;
 use crate::prolog::machine::modules::*;
 use crate::prolog::machine::stack::*;
 use crate::prolog::machine::streams::*;
+use crate::prolog::read::readline;
 use crate::prolog::rug::Integer;
 
 use downcast::Any;
@@ -492,6 +494,63 @@ pub struct MachineState {
 }
 
 impl MachineState {
+    pub(crate)
+    fn read_term(
+        &mut self,
+        current_input_stream: &mut Stream,
+        indices: &mut IndexStore,
+    ) -> CallResult {
+        match self.read(
+            &mut parsing_stream(current_input_stream.clone()),
+            indices.atom_tbl.clone(),
+            &indices.op_dir,
+        ) {
+            Ok(term_write_result) => {
+                let a1 = self[temp_v!(1)];
+                self.unify(Addr::HeapCell(term_write_result.heap_loc), a1);
+
+                if self.fail {
+                    return Ok(());
+                }
+
+                let mut list_of_var_eqs = vec![];
+
+                for (var, binding) in term_write_result.var_dict.into_iter().rev() {
+                    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);
+
+                    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));
+                }
+
+                let a2 = self[temp_v!(2)];
+                let list_offset =
+                    Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter()));
+
+                Ok(self.unify(list_offset, a2))
+            }
+            Err(err) => {
+                if let ParserError::UnexpectedEOF = err {
+                    std::process::exit(0);
+                }
+
+                // reset the input stream after an input failure.
+                *current_input_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))
+            }
+        }
+    }
+
     pub(crate)
     fn write_term<'a>(
         &'a self,
index 170c02af3e3ee6d2df7ec1ebdd204a9105818bd4..cd9cc86f16aa0e117ff944d1cc837a435a726788 100644 (file)
@@ -421,62 +421,6 @@ impl MachineState {
         })
     }
 
-    fn read_term(
-        &mut self,
-        current_input_stream: &mut Stream,
-        indices: &mut IndexStore,
-    ) -> CallResult {
-        match self.read(
-            &mut parsing_stream(current_input_stream.clone()),
-            indices.atom_tbl.clone(),
-            &indices.op_dir,
-        ) {
-            Ok(term_write_result) => {
-                let a1 = self[temp_v!(1)];
-                self.unify(Addr::HeapCell(term_write_result.heap_loc), a1);
-
-                if self.fail {
-                    return Ok(());
-                }
-
-                let mut list_of_var_eqs = vec![];
-
-                for (var, binding) in term_write_result.var_dict.into_iter().rev() {
-                    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);
-
-                    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));
-                }
-
-                let a2 = self[temp_v!(2)];
-                let list_offset =
-                    Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter()));
-
-                Ok(self.unify(list_offset, a2))
-            }
-            Err(err) => {
-                if let ParserError::UnexpectedEOF = err {
-                    std::process::exit(0);
-                }
-
-                // reset the input stream after an input failure.
-                *current_input_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))
-            }
-        }
-    }
-
     #[inline]
     fn install_new_block(&mut self, r: RegType) -> usize {
         self.block = self.b;
@@ -2479,6 +2423,15 @@ impl MachineState {
 
                             self.unify(target, module);
                         }
+                        HeapCellValue::Addr(addr) if addr.is_ref() => {
+                            let err = MachineError::uninstantiation_error(addr);
+                            let stub = MachineError::functor_stub(
+                                clause_name!("$module_of"),
+                                2,
+                            );
+
+                            return Err(self.error_form(err, stub));
+                        }
                         _ => {
                             unreachable!()
                         }
@@ -3062,6 +3015,44 @@ impl MachineState {
                 readline::set_prompt(false);
                 self.read_term(current_input_stream, indices)?;
             }
+            &SystemClauseType::ReadTermFromChars => {
+                let mut heap_pstr_iter = self.heap_pstr_iter(self[temp_v!(1)]);
+                let chars = heap_pstr_iter.to_string();
+
+                if let Addr::EmptyList = heap_pstr_iter.focus() {
+                    let term_write_result =
+                        match self.read(
+                            &mut parsing_stream(Stream::from(chars)),
+                            indices.atom_tbl.clone(),
+                            &indices.op_dir,
+                        ) {
+                            Ok(term_write_result) => {
+                                term_write_result
+                            }
+                            Err(e) => {
+                                let stub = MachineError::functor_stub(
+                                    clause_name!("read_term_from_chars"),
+                                    2,
+                                );
+
+                                let h = self.heap.h();
+                                let e = MachineError::session_error(h, SessionError::from(e));
+
+                                return Err(self.error_form(e, stub));
+                            }
+                        };
+
+                    let result = Addr::HeapCell(term_write_result.heap_loc);
+
+                    if let Some(var) = self.store(self.deref(self[temp_v!(2)])).as_var() {
+                        self.bind(var, result);
+                    } else {
+                        unreachable!()
+                    }
+                } else {
+                    unreachable!()
+                }
+            }
             &SystemClauseType::ResetBlock => {
                 let addr = self.deref(self[temp_v!(1)]);
                 self.reset_block(addr);
index a04b13d161c0bf51cd3e8e07058ec2097a988c96..72be1b1870e1d5006f81f609dcf0814ab45796cf 100644 (file)
@@ -208,10 +208,7 @@ impl<'a> TermWriter<'a> {
                 &TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) |
                 &TermRef::Var(Level::Root, ..) => {
                     let addr = self.term_as_addr(&term, h);
-
-                    if !addr.is_heap_bound() {
-                        self.machine_st.heap.push(HeapCellValue::Addr(addr));
-                    }
+                    self.machine_st.heap.push(HeapCellValue::Addr(addr));
                 }
                 &TermRef::AnonVar(_) => {
                     if let Some((arity, site_h)) = self.queue.pop_front() {