[package]
name = "scryer-prolog"
-version = "0.8.67"
+version = "0.8.68"
repository = "https://github.com/mthom/scryer-prolog"
description = "A modern Prolog implementation written mostly in Rust."
fn char_to_string(c: char) -> String {
match c {
+ '\'' => "\\'".to_string(),
'\n' => "\\n".to_string(),
'\r' => "\\r".to_string(),
'\t' => "\\t".to_string(),
}
}
+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 {
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)
},
*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>
{
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};
}
}
-impl MachineState {
+impl MachineState {
// a step in Brent's algorithm.
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
{
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!()
}
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() }
}
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);
}
}
-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)?;
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);
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);
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 }
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);
}
}
- 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![];
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 | _]"]]);