provide read_term_from_chars/2 (#334)
This commit is contained in:
@@ -242,6 +242,7 @@ pub enum SystemClauseType {
|
|||||||
Maybe,
|
Maybe,
|
||||||
QuotedToken,
|
QuotedToken,
|
||||||
RawInputReadChar,
|
RawInputReadChar,
|
||||||
|
ReadTermFromChars,
|
||||||
ResetBlock,
|
ResetBlock,
|
||||||
ReturnFromVerifyAttr,
|
ReturnFromVerifyAttr,
|
||||||
SetBall,
|
SetBall,
|
||||||
@@ -388,6 +389,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::NextEP => clause_name!("$nextEP"),
|
&SystemClauseType::NextEP => clause_name!("$nextEP"),
|
||||||
&SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"),
|
&SystemClauseType::ReadQueryTerm => clause_name!("$read_query_term"),
|
||||||
&SystemClauseType::ReadTerm => clause_name!("$read_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::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
|
||||||
&SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
|
&SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
|
||||||
&SystemClauseType::RetractClause => clause_name!("$retract_clause"),
|
&SystemClauseType::RetractClause => clause_name!("$retract_clause"),
|
||||||
@@ -508,6 +510,7 @@ impl SystemClauseType {
|
|||||||
("$nextEP", 3) => Some(SystemClauseType::NextEP),
|
("$nextEP", 3) => Some(SystemClauseType::NextEP),
|
||||||
("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
|
("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
|
||||||
("$read_term", 2) => Some(SystemClauseType::ReadTerm),
|
("$read_term", 2) => Some(SystemClauseType::ReadTerm),
|
||||||
|
("$read_term_from_chars", 2) => Some(SystemClauseType::ReadTermFromChars),
|
||||||
("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
|
("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
|
||||||
("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
|
("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
|
||||||
("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
|
("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
|
||||||
|
|||||||
@@ -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, _) :-
|
write_term_to_chars(_, Options, _) :-
|
||||||
var(Options), throw(error(instantiation_error, write_term_to_chars/3)).
|
var(Options), throw(error(instantiation_error, write_term_to_chars/3)).
|
||||||
|
|||||||
@@ -145,7 +145,8 @@ impl DomainError for Number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MachineError {
|
impl MachineError {
|
||||||
pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
|
pub(super)
|
||||||
|
fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
|
||||||
functor!(
|
functor!(
|
||||||
"/",
|
"/",
|
||||||
SharedOpDesc::new(400, YFX),
|
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())]);
|
let stub = functor!("evaluation_error", [atom(eval_error.as_str())]);
|
||||||
|
|
||||||
MachineError {
|
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)
|
pub(super)
|
||||||
fn session_error(h: usize, err: SessionError) -> Self {
|
fn session_error(h: usize, err: SessionError) -> Self {
|
||||||
match err {
|
match err {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
use prolog_parser::tabled_rc::*;
|
||||||
|
|
||||||
use crate::prolog::clause_types::*;
|
use crate::prolog::clause_types::*;
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
@@ -11,6 +12,7 @@ use crate::prolog::machine::machine_indices::*;
|
|||||||
use crate::prolog::machine::modules::*;
|
use crate::prolog::machine::modules::*;
|
||||||
use crate::prolog::machine::stack::*;
|
use crate::prolog::machine::stack::*;
|
||||||
use crate::prolog::machine::streams::*;
|
use crate::prolog::machine::streams::*;
|
||||||
|
use crate::prolog::read::readline;
|
||||||
use crate::prolog::rug::Integer;
|
use crate::prolog::rug::Integer;
|
||||||
|
|
||||||
use downcast::Any;
|
use downcast::Any;
|
||||||
@@ -492,6 +494,63 @@ pub struct MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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)
|
pub(crate)
|
||||||
fn write_term<'a>(
|
fn write_term<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
|
|||||||
@@ -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]
|
#[inline]
|
||||||
fn install_new_block(&mut self, r: RegType) -> usize {
|
fn install_new_block(&mut self, r: RegType) -> usize {
|
||||||
self.block = self.b;
|
self.block = self.b;
|
||||||
@@ -2479,6 +2423,15 @@ impl MachineState {
|
|||||||
|
|
||||||
self.unify(target, module);
|
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!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -3062,6 +3015,44 @@ impl MachineState {
|
|||||||
readline::set_prompt(false);
|
readline::set_prompt(false);
|
||||||
self.read_term(current_input_stream, indices)?;
|
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 => {
|
&SystemClauseType::ResetBlock => {
|
||||||
let addr = self.deref(self[temp_v!(1)]);
|
let addr = self.deref(self[temp_v!(1)]);
|
||||||
self.reset_block(addr);
|
self.reset_block(addr);
|
||||||
|
|||||||
@@ -208,10 +208,7 @@ impl<'a> TermWriter<'a> {
|
|||||||
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) |
|
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) |
|
||||||
&TermRef::Var(Level::Root, ..) => {
|
&TermRef::Var(Level::Root, ..) => {
|
||||||
let addr = self.term_as_addr(&term, h);
|
let addr = self.term_as_addr(&term, h);
|
||||||
|
self.machine_st.heap.push(HeapCellValue::Addr(addr));
|
||||||
if !addr.is_heap_bound() {
|
|
||||||
self.machine_st.heap.push(HeapCellValue::Addr(addr));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&TermRef::AnonVar(_) => {
|
&TermRef::AnonVar(_) => {
|
||||||
if let Some((arity, site_h)) = self.queue.pop_front() {
|
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||||
|
|||||||
Reference in New Issue
Block a user