]> Repositorios git - scryer-prolog.git/commitdiff
add write_term_to_chars/3 to iso_ext.pl (#288)
authorMark Thom <[email protected]>
Sun, 12 Apr 2020 20:29:28 +0000 (14:29 -0600)
committerMark Thom <[email protected]>
Sun, 12 Apr 2020 20:29:28 +0000 (14:29 -0600)
src/prolog/clause_types.rs
src/prolog/lib/iso_ext.pl
src/prolog/machine/machine_state.rs
src/prolog/machine/system_calls.rs

index 3a021d00cc929a3a10351c03eacde653a3a3d895..485928dc1350cc04c4b800768c2d9fddce0ae1f4 100644 (file)
@@ -258,6 +258,7 @@ pub enum SystemClauseType {
     Variant,
     WAMInstructions,
     WriteTerm,
+    WriteTermToChars,
 }
 
 impl SystemClauseType {
@@ -284,16 +285,16 @@ impl SystemClauseType {
             &SystemClauseType::CurrentInput => clause_name!("$current_input"),
             &SystemClauseType::CurrentOutput => clause_name!("$current_output"),
             &SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
-           &SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
-           &SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
-               clause_name!("$use_qualified_module")
-           }
-           &SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile) => {
-               clause_name!("$use_module_from_file")
-           }
-           &SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile) => {
-               clause_name!("$use_qualified_module_from_file")
-           }
+               &SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
+               &SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
+                       clause_name!("$use_qualified_module")
+               }
+               &SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile) => {
+                       clause_name!("$use_module_from_file")
+               }
+               &SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile) => {
+                       clause_name!("$use_qualified_module_from_file")
+               }
             &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
             &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
             &SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
@@ -406,6 +407,7 @@ impl SystemClauseType {
             &SystemClauseType::Variant => clause_name!("$variant"),
             &SystemClauseType::WAMInstructions => clause_name!("$wam_instructions"),
             &SystemClauseType::WriteTerm => clause_name!("$write_term"),
+            &SystemClauseType::WriteTermToChars => clause_name!("$write_term_to_chars"),
         }
     }
 
@@ -524,16 +526,17 @@ impl SystemClauseType {
             ("$unwind_environments", 0) => Some(SystemClauseType::UnwindEnvironments),
             ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
             ("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck),
-           ("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
-           ("$use_module_from_file", 1) =>
-               Some(SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile)),       
-           ("$use_qualified_module", 2) =>
-               Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule)),
-           ("$use_qualified_module_from_file", 2) =>
-               Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
+               ("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
+               ("$use_module_from_file", 1) =>
+                       Some(SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile)),
+               ("$use_qualified_module", 2) =>
+                       Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule)),
+               ("$use_qualified_module_from_file", 2) =>
+                       Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
             ("$variant", 2) => Some(SystemClauseType::Variant),
-            ("$write_term", 6) => Some(SystemClauseType::WriteTerm),
             ("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
+            ("$write_term", 6) => Some(SystemClauseType::WriteTerm),
+            ("$write_term_to_chars", 7) => Some(SystemClauseType::WriteTermToChars),
             _ => None,
         }
     }
index f91215acf209ba00429679940f2dad0679f75d55..3c57d2f2b10d9897ab2af4865bfbea61c852d7b2 100644 (file)
@@ -4,10 +4,11 @@
 %% ?- use_module(library(iso_ext)).
 
 :- module(iso_ext, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2,
-                   call_with_inference_limit/3, forall/2, maybe/0,
-                   partial_string/1, partial_string/3,
-                   partial_string_tail/2, set_random/1,
-                   setup_call_cleanup/3, variant/2]).
+                           call_with_inference_limit/3, forall/2, maybe/0,
+                           partial_string/1, partial_string/3,
+                           partial_string_tail/2, set_random/1,
+                           setup_call_cleanup/3, variant/2,
+                    write_term_to_chars/3]).
 
 forall(Generate, Test) :-
     \+ (Generate, \+ Test).
@@ -157,6 +158,7 @@ set_random(Seed) :-
     ;  throw(error(instantiation_error, set_random/1))
     ).
 
+
 partial_string(String, L, L0) :-
     (  String == [] ->
        L = L0
@@ -174,3 +176,26 @@ partial_string_tail(String, Tail) :-
        '$partial_string_tail'(String, Tail)
     ;  throw(error(type_error(partial_string, String), partial_string_tail/2))
     ).
+
+
+write_term_to_chars(_, Options, _) :-
+    var(Options), throw(error(instantiation_error, write_term_to_chars/3)).
+write_term_to_chars(Term, Options, Chars) :-
+    '$skip_max_list'(_, -1, Options, Options0),
+    (  var(Options0)  ->
+       throw(error(instantiation_error, write_term_to_chars/3))
+    ;  var(Term) ->
+       throw(error(instantiation_error, write_term_to_chars/3))
+    ;  nonvar(Chars)  ->
+       throw(error(uninstantiation_error(Chars), write_term_to_chars/3))
+    ;  Options0 == [] ->
+       true
+    ;
+       throw(error(type_error(list, Options), write_term_to_chars/3))
+    ),
+    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)),
+    '$write_term_to_chars'(Term, IgnoreOps, NumberVars, Quoted, VarNames, MaxDepth, Chars).
index 721d7925ebce112b02a0b8a2d7f6d867bfbc3e89..e94b039bdb15303a560da2f914779f1c735e7483 100644 (file)
@@ -2,6 +2,7 @@ use prolog_parser::ast::*;
 
 use crate::prolog::clause_types::*;
 use crate::prolog::forms::*;
+use crate::prolog::heap_print::*;
 use crate::prolog::machine::attributed_variables::*;
 use crate::prolog::machine::copier::*;
 use crate::prolog::machine::heap::*;
@@ -14,9 +15,10 @@ use crate::prolog::rug::Integer;
 
 use downcast::Any;
 
-use indexmap::IndexSet;
+use indexmap::{IndexMap, IndexSet};
 
 use std::cmp::Ordering;
+use std::convert::TryFrom;
 use std::io::Write;
 use std::mem;
 use std::ops::{Index, IndexMut};
@@ -490,6 +492,114 @@ pub struct MachineState {
 }
 
 impl MachineState {
+    pub(crate)
+    fn write_term<'a>(
+        &'a self,
+        op_dir: &'a OpDir,
+    ) -> Result<Option<HCPrinter<'a, PrinterOutputter>>, MachineStub>
+    {
+        let ignore_ops = self.store(self.deref(self[temp_v!(2)]));
+        let numbervars = self.store(self.deref(self[temp_v!(3)]));
+        let quoted = self.store(self.deref(self[temp_v!(4)]));
+        let max_depth = self.store(self.deref(self[temp_v!(6)]));
+
+        let mut printer = HCPrinter::new(&self, op_dir, PrinterOutputter::new());
+
+        if let &Addr::Con(h) = &ignore_ops {
+               if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+                printer.ignore_ops = name.as_str() == "true";
+            } else {
+                unreachable!()
+            }
+        }
+
+        if let &Addr::Con(h) = &numbervars {
+               if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+                printer.numbervars = name.as_str() == "true";
+            } else {
+                unreachable!()
+            }
+        }
+
+        if let &Addr::Con(h) = &quoted {
+               if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+                printer.quoted = name.as_str() == "true";
+            } else {
+                unreachable!()
+            }
+        }
+
+        match Number::try_from((max_depth, &self.heap)) {
+            Ok(Number::Fixnum(n)) => {
+                if let Ok(n) = usize::try_from(n) {
+                    printer.max_depth = n;
+                } else {
+                    return Ok(None);
+                }
+            }
+            Ok(Number::Integer(n)) => {
+                if let Some(n) = n.to_usize() {
+                    printer.max_depth = n;
+                } else {
+                    return Ok(None);
+                }
+            }
+            _ => {
+                unreachable!();
+            }
+        }
+
+        let stub = MachineError::functor_stub(clause_name!("write_term"), 2);
+
+        match self.try_from_list(temp_v!(5), stub) {
+            Ok(addrs) => {
+                let mut var_names: IndexMap<Addr, String> = IndexMap::new();
+
+                for addr in addrs {
+                    match addr {
+                        Addr::Str(s) => match &self.heap[s] {
+                            &HeapCellValue::NamedStr(2, ref name, _)
+                                if name.as_str() == "=" =>
+                            {
+                                let atom = self.heap[s + 1].as_addr(s + 1);
+                                let var = self.heap[s + 2].as_addr(s + 2);
+
+                                let atom = match self.store(self.deref(atom)) {
+                                    Addr::Con(h) => {
+                                        if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
+                                            atom.to_string()
+                                        } else {
+                                            unreachable!()
+                                        }
+                                    }
+                                    Addr::Char(c) => c.to_string(),
+                                    _ => unreachable!(),
+                                };
+
+                                let var = self.store(self.deref(var));
+
+                                if var_names.contains_key(&var) {
+                                    continue;
+                                }
+
+                                var_names.insert(var, atom);
+                            }
+                            _ => unreachable!(),
+                        },
+                        _ => unreachable!(),
+                    }
+                }
+
+                printer.var_names = var_names;
+            }
+            Err(err) => {
+                return Err(err);
+            }
+        }
+
+        Ok(Some(printer))
+    }
+
     #[inline]
     pub(crate)
     fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> {
index f1004193adf74342faa3803daad5acb9a3801ae4..170c02af3e3ee6d2df7ec1ebdd204a9105818bd4 100644 (file)
@@ -4,11 +4,11 @@ use prolog_parser::tabled_rc::*;
 
 use crate::prolog::clause_types::*;
 use crate::prolog::forms::*;
-use crate::prolog::heap_print::*;
 use crate::prolog::instructions::*;
 use crate::prolog::machine::code_repo::CodeRepo;
 use crate::prolog::machine::copier::*;
 use crate::prolog::machine::code_walker::*;
+use crate::prolog::heap_print::*;
 use crate::prolog::machine::machine_errors::*;
 use crate::prolog::machine::machine_indices::*;
 use crate::prolog::machine::machine_state::*;
@@ -20,7 +20,7 @@ use crate::prolog::rug::Integer;
 
 use crate::ref_thread_local::RefThreadLocal;
 
-use indexmap::{IndexMap, IndexSet};
+use indexmap::IndexSet;
 
 use std::cmp;
 use std::convert::TryFrom;
@@ -3313,108 +3313,46 @@ impl MachineState {
             &SystemClauseType::WriteTerm => {
                 let addr = self[temp_v!(1)];
 
-                let ignore_ops = self.store(self.deref(self[temp_v!(2)]));
-                let numbervars = self.store(self.deref(self[temp_v!(3)]));
-                let quoted = self.store(self.deref(self[temp_v!(4)]));
-                let max_depth = self.store(self.deref(self[temp_v!(6)]));
-
-                let mut printer = HCPrinter::new(&self, &indices.op_dir, PrinterOutputter::new());
-
-                if let &Addr::Con(h) = &ignore_ops {
-                       if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
-                        printer.ignore_ops = name.as_str() == "true";
-                    } else {
-                        unreachable!()
-                    }
-                }
-
-                if let &Addr::Con(h) = &numbervars {
-                       if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
-                        printer.numbervars = name.as_str() == "true";
-                    } else {
-                        unreachable!()
-                    }
-                }
-
-                if let &Addr::Con(h) = &quoted {
-                       if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
-                        printer.quoted = name.as_str() == "true";
-                    } else {
-                        unreachable!()
-                    }
-                }
-
-                match Number::try_from((max_depth, &self.heap)) {
-                    Ok(Number::Fixnum(n)) => {
-                        if let Ok(n) = usize::try_from(n) {
-                            printer.max_depth = n;
-                        } else {
+                let printer =
+                    match self.write_term(&indices.op_dir)? {
+                        None => {
                             self.fail = true;
                             return Ok(());
                         }
-                    }
-                    Ok(Number::Integer(n)) => {
-                        if let Some(n) = n.to_usize() {
-                            printer.max_depth = n;
-                        } else {
-                            self.fail = true;
-                            return Ok(());
+                        Some(printer) => {
+                            printer
                         }
-                    }
-                    _ => {
-                        unreachable!();
-                    }
-                }
-
-                let stub = MachineError::functor_stub(clause_name!("write_term"), 2);
+                    };
 
-                match self.try_from_list(temp_v!(5), stub) {
-                    Ok(addrs) => {
-                        let mut var_names: IndexMap<Addr, String> = IndexMap::new();
+                let output = printer.print(addr);
 
-                        for addr in addrs {
-                            match addr {
-                                Addr::Str(s) => match &self.heap[s] {
-                                    &HeapCellValue::NamedStr(2, ref name, _)
-                                        if name.as_str() == "=" =>
-                                    {
-                                        let atom = self.heap[s + 1].as_addr(s + 1);
-                                        let var = self.heap[s + 2].as_addr(s + 2);
-
-                                        let atom = match self.store(self.deref(atom)) {
-                                            Addr::Con(h) => {
-                                                if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
-                                                    atom.to_string()
-                                                } else {
-                                                    unreachable!()
-                                                }
-                                            }
-                                            Addr::Char(c) => c.to_string(),
-                                            _ => unreachable!(),
-                                        };
+                print!("{}", output.result());
+                stdout().flush().unwrap();
+            }
+            &SystemClauseType::WriteTermToChars => {
+                let addr = self[temp_v!(1)];
 
-                                        let var = self.store(self.deref(var));
+                let printer =
+                    match self.write_term(&indices.op_dir)? {
+                        None => {
+                            self.fail = true;
+                            return Ok(());
+                        }
+                        Some(printer) => {
+                            printer
+                        }
+                    };
 
-                                        if var_names.contains_key(&var) {
-                                            continue;
-                                        }
+                let result = printer.print(addr).result();
+                let chars = self.heap.put_complete_string(&result);
 
-                                        var_names.insert(var, atom);
-                                    }
-                                    _ => unreachable!(),
-                                },
-                                _ => unreachable!(),
-                            }
-                        }
+                let result_addr = self.store(self.deref(self[temp_v!(7)]));
 
-                        printer.var_names = var_names;
-                    }
-                    Err(err) => return Err(err),
+                if let Some(var) = result_addr.as_var() {
+                    self.bind(var, chars);
+                } else {
+                    unreachable!()
                 }
-
-                let output = printer.print(addr);
-                print!("{}", output.result());
-                stdout().flush().unwrap();
             }
         };