fix offsetting of heap in existence errors
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user