re: issue #120
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scryer-prolog"
|
name = "scryer-prolog"
|
||||||
version = "0.8.67"
|
version = "0.8.68"
|
||||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||||
repository = "https://github.com/mthom/scryer-prolog"
|
repository = "https://github.com/mthom/scryer-prolog"
|
||||||
description = "A modern Prolog implementation written mostly in Rust."
|
description = "A modern Prolog implementation written mostly in Rust."
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
|
|
||||||
fn char_to_string(c: char) -> String {
|
fn char_to_string(c: char) -> String {
|
||||||
match c {
|
match c {
|
||||||
|
'\'' => "\\'".to_string(),
|
||||||
'\n' => "\\n".to_string(),
|
'\n' => "\\n".to_string(),
|
||||||
'\r' => "\\r".to_string(),
|
'\r' => "\\r".to_string(),
|
||||||
'\t' => "\\t".to_string(),
|
'\t' => "\\t".to_string(),
|
||||||
|
|||||||
@@ -320,6 +320,26 @@ fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn try_char_list(addrs: Vec<Addr>) -> Result<String, MachineError>
|
||||||
|
{
|
||||||
|
let mut chars = String::new();
|
||||||
|
|
||||||
|
for addr in addrs.iter() {
|
||||||
|
match addr {
|
||||||
|
&Addr::Con(Constant::Char(c)) =>
|
||||||
|
chars.push(c),
|
||||||
|
&Addr::Con(Constant::Atom(ref name, _))
|
||||||
|
if name.as_str().len() == 1 => {
|
||||||
|
chars += name.as_str();
|
||||||
|
},
|
||||||
|
_ =>
|
||||||
|
return Err(MachineError::type_error(ValidType::Character, addr.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(chars)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
|
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
|
||||||
|
|
||||||
pub(crate) trait CallPolicy: Any {
|
pub(crate) trait CallPolicy: Any {
|
||||||
@@ -635,15 +655,11 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
},
|
},
|
||||||
&BuiltInClauseType::PartialString => {
|
&BuiltInClauseType::PartialString => {
|
||||||
let a1 = machine_st[temp_v!(1)].clone();
|
let mut s = machine_st.try_string_list(temp_v!(1))?;
|
||||||
let a2 = machine_st[temp_v!(2)].clone();
|
let a2 = machine_st[temp_v!(2)].clone();
|
||||||
|
|
||||||
if let Addr::Con(Constant::String(s)) = a1 {
|
s.set_expandable(true);
|
||||||
s.set_expandable(true);
|
machine_st.write_constant_to_var(a2, Constant::String(s));
|
||||||
machine_st.write_constant_to_var(a2, Constant::String(s));
|
|
||||||
} else {
|
|
||||||
machine_st.fail = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2165,6 +2165,29 @@ impl MachineState {
|
|||||||
*list = result;
|
*list = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn try_string_list(&self, r: RegType) -> Result<StringList, MachineStub> {
|
||||||
|
let a1 = self[r].clone();
|
||||||
|
let a1 = self.store(self.deref(a1));
|
||||||
|
|
||||||
|
if let Addr::Con(Constant::String(s)) = a1 {
|
||||||
|
return Ok(s);
|
||||||
|
} else {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("partial_string"), 2);
|
||||||
|
|
||||||
|
match self.try_from_list(r, stub.clone()) {
|
||||||
|
Ok(addrs) =>
|
||||||
|
Ok(StringList::new(match try_char_list(addrs) {
|
||||||
|
Ok(string) => string,
|
||||||
|
Err(err) => {
|
||||||
|
return Err(self.error_form(err, stub));
|
||||||
|
}
|
||||||
|
}, false)),
|
||||||
|
Err(err) => return Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn try_from_list(&self, r: RegType, caller: MachineStub) -> Result<Vec<Addr>, MachineStub>
|
fn try_from_list(&self, r: RegType, caller: MachineStub) -> Result<Vec<Addr>, MachineStub>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use prolog::machine::copier::*;
|
|||||||
use prolog::machine::machine_errors::*;
|
use prolog::machine::machine_errors::*;
|
||||||
use prolog::machine::machine_indices::*;
|
use prolog::machine::machine_indices::*;
|
||||||
use prolog::machine::machine_state::*;
|
use prolog::machine::machine_state::*;
|
||||||
use prolog::machine::toplevel::to_op_decl;
|
use prolog::machine::toplevel::{to_op_decl};
|
||||||
use prolog::num::{FromPrimitive, ToPrimitive, Zero};
|
use prolog::num::{FromPrimitive, ToPrimitive, Zero};
|
||||||
use prolog::num::bigint::{BigInt};
|
use prolog::num::bigint::{BigInt};
|
||||||
use prolog::read::{PrologStream, readline};
|
use prolog::read::{PrologStream, readline};
|
||||||
@@ -35,7 +35,7 @@ impl BrentAlgState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
// a step in Brent's algorithm.
|
// a step in Brent's algorithm.
|
||||||
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
|
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
|
||||||
{
|
{
|
||||||
@@ -393,28 +393,15 @@ impl MachineState {
|
|||||||
|
|
||||||
match self.try_from_list(temp_v!(2), stub.clone()) {
|
match self.try_from_list(temp_v!(2), stub.clone()) {
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
Ok(addrs) => {
|
Ok(addrs) =>
|
||||||
let mut chars = String::new();
|
match try_char_list(addrs) {
|
||||||
|
Ok(string) => {
|
||||||
for addr in addrs.iter() {
|
let chars = clause_name!(string, indices.atom_tbl);
|
||||||
match addr {
|
self.unify(addr.clone(), Addr::Con(Constant::Atom(chars, None)));
|
||||||
&Addr::Con(Constant::Char(c)) =>
|
},
|
||||||
chars.push(c),
|
Err(err) =>
|
||||||
&Addr::Con(Constant::Atom(ref name, _))
|
return Err(self.error_form(err, stub))
|
||||||
if name.as_str().len() == 1 => {
|
}
|
||||||
chars += name.as_str();
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
let err = MachineError::type_error(ValidType::Character,
|
|
||||||
addr.clone());
|
|
||||||
return Err(self.error_form(err, stub));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let chars = clause_name!(chars, indices.atom_tbl);
|
|
||||||
self.unify(addr.clone(), Addr::Con(Constant::Atom(chars, None)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
|
|||||||
@@ -390,13 +390,15 @@ pub enum TopLevelPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct RelationWorker {
|
struct RelationWorker {
|
||||||
|
flags: MachineFlags,
|
||||||
dynamic_clauses: Vec<(Term, Term)>, // Head, Body.
|
dynamic_clauses: Vec<(Term, Term)>, // Head, Body.
|
||||||
queue: VecDeque<VecDeque<Term>>,
|
queue: VecDeque<VecDeque<Term>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RelationWorker {
|
impl RelationWorker {
|
||||||
fn new() -> Self {
|
fn new(flags: MachineFlags) -> Self {
|
||||||
RelationWorker { dynamic_clauses: vec![],
|
RelationWorker { dynamic_clauses: vec![],
|
||||||
|
flags,
|
||||||
queue: VecDeque::new() }
|
queue: VecDeque::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,14 +540,8 @@ impl RelationWorker {
|
|||||||
Err(ParserError::InadmissibleQueryTerm)
|
Err(ParserError::InadmissibleQueryTerm)
|
||||||
},
|
},
|
||||||
("partial_string", 2) => {
|
("partial_string", 2) => {
|
||||||
if let Term::Constant(_, Constant::String(_)) = *terms[0].clone() {
|
let ct = ClauseType::BuiltIn(BuiltInClauseType::PartialString);
|
||||||
if let Term::Var(..) = *terms[1].clone() {
|
return Ok(QueryTerm::Clause(Cell::default(), ct, terms, false));
|
||||||
let ct = ClauseType::BuiltIn(BuiltInClauseType::PartialString);
|
|
||||||
return Ok(QueryTerm::Clause(Cell::default(), ct, terms, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(ParserError::InadmissibleQueryTerm)
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let ct = indices.get_clause_type(name, terms.len(), fixity);
|
let ct = indices.get_clause_type(name, terms.len(), fixity);
|
||||||
@@ -768,11 +764,11 @@ impl RelationWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn term_to_toplevel<R>(term_stream: &mut TermStream<R>, code_dir: &mut CodeDir, term: Term)
|
fn term_to_toplevel<R>(term_stream: &mut TermStream<R>, code_dir: &mut CodeDir, term: Term, flags: MachineFlags)
|
||||||
-> Result<(TopLevel, RelationWorker), ParserError>
|
-> Result<(TopLevel, RelationWorker), ParserError>
|
||||||
where R: Read
|
where R: Read
|
||||||
{
|
{
|
||||||
let mut rel_worker = RelationWorker::new();
|
let mut rel_worker = RelationWorker::new(flags);
|
||||||
let mut indices = composite_indices!(false, term_stream.indices, code_dir);
|
let mut indices = composite_indices!(false, term_stream.indices, code_dir);
|
||||||
|
|
||||||
let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
|
let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
|
||||||
@@ -784,6 +780,7 @@ pub
|
|||||||
fn stream_to_toplevel<R: Read>(mut buffer: ParsingStream<R>, wam: &mut Machine)
|
fn stream_to_toplevel<R: Read>(mut buffer: ParsingStream<R>, wam: &mut Machine)
|
||||||
-> Result<TopLevelPacket, SessionError>
|
-> Result<TopLevelPacket, SessionError>
|
||||||
{
|
{
|
||||||
|
let flags = wam.machine_flags();
|
||||||
let mut term_stream = TermStream::new(&mut buffer, wam.indices.atom_tbl(),
|
let mut term_stream = TermStream::new(&mut buffer, wam.indices.atom_tbl(),
|
||||||
wam.machine_flags(), &mut wam.indices,
|
wam.machine_flags(), &mut wam.indices,
|
||||||
&mut wam.policies, &mut wam.code_repo);
|
&mut wam.policies, &mut wam.code_repo);
|
||||||
@@ -791,9 +788,9 @@ fn stream_to_toplevel<R: Read>(mut buffer: ParsingStream<R>, wam: &mut Machine)
|
|||||||
term_stream.add_to_top("?- ");
|
term_stream.add_to_top("?- ");
|
||||||
|
|
||||||
let term = term_stream.read_term(&OpDir::new())?;
|
let term = term_stream.read_term(&OpDir::new())?;
|
||||||
let mut code_dir = CodeDir::new();
|
let mut code_dir = CodeDir::new();
|
||||||
|
|
||||||
let (tl, mut rel_worker) = term_to_toplevel(&mut term_stream, &mut code_dir, term)?;
|
let (tl, mut rel_worker) = term_to_toplevel(&mut term_stream, &mut code_dir, term, flags)?;
|
||||||
rel_worker.expand_queue_contents(&mut term_stream, &OpDir::new())?;
|
rel_worker.expand_queue_contents(&mut term_stream, &OpDir::new())?;
|
||||||
|
|
||||||
let mut indices = composite_indices!(false, term_stream.indices, &mut code_dir);
|
let mut indices = composite_indices!(false, term_stream.indices, &mut code_dir);
|
||||||
@@ -823,7 +820,7 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
|
|||||||
indices, policies, code_repo);
|
indices, policies, code_repo);
|
||||||
|
|
||||||
TopLevelBatchWorker { term_stream,
|
TopLevelBatchWorker { term_stream,
|
||||||
rel_worker: RelationWorker::new(),
|
rel_worker: RelationWorker::new(flags),
|
||||||
results: vec![],
|
results: vec![],
|
||||||
dynamic_clause_map: HashMap::new(),
|
dynamic_clause_map: HashMap::new(),
|
||||||
in_module: false }
|
in_module: false }
|
||||||
@@ -832,7 +829,7 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
|
|||||||
fn try_term_to_tl(&self, indices: &mut IndexStore, term: Term)
|
fn try_term_to_tl(&self, indices: &mut IndexStore, term: Term)
|
||||||
-> Result<(TopLevel, RelationWorker), SessionError>
|
-> Result<(TopLevel, RelationWorker), SessionError>
|
||||||
{
|
{
|
||||||
let mut new_rel_worker = RelationWorker::new();
|
let mut new_rel_worker = RelationWorker::new(self.rel_worker.flags);
|
||||||
let mut indices = composite_indices!(self.in_module, indices,
|
let mut indices = composite_indices!(self.in_module, indices,
|
||||||
&self.term_stream.indices.code_dir);
|
&self.term_stream.indices.code_dir);
|
||||||
|
|
||||||
@@ -877,7 +874,8 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn consume(&mut self, indices: &mut IndexStore) -> Result<Option<Declaration>, SessionError>
|
pub fn consume(&mut self, indices: &mut IndexStore)
|
||||||
|
-> Result<Option<Declaration>, SessionError>
|
||||||
{
|
{
|
||||||
let mut preds = vec![];
|
let mut preds = vec![];
|
||||||
|
|
||||||
|
|||||||
@@ -2391,7 +2391,7 @@ fn test_queries_on_string_lists()
|
|||||||
assert_prolog_success!(&mut wam, "partial_string(\"appendy\", X), f(X).",
|
assert_prolog_success!(&mut wam, "partial_string(\"appendy\", X), f(X).",
|
||||||
[["X = [a, p, p, e, n, d, y, ' ', j, o, n, e, s]"],
|
[["X = [a, p, p, e, n, d, y, ' ', j, o, n, e, s]"],
|
||||||
["X = [a, p, p, e, n, d, y, ' ', s, m, i, t, h, e, r, s, ' ', j, o, n, e, s]"],
|
["X = [a, p, p, e, n, d, y, ' ', s, m, i, t, h, e, r, s, ' ', j, o, n, e, s]"],
|
||||||
["X = [a, p, p, e, n, d, y, ' ', o, ''', t, o, o, l, e]"]]);
|
["X = [a, p, p, e, n, d, y, ' ', o, '\\'', t, o, o, l, e]"]]);
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abcdef\", X).",
|
assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abcdef\", X).",
|
||||||
[["X = [a, b, c, d, e, f | _]"]]);
|
[["X = [a, b, c, d, e, f | _]"]]);
|
||||||
|
|||||||
Reference in New Issue
Block a user