fix offsetting of heap in existence errors

This commit is contained in:
Mark Thom
2018-05-20 16:26:52 -06:00
parent a60af300fd
commit 4608c4fe58
5 changed files with 228 additions and 170 deletions

View File

@@ -4,9 +4,79 @@ use prolog::num::bigint::BigInt;
use std::rc::Rc;
pub(super) type MachineError = Vec<HeapCellValue>;
pub(super) type MachineStub = Vec<HeapCellValue>;
#[derive(Clone, Copy)]
enum ErrorProvenance {
Constructed, // if constructed, offset the addresses.
Received // otherwise, preserve the addresses.
}
pub(super) struct MachineError {
stub: MachineStub,
from: ErrorProvenance
}
impl MachineError {
pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name)));
functor!("/", 2, [name, heap_integer!(arity)], Fixity::In)
}
pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]);
MachineError { stub, from: ErrorProvenance::Received }
}
pub(super) fn type_error(valid_type: ValidType, culprit: Addr) -> Self {
let stub = functor!("type_error", 2, [heap_atom!(valid_type.as_str()),
HeapCellValue::Addr(culprit)]);
MachineError { stub, from: ErrorProvenance::Received }
}
pub(super) fn existence_error(h: usize, name: ClauseName, arity: usize) -> Self {
let mut stub = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
stub.append(&mut Self::functor_stub(name, arity));
MachineError { stub, from: ErrorProvenance::Constructed }
}
pub(super) fn domain_error(error: DomainError, culprit: Addr) -> Self {
let stub = functor!("domain_error", 2, [heap_atom!(error.as_str()),
HeapCellValue::Addr(culprit)]);
MachineError { stub, from: ErrorProvenance::Received }
}
pub(super) fn instantiation_error() -> Self {
let stub = functor!("instantiation_error");
MachineError { stub, from: ErrorProvenance::Received }
}
pub(super) fn representation_error(flag: RepFlag) -> Self {
let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]);
MachineError { stub, from: ErrorProvenance::Received }
}
fn into_iter(self, offset: usize) -> Box<Iterator<Item=HeapCellValue>> {
match self.from {
ErrorProvenance::Constructed =>
Box::new(self.stub.into_iter().map(move |hcv| {
match hcv {
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr + offset),
hcv => hcv
}
})),
ErrorProvenance::Received =>
Box::new(self.stub.into_iter())
}
}
fn len(&self) -> usize {
self.stub.len()
}
}
// from 7.12.2 b) of 13211-1:1995
#[derive(Clone, Copy)]
pub enum ValidType {
@@ -119,32 +189,32 @@ pub(super) enum CycleSearchResult {
impl MachineState {
// see 8.4.3 of Draft Technical Corrigendum 2.
pub(super) fn check_sort_errors(&self) -> Result<(), MachineError> {
let stub = self.functor_stub(clause_name!("sort"), 2);
pub(super) fn check_sort_errors(&self) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
let list = self.store(self.deref(self[temp_v!(1)].clone()));
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
match self.detect_cycles(list.clone()) {
CycleSearchResult::PartialList(..) =>
Err(self.error_form(self.instantiation_error(), stub.clone())),
return Err(self.error_form(MachineError::instantiation_error(), stub)),
CycleSearchResult::NotList =>
Err(self.error_form(self.type_error(ValidType::List, list), stub.clone())),
_ => Ok(())
}?;
return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub)),
_ => {}
};
match self.detect_cycles(sorted.clone()) {
CycleSearchResult::NotList if !sorted.is_ref() =>
Err(self.error_form(self.type_error(ValidType::List, sorted), stub)),
Err(self.error_form(MachineError::type_error(ValidType::List, sorted), stub)),
_ => Ok(())
}
}
fn check_for_list_pairs(&self, list: Addr) -> Result<(), MachineError> {
let stub = self.functor_stub(clause_name!("keysort"), 2);
fn check_for_list_pairs(&self, list: Addr) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
match self.detect_cycles(list.clone()) {
CycleSearchResult::NotList if !list.is_ref() =>
Err(self.error_form(self.type_error(ValidType::List, list), stub)),
Err(self.error_form(MachineError::type_error(ValidType::List, list), stub)),
_ => {
let mut addr = list;
@@ -158,8 +228,8 @@ impl MachineState {
if name.as_str() == "-" => break,
HeapCellValue::Addr(Addr::HeapCell(_)) => break,
HeapCellValue::Addr(Addr::StackCell(..)) => break,
_ => return Err(self.error_form(self.type_error(ValidType::Pair,
Addr::HeapCell(l)),
_ => return Err(self.error_form(MachineError::type_error(ValidType::Pair,
Addr::HeapCell(l)),
stub))
};
}
@@ -173,70 +243,35 @@ impl MachineState {
}
// see 8.4.4 of Draft Technical Corrigendum 2.
pub(super) fn check_keysort_errors(&self) -> Result<(), MachineError> {
let stub = self.functor_stub(clause_name!("keysort"), 2);
pub(super) fn check_keysort_errors(&self) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
match self.detect_cycles(pairs.clone()) {
CycleSearchResult::PartialList(..) =>
Err(self.error_form(self.instantiation_error(), stub)),
Err(self.error_form(MachineError::instantiation_error(), stub)),
CycleSearchResult::NotList =>
Err(self.error_form(self.type_error(ValidType::List, pairs), stub)),
Err(self.error_form(MachineError::type_error(ValidType::List, pairs), stub)),
_ => Ok(())
}?;
self.check_for_list_pairs(sorted)
}
pub(super) fn functor_stub(&self, name: ClauseName, arity: usize) -> MachineStub {
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name)));
functor!("/", 2, [name, heap_integer!(arity)], Fixity::In)
}
pub(super) fn evaluation_error(&self, eval_error: EvalError) -> MachineError {
functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())])
}
pub(super) fn type_error(&self, valid_type: ValidType, culprit: Addr) -> MachineError {
functor!("type_error", 2, [heap_atom!(valid_type.as_str()), HeapCellValue::Addr(culprit)])
}
pub(super) fn existence_error(&self, name: ClauseName, arity: usize) -> MachineError {
pub(super) fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub {
let h = self.heap.h;
let mut stub = vec![HeapCellValue::NamedStr(2, clause_name!("error"), None),
HeapCellValue::Addr(Addr::HeapCell(h + 3)),
HeapCellValue::Addr(Addr::HeapCell(h + 3 + err.len()))];
let mut error = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
error.append(&mut self.functor_stub(name, arity));
stub.extend(err.into_iter(3));
stub.extend(src.into_iter());
error
stub
}
pub(super) fn domain_error(&self, error: DomainError, culprit: Addr) -> MachineError {
functor!("domain_error", 2, [heap_atom!(error.as_str()), HeapCellValue::Addr(culprit)])
}
pub(super) fn instantiation_error(&self) -> MachineError {
functor!("instantiation_error")
}
pub(super) fn representation_error(&self, flag: RepFlag) -> MachineError {
functor!("representation_error", 1, [heap_atom!(flag.as_str())])
}
pub(super) fn error_form(&self, err: MachineError, src: MachineStub) -> MachineError {
let h = self.heap.h;
let mut error_form = vec![HeapCellValue::NamedStr(2, clause_name!("error"), None),
HeapCellValue::Addr(Addr::HeapCell(h + 3)),
HeapCellValue::Addr(Addr::HeapCell(h + 3 + err.len()))];
error_form.extend(err.into_iter());
error_form.extend(src.into_iter());
error_form
}
pub(super) fn throw_exception(&mut self, err: MachineError) {
pub(super) fn throw_exception(&mut self, err: MachineStub) {
let h = self.heap.h;
self.ball.boundary = 0;