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

@@ -61,6 +61,7 @@ pub(crate) trait CopierTarget
} }
list_redirect.insert(a, self.threshold()); list_redirect.insert(a, self.threshold());
self[scan] = HeapCellValue::Addr(Addr::Lis(self.threshold())); self[scan] = HeapCellValue::Addr(Addr::Lis(self.threshold()));
let hcv = self[a].clone(); let hcv = self[a].clone();

View File

@@ -4,9 +4,79 @@ use prolog::num::bigint::BigInt;
use std::rc::Rc; use std::rc::Rc;
pub(super) type MachineError = Vec<HeapCellValue>;
pub(super) type MachineStub = 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 // from 7.12.2 b) of 13211-1:1995
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum ValidType { pub enum ValidType {
@@ -119,32 +189,32 @@ pub(super) enum CycleSearchResult {
impl MachineState { impl MachineState {
// see 8.4.3 of Draft Technical Corrigendum 2. // see 8.4.3 of Draft Technical Corrigendum 2.
pub(super) fn check_sort_errors(&self) -> Result<(), MachineError> { pub(super) fn check_sort_errors(&self) -> CallResult {
let stub = self.functor_stub(clause_name!("sort"), 2); let stub = MachineError::functor_stub(clause_name!("sort"), 2);
let list = self.store(self.deref(self[temp_v!(1)].clone())); let list = self.store(self.deref(self[temp_v!(1)].clone()));
let sorted = self.store(self.deref(self[temp_v!(2)].clone())); let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
match self.detect_cycles(list.clone()) { match self.detect_cycles(list.clone()) {
CycleSearchResult::PartialList(..) => CycleSearchResult::PartialList(..) =>
Err(self.error_form(self.instantiation_error(), stub.clone())), return Err(self.error_form(MachineError::instantiation_error(), stub)),
CycleSearchResult::NotList => CycleSearchResult::NotList =>
Err(self.error_form(self.type_error(ValidType::List, list), stub.clone())), return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub)),
_ => Ok(()) _ => {}
}?; };
match self.detect_cycles(sorted.clone()) { match self.detect_cycles(sorted.clone()) {
CycleSearchResult::NotList if !sorted.is_ref() => 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(()) _ => Ok(())
} }
} }
fn check_for_list_pairs(&self, list: Addr) -> Result<(), MachineError> { fn check_for_list_pairs(&self, list: Addr) -> CallResult {
let stub = self.functor_stub(clause_name!("keysort"), 2); let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
match self.detect_cycles(list.clone()) { match self.detect_cycles(list.clone()) {
CycleSearchResult::NotList if !list.is_ref() => 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; let mut addr = list;
@@ -158,8 +228,8 @@ impl MachineState {
if name.as_str() == "-" => break, if name.as_str() == "-" => break,
HeapCellValue::Addr(Addr::HeapCell(_)) => break, HeapCellValue::Addr(Addr::HeapCell(_)) => break,
HeapCellValue::Addr(Addr::StackCell(..)) => break, HeapCellValue::Addr(Addr::StackCell(..)) => break,
_ => return Err(self.error_form(self.type_error(ValidType::Pair, _ => return Err(self.error_form(MachineError::type_error(ValidType::Pair,
Addr::HeapCell(l)), Addr::HeapCell(l)),
stub)) stub))
}; };
} }
@@ -173,70 +243,35 @@ impl MachineState {
} }
// see 8.4.4 of Draft Technical Corrigendum 2. // see 8.4.4 of Draft Technical Corrigendum 2.
pub(super) fn check_keysort_errors(&self) -> Result<(), MachineError> { pub(super) fn check_keysort_errors(&self) -> CallResult {
let stub = self.functor_stub(clause_name!("keysort"), 2); let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
let pairs = self.store(self.deref(self[temp_v!(1)].clone())); let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
let sorted = self.store(self.deref(self[temp_v!(2)].clone())); let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
match self.detect_cycles(pairs.clone()) { match self.detect_cycles(pairs.clone()) {
CycleSearchResult::PartialList(..) => CycleSearchResult::PartialList(..) =>
Err(self.error_form(self.instantiation_error(), stub)), Err(self.error_form(MachineError::instantiation_error(), stub)),
CycleSearchResult::NotList => 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(()) _ => Ok(())
}?; }?;
self.check_for_list_pairs(sorted) self.check_for_list_pairs(sorted)
} }
pub(super) fn functor_stub(&self, name: ClauseName, arity: usize) -> MachineStub { pub(super) fn error_form(&self, err: MachineError, src: MachineStub) -> 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 {
let h = self.heap.h; 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)]); stub.extend(err.into_iter(3));
error.append(&mut self.functor_stub(name, arity)); stub.extend(src.into_iter());
error stub
} }
pub(super) fn domain_error(&self, error: DomainError, culprit: Addr) -> MachineError { pub(super) fn throw_exception(&mut self, err: MachineStub) {
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) {
let h = self.heap.h; let h = self.heap.h;
self.ball.boundary = 0; self.ball.boundary = 0;

View File

@@ -365,10 +365,15 @@ pub(crate) trait CallPolicy: Any {
fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName, fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName,
arity: usize, idx: CodeIndex) arity: usize, idx: CodeIndex)
-> CallResult -> CallResult
{ {
match idx.0.borrow().0 { match idx.0.borrow().0 {
IndexPtr::Undefined => IndexPtr::Undefined => {
return Err(machine_st.existence_error(name, arity)), let stub = MachineError::functor_stub(name.clone(), arity);
let h = machine_st.heap.h;
return Err(machine_st.error_form(MachineError::existence_error(h, name, arity),
stub));
},
IndexPtr::Index(compiled_tl_index) => { IndexPtr::Index(compiled_tl_index) => {
let module_name = idx.0.borrow().1.clone(); let module_name = idx.0.borrow().1.clone();
@@ -387,8 +392,13 @@ pub(crate) trait CallPolicy: Any {
-> CallResult -> CallResult
{ {
match idx.0.borrow().0 { match idx.0.borrow().0 {
IndexPtr::Undefined => IndexPtr::Undefined => {
return Err(machine_st.existence_error(name, arity)), let stub = MachineError::functor_stub(name.clone(), arity);
let h = machine_st.heap.h;
return Err(machine_st.error_form(MachineError::existence_error(h, name, arity),
stub));
},
IndexPtr::Index(compiled_tl_index) => { IndexPtr::Index(compiled_tl_index) => {
let module_name = idx.0.borrow().1.clone(); let module_name = idx.0.borrow().1.clone();
@@ -475,7 +485,7 @@ pub(crate) trait CallPolicy: Any {
&BuiltInClauseType::Sort => { &BuiltInClauseType::Sort => {
machine_st.check_sort_errors()?; machine_st.check_sort_errors()?;
let stub = machine_st.functor_stub(clause_name!("sort"), 2); let stub = MachineError::functor_stub(clause_name!("sort"), 2);
let mut list = machine_st.try_from_list(temp_v!(1), stub)?; let mut list = machine_st.try_from_list(temp_v!(1), stub)?;
list.sort_unstable_by(|a1, a2| machine_st.compare_term_test(a1, a2)); list.sort_unstable_by(|a1, a2| machine_st.compare_term_test(a1, a2));
@@ -491,7 +501,7 @@ pub(crate) trait CallPolicy: Any {
&BuiltInClauseType::KeySort => { &BuiltInClauseType::KeySort => {
machine_st.check_keysort_errors()?; machine_st.check_keysort_errors()?;
let stub = machine_st.functor_stub(clause_name!("keysort"), 2); let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
let mut list = machine_st.try_from_list(temp_v!(1), stub)?; let mut list = machine_st.try_from_list(temp_v!(1), stub)?;
let mut key_pairs = Vec::new(); let mut key_pairs = Vec::new();
@@ -544,11 +554,19 @@ pub(crate) trait CallPolicy: Any {
if let Some(idx) = code_dirs.get(name.clone(), arity, user) { if let Some(idx) = code_dirs.get(name.clone(), arity, user) {
self.context_call(machine_st, name, arity, idx)?; self.context_call(machine_st, name, arity, idx)?;
} else { } else {
return Err(machine_st.existence_error(name, arity)); let h = machine_st.heap.h;
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
return Err(machine_st.error_form(MachineError::existence_error(h, name, arity),
stub));
}, },
ClauseType::System(_) => ClauseType::System(_) => {
return Err(machine_st.type_error(ValidType::Callable, let name = Addr::Con(Constant::Atom(name));
Addr::Con(Constant::Atom(name)))) let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
return Err(machine_st.error_form(MachineError::type_error(ValidType::Callable,
name),
stub));
}
}; };
} }

View File

@@ -323,7 +323,7 @@ impl MachineState {
}; };
} }
pub(super) fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, MachineError> { pub(super) fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, MachineStub> {
match at { match at {
&ArithmeticTerm::Reg(r) => self.arith_eval_by_metacall(r), &ArithmeticTerm::Reg(r) => self.arith_eval_by_metacall(r),
&ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()), &ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()),
@@ -332,7 +332,7 @@ impl MachineState {
} }
fn get_rational(&self, at: &ArithmeticTerm, caller: &MachineStub) fn get_rational(&self, at: &ArithmeticTerm, caller: &MachineStub)
-> Result<Rc<Ratio<BigInt>>, MachineError> -> Result<Rc<Ratio<BigInt>>, MachineStub>
{ {
let n = self.get_number(at)?; let n = self.get_number(at)?;
@@ -342,7 +342,7 @@ impl MachineState {
if let Some(r) = Ratio::from_float(fl.into_inner()) { if let Some(r) = Ratio::from_float(fl.into_inner()) {
Ok(Rc::new(r)) Ok(Rc::new(r))
} else { } else {
Err(self.error_form(self.instantiation_error(), caller.clone())) Err(self.error_form(MachineError::instantiation_error(), caller.clone()))
}, },
Number::Integer(bi) => Number::Integer(bi) =>
Ok(Rc::new(Ratio::from_integer((*bi).clone()))) Ok(Rc::new(Ratio::from_integer((*bi).clone())))
@@ -361,11 +361,11 @@ impl MachineState {
Rc::new(BigInt::from_signed_bytes_le(&f(&u_n1, &u_n2).to_bytes_le())) Rc::new(BigInt::from_signed_bytes_le(&f(&u_n1, &u_n2).to_bytes_le()))
} }
pub(super) fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, MachineError> pub(super) fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, MachineStub>
{ {
let a = self[r].clone(); let a = self[r].clone();
let caller = self.functor_stub(clause_name!("(is)"), 2); let caller = MachineError::functor_stub(clause_name!("(is)"), 2);
let mut interms: Vec<Number> = Vec::with_capacity(64); let mut interms: Vec<Number> = Vec::with_capacity(64);
for heap_val in self.post_order_iter(a) { for heap_val in self.post_order_iter(a) {
@@ -395,7 +395,8 @@ impl MachineState {
"xor" => interms.push(Number::Integer(self.xor(a1, a2)?)), "xor" => interms.push(Number::Integer(self.xor(a1, a2)?)),
"mod" => interms.push(Number::Integer(self.modulus(a1, a2)?)), "mod" => interms.push(Number::Integer(self.modulus(a1, a2)?)),
"rem" => interms.push(Number::Integer(self.remainder(a1, a2)?)), "rem" => interms.push(Number::Integer(self.remainder(a1, a2)?)),
_ => return Err(self.error_form(self.instantiation_error(), caller)) _ => return Err(self.error_form(MachineError::instantiation_error(),
caller))
} }
}, },
HeapCellValue::NamedStr(1, name, Some(Fixity::Pre)) => { HeapCellValue::NamedStr(1, name, Some(Fixity::Pre)) => {
@@ -403,13 +404,14 @@ impl MachineState {
match name.as_str() { match name.as_str() {
"-" => interms.push(- a1), "-" => interms.push(- a1),
_ => return Err(self.error_form(self.instantiation_error(), caller)) _ => return Err(self.error_form(MachineError::instantiation_error(),
caller))
} }
}, },
HeapCellValue::Addr(Addr::Con(Constant::Number(n))) => HeapCellValue::Addr(Addr::Con(Constant::Number(n))) =>
interms.push(n), interms.push(n),
_ => _ =>
return Err(self.error_form(self.instantiation_error(), caller)) return Err(self.error_form(MachineError::instantiation_error(), caller))
} }
}; };
@@ -417,75 +419,75 @@ impl MachineState {
} }
fn rdiv(&self, r1: Rc<Ratio<BigInt>>, r2: Rc<Ratio<BigInt>>) fn rdiv(&self, r1: Rc<Ratio<BigInt>>, r2: Rc<Ratio<BigInt>>)
-> Result<Rc<Ratio<BigInt>>, MachineError> -> Result<Rc<Ratio<BigInt>>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(rdiv)"), 2); let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2);
if *r2 == Ratio::zero() { if *r2 == Ratio::zero() {
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor), stub)) Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
} else { } else {
Ok(Rc::new(&*r1 / &*r2)) Ok(Rc::new(&*r1 / &*r2))
} }
} }
fn fidiv(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError> fn fidiv(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(div)"), 2); let stub = MachineError::functor_stub(clause_name!("(div)"), 2);
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() { if *n2 == BigInt::zero() {
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor), stub)) Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
} else { } else {
Ok(Rc::new(n1.div_floor(&n2))) Ok(Rc::new(n1.div_floor(&n2)))
}, },
(Number::Integer(_), n2) => (Number::Integer(_), n2) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n2))), Addr::Con(Constant::Number(n2))),
stub)), stub)),
(n1, _) => (n1, _) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n1))), Addr::Con(Constant::Number(n1))),
stub)) stub))
} }
} }
fn idiv(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError> fn idiv(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(//)"), 2); let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() { if *n2 == BigInt::zero() {
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor), stub)) Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
} else { } else {
Ok(Rc::new(&*n1 / &*n2)) Ok(Rc::new(&*n1 / &*n2))
}, },
(Number::Integer(_), n2) => (Number::Integer(_), n2) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n2))), Addr::Con(Constant::Number(n2))),
stub)), stub)),
(n1, _) => (n1, _) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n1))), Addr::Con(Constant::Number(n1))),
stub)) stub))
} }
} }
fn div(&self, n1: Number, n2: Number) -> Result<Number, MachineError> fn div(&self, n1: Number, n2: Number) -> Result<Number, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(/)"), 2); let stub = MachineError::functor_stub(clause_name!("(/)"), 2);
if n2.is_zero() { if n2.is_zero() {
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor), stub)) Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
} else { } else {
Ok(n1 / n2) Ok(n1 / n2)
} }
} }
fn shr(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError> fn shr(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(>>)"), 2); let stub = MachineError::functor_stub(clause_name!("(>>)"), 2);
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
@@ -494,19 +496,19 @@ impl MachineState {
_ => Ok(Rc::new(&*n1 >> usize::max_value())) _ => Ok(Rc::new(&*n1 >> usize::max_value()))
}, },
(Number::Integer(_), n2) => (Number::Integer(_), n2) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n2))), Addr::Con(Constant::Number(n2))),
stub)), stub)),
(n1, _) => (n1, _) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n1))), Addr::Con(Constant::Number(n1))),
stub)) stub))
} }
} }
fn shl(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError> fn shl(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(<<)"), 2); let stub = MachineError::functor_stub(clause_name!("(<<)"), 2);
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
@@ -515,110 +517,112 @@ impl MachineState {
_ => Ok(Rc::new(&*n1 << usize::max_value())) _ => Ok(Rc::new(&*n1 << usize::max_value()))
}, },
(Number::Integer(_), n2) => (Number::Integer(_), n2) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n2))), Addr::Con(Constant::Number(n2))),
stub)), stub)),
(n1, _) => (n1, _) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n1))), Addr::Con(Constant::Number(n1))),
stub)) stub))
} }
} }
fn xor(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError> fn xor(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(xor)"), 2); let stub = MachineError::functor_stub(clause_name!("(xor)"), 2);
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 ^ u_n2)), Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 ^ u_n2)),
(Number::Integer(_), n2) => (Number::Integer(_), n2) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n2))), Addr::Con(Constant::Number(n2))),
stub)), stub)),
(n1, _) => (n1, _) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n1))), Addr::Con(Constant::Number(n1))),
stub)) stub))
} }
} }
fn and(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError> fn and(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(/\\)"), 2); let stub = MachineError::functor_stub(clause_name!("(/\\)"), 2);
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)), Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
(Number::Integer(_), n2) => (Number::Integer(_), n2) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n2))), Addr::Con(Constant::Number(n2))),
stub)), stub)),
(n1, _) => (n1, _) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n1))), Addr::Con(Constant::Number(n1))),
stub)) stub))
} }
} }
fn modulus(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError> fn modulus(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(mod)"), 2); let stub = MachineError::functor_stub(clause_name!("(mod)"), 2);
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() { if *n2 == BigInt::zero() {
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor), stub)) Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor),
stub))
} else { } else {
Ok(Rc::new(n1.mod_floor(&n2))) Ok(Rc::new(n1.mod_floor(&n2)))
}, },
(Number::Integer(_), n2) => (Number::Integer(_), n2) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n2))), Addr::Con(Constant::Number(n2))),
stub)), stub)),
(n1, _) => (n1, _) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n1))), Addr::Con(Constant::Number(n1))),
stub)) stub))
} }
} }
fn remainder(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError> fn remainder(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(rem)"), 2); let stub = MachineError::functor_stub(clause_name!("(rem)"), 2);
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() { if *n2 == BigInt::zero() {
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor), stub)) Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor),
stub))
} else { } else {
Ok(Rc::new(&*n1 % &*n2)) Ok(Rc::new(&*n1 % &*n2))
}, },
(Number::Integer(_), n2) => (Number::Integer(_), n2) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n2))), Addr::Con(Constant::Number(n2))),
stub)), stub)),
(n1, _) => (n1, _) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n1))), Addr::Con(Constant::Number(n1))),
stub)) stub))
} }
} }
fn or(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError> fn or(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
{ {
let stub = self.functor_stub(clause_name!("(\\/)"), 2); let stub = MachineError::functor_stub(clause_name!("(\\/)"), 2);
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)), Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
(Number::Integer(_), n2) => (Number::Integer(_), n2) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n2))), Addr::Con(Constant::Number(n2))),
stub)), stub)),
(n1, _) => (n1, _) =>
Err(self.error_form(self.type_error(ValidType::Integer, Err(self.error_form(MachineError::type_error(ValidType::Integer,
Addr::Con(Constant::Number(n1))), Addr::Con(Constant::Number(n1))),
stub)) stub))
} }
} }
@@ -647,7 +651,7 @@ impl MachineState {
self.p += 1; self.p += 1;
}, },
&ArithmeticInstruction::RDiv(ref a1, ref a2, t) => { &ArithmeticInstruction::RDiv(ref a1, ref a2, t) => {
let stub = self.functor_stub(clause_name!("(rdiv)"), 2); let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2);
let r1 = try_or_fail!(self, self.get_rational(a1, &stub)); let r1 = try_or_fail!(self, self.get_rational(a1, &stub));
let r2 = try_or_fail!(self, self.get_rational(a2, &stub)); let r2 = try_or_fail!(self, self.get_rational(a2, &stub));
@@ -1067,7 +1071,7 @@ impl MachineState {
pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey> pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey>
{ {
let stub = self.functor_stub(clause_name!("call"), arity + 1); let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
let addr = self.store(self.deref(self.registers[arity].clone())); let addr = self.store(self.deref(self.registers[arity].clone()));
let (name, narity) = match addr { let (name, narity) = match addr {
@@ -1077,7 +1081,7 @@ impl MachineState {
if let HeapCellValue::NamedStr(narity, name, _) = result { if let HeapCellValue::NamedStr(narity, name, _) = result {
if narity + arity > 63 { if narity + arity > 63 {
let representation_error = let representation_error =
self.error_form(self.representation_error(RepFlag::MaxArity), stub); self.error_form(MachineError::representation_error(RepFlag::MaxArity), stub);
self.throw_exception(representation_error); self.throw_exception(representation_error);
return None; return None;
@@ -1099,13 +1103,13 @@ impl MachineState {
}, },
Addr::Con(Constant::Atom(name)) => (name, 0), Addr::Con(Constant::Atom(name)) => (name, 0),
Addr::HeapCell(_) | Addr::StackCell(_, _) => { Addr::HeapCell(_) | Addr::StackCell(_, _) => {
let instantiation_error = self.error_form(self.instantiation_error(), stub); let instantiation_error = self.error_form(MachineError::instantiation_error(), stub);
self.throw_exception(instantiation_error); self.throw_exception(instantiation_error);
return None; return None;
}, },
_ => { _ => {
let type_error = self.error_form(self.type_error(ValidType::Callable, addr), stub); let type_error = self.error_form(MachineError::type_error(ValidType::Callable, addr), stub);
self.throw_exception(type_error); self.throw_exception(type_error);
return None; return None;
@@ -1169,19 +1173,19 @@ impl MachineState {
// arg(+N, +Term, ?Arg) // arg(+N, +Term, ?Arg)
pub(super) fn try_arg(&mut self) -> CallResult pub(super) fn try_arg(&mut self) -> CallResult
{ {
let stub = self.functor_stub(clause_name!("arg"), 3); let stub = MachineError::functor_stub(clause_name!("arg"), 3);
let n = self.store(self.deref(self[temp_v!(1)].clone())); let n = self.store(self.deref(self[temp_v!(1)].clone()));
match n { match n {
Addr::HeapCell(_) | Addr::StackCell(..) => // 8.5.2.3 a) Addr::HeapCell(_) | Addr::StackCell(..) => // 8.5.2.3 a)
return Err(self.error_form(self.instantiation_error(), stub)), return Err(self.error_form(MachineError::instantiation_error(), stub)),
Addr::Con(Constant::Number(Number::Integer(n))) => { Addr::Con(Constant::Number(Number::Integer(n))) => {
if n.is_negative() { if n.is_negative() {
// 8.5.2.3 e) // 8.5.2.3 e)
let n = Addr::Con(Constant::Number(Number::Integer(n))); let n = Addr::Con(Constant::Number(Number::Integer(n)));
return Err(self.error_form(self.domain_error(DomainError::NotLessThanZero, let dom_err = MachineError::domain_error(DomainError::NotLessThanZero, n);
n),
stub)); return Err(self.error_form(dom_err, stub));
} }
let n = match n.to_usize() { let n = match n.to_usize() {
@@ -1196,7 +1200,7 @@ impl MachineState {
match term { match term {
Addr::HeapCell(_) | Addr::StackCell(..) => // 8.5.2.3 b) Addr::HeapCell(_) | Addr::StackCell(..) => // 8.5.2.3 b)
return Err(self.error_form(self.instantiation_error(), stub)), return Err(self.error_form(MachineError::instantiation_error(), stub)),
Addr::Str(o) => Addr::Str(o) =>
match self.heap[o].clone() { match self.heap[o].clone() {
HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => { HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => {
@@ -1217,14 +1221,14 @@ impl MachineState {
self.fail = true; self.fail = true;
}, },
_ => // 8.5.2.3 d) _ => // 8.5.2.3 d)
return Err(self.error_form(self.type_error(ValidType::Compound, term), return Err(self.error_form(MachineError::type_error(ValidType::Compound, term),
stub)) stub))
} }
}, },
_ => // 8.5.2.3 c) _ => // 8.5.2.3 c)
return Err(self.error_form(self.type_error(ValidType::Integer, n), stub)) return Err(self.error_form(MachineError::type_error(ValidType::Integer, n), stub))
} }
Ok(()) Ok(())
@@ -1482,7 +1486,7 @@ impl MachineState {
} }
pub(super) fn try_functor(&mut self) -> CallResult { pub(super) fn try_functor(&mut self) -> CallResult {
let stub = self.functor_stub(clause_name!("functor"), 3); let stub = MachineError::functor_stub(clause_name!("functor"), 3);
let a1 = self.store(self.deref(self[temp_v!(1)].clone())); let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
match a1.clone() { match a1.clone() {
@@ -1501,7 +1505,7 @@ impl MachineState {
let arity = self.store(self.deref(self[temp_v!(3)].clone())); let arity = self.store(self.deref(self[temp_v!(3)].clone()));
if name.is_ref() || arity.is_ref() { // 8.5.1.3 a) & 8.5.1.3 b) if name.is_ref() || arity.is_ref() { // 8.5.1.3 a) & 8.5.1.3 b)
return Err(self.error_form(self.instantiation_error(), stub)); return Err(self.error_form(MachineError::instantiation_error(), stub));
} }
if let Addr::Con(Constant::Number(Number::Integer(arity))) = arity { if let Addr::Con(Constant::Number(Number::Integer(arity))) = arity {
@@ -1514,14 +1518,14 @@ impl MachineState {
}; };
if arity > MAX_ARITY as isize { if arity > MAX_ARITY as isize {
let rep_err = MachineError::representation_error(RepFlag::MaxArity);
// 8.5.1.3 f) // 8.5.1.3 f)
return Err(self.error_form(self.representation_error(RepFlag::MaxArity), return Err(self.error_form(rep_err, stub));
stub));
} else if arity < 0 { } else if arity < 0 {
// 8.5.1.3 g) // 8.5.1.3 g)
return Err(self.error_form(self.domain_error(DomainError::NotLessThanZero, let dom_err = MachineError::domain_error(DomainError::NotLessThanZero,
Addr::Con(integer!(arity))), Addr::Con(integer!(arity)));
stub)); return Err(self.error_form(dom_err, stub));
} }
match name { match name {
@@ -1544,15 +1548,15 @@ impl MachineState {
self.unify(a1, f_a); self.unify(a1, f_a);
}, },
Addr::Con(_) => Addr::Con(_) =>
return Err(self.error_form(self.type_error(ValidType::Atom, name), return Err(self.error_form(MachineError::type_error(ValidType::Atom, name),
stub)), // 8.5.1.3 e) stub)), // 8.5.1.3 e)
_ => _ =>
return Err(self.error_form(self.type_error(ValidType::Atomic, name), return Err(self.error_form(MachineError::type_error(ValidType::Atomic, name),
stub)) // 8.5.1.3 c) stub)) // 8.5.1.3 c)
}; };
} else if !arity.is_ref() { } else if !arity.is_ref() {
// 8.5.1.3 d) // 8.5.1.3 d)
return Err(self.error_form(self.type_error(ValidType::Integer, arity), stub)); return Err(self.error_form(MachineError::type_error(ValidType::Integer, arity), stub));
} }
} }
}; };
@@ -1591,7 +1595,7 @@ impl MachineState {
} }
pub(super) fn try_from_list(&self, r: RegType, caller: MachineStub) pub(super) fn try_from_list(&self, r: RegType, caller: MachineStub)
-> Result<Vec<Addr>, MachineError> -> Result<Vec<Addr>, MachineStub>
{ {
let a1 = self.store(self.deref(self[r].clone())); let a1 = self.store(self.deref(self[r].clone()));
@@ -1613,13 +1617,13 @@ impl MachineState {
Addr::Con(Constant::EmptyList) => Addr::Con(Constant::EmptyList) =>
break, break,
Addr::HeapCell(_) | Addr::StackCell(..) => Addr::HeapCell(_) | Addr::StackCell(..) =>
return Err(self.error_form(self.instantiation_error(), caller)), return Err(self.error_form(MachineError::instantiation_error(), caller)),
_ => _ =>
return Err(self.error_form(self.type_error(ValidType::List, a1), return Err(self.error_form(MachineError::type_error(ValidType::List, a1),
caller)) caller))
}, },
_ => _ =>
return Err(self.error_form(self.type_error(ValidType::List, a1), return Err(self.error_form(MachineError::type_error(ValidType::List, a1),
caller)) caller))
}; };
} }
@@ -1627,31 +1631,31 @@ impl MachineState {
Ok(result) Ok(result)
}, },
Addr::HeapCell(_) | Addr::StackCell(..) => Addr::HeapCell(_) | Addr::StackCell(..) =>
Err(self.error_form(self.instantiation_error(), caller)), Err(self.error_form(MachineError::instantiation_error(), caller)),
Addr::Con(Constant::EmptyList) => Addr::Con(Constant::EmptyList) =>
Ok(vec![]), Ok(vec![]),
_ => _ =>
Err(self.error_form(self.type_error(ValidType::List, a1), caller)) Err(self.error_form(MachineError::type_error(ValidType::List, a1), caller))
} }
} }
// see 8.4.4.3 of Draft Technical Corrigendum 2 for an error guide. // see 8.4.4.3 of Draft Technical Corrigendum 2 for an error guide.
pub(super) fn project_onto_key(&self, a: Addr) -> Result<Addr, MachineError> { pub(super) fn project_onto_key(&self, a: Addr) -> Result<Addr, MachineStub> {
let stub = self.functor_stub(clause_name!("keysort"), 2); let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
match self.store(self.deref(a)) { match self.store(self.deref(a)) {
Addr::HeapCell(_) | Addr::StackCell(..) => Addr::HeapCell(_) | Addr::StackCell(..) =>
Err(self.error_form(self.instantiation_error(), stub)), Err(self.error_form(MachineError::instantiation_error(), stub)),
Addr::Str(s) => Addr::Str(s) =>
match self.heap[s].clone() { match self.heap[s].clone() {
HeapCellValue::NamedStr(2, ref name, Some(Fixity::In)) HeapCellValue::NamedStr(2, ref name, Some(Fixity::In))
if *name == clause_name!("-") => if *name == clause_name!("-") =>
Ok(Addr::HeapCell(s+1)), Ok(Addr::HeapCell(s+1)),
_ => Err(self.error_form(self.type_error(ValidType::Pair, _ => Err(self.error_form(MachineError::type_error(ValidType::Pair,
self.heap[s].as_addr(s)), self.heap[s].as_addr(s)),
stub)) stub))
}, },
a => Err(self.error_form(self.type_error(ValidType::Pair, a), stub)) a => Err(self.error_form(MachineError::type_error(ValidType::Pair, a), stub))
} }
} }

View File

@@ -102,7 +102,7 @@ impl MachineState {
} }
} }
pub(super) fn skip_max_list(&mut self) -> Result<(), MachineError> { pub(super) fn skip_max_list(&mut self) -> CallResult {
let max_steps = self.store(self.deref(self[temp_v!(2)].clone())); let max_steps = self.store(self.deref(self[temp_v!(2)].clone()));
match max_steps { match max_steps {
@@ -149,8 +149,8 @@ impl MachineState {
self.fail = true; self.fail = true;
}, },
_ => { _ => {
let stub = self.functor_stub(clause_name!("$skip_max_list"), 4); let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
return Err(self.error_form(self.instantiation_error(), stub)); return Err(self.error_form(MachineError::instantiation_error(), stub));
} }
}; };
@@ -242,8 +242,8 @@ impl MachineState {
CallWithInferenceLimitCallPolicy.") CallWithInferenceLimitCallPolicy.")
}, },
_ => { _ => {
let stub = self.functor_stub(clause_name!("call_with_inference_limit"), 3); let stub = MachineError::functor_stub(clause_name!("call_with_inference_limit"), 3);
let type_error = self.error_form(self.type_error(ValidType::Integer, a2), let type_error = self.error_form(MachineError::type_error(ValidType::Integer, a2),
stub); stub);
self.throw_exception(type_error) self.throw_exception(type_error)
} }