add write_term_to_chars/3 to iso_ext.pl (#288)
This commit is contained in:
@@ -258,6 +258,7 @@ pub enum SystemClauseType {
|
|||||||
Variant,
|
Variant,
|
||||||
WAMInstructions,
|
WAMInstructions,
|
||||||
WriteTerm,
|
WriteTerm,
|
||||||
|
WriteTermToChars,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemClauseType {
|
impl SystemClauseType {
|
||||||
@@ -284,16 +285,16 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::CurrentInput => clause_name!("$current_input"),
|
&SystemClauseType::CurrentInput => clause_name!("$current_input"),
|
||||||
&SystemClauseType::CurrentOutput => clause_name!("$current_output"),
|
&SystemClauseType::CurrentOutput => clause_name!("$current_output"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
|
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
|
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
|
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
|
||||||
clause_name!("$use_qualified_module")
|
clause_name!("$use_qualified_module")
|
||||||
}
|
}
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile) => {
|
&SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile) => {
|
||||||
clause_name!("$use_module_from_file")
|
clause_name!("$use_module_from_file")
|
||||||
}
|
}
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile) => {
|
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile) => {
|
||||||
clause_name!("$use_qualified_module_from_file")
|
clause_name!("$use_qualified_module_from_file")
|
||||||
}
|
}
|
||||||
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
||||||
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
||||||
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
|
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
|
||||||
@@ -406,6 +407,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::Variant => clause_name!("$variant"),
|
&SystemClauseType::Variant => clause_name!("$variant"),
|
||||||
&SystemClauseType::WAMInstructions => clause_name!("$wam_instructions"),
|
&SystemClauseType::WAMInstructions => clause_name!("$wam_instructions"),
|
||||||
&SystemClauseType::WriteTerm => clause_name!("$write_term"),
|
&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_environments", 0) => Some(SystemClauseType::UnwindEnvironments),
|
||||||
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
|
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
|
||||||
("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck),
|
("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck),
|
||||||
("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
|
("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
|
||||||
("$use_module_from_file", 1) =>
|
("$use_module_from_file", 1) =>
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile)),
|
Some(SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile)),
|
||||||
("$use_qualified_module", 2) =>
|
("$use_qualified_module", 2) =>
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule)),
|
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule)),
|
||||||
("$use_qualified_module_from_file", 2) =>
|
("$use_qualified_module_from_file", 2) =>
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
|
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
|
||||||
("$variant", 2) => Some(SystemClauseType::Variant),
|
("$variant", 2) => Some(SystemClauseType::Variant),
|
||||||
("$write_term", 6) => Some(SystemClauseType::WriteTerm),
|
|
||||||
("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
|
("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
|
||||||
|
("$write_term", 6) => Some(SystemClauseType::WriteTerm),
|
||||||
|
("$write_term_to_chars", 7) => Some(SystemClauseType::WriteTermToChars),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
%% ?- use_module(library(iso_ext)).
|
%% ?- use_module(library(iso_ext)).
|
||||||
|
|
||||||
:- module(iso_ext, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2,
|
:- 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,
|
call_with_inference_limit/3, forall/2, maybe/0,
|
||||||
partial_string/1, partial_string/3,
|
partial_string/1, partial_string/3,
|
||||||
partial_string_tail/2, set_random/1,
|
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) :-
|
forall(Generate, Test) :-
|
||||||
\+ (Generate, \+ Test).
|
\+ (Generate, \+ Test).
|
||||||
@@ -157,6 +158,7 @@ set_random(Seed) :-
|
|||||||
; throw(error(instantiation_error, set_random/1))
|
; throw(error(instantiation_error, set_random/1))
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
partial_string(String, L, L0) :-
|
partial_string(String, L, L0) :-
|
||||||
( String == [] ->
|
( String == [] ->
|
||||||
L = L0
|
L = L0
|
||||||
@@ -174,3 +176,26 @@ partial_string_tail(String, Tail) :-
|
|||||||
'$partial_string_tail'(String, Tail)
|
'$partial_string_tail'(String, Tail)
|
||||||
; throw(error(type_error(partial_string, String), partial_string_tail/2))
|
; 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::clause_types::*;
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
|
use crate::prolog::heap_print::*;
|
||||||
use crate::prolog::machine::attributed_variables::*;
|
use crate::prolog::machine::attributed_variables::*;
|
||||||
use crate::prolog::machine::copier::*;
|
use crate::prolog::machine::copier::*;
|
||||||
use crate::prolog::machine::heap::*;
|
use crate::prolog::machine::heap::*;
|
||||||
@@ -14,9 +15,10 @@ use crate::prolog::rug::Integer;
|
|||||||
|
|
||||||
use downcast::Any;
|
use downcast::Any;
|
||||||
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::{IndexMap, IndexSet};
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
@@ -490,6 +492,114 @@ pub struct MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> {
|
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::clause_types::*;
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
use crate::prolog::heap_print::*;
|
|
||||||
use crate::prolog::instructions::*;
|
use crate::prolog::instructions::*;
|
||||||
use crate::prolog::machine::code_repo::CodeRepo;
|
use crate::prolog::machine::code_repo::CodeRepo;
|
||||||
use crate::prolog::machine::copier::*;
|
use crate::prolog::machine::copier::*;
|
||||||
use crate::prolog::machine::code_walker::*;
|
use crate::prolog::machine::code_walker::*;
|
||||||
|
use crate::prolog::heap_print::*;
|
||||||
use crate::prolog::machine::machine_errors::*;
|
use crate::prolog::machine::machine_errors::*;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::*;
|
use crate::prolog::machine::machine_state::*;
|
||||||
@@ -20,7 +20,7 @@ use crate::prolog::rug::Integer;
|
|||||||
|
|
||||||
use crate::ref_thread_local::RefThreadLocal;
|
use crate::ref_thread_local::RefThreadLocal;
|
||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -3313,109 +3313,47 @@ impl MachineState {
|
|||||||
&SystemClauseType::WriteTerm => {
|
&SystemClauseType::WriteTerm => {
|
||||||
let addr = self[temp_v!(1)];
|
let addr = self[temp_v!(1)];
|
||||||
|
|
||||||
let ignore_ops = self.store(self.deref(self[temp_v!(2)]));
|
let printer =
|
||||||
let numbervars = self.store(self.deref(self[temp_v!(3)]));
|
match self.write_term(&indices.op_dir)? {
|
||||||
let quoted = self.store(self.deref(self[temp_v!(4)]));
|
None => {
|
||||||
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 {
|
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
Some(printer) => {
|
||||||
Ok(Number::Integer(n)) => {
|
printer
|
||||||
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);
|
let output = printer.print(addr);
|
||||||
|
|
||||||
print!("{}", output.result());
|
print!("{}", output.result());
|
||||||
stdout().flush().unwrap();
|
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)
|
return_from_clause!(self.last_call, self)
|
||||||
|
|||||||
Reference in New Issue
Block a user