add write_term_to_chars/3 to iso_ext.pl (#288)
This commit is contained in:
@@ -258,6 +258,7 @@ pub enum SystemClauseType {
|
||||
Variant,
|
||||
WAMInstructions,
|
||||
WriteTerm,
|
||||
WriteTermToChars,
|
||||
}
|
||||
|
||||
impl SystemClauseType {
|
||||
@@ -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"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,8 +534,9 @@ impl SystemClauseType {
|
||||
("$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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
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]).
|
||||
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).
|
||||
|
||||
@@ -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) = "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<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> {
|
||||
|
||||
@@ -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,109 +3313,47 @@ 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(());
|
||||
}
|
||||
Some(printer) => {
|
||||
printer
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
if let Some(n) = n.to_usize() {
|
||||
printer.max_depth = n;
|
||||
} else {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
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),
|
||||
}
|
||||
|
||||
let output = printer.print(addr);
|
||||
|
||||
print!("{}", output.result());
|
||||
stdout().flush().unwrap();
|
||||
}
|
||||
&SystemClauseType::WriteTermToChars => {
|
||||
let addr = self[temp_v!(1)];
|
||||
|
||||
let printer =
|
||||
match self.write_term(&indices.op_dir)? {
|
||||
None => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
Some(printer) => {
|
||||
printer
|
||||
}
|
||||
};
|
||||
|
||||
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)]));
|
||||
|
||||
if let Some(var) = result_addr.as_var() {
|
||||
self.bind(var, chars);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return_from_clause!(self.last_call, self)
|
||||
|
||||
Reference in New Issue
Block a user