From: Mark Thom Date: Sun, 12 Apr 2020 20:29:28 +0000 (-0600) Subject: add write_term_to_chars/3 to iso_ext.pl (#288) X-Git-Tag: v0.8.119~8 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=0380d70a461d1ed83d38a1d25ea52b5c5270bda5;p=scryer-prolog.git add write_term_to_chars/3 to iso_ext.pl (#288) --- diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index 3a021d00..485928dc 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -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, } } diff --git a/src/prolog/lib/iso_ext.pl b/src/prolog/lib/iso_ext.pl index f91215ac..3c57d2f2 100644 --- a/src/prolog/lib/iso_ext.pl +++ b/src/prolog/lib/iso_ext.pl @@ -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). diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 721d7925..e94b039b 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -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>, 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) = "ed { + 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 = 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> { diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index f1004193..170c02af 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -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) = "ed { - 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 = 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(); } };