add error handling appartus
This commit is contained in:
@@ -224,7 +224,7 @@ pub trait SubModuleUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !self.import_decl(name, arity, submodule) {
|
if !self.import_decl(name, arity, submodule) {
|
||||||
return EvalSession::from(EvalError::ModuleDoesNotContainExport);
|
return EvalSession::from(SessionError::ModuleDoesNotContainExport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +234,7 @@ pub trait SubModuleUser {
|
|||||||
fn use_module(&mut self, submodule: &Module) -> EvalSession {
|
fn use_module(&mut self, submodule: &Module) -> EvalSession {
|
||||||
for (name, arity) in submodule.module_decl.exports.iter().cloned() {
|
for (name, arity) in submodule.module_decl.exports.iter().cloned() {
|
||||||
if !self.import_decl(name, arity, submodule) {
|
if !self.import_decl(name, arity, submodule) {
|
||||||
return EvalSession::from(EvalError::ModuleDoesNotContainExport);
|
return EvalSession::from(SessionError::ModuleDoesNotContainExport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +375,7 @@ pub struct TempVarData {
|
|||||||
pub type HeapVarDict = HashMap<Rc<Var>, Addr>;
|
pub type HeapVarDict = HashMap<Rc<Var>, Addr>;
|
||||||
pub type AllocVarDict = HashMap<Rc<Var>, VarData>;
|
pub type AllocVarDict = HashMap<Rc<Var>, VarData>;
|
||||||
|
|
||||||
pub enum EvalError {
|
pub enum SessionError {
|
||||||
ImpermissibleEntry(String),
|
ImpermissibleEntry(String),
|
||||||
ModuleDoesNotContainExport,
|
ModuleDoesNotContainExport,
|
||||||
ModuleNotFound,
|
ModuleNotFound,
|
||||||
@@ -388,46 +388,46 @@ pub enum EvalError {
|
|||||||
|
|
||||||
pub enum EvalSession {
|
pub enum EvalSession {
|
||||||
EntrySuccess,
|
EntrySuccess,
|
||||||
Error(EvalError),
|
Error(SessionError),
|
||||||
InitialQuerySuccess(AllocVarDict, HeapVarDict),
|
InitialQuerySuccess(AllocVarDict, HeapVarDict),
|
||||||
SubsequentQuerySuccess,
|
SubsequentQuerySuccess,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<EvalError> for EvalSession {
|
impl From<SessionError> for EvalSession {
|
||||||
fn from(err: EvalError) -> Self {
|
fn from(err: SessionError) -> Self {
|
||||||
EvalSession::Error(err)
|
EvalSession::Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ParserError> for EvalError {
|
impl From<ParserError> for SessionError {
|
||||||
fn from(err: ParserError) -> Self {
|
fn from(err: ParserError) -> Self {
|
||||||
EvalError::ParserError(err)
|
SessionError::ParserError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ParserError> for EvalSession {
|
impl From<ParserError> for EvalSession {
|
||||||
fn from(err: ParserError) -> Self {
|
fn from(err: ParserError) -> Self {
|
||||||
EvalSession::from(EvalError::ParserError(err))
|
EvalSession::from(SessionError::ParserError(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OpDecl(pub usize, pub Specifier, pub ClauseName);
|
pub struct OpDecl(pub usize, pub Specifier, pub ClauseName);
|
||||||
|
|
||||||
impl OpDecl {
|
impl OpDecl {
|
||||||
pub fn submit(&self, module: ClauseName, op_dir: &mut OpDir) -> Result<(), EvalError>
|
pub fn submit(&self, module: ClauseName, op_dir: &mut OpDir) -> Result<(), SessionError>
|
||||||
{
|
{
|
||||||
let (prec, spec, name) = (self.0, self.1, self.2.clone());
|
let (prec, spec, name) = (self.0, self.1, self.2.clone());
|
||||||
|
|
||||||
if is_infix!(spec) {
|
if is_infix!(spec) {
|
||||||
match op_dir.get(&(name.clone(), Fixity::Post)) {
|
match op_dir.get(&(name.clone(), Fixity::Post)) {
|
||||||
Some(_) => return Err(EvalError::OpIsInfixAndPostFix),
|
Some(_) => return Err(SessionError::OpIsInfixAndPostFix),
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_postfix!(spec) {
|
if is_postfix!(spec) {
|
||||||
match op_dir.get(&(name.clone(), Fixity::In)) {
|
match op_dir.get(&(name.clone(), Fixity::In)) {
|
||||||
Some(_) => return Err(EvalError::OpIsInfixAndPostFix),
|
Some(_) => return Err(SessionError::OpIsInfixAndPostFix),
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,92 @@ use prolog::num::bigint::{BigInt};
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
// from 7.12.2 b) of 13211-1:1995
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum ValidType {
|
||||||
|
Atom,
|
||||||
|
Atomic,
|
||||||
|
Byte,
|
||||||
|
Callable,
|
||||||
|
Character,
|
||||||
|
Compound,
|
||||||
|
Evaluable,
|
||||||
|
InByte,
|
||||||
|
InCharacter,
|
||||||
|
Integer,
|
||||||
|
List,
|
||||||
|
Number,
|
||||||
|
PredicateIndicator,
|
||||||
|
Variable
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValidType {
|
||||||
|
pub fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
ValidType::Atom => "atom",
|
||||||
|
ValidType::Atomic => "atomic",
|
||||||
|
ValidType::Byte => "byte",
|
||||||
|
ValidType::Callable => "callable",
|
||||||
|
ValidType::Character => "character",
|
||||||
|
ValidType::Compound => "compound",
|
||||||
|
ValidType::Evaluable => "evaluable",
|
||||||
|
ValidType::InByte => "in_byte",
|
||||||
|
ValidType::InCharacter => "in_character",
|
||||||
|
ValidType::Integer => "integer",
|
||||||
|
ValidType::List => "list",
|
||||||
|
ValidType::Number => "number",
|
||||||
|
ValidType::PredicateIndicator => "predicate_indicator",
|
||||||
|
ValidType::Variable => "variable"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from 7.12.2 f) of 13211-1:1995
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum RepFlag {
|
||||||
|
Character,
|
||||||
|
CharacterCode,
|
||||||
|
InCharacterCode,
|
||||||
|
MaxArity,
|
||||||
|
MaxInteger,
|
||||||
|
MinInteger
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RepFlag {
|
||||||
|
pub fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
RepFlag::Character => "character",
|
||||||
|
RepFlag::CharacterCode => "character_code",
|
||||||
|
RepFlag::InCharacterCode => "in_character_code",
|
||||||
|
RepFlag::MaxArity => "max_arity",
|
||||||
|
RepFlag::MaxInteger => "max_integer",
|
||||||
|
RepFlag::MinInteger => "min_integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from 7.12.2 g) of 13211-1:1995
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum EvalError {
|
||||||
|
FloatOverflow,
|
||||||
|
IntOverflow,
|
||||||
|
Undefined,
|
||||||
|
Underflow,
|
||||||
|
ZeroDivisor
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EvalError {
|
||||||
|
pub fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
EvalError::FloatOverflow => "float_overflow",
|
||||||
|
EvalError::IntOverflow => "int_overflow",
|
||||||
|
EvalError::Undefined => "undefined",
|
||||||
|
EvalError::Underflow => "underflow",
|
||||||
|
EvalError::ZeroDivisor => "zero_divisor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_builtins() -> Code {
|
fn get_builtins() -> Code {
|
||||||
vec![internal_call_n!(), // callN/N, 0.
|
vec![internal_call_n!(), // callN/N, 0.
|
||||||
is_atomic!(temp_v!(1)), // atomic/1, 1.
|
is_atomic!(temp_v!(1)), // atomic/1, 1.
|
||||||
@@ -234,8 +320,12 @@ fn get_builtins() -> Code {
|
|||||||
goto_execute!(165, 3), // goto get_arg/3, 185.
|
goto_execute!(165, 3), // goto get_arg/3, 185.
|
||||||
trust_me!(),
|
trust_me!(),
|
||||||
query![get_var_in_query!(temp_v!(4), 1),
|
query![get_var_in_query!(temp_v!(4), 1),
|
||||||
put_structure!("type_error", 1, temp_v!(1), None),
|
put_structure!("type_error", 2, temp_v!(2), None),
|
||||||
set_constant!(atom!("integer_expected"))],
|
set_constant!(atom!(ValidType::Integer.as_str())),
|
||||||
|
set_value!(temp_v!(4)),
|
||||||
|
put_structure!("error", 2, temp_v!(1), None),
|
||||||
|
set_value!(temp_v!(2)),
|
||||||
|
set_void!(1)],
|
||||||
goto_execute!(59, 1), // goto throw/1.
|
goto_execute!(59, 1), // goto throw/1.
|
||||||
try_me_else!(5), // arg_/5, 189.
|
try_me_else!(5), // arg_/5, 189.
|
||||||
fact![get_value!(temp_v!(1), 2),
|
fact![get_value!(temp_v!(1), 2),
|
||||||
|
|||||||
@@ -259,18 +259,18 @@ impl fmt::Display for IndexingInstruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for EvalError {
|
impl fmt::Display for SessionError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&EvalError::ModuleNotFound => write!(f, "module not found."),
|
&SessionError::ModuleNotFound => write!(f, "module not found."),
|
||||||
&EvalError::ModuleDoesNotContainExport => write!(f, "module does not contain claimed export."),
|
&SessionError::ModuleDoesNotContainExport => write!(f, "module does not contain claimed export."),
|
||||||
&EvalError::QueryFailure => write!(f, "false."),
|
&SessionError::QueryFailure => write!(f, "false."),
|
||||||
&EvalError::QueryFailureWithException(ref e) => write!(f, "{}", error_string(e)),
|
&SessionError::QueryFailureWithException(ref e) => write!(f, "{}", error_string(e)),
|
||||||
&EvalError::ImpermissibleEntry(ref msg) => write!(f, "cannot overwrite {}.", msg),
|
&SessionError::ImpermissibleEntry(ref msg) => write!(f, "cannot overwrite {}.", msg),
|
||||||
&EvalError::OpIsInfixAndPostFix =>
|
&SessionError::OpIsInfixAndPostFix =>
|
||||||
write!(f, "cannot define an op to be both postfix and infix."),
|
write!(f, "cannot define an op to be both postfix and infix."),
|
||||||
&EvalError::NamelessEntry => write!(f, "the predicate head is not an atom or clause."),
|
&SessionError::NamelessEntry => write!(f, "the predicate head is not an atom or clause."),
|
||||||
&EvalError::ParserError(ref e) => write!(f, "{:?}", e)
|
&SessionError::ParserError(ref e) => write!(f, "{:?}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -574,7 +574,7 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
|
|||||||
let name = try_eval_session!(if let Some(name) = tl.name() {
|
let name = try_eval_session!(if let Some(name) = tl.name() {
|
||||||
Ok(name)
|
Ok(name)
|
||||||
} else {
|
} else {
|
||||||
Err(EvalError::NamelessEntry)
|
Err(SessionError::NamelessEntry)
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut code = try_eval_session!(compile_relation(&tl));
|
let mut code = try_eval_session!(compile_relation(&tl));
|
||||||
@@ -588,7 +588,7 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
|
|||||||
if !code.is_empty() {
|
if !code.is_empty() {
|
||||||
wam.add_user_code(name, tl.arity(), code, tl.as_predicate().ok().unwrap())
|
wam.add_user_code(name, tl.arity(), code, tl.as_predicate().ok().unwrap())
|
||||||
} else {
|
} else {
|
||||||
EvalSession::from(EvalError::ImpermissibleEntry(String::from("no code generated.")))
|
EvalSession::from(SessionError::ImpermissibleEntry(String::from("no code generated.")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -650,7 +650,7 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return EvalSession::from(EvalError::ModuleNotFound);
|
return EvalSession::from(SessionError::ModuleNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
wam.use_module_in_toplevel(name);
|
wam.use_module_in_toplevel(name);
|
||||||
@@ -666,7 +666,7 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return EvalSession::from(EvalError::ModuleNotFound);
|
return EvalSession::from(SessionError::ModuleNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
wam.use_qualified_module_in_toplevel(name, exports);
|
wam.use_qualified_module_in_toplevel(name, exports);
|
||||||
@@ -681,7 +681,7 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
|||||||
let name = try_eval_session!(if let Some(name) = decl.name() {
|
let name = try_eval_session!(if let Some(name) = decl.name() {
|
||||||
Ok(name)
|
Ok(name)
|
||||||
} else {
|
} else {
|
||||||
Err(EvalError::NamelessEntry)
|
Err(SessionError::NamelessEntry)
|
||||||
});
|
});
|
||||||
|
|
||||||
let module_name = get_module_name(&module);
|
let module_name = get_module_name(&module);
|
||||||
@@ -734,7 +734,7 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut result = EvalSession::from(EvalError::QueryFailure);
|
let mut result = EvalSession::from(SessionError::QueryFailure);
|
||||||
let mut output = PrinterOutputter::new();
|
let mut output = PrinterOutputter::new();
|
||||||
|
|
||||||
let bindings = wam.heap_view(&heap_locs, output).result();
|
let bindings = wam.heap_view(&heap_locs, output).result();
|
||||||
@@ -763,14 +763,14 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let &EvalSession::Error(EvalError::QueryFailure) = &result
|
if let &EvalSession::Error(SessionError::QueryFailure) = &result
|
||||||
{
|
{
|
||||||
write!(stdout, "false.\n\r").unwrap();
|
write!(stdout, "false.\n\r").unwrap();
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let &EvalSession::Error(EvalError::QueryFailureWithException(ref e)) = &result
|
if let &EvalSession::Error(SessionError::QueryFailureWithException(ref e)) = &result
|
||||||
{
|
{
|
||||||
write!(stdout, "{}\n\r", error_string(e)).unwrap();
|
write!(stdout, "{}\n\r", error_string(e)).unwrap();
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
|
|||||||
58
src/prolog/machine/machine_errors.rs
Normal file
58
src/prolog/machine/machine_errors.rs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
use prolog::ast::*;
|
||||||
|
use prolog::builtins::*;
|
||||||
|
use prolog::machine::machine_state::*;
|
||||||
|
use prolog::num::bigint::BigInt;
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub(super) type MachineError = Vec<HeapCellValue>;
|
||||||
|
|
||||||
|
impl MachineState {
|
||||||
|
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 name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name)));
|
||||||
|
let h = self.heap.h;
|
||||||
|
|
||||||
|
let mut error = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
|
||||||
|
error.append(&mut functor!("/", 2, [name, heap_integer!(arity)], Fixity::In));
|
||||||
|
|
||||||
|
error
|
||||||
|
}
|
||||||
|
|
||||||
|
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, mut err: MachineError) -> MachineError {
|
||||||
|
let h = self.heap.h;
|
||||||
|
let mut error_form = functor!("error", 2,
|
||||||
|
[HeapCellValue::Addr(Addr::HeapCell(h + 3)),
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell(h + 2))]);
|
||||||
|
|
||||||
|
error_form.append(&mut err);
|
||||||
|
error_form
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn throw_exception(&mut self, err: MachineError) {
|
||||||
|
let h = self.heap.h;
|
||||||
|
|
||||||
|
self.ball.0 = 0;
|
||||||
|
self.ball.1.truncate(0);
|
||||||
|
|
||||||
|
self.heap.append(err);
|
||||||
|
|
||||||
|
self.registers[1] = Addr::HeapCell(h);
|
||||||
|
self.goto_throw();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
use prolog::and_stack::*;
|
use prolog::and_stack::*;
|
||||||
use prolog::ast::*;
|
use prolog::ast::*;
|
||||||
|
use prolog::builtins::*;
|
||||||
use prolog::copier::*;
|
use prolog::copier::*;
|
||||||
use prolog::heap_iter::*;
|
use prolog::heap_iter::*;
|
||||||
use prolog::heap_print::*;
|
use prolog::heap_print::*;
|
||||||
|
use prolog::machine::machine_errors::*;
|
||||||
use prolog::machine::machine_state::*;
|
use prolog::machine::machine_state::*;
|
||||||
use prolog::num::{Integer, Signed, ToPrimitive, Zero};
|
use prolog::num::{Integer, Signed, ToPrimitive, Zero};
|
||||||
use prolog::num::bigint::{BigInt, BigUint};
|
use prolog::num::bigint::{BigInt, BigUint};
|
||||||
@@ -29,7 +31,7 @@ macro_rules! try_or_fail {
|
|||||||
// used by '$skip_max_list'.
|
// used by '$skip_max_list'.
|
||||||
enum CycleSearchResult {
|
enum CycleSearchResult {
|
||||||
EmptyList,
|
EmptyList,
|
||||||
NotList,
|
NotList,
|
||||||
PartialList(usize, usize), // the list length (up to max), and an offset into the heap.
|
PartialList(usize, usize), // the list length (up to max), and an offset into the heap.
|
||||||
ProperList(usize), // the list length.
|
ProperList(usize), // the list length.
|
||||||
UntouchedList(usize) // the address of an uniterated Addr::Lis(address).
|
UntouchedList(usize) // the address of an uniterated Addr::Lis(address).
|
||||||
@@ -269,7 +271,7 @@ impl MachineState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, Vec<HeapCellValue>> {
|
fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, MachineError> {
|
||||||
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()),
|
||||||
@@ -277,7 +279,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_rational(&self, at: &ArithmeticTerm) -> Result<Rc<Ratio<BigInt>>, Vec<HeapCellValue>> {
|
fn get_rational(&self, at: &ArithmeticTerm) -> Result<Rc<Ratio<BigInt>>, MachineError> {
|
||||||
let n = self.get_number(at)?;
|
let n = self.get_number(at)?;
|
||||||
|
|
||||||
match n {
|
match n {
|
||||||
@@ -286,7 +288,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(functor!("instantiation_error", 1, [heap_atom!("(is)/2")]))
|
Err(self.error_form(self.instantiation_error()))
|
||||||
},
|
},
|
||||||
Number::Integer(bi) =>
|
Number::Integer(bi) =>
|
||||||
Ok(Rc::new(Ratio::from_integer((*bi).clone())))
|
Ok(Rc::new(Ratio::from_integer((*bi).clone())))
|
||||||
@@ -305,9 +307,8 @@ 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, Vec<HeapCellValue>>
|
pub(super) fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, MachineError>
|
||||||
{
|
{
|
||||||
let instantiation_err = functor!("instantiation_error", 1, [heap_atom!("(is)/2")]);
|
|
||||||
let a = self[r].clone();
|
let a = self[r].clone();
|
||||||
|
|
||||||
let mut interms: Vec<Number> = Vec::with_capacity(64);
|
let mut interms: Vec<Number> = Vec::with_capacity(64);
|
||||||
@@ -338,7 +339,7 @@ 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(instantiation_err)
|
_ => return Err(self.error_form(self.instantiation_error()))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HeapCellValue::NamedStr(1, name, Some(Fixity::Pre)) => {
|
HeapCellValue::NamedStr(1, name, Some(Fixity::Pre)) => {
|
||||||
@@ -346,13 +347,13 @@ impl MachineState {
|
|||||||
|
|
||||||
match name.as_str() {
|
match name.as_str() {
|
||||||
"-" => interms.push(- a1),
|
"-" => interms.push(- a1),
|
||||||
_ => return Err(instantiation_err)
|
_ => return Err(self.error_form(self.instantiation_error()))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::Number(n))) =>
|
HeapCellValue::Addr(Addr::Con(Constant::Number(n))) =>
|
||||||
interms.push(n),
|
interms.push(n),
|
||||||
_ =>
|
_ =>
|
||||||
return Err(instantiation_err)
|
return Err(self.error_form(self.instantiation_error()))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -360,52 +361,61 @@ 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>>, Vec<HeapCellValue>>
|
-> Result<Rc<Ratio<BigInt>>, MachineError>
|
||||||
{
|
{
|
||||||
if *r2 == Ratio::zero() {
|
if *r2 == Ratio::zero() {
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Rc::new(&*r1 / &*r2))
|
Ok(Rc::new(&*r1 / &*r2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fidiv(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, Vec<HeapCellValue>>
|
fn fidiv(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError>
|
||||||
{
|
{
|
||||||
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(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Rc::new(n1.div_floor(&n2)))
|
Ok(Rc::new(n1.div_floor(&n2)))
|
||||||
},
|
},
|
||||||
_ => Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
(Number::Integer(_), n2) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n2))))),
|
||||||
|
(n1, _) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n1)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn idiv(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, Vec<HeapCellValue>>
|
fn idiv(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError>
|
||||||
{
|
{
|
||||||
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(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Rc::new(&*n1 / &*n2))
|
Ok(Rc::new(&*n1 / &*n2))
|
||||||
},
|
},
|
||||||
_ =>
|
(Number::Integer(_), n2) =>
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n2))))),
|
||||||
|
(n1, _) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n1)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn div(&self, n1: Number, n2: Number) -> Result<Number, Vec<HeapCellValue>>
|
fn div(&self, n1: Number, n2: Number) -> Result<Number, MachineError>
|
||||||
{
|
{
|
||||||
if n2.is_zero() {
|
if n2.is_zero() {
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor)))
|
||||||
} else {
|
} else {
|
||||||
Ok(n1 / n2)
|
Ok(n1 / n2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shr(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, Vec<HeapCellValue>>
|
fn shr(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError>
|
||||||
{
|
{
|
||||||
match (n1, n2) {
|
match (n1, n2) {
|
||||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||||
@@ -413,12 +423,16 @@ impl MachineState {
|
|||||||
Some(n2) => Ok(Rc::new(&*n1 >> n2)),
|
Some(n2) => Ok(Rc::new(&*n1 >> n2)),
|
||||||
_ => Ok(Rc::new(&*n1 >> usize::max_value()))
|
_ => Ok(Rc::new(&*n1 >> usize::max_value()))
|
||||||
},
|
},
|
||||||
_ =>
|
(Number::Integer(_), n2) =>
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n2))))),
|
||||||
|
(n1, _) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n1)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shl(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, Vec<HeapCellValue>>
|
fn shl(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError>
|
||||||
{
|
{
|
||||||
match (n1, n2) {
|
match (n1, n2) {
|
||||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||||
@@ -426,66 +440,90 @@ impl MachineState {
|
|||||||
Some(n2) => Ok(Rc::new(&*n1 << n2)),
|
Some(n2) => Ok(Rc::new(&*n1 << n2)),
|
||||||
_ => Ok(Rc::new(&*n1 << usize::max_value()))
|
_ => Ok(Rc::new(&*n1 << usize::max_value()))
|
||||||
},
|
},
|
||||||
_ =>
|
(Number::Integer(_), n2) =>
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n2))))),
|
||||||
|
(n1, _) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n1)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn xor(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, Vec<HeapCellValue>>
|
fn xor(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError>
|
||||||
{
|
{
|
||||||
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) =>
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n2))))),
|
||||||
|
(n1, _) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n1)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn and(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, Vec<HeapCellValue>>
|
fn and(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError>
|
||||||
{
|
{
|
||||||
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) =>
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n2))))),
|
||||||
|
(n1, _) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n1)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modulus(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, Vec<HeapCellValue>>
|
fn modulus(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError>
|
||||||
{
|
{
|
||||||
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(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Rc::new(n1.mod_floor(&n2)))
|
Ok(Rc::new(n1.mod_floor(&n2)))
|
||||||
},
|
},
|
||||||
_ =>
|
(Number::Integer(_), n2) =>
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n2))))),
|
||||||
|
(n1, _) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n1)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remainder(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, Vec<HeapCellValue>>
|
fn remainder(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError>
|
||||||
{
|
{
|
||||||
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(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
Err(self.error_form(self.evaluation_error(EvalError::ZeroDivisor)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Rc::new(&*n1 % &*n2))
|
Ok(Rc::new(&*n1 % &*n2))
|
||||||
},
|
},
|
||||||
_ =>
|
(Number::Integer(_), n2) =>
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n2))))),
|
||||||
|
(n1, _) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n1)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn or(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, Vec<HeapCellValue>>
|
fn or(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineError>
|
||||||
{
|
{
|
||||||
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) =>
|
||||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n2))))),
|
||||||
|
(n1, _) =>
|
||||||
|
Err(self.error_form(self.type_error(ValidType::Integer,
|
||||||
|
Addr::Con(Constant::Number(n1)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -941,28 +979,6 @@ impl MachineState {
|
|||||||
self.fail = true;
|
self.fail = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn throw_exception(&mut self, hcv: Vec<HeapCellValue>) {
|
|
||||||
let h = self.heap.h;
|
|
||||||
|
|
||||||
self.ball.0 = 0;
|
|
||||||
self.ball.1.truncate(0);
|
|
||||||
|
|
||||||
self.registers[1] = Addr::HeapCell(h);
|
|
||||||
|
|
||||||
self.heap.append(hcv);
|
|
||||||
self.goto_throw();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn existence_error(&self, name: ClauseName, arity: usize) -> Vec<HeapCellValue> {
|
|
||||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name)));
|
|
||||||
let h = self.heap.h;
|
|
||||||
|
|
||||||
let mut error = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
|
|
||||||
error.append(&mut functor!("/", 2, [name, heap_integer!(arity)], Fixity::In));
|
|
||||||
|
|
||||||
error
|
|
||||||
}
|
|
||||||
|
|
||||||
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 addr = self.store(self.deref(self.registers[arity].clone()));
|
let addr = self.store(self.deref(self.registers[arity].clone()));
|
||||||
@@ -973,8 +989,11 @@ impl MachineState {
|
|||||||
|
|
||||||
if let HeapCellValue::NamedStr(narity, name, _) = result {
|
if let HeapCellValue::NamedStr(narity, name, _) = result {
|
||||||
if narity + arity > 63 {
|
if narity + arity > 63 {
|
||||||
self.throw_exception(functor!("representation_error", 1,
|
let representation_error =
|
||||||
[heap_atom!("exceeds_max_arity")]));
|
self.error_form(self.representation_error(RepFlag::MaxArity));
|
||||||
|
|
||||||
|
self.throw_exception(representation_error);
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -994,13 +1013,15 @@ impl MachineState {
|
|||||||
},
|
},
|
||||||
Addr::Con(Constant::Atom(name)) => (name, 0),
|
Addr::Con(Constant::Atom(name)) => (name, 0),
|
||||||
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
|
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
|
||||||
self.throw_exception(functor!("instantiation_error"));
|
let instantiation_error = self.error_form(self.instantiation_error());
|
||||||
|
self.throw_exception(instantiation_error);
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
self.throw_exception(functor!("type_error", 2,
|
let type_error = self.error_form(self.type_error(ValidType::Callable, addr));
|
||||||
[heap_atom!("callable"),
|
self.throw_exception(type_error);
|
||||||
HeapCellValue::Addr(addr)]));
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1054,7 +1075,7 @@ impl MachineState {
|
|||||||
fail
|
fail
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_get_arg(&mut self) -> Result<(), Vec<HeapCellValue>>
|
fn try_get_arg(&mut self) -> Result<(), MachineError>
|
||||||
{
|
{
|
||||||
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
|
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
|
|
||||||
@@ -1076,7 +1097,7 @@ impl MachineState {
|
|||||||
_ => self.fail = true
|
_ => self.fail = true
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return Err(functor!("type_error", 1, [heap_atom!("compound_expected")]))
|
return Err(self.error_form(self.type_error(ValidType::Compound, a2)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1447,7 +1468,7 @@ impl MachineState {
|
|||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
|
|
||||||
match (a1, a2) {
|
match (a1, a2.clone()) {
|
||||||
(Addr::Con(Constant::Usize(bp)),
|
(Addr::Con(Constant::Usize(bp)),
|
||||||
Addr::Con(Constant::Number(Number::Integer(n)))) =>
|
Addr::Con(Constant::Number(Number::Integer(n)))) =>
|
||||||
match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
|
match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
|
||||||
@@ -1458,7 +1479,10 @@ impl MachineState {
|
|||||||
None => panic!("install_inference_counter: should have installed \\
|
None => panic!("install_inference_counter: should have installed \\
|
||||||
CallWithInferenceLimitCallPolicy.")
|
CallWithInferenceLimitCallPolicy.")
|
||||||
},
|
},
|
||||||
_ => self.throw_exception(functor!("type_error", 1, [heap_atom!("integer_expected")]))
|
_ => {
|
||||||
|
let type_error = self.error_form(self.type_error(ValidType::Integer, a2));
|
||||||
|
self.throw_exception(type_error)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
&BuiltInInstruction::RemoveCallPolicyCheck => {
|
&BuiltInInstruction::RemoveCallPolicyCheck => {
|
||||||
@@ -1582,7 +1606,7 @@ impl MachineState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn try_functor(&mut self) -> Result<(), Vec<HeapCellValue>> {
|
pub(super) fn try_functor(&mut self) -> Result<(), MachineError> {
|
||||||
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() {
|
||||||
@@ -1631,10 +1655,10 @@ impl MachineState {
|
|||||||
|
|
||||||
self.unify(a1, f_a);
|
self.unify(a1, f_a);
|
||||||
} else {
|
} else {
|
||||||
return Err(functor!("instantiation_error"));
|
return Err(self.error_form(self.instantiation_error()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(functor!("instantiation_error"));
|
return Err(self.error_form(self.instantiation_error()));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
@@ -1681,7 +1705,7 @@ impl MachineState {
|
|||||||
head_addr
|
head_addr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn try_from_list(&self, r: RegType) -> Result<Vec<Addr>, Vec<HeapCellValue>>
|
pub(super) fn try_from_list(&self, r: RegType) -> Result<Vec<Addr>, MachineError>
|
||||||
{
|
{
|
||||||
let a1 = self.store(self.deref(self[r].clone()));
|
let a1 = self.store(self.deref(self[r].clone()));
|
||||||
|
|
||||||
@@ -1707,20 +1731,20 @@ impl MachineState {
|
|||||||
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
|
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
|
||||||
break,
|
break,
|
||||||
hcv =>
|
hcv =>
|
||||||
return Err(functor!("type_error", 2, [heap_atom!("list"), hcv]))
|
return Err(self.type_error(ValidType::List, hcv.as_addr(l)))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
},
|
},
|
||||||
Addr::HeapCell(_) | Addr::StackCell(..) =>
|
Addr::HeapCell(_) | Addr::StackCell(..) =>
|
||||||
Err(functor!("instantiation_error")),
|
Err(self.error_form(self.instantiation_error())),
|
||||||
addr =>
|
addr =>
|
||||||
Err(functor!("type_error", 2, [heap_atom!("list"), HeapCellValue::Addr(addr)]))
|
Err(self.error_form(self.type_error(ValidType::List, addr)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn project_onto_key(&self, a: Addr) -> Result<Addr, Vec<HeapCellValue>> {
|
pub(super) fn project_onto_key(&self, a: Addr) -> Result<Addr, MachineError> {
|
||||||
match self.store(self.deref(a)) {
|
match self.store(self.deref(a)) {
|
||||||
Addr::Str(s) =>
|
Addr::Str(s) =>
|
||||||
match self.heap[s].clone() {
|
match self.heap[s].clone() {
|
||||||
@@ -1730,7 +1754,7 @@ impl MachineState {
|
|||||||
_ =>
|
_ =>
|
||||||
panic!("Addr::Str doesn't point to NamedStr.")
|
panic!("Addr::Str doesn't point to NamedStr.")
|
||||||
},
|
},
|
||||||
a => Err(functor!("type_error", 2, [heap_atom!("callable"), HeapCellValue::Addr(a)]))
|
a => Err(self.error_form(self.type_error(ValidType::Callable, a)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1783,7 +1807,7 @@ impl MachineState {
|
|||||||
self.unify(addr, xs);
|
self.unify(addr, xs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn skip_max_list(&mut self) {
|
pub(super) fn skip_max_list(&mut self) {
|
||||||
let max = self.store(self.deref(self[temp_v!(2)].clone()));
|
let max = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use prolog::builtins::*;
|
|||||||
use prolog::heap_print::*;
|
use prolog::heap_print::*;
|
||||||
use prolog::tabled_rc::*;
|
use prolog::tabled_rc::*;
|
||||||
|
|
||||||
|
mod machine_errors;
|
||||||
pub(crate) mod machine_state;
|
pub(crate) mod machine_state;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod machine_state_impl;
|
mod machine_state_impl;
|
||||||
@@ -150,7 +151,7 @@ impl Machine {
|
|||||||
|
|
||||||
indices.use_qualified_module(module, &exports)
|
indices.use_qualified_module(module, &exports)
|
||||||
},
|
},
|
||||||
None => EvalSession::from(EvalError::ModuleNotFound)
|
None => EvalSession::from(SessionError::ModuleNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +165,7 @@ impl Machine {
|
|||||||
|
|
||||||
indices.use_module(module)
|
indices.use_module(module)
|
||||||
},
|
},
|
||||||
None => EvalSession::from(EvalError::ModuleNotFound)
|
None => EvalSession::from(SessionError::ModuleNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +192,7 @@ impl Machine {
|
|||||||
{
|
{
|
||||||
match self.code_dir.get(&(name.clone(), arity)) {
|
match self.code_dir.get(&(name.clone(), arity)) {
|
||||||
Some(&CodeIndex (ref idx)) if idx.borrow().1 != clause_name!("user") =>
|
Some(&CodeIndex (ref idx)) if idx.borrow().1 != clause_name!("user") =>
|
||||||
return EvalSession::from(EvalError::ImpermissibleEntry(format!("{}/{}",
|
return EvalSession::from(SessionError::ImpermissibleEntry(format!("{}/{}",
|
||||||
name,
|
name,
|
||||||
arity))),
|
arity))),
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -380,9 +381,9 @@ impl Machine {
|
|||||||
PrinterOutputter::new())
|
PrinterOutputter::new())
|
||||||
.result();
|
.result();
|
||||||
|
|
||||||
EvalSession::from(EvalError::QueryFailureWithException(msg))
|
EvalSession::from(SessionError::QueryFailureWithException(msg))
|
||||||
} else {
|
} else {
|
||||||
EvalSession::from(EvalError::QueryFailure)
|
EvalSession::from(SessionError::QueryFailure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,7 +408,7 @@ impl Machine {
|
|||||||
self.ms.p = self.ms.or_stack[b].bp.clone();
|
self.ms.p = self.ms.or_stack[b].bp.clone();
|
||||||
|
|
||||||
if let CodePtr::TopLevel(_, 0) = self.ms.p {
|
if let CodePtr::TopLevel(_, 0) = self.ms.p {
|
||||||
return EvalSession::from(EvalError::QueryFailure);
|
return EvalSession::from(SessionError::QueryFailure);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.run_query(alloc_l, heap_l);
|
self.run_query(alloc_l, heap_l);
|
||||||
@@ -418,7 +419,7 @@ impl Machine {
|
|||||||
EvalSession::SubsequentQuerySuccess
|
EvalSession::SubsequentQuerySuccess
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EvalSession::from(EvalError::QueryFailure)
|
EvalSession::from(SessionError::QueryFailure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,12 @@ macro_rules! get_value {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! set_void {
|
||||||
|
($n:expr) => (
|
||||||
|
QueryInstruction::SetVoid($n)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! set_value {
|
macro_rules! set_value {
|
||||||
($r:expr) => (
|
($r:expr) => (
|
||||||
QueryInstruction::SetValue($r)
|
QueryInstruction::SetValue($r)
|
||||||
|
|||||||
@@ -568,7 +568,7 @@ impl<R: Read> TopLevelWorker<R> {
|
|||||||
TopLevelWorker { parser: Parser::new(inner, atom_tbl) }
|
TopLevelWorker { parser: Parser::new(inner, atom_tbl) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_batch(&mut self, op_dir: &mut OpDir) -> Result<Vec<TopLevelPacket>, EvalError>
|
pub fn parse_batch(&mut self, op_dir: &mut OpDir) -> Result<Vec<TopLevelPacket>, SessionError>
|
||||||
{
|
{
|
||||||
let mut preds = vec![];
|
let mut preds = vec![];
|
||||||
let mut mod_name = clause_name!("user");
|
let mut mod_name = clause_name!("user");
|
||||||
|
|||||||
27
src/tests.rs
27
src/tests.rs
@@ -1067,17 +1067,17 @@ fn test_queries_on_arithmetic()
|
|||||||
|
|
||||||
submit(&mut wam, "f(X) :- X is 5 // 0.");
|
submit(&mut wam, "f(X) :- X is 5 // 0.");
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor.",
|
assert_prolog_success!(&mut wam, "?- catch(f(X), error(evaluation_error(E), _), true), E = zero_divisor.",
|
||||||
[["E = zero_divisor", "X = _1"]]);
|
[["E = zero_divisor", "X = _1"]]);
|
||||||
|
|
||||||
submit(&mut wam, "f(X) :- X is (5 rdiv 1) / 0.");
|
submit(&mut wam, "f(X) :- X is (5 rdiv 1) / 0.");
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor.",
|
assert_prolog_success!(&mut wam, "?- catch(f(X), error(evaluation_error(E), _), true), E = zero_divisor.",
|
||||||
[["E = zero_divisor", "X = _1"]]);
|
[["E = zero_divisor", "X = _1"]]);
|
||||||
|
|
||||||
submit(&mut wam, "f(X) :- X is 5.0 / 0.");
|
submit(&mut wam, "f(X) :- X is 5.0 / 0.");
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor.",
|
assert_prolog_success!(&mut wam, "?- catch(f(X), error(evaluation_error(E), _), true), E = zero_divisor.",
|
||||||
[["E = zero_divisor", "X = _1"]]);
|
[["E = zero_divisor", "X = _1"]]);
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z is X+Y.",
|
assert_prolog_success!(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z is X+Y.",
|
||||||
@@ -1108,7 +1108,7 @@ fn test_queries_on_arithmetic()
|
|||||||
assert_prolog_success!(&mut wam, "?- X is 3 + 3, call(<, 3, X).", [["X = 6"]]);
|
assert_prolog_success!(&mut wam, "?- X is 3 + 3, call(<, 3, X).", [["X = 6"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- X is 3 + 3, X =:= 3 + 3.", [["X = 6"]]);
|
assert_prolog_success!(&mut wam, "?- X is 3 + 3, X =:= 3 + 3.", [["X = 6"]]);
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- catch(call(is, X, 3 // 0), E, true).",
|
assert_prolog_success!(&mut wam, "?- catch(call(is, X, 3 // 0), error(E, _), true).",
|
||||||
[["X = _5", "E = evaluation_error(zero_divisor)"]]);
|
[["X = _5", "E = evaluation_error(zero_divisor)"]]);
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- catch(call(is, X, 3 // 3), _, true).", [["X = 1"]]);
|
assert_prolog_success!(&mut wam, "?- catch(call(is, X, 3 // 3), _, true).", [["X = 1"]]);
|
||||||
@@ -1134,7 +1134,7 @@ fn test_queries_on_conditionals()
|
|||||||
; A = \"not 2 or 3\"
|
; A = \"not 2 or 3\"
|
||||||
).");
|
).");
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- catch(test(A), instantiation_error(_), true).");
|
assert_prolog_success!(&mut wam, "?- catch(test(A), error(instantiation_error, _), true).");
|
||||||
assert_prolog_success!(&mut wam, "?- A = 2, test(A).", [["A = 2"]]);
|
assert_prolog_success!(&mut wam, "?- A = 2, test(A).", [["A = 2"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- A = 3, test(A), B = 3, test(B).", [["A = 3", "B = 3"]]);
|
assert_prolog_success!(&mut wam, "?- A = 3, test(A), B = 3, test(B).", [["A = 3", "B = 3"]]);
|
||||||
|
|
||||||
@@ -1227,9 +1227,10 @@ fn test_queries_on_builtins()
|
|||||||
assert_prolog_success!(&mut wam, "?- arg(3, f(a,b,c,d), Arg).", [["Arg = c"]]);
|
assert_prolog_success!(&mut wam, "?- arg(3, f(a,b,c,d), Arg).", [["Arg = c"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- arg(4, f(a,b,c,d), Arg).", [["Arg = d"]]);
|
assert_prolog_success!(&mut wam, "?- arg(4, f(a,b,c,d), Arg).", [["Arg = d"]]);
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- catch(arg(N, f, Arg), type_error(E), true).",
|
assert_prolog_success!(&mut wam, "?- catch(arg(N, f, Arg), error(type_error(E, _), _), true).",
|
||||||
[["E = compound_expected", "Arg = _3", "N = _1"]]);
|
[["E = compound", "Arg = _3", "N = _1"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- catch(arg(N, _, Arg), E, true).",
|
|
||||||
|
assert_prolog_success!(&mut wam, "?- catch(arg(N, _, Arg), error(E, _), true).",
|
||||||
[["E = instantiation_error", "Arg = _3", "N = _1"]]);
|
[["E = instantiation_error", "Arg = _3", "N = _1"]]);
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- arg(N, f(X, Y, Z), arg_val).",
|
assert_prolog_success!(&mut wam, "?- arg(N, f(X, Y, Z), arg_val).",
|
||||||
@@ -1262,13 +1263,13 @@ fn test_queries_on_builtins()
|
|||||||
assert_prolog_success!(&mut wam, "?- functor(Func, f, 3).", [["Func = f(_2, _3, _4)"]]);
|
assert_prolog_success!(&mut wam, "?- functor(Func, f, 3).", [["Func = f(_2, _3, _4)"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- functor(Func, f, 4).", [["Func = f(_2, _3, _4, _5)"]]);
|
assert_prolog_success!(&mut wam, "?- functor(Func, f, 4).", [["Func = f(_2, _3, _4, _5)"]]);
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- catch(functor(F, \"sdf\", 3), E, true).",
|
assert_prolog_success!(&mut wam, "?- catch(functor(F, \"sdf\", 3), error(E, _), true).",
|
||||||
[["E = instantiation_error", "F = _1"]]);
|
[["E = instantiation_error", "F = _1"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- catch(functor(Func, F, 3), E, true).",
|
assert_prolog_success!(&mut wam, "?- catch(functor(Func, F, 3), error(E, _), true).",
|
||||||
[["E = instantiation_error", "Func = _1", "F = _2"]]);
|
[["E = instantiation_error", "Func = _1", "F = _2"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- catch(functor(Func, f, N), E, true).",
|
assert_prolog_success!(&mut wam, "?- catch(functor(Func, f, N), error(E, _), true).",
|
||||||
[["E = instantiation_error", "Func = _1", "N = _3"]]);
|
[["E = instantiation_error", "Func = _1", "N = _3"]]);
|
||||||
assert_prolog_failure!(&mut wam, "?- catch(functor(Func, f, N), E, false).");
|
assert_prolog_failure!(&mut wam, "?- catch(functor(Func, f, N), error(E, _), false).");
|
||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- X is 3, call(integer, X).");
|
assert_prolog_success!(&mut wam, "?- X is 3, call(integer, X).");
|
||||||
assert_prolog_failure!(&mut wam, "?- X is 3 + 3.5, call(integer, X).");
|
assert_prolog_failure!(&mut wam, "?- X is 3 + 3.5, call(integer, X).");
|
||||||
@@ -1278,7 +1279,7 @@ fn test_queries_on_builtins()
|
|||||||
assert_prolog_success!(&mut wam, "?- Func =.. [atom].", [["Func = atom"]]);
|
assert_prolog_success!(&mut wam, "?- Func =.. [atom].", [["Func = atom"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- Func =.. [\"sdf\"].", [["Func = \"sdf\""]]);
|
assert_prolog_success!(&mut wam, "?- Func =.. [\"sdf\"].", [["Func = \"sdf\""]]);
|
||||||
assert_prolog_success!(&mut wam, "?- Func =.. [1].", [["Func = 1"]]);
|
assert_prolog_success!(&mut wam, "?- Func =.. [1].", [["Func = 1"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- catch(Func =.. [1,2], instantiation_error, true).");
|
assert_prolog_success!(&mut wam, "?- catch(Func =.. [1,2], error(instantiation_error, _), true).");
|
||||||
assert_prolog_success!(&mut wam, "?- f(1,2,3) =.. List.", [["List = [f, 1, 2, 3]"]]);
|
assert_prolog_success!(&mut wam, "?- f(1,2,3) =.. List.", [["List = [f, 1, 2, 3]"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- f(1,2,3) =.. [f,1,2,3].");
|
assert_prolog_success!(&mut wam, "?- f(1,2,3) =.. [f,1,2,3].");
|
||||||
assert_prolog_failure!(&mut wam, "?- f(1,2,3) =.. [f,1].");
|
assert_prolog_failure!(&mut wam, "?- f(1,2,3) =.. [f,1].");
|
||||||
|
|||||||
Reference in New Issue
Block a user