correct various bugs

This commit is contained in:
Mark Thom
2019-04-28 21:09:56 -06:00
parent 918da4f423
commit 9dbadac14f
6 changed files with 145 additions and 57 deletions

View File

@@ -1,4 +1,5 @@
use prolog_parser::ast::*;
use prolog_parser::string_list::*;
use prolog::machine::machine_indices::*;
use prolog::machine::machine_state::*;
@@ -273,6 +274,7 @@ pub(super) enum CycleSearchResult {
NotList,
PartialList(usize, usize), // the list length (up to max), and an offset into the heap.
ProperList(usize), // the list length.
String(usize, StringList), // the number of elements iterated, the string tail.
UntouchedList(usize) // the address of an uniterated Addr::Lis(address).
}

View File

@@ -239,6 +239,36 @@ pub struct MachineState {
}
impl MachineState {
pub(super)
fn try_char_list(&self, addrs: Vec<Addr>) -> Result<String, MachineError>
{
let mut chars = String::new();
let mut iter = addrs.iter();
while let Some(addr) = iter.next() {
match addr {
&Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() => {
chars += s.borrow().as_str();
if iter.next().is_some() {
return Err(MachineError::type_error(ValidType::Character, addr.clone()));
}
},
&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)
}
fn call_at_index(&mut self, arity: usize, p: usize)
{
self.cp.assign_if_local(self.p.clone() + 1);
@@ -320,27 +350,6 @@ 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 {

View File

@@ -1691,6 +1691,21 @@ impl MachineState {
} else {
self.fail = true;
},
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() && !s.is_empty() => {
if n == 1 || n == 2 {
let a3 = self[temp_v!(3)].clone();
let h_a = if n == 1 {
Addr::Con(Constant::Char(s.head().unwrap()))
} else {
Addr::Con(Constant::String(s.tail()))
};
self.unify(a3, h_a);
} else {
self.fail = true;
}
},
_ => // 8.5.2.3 d)
return Err(self.error_form(MachineError::type_error(ValidType::Compound, term),
stub))
@@ -2089,6 +2104,11 @@ impl MachineState {
match a1.clone() {
Addr::DBRef(_) =>
self.fail = true,
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() && !s.is_empty() => {
let shared_op_desc = fetch_op_spec(clause_name!("."), 2, None, &indices.op_dir);
self.try_functor_compound_case(clause_name!("."), 2, shared_op_desc)
},
Addr::Con(_) =>
self.try_functor_unify_components(a1, Addr::Con(integer!(0))),
Addr::Str(o) =>
@@ -2187,7 +2207,7 @@ impl MachineState {
match self.try_from_list(r, stub.clone()) {
Ok(addrs) =>
Ok(StringList::new(match try_char_list(addrs) {
Ok(StringList::new(match self.try_char_list(addrs) {
Ok(string) => string,
Err(err) => {
return Err(self.error_form(err, stub));
@@ -2218,6 +2238,11 @@ impl MachineState {
result.push(self.heap[hcp].as_addr(hcp));
l = hcp + 1;
},
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() => {
result.push(Addr::Con(Constant::String(s.clone())));
break;
},
Addr::Con(Constant::EmptyList) =>
break,
Addr::HeapCell(_) | Addr::StackCell(..) =>
@@ -2229,11 +2254,13 @@ impl MachineState {
_ =>
return Err(self.error_form(MachineError::type_error(ValidType::List, a1),
caller))
};
}
}
Ok(result)
},
Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_chars() =>
Ok(vec![Addr::Con(Constant::String(s.clone()))]),
Addr::HeapCell(_) | Addr::StackCell(..) =>
Err(self.error_form(MachineError::instantiation_error(), caller)),
Addr::Con(Constant::EmptyList) =>

View File

@@ -1,5 +1,6 @@
use prolog_parser::ast::*;
use prolog_parser::parser::*;
use prolog_parser::string_list::*;
use prolog_parser::tabled_rc::*;
use prolog::clause_types::*;
@@ -49,6 +50,9 @@ impl MachineState {
Some(CycleSearchResult::ProperList(brent_st.steps)),
Addr::HeapCell(_) | Addr::StackCell(..) =>
Some(CycleSearchResult::PartialList(brent_st.steps, brent_st.hare)),
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() =>
Some(CycleSearchResult::String(brent_st.steps, s.clone())),
Addr::Lis(l) => {
brent_st.hare = l + 1;
brent_st.steps += 1;
@@ -75,6 +79,9 @@ impl MachineState {
Addr::Lis(offset) if max_steps > 0 => offset + 1,
Addr::Lis(offset) => return CycleSearchResult::UntouchedList(offset),
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() =>
return CycleSearchResult::String(0, s.clone()),
_ => return CycleSearchResult::NotList
};
@@ -97,6 +104,9 @@ impl MachineState {
let hare = match addr {
Addr::Lis(offset) => offset + 1,
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() =>
return CycleSearchResult::String(0, s.clone()),
_ => return CycleSearchResult::NotList
};
@@ -135,18 +145,35 @@ impl MachineState {
self.unify(xs0, xs);
},
_ => {
let search_result = if let Some(max_steps) = max_steps.to_isize() {
if max_steps == -1 {
self.detect_cycles(self[temp_v!(3)].clone())
let (max_steps, search_result) =
if let Some(max_steps) = max_steps.to_isize() {
(max_steps, if max_steps == -1 {
self.detect_cycles(self[temp_v!(3)].clone())
} else {
self.detect_cycles_with_max(max_steps as usize,
self[temp_v!(3)].clone())
})
} else {
self.detect_cycles_with_max(max_steps as usize,
self[temp_v!(3)].clone())
}
} else {
self.detect_cycles(self[temp_v!(3)].clone())
};
(-1, self.detect_cycles(self[temp_v!(3)].clone()))
};
match search_result {
CycleSearchResult::String(n, s) =>
if max_steps == -1 {
self.finalize_skip_max_list(n + s.len(),
Addr::Con(Constant::EmptyList))
} else {
let i = max_steps.to_usize().unwrap() - n;
if s.len() < i {
self.finalize_skip_max_list(n + s.len(),
Addr::Con(Constant::EmptyList))
} else {
let s = StringList::new(s.char_span(i), s.is_expandable());
self.finalize_skip_max_list(i + n,
Addr::Con(Constant::String(s)))
}
},
CycleSearchResult::UntouchedList(l) =>
self.finalize_skip_max_list(0, Addr::Lis(l)),
CycleSearchResult::EmptyList =>
@@ -395,7 +422,7 @@ impl MachineState {
match self.try_from_list(temp_v!(2), stub.clone()) {
Err(e) => return Err(e),
Ok(addrs) =>
match try_char_list(addrs) {
match self.try_char_list(addrs) {
Ok(string) => {
let chars = clause_name!(string, indices.atom_tbl);
self.unify(addr.clone(), Addr::Con(Constant::Atom(chars, None)));
@@ -453,7 +480,7 @@ impl MachineState {
&Addr::Con(Constant::CharCode(c)) =>
chars.push(c as char),
_ => {
let err = MachineError::representation_error(RepFlag::CharacterCode);
let err = MachineError::type_error(ValidType::Integer, addr.clone());
return Err(self.error_form(err, stub));
}
}
@@ -489,19 +516,19 @@ impl MachineState {
match self.try_from_list(temp_v!(1), stub.clone()) {
Err(e) => return Err(e),
Ok(addrs) =>
match try_char_list(addrs) {
match self.try_char_list(addrs) {
Ok(mut string) => {
if let Some(c) = string.chars().last() {
if layout_char!(c) {
let err = ParserError::UnexpectedChar(c);
let h = self.heap.h;
let err = MachineError::syntax_error(h, err);
return Err(self.error_form(err, stub));
}
}
string.push('.');
let mut stream = parsing_stream(std::io::Cursor::new(string));
@@ -521,7 +548,7 @@ impl MachineState {
self.unify(nx, Addr::Con(Constant::CharCode(c))),
_ => {
let err = ParserError::ParseBigInt;
let h = self.heap.h;
let err = MachineError::syntax_error(h, err);