re: issue #120
This commit is contained in:
@@ -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(),
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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!()
|
||||
|
||||
@@ -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![];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user