This commit is contained in:
Mark Thom
2019-04-27 00:40:00 -06:00
parent 7bda7c5bf3
commit 531d8b3352
7 changed files with 74 additions and 49 deletions

View File

@@ -1,6 +1,6 @@
[package]
name = "scryer-prolog"
version = "0.8.67"
version = "0.8.68"
authors = ["Mark Thom <markjordanthom@gmail.com>"]
repository = "https://github.com/mthom/scryer-prolog"
description = "A modern Prolog implementation written mostly in Rust."

View File

@@ -137,6 +137,7 @@ impl<'a> HCPreOrderIterator<'a> {
fn char_to_string(c: char) -> String {
match c {
'\'' => "\\'".to_string(),
'\n' => "\\n".to_string(),
'\r' => "\\r".to_string(),
'\t' => "\\t".to_string(),

View File

@@ -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) trait CallPolicy: Any {
@@ -635,15 +655,11 @@ pub(crate) trait CallPolicy: Any {
return_from_clause!(machine_st.last_call, machine_st)
},
&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();
if let Addr::Con(Constant::String(s)) = a1 {
s.set_expandable(true);
machine_st.write_constant_to_var(a2, Constant::String(s));
} else {
machine_st.fail = true;
}
s.set_expandable(true);
machine_st.write_constant_to_var(a2, Constant::String(s));
return_from_clause!(machine_st.last_call, machine_st)
},

View File

@@ -2165,6 +2165,29 @@ impl MachineState {
*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)
fn try_from_list(&self, r: RegType, caller: MachineStub) -> Result<Vec<Addr>, MachineStub>
{

View File

@@ -9,7 +9,7 @@ use prolog::machine::copier::*;
use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*;
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::bigint::{BigInt};
use prolog::read::{PrologStream, readline};
@@ -35,7 +35,7 @@ impl BrentAlgState {
}
}
impl MachineState {
impl MachineState {
// a step in Brent's algorithm.
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()) {
Err(e) => return Err(e),
Ok(addrs) => {
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();
},
_ => {
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)));
}
Ok(addrs) =>
match try_char_list(addrs) {
Ok(string) => {
let chars = clause_name!(string, indices.atom_tbl);
self.unify(addr.clone(), Addr::Con(Constant::Atom(chars, None)));
},
Err(err) =>
return Err(self.error_form(err, stub))
}
}
},
_ => unreachable!()

View File

@@ -390,13 +390,15 @@ pub enum TopLevelPacket {
}
struct RelationWorker {
flags: MachineFlags,
dynamic_clauses: Vec<(Term, Term)>, // Head, Body.
queue: VecDeque<VecDeque<Term>>,
}
impl RelationWorker {
fn new() -> Self {
fn new(flags: MachineFlags) -> Self {
RelationWorker { dynamic_clauses: vec![],
flags,
queue: VecDeque::new() }
}
@@ -538,14 +540,8 @@ impl RelationWorker {
Err(ParserError::InadmissibleQueryTerm)
},
("partial_string", 2) => {
if let Term::Constant(_, Constant::String(_)) = *terms[0].clone() {
if let Term::Var(..) = *terms[1].clone() {
let ct = ClauseType::BuiltIn(BuiltInClauseType::PartialString);
return Ok(QueryTerm::Clause(Cell::default(), ct, terms, false));
}
}
Err(ParserError::InadmissibleQueryTerm)
let ct = ClauseType::BuiltIn(BuiltInClauseType::PartialString);
return Ok(QueryTerm::Clause(Cell::default(), ct, terms, false));
},
_ => {
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>
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 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)
-> Result<TopLevelPacket, SessionError>
{
let flags = wam.machine_flags();
let mut term_stream = TermStream::new(&mut buffer, wam.indices.atom_tbl(),
wam.machine_flags(), &mut wam.indices,
&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("?- ");
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())?;
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);
TopLevelBatchWorker { term_stream,
rel_worker: RelationWorker::new(),
rel_worker: RelationWorker::new(flags),
results: vec![],
dynamic_clause_map: HashMap::new(),
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)
-> 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,
&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![];

View File

@@ -2391,7 +2391,7 @@ fn test_queries_on_string_lists()
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, ' ', 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).",
[["X = [a, b, c, d, e, f | _]"]]);