add support for rational numbers, division.
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
[root]
|
||||
name = "rusty-wam"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rusty-wam"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
authors = ["Mark Thom"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -19,7 +19,7 @@ Extend rusty-wam to include the following, among other features:
|
||||
* ISO Prolog compliant throw/catch (_done_).
|
||||
* Built-in and user-defined operators of all fixities, with custom
|
||||
associativity and precedence (_done_).
|
||||
* Bignum and floating point arithmetic (_in progress_).
|
||||
* Bignum, rational number and floating point arithmetic (_in progress_).
|
||||
* Built-in control operators (`,`, `;`, `->`, etc.).
|
||||
* Built-in predicates for list processing and top-level declarative
|
||||
control (`setup_call_control/3`, `call_with_inference_limit/3`,
|
||||
@@ -47,7 +47,7 @@ ideally, very fast) [Shen](http://shenlanguage.org) implementation.
|
||||
The following predicates are built-in to rusty-wam.
|
||||
|
||||
* Arithmetic support:
|
||||
* is/2 works for (+)/2, (-)/{1,2}, (*)/2, (//)/2, (div)/2.
|
||||
* is/2 works for (+)/2, (-)/{1,2}, (*)/2, (//)/2, (div)/2, (/)/2, (rdiv)/2.
|
||||
* atomic/1
|
||||
* call/N (1 <= N <= 63)
|
||||
* catch/3
|
||||
|
||||
15
src/main.rs
15
src/main.rs
@@ -757,17 +757,32 @@ mod tests {
|
||||
assert_eq!(submit(&mut wam, "?- 7 is 3 * 2."), false);
|
||||
assert_eq!(submit(&mut wam, "?- 7 is 3.5 * 2."), false);
|
||||
assert_eq!(submit(&mut wam, "?- 7.0 is 3.5 * 2."), true);
|
||||
assert_eq!(submit(&mut wam, "?- 7.0 is 14 / 2."), true);
|
||||
assert_eq!(submit(&mut wam, "?- 4.666 is 14.0 / 3."), false);
|
||||
assert_eq!(submit(&mut wam, "?- 4.0 is 8.0 / 2."), true);
|
||||
|
||||
submit(&mut wam, "f(X) :- X is 5 // 0.");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor."),
|
||||
true);
|
||||
|
||||
submit(&mut wam, "f(X) :- X is (5 rdiv 1) / 0.");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor."),
|
||||
true);
|
||||
|
||||
submit(&mut wam, "f(X) :- X is 5.0 / 0.");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor."),
|
||||
true);
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z is X+Y."),
|
||||
true);
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z = 8, Y is 4."),
|
||||
true);
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- X is (3 rdiv 4) / 2, Y is 3 rdiv 8, X = Y."), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,12 +97,14 @@ impl<'a> ArithmeticEvaluator<'a> {
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
{
|
||||
match name.as_str() {
|
||||
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
|
||||
"-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
|
||||
"//" => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
|
||||
"div" => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
|
||||
"*" => Ok(ArithmeticInstruction::Mul(a1, a2, t)),
|
||||
_ => Err(ArithmeticError::InvalidOp)
|
||||
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
|
||||
"-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
|
||||
"/" => Ok(ArithmeticInstruction::Div(a1, a2, t)),
|
||||
"//" => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
|
||||
"div" => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
|
||||
"rdiv" => Ok(ArithmeticInstruction::RDiv(a1, a2, t)),
|
||||
"*" => Ok(ArithmeticInstruction::Mul(a1, a2, t)),
|
||||
_ => Err(ArithmeticError::InvalidOp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use prolog::num::bigint::BigInt;
|
||||
use prolog::num::ToPrimitive;
|
||||
use prolog::num::{Float, ToPrimitive, Zero};
|
||||
use prolog::num::rational::Ratio;
|
||||
|
||||
use prolog::ordered_float::*;
|
||||
|
||||
@@ -9,7 +10,7 @@ use std::collections::{HashMap, VecDeque};
|
||||
use std::fmt;
|
||||
use std::io::Error as IOError;
|
||||
use std::num::{ParseFloatError};
|
||||
use std::ops::{Add, AddAssign, Sub, Mul, Neg};
|
||||
use std::ops::{Add, AddAssign, Div, Sub, Mul, Neg};
|
||||
use std::str::Utf8Error;
|
||||
use std::vec::Vec;
|
||||
|
||||
@@ -268,6 +269,7 @@ pub enum Constant {
|
||||
Atom(Atom),
|
||||
Float(OrderedFloat<f64>),
|
||||
Integer(BigInt),
|
||||
Rational(Ratio<BigInt>),
|
||||
String(String),
|
||||
Usize(usize),
|
||||
EmptyList
|
||||
@@ -284,6 +286,8 @@ impl fmt::Display for Constant {
|
||||
write!(f, "{}", fl),
|
||||
&Constant::Integer(ref i) =>
|
||||
write!(f, "{}", i),
|
||||
&Constant::Rational(ref r) =>
|
||||
write!(f, "{}", r),
|
||||
&Constant::String(ref s) =>
|
||||
write!(f, "{}", s),
|
||||
&Constant::Usize(integer) =>
|
||||
@@ -295,6 +299,7 @@ impl fmt::Display for Constant {
|
||||
impl From<Number> for Constant {
|
||||
fn from(n: Number) -> Self {
|
||||
match n {
|
||||
Number::Rational(r) => Constant::Rational(r),
|
||||
Number::Integer(n) => Constant::Integer(n),
|
||||
Number::Float(f) => Constant::Float(f)
|
||||
}
|
||||
@@ -309,10 +314,10 @@ pub enum Term {
|
||||
Var(Cell<VarReg>, Var)
|
||||
}
|
||||
|
||||
pub enum InlinedQueryTerm {
|
||||
pub enum InlinedQueryTerm {
|
||||
IsAtomic(Vec<Box<Term>>),
|
||||
IsVar(Vec<Box<Term>>)
|
||||
}
|
||||
}
|
||||
|
||||
impl InlinedQueryTerm {
|
||||
pub fn arity(&self) -> usize {
|
||||
@@ -434,24 +439,98 @@ impl IndexedChoiceInstruction {
|
||||
#[derive(Clone)]
|
||||
pub enum Number {
|
||||
Float(OrderedFloat<f64>),
|
||||
Integer(BigInt)
|
||||
Integer(BigInt),
|
||||
Rational(Ratio<BigInt>)
|
||||
}
|
||||
|
||||
impl Number {
|
||||
pub fn is_zero(&self) -> bool {
|
||||
match self {
|
||||
&Number::Float(fl) => fl.into_inner().is_zero(),
|
||||
&Number::Integer(ref bi) => bi.is_zero(),
|
||||
&Number::Rational(ref r) => r.is_zero()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum NumberPair {
|
||||
Float(OrderedFloat<f64>, OrderedFloat<f64>),
|
||||
Integer(BigInt, BigInt),
|
||||
Rational(Ratio<BigInt>, Ratio<BigInt>)
|
||||
}
|
||||
|
||||
impl NumberPair {
|
||||
fn flip(self) -> NumberPair {
|
||||
match self {
|
||||
NumberPair::Float(f1, f2) => NumberPair::Float(f2, f1),
|
||||
NumberPair::Integer(n1, n2) => NumberPair::Integer(n2, n1),
|
||||
NumberPair::Rational(r1, r2) => NumberPair::Rational(r2, r1)
|
||||
}
|
||||
}
|
||||
|
||||
fn integer_float_pair(n1: BigInt, n2: OrderedFloat<f64>) -> NumberPair {
|
||||
match n1.to_f64() {
|
||||
Some(f1) => NumberPair::Float(OrderedFloat(f1), n2),
|
||||
None => if let Some(r) = Ratio::from_float(n2.into_inner()) {
|
||||
NumberPair::Rational(Ratio::from_integer(n1), r)
|
||||
} else if n2.into_inner().is_sign_positive() {
|
||||
NumberPair::Float(OrderedFloat(f64::infinity()),
|
||||
OrderedFloat(f64::infinity()))
|
||||
} else {
|
||||
NumberPair::Float(OrderedFloat(f64::neg_infinity()),
|
||||
OrderedFloat(f64::neg_infinity()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn float_rational_pair(n1: OrderedFloat<f64>, n2: Ratio<BigInt>) -> NumberPair {
|
||||
if let Some(r) = Ratio::from_float(n1.into_inner()) {
|
||||
NumberPair::Rational(r, n2)
|
||||
} else if n1.into_inner().is_sign_positive() {
|
||||
NumberPair::Float(OrderedFloat(f64::infinity()),
|
||||
OrderedFloat(f64::infinity()))
|
||||
} else {
|
||||
NumberPair::Float(OrderedFloat(f64::neg_infinity()),
|
||||
OrderedFloat(f64::neg_infinity()))
|
||||
}
|
||||
}
|
||||
|
||||
fn from(n1: Number, n2: Number) -> NumberPair
|
||||
{
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
NumberPair::Integer(n1, n2),
|
||||
(Number::Float(n1), Number::Float(n2)) =>
|
||||
NumberPair::Float(n1, n2),
|
||||
(Number::Rational(n1), Number::Rational(n2)) =>
|
||||
NumberPair::Rational(n1, n2),
|
||||
(Number::Integer(n1), Number::Float(n2)) =>
|
||||
Self::integer_float_pair(n1, n2),
|
||||
(Number::Float(n1), Number::Integer(n2)) =>
|
||||
Self::integer_float_pair(n2, n1).flip(),
|
||||
(Number::Float(n1), Number::Rational(n2)) =>
|
||||
Self::float_rational_pair(n1, n2),
|
||||
(Number::Rational(n1), Number::Float(n2)) =>
|
||||
Self::float_rational_pair(n2, n1).flip(),
|
||||
(Number::Rational(n1), Number::Integer(n2)) =>
|
||||
NumberPair::Rational(n1, Ratio::from_integer(n2)),
|
||||
(Number::Integer(n1), Number::Rational(n2)) =>
|
||||
NumberPair::Rational(Ratio::from_integer(n1), n2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Number> for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn add(self, rhs: Number) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
match NumberPair::from(self, rhs) {
|
||||
NumberPair::Float(f1, f2) =>
|
||||
Number::Float(OrderedFloat(f1.into_inner() + f2.into_inner())),
|
||||
NumberPair::Integer(n1, n2) =>
|
||||
Number::Integer(n1 + n2),
|
||||
(Number::Float(n1), Number::Float(n2)) =>
|
||||
Number::Float(OrderedFloat(n1.into_inner() + n2.into_inner())),
|
||||
(Number::Integer(n1), Number::Float(n2))
|
||||
| (Number::Float(n2), Number::Integer(n1)) =>
|
||||
match n1.to_f64() {
|
||||
Some(n1) => Number::Float(OrderedFloat(n1 + n2.into_inner())),
|
||||
None => Number::Integer(n1)
|
||||
}
|
||||
NumberPair::Rational(r1, r2) =>
|
||||
Number::Rational(r1 + r2)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -460,17 +539,13 @@ impl Sub<Number> for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn sub(self, rhs: Number) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
match NumberPair::from(self, rhs) {
|
||||
NumberPair::Float(f1, f2) =>
|
||||
Number::Float(OrderedFloat(f1.into_inner() - f2.into_inner())),
|
||||
NumberPair::Integer(n1, n2) =>
|
||||
Number::Integer(n1 - n2),
|
||||
(Number::Float(n1), Number::Float(n2)) =>
|
||||
Number::Float(OrderedFloat(n1.into_inner() - n2.into_inner())),
|
||||
(Number::Integer(n1), Number::Float(n2))
|
||||
| (Number::Float(n2), Number::Integer(n1)) =>
|
||||
match n1.to_f64() {
|
||||
Some(n1) => Number::Float(OrderedFloat(n1 - n2.into_inner())),
|
||||
None => Number::Integer(n1)
|
||||
}
|
||||
NumberPair::Rational(r1, r2) =>
|
||||
Number::Rational(r1 - r2)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,41 +554,46 @@ impl Mul<Number> for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn mul(self, rhs: Number) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
match NumberPair::from(self, rhs) {
|
||||
NumberPair::Float(f1, f2) =>
|
||||
Number::Float(OrderedFloat(f1.into_inner() * f2.into_inner())),
|
||||
NumberPair::Integer(n1, n2) =>
|
||||
Number::Integer(n1 * n2),
|
||||
(Number::Float(n1), Number::Float(n2)) =>
|
||||
Number::Float(OrderedFloat(n1.into_inner() * n2.into_inner())),
|
||||
(Number::Integer(n1), Number::Float(n2))
|
||||
| (Number::Float(n2), Number::Integer(n1)) =>
|
||||
match n1.to_f64() {
|
||||
Some(n1) => Number::Float(OrderedFloat(n1 * n2.into_inner())),
|
||||
None => Number::Integer(n1)
|
||||
}
|
||||
}
|
||||
NumberPair::Rational(r1, r2) =>
|
||||
Number::Rational(r1 * r2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*TODO: reserved for proper division.
|
||||
|
||||
impl Div<Number> for Number {
|
||||
type Output = Number;
|
||||
|
||||
fn div(self, rhs: Number) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
Number::Integer(n1 / n2),
|
||||
(Number::Float(n1), Number::Float(n2)) =>
|
||||
Number::Float(OrderedFloat(n1.into_inner() / n2.into_inner())),
|
||||
(Number::Integer(n1), Number::Float(n2))
|
||||
| (Number::Float(n2), Number::Integer(n1)) =>
|
||||
match NumberPair::from(self, rhs) {
|
||||
NumberPair::Float(f1, f2) =>
|
||||
Number::Float(OrderedFloat(f1.into_inner() / f2.into_inner())),
|
||||
NumberPair::Integer(n1, n2) =>
|
||||
match n1.to_f64() {
|
||||
Some(n1) => Number::Float(OrderedFloat(n1 / n2.into_inner())),
|
||||
None => Number::Integer(n1)
|
||||
}
|
||||
Some(f1) => if let Some(f2) = n2.to_f64() {
|
||||
Number::Float(OrderedFloat(f1 / f2))
|
||||
} else {
|
||||
let r1 = Ratio::from_integer(n1);
|
||||
let r2 = Ratio::from_integer(n2);
|
||||
|
||||
Number::Rational(r1 / r2)
|
||||
},
|
||||
None => {
|
||||
let r1 = Ratio::from_integer(n1);
|
||||
let r2 = Ratio::from_integer(n2);
|
||||
|
||||
Number::Rational(r1 / r2)
|
||||
},
|
||||
},
|
||||
NumberPair::Rational(r1, r2) =>
|
||||
Number::Rational(r1 / r2)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
impl Neg for Number {
|
||||
type Output = Number;
|
||||
@@ -521,7 +601,8 @@ impl Neg for Number {
|
||||
fn neg(self) -> Self::Output {
|
||||
match self {
|
||||
Number::Integer(n) => Number::Integer(-n),
|
||||
Number::Float(f) => Number::Float(OrderedFloat(-1.0 * f.into_inner()))
|
||||
Number::Float(f) => Number::Float(OrderedFloat(-1.0 * f.into_inner())),
|
||||
Number::Rational(r) => Number::Rational(- r)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -549,6 +630,8 @@ pub enum ArithmeticInstruction {
|
||||
Sub(ArithmeticTerm, ArithmeticTerm, usize),
|
||||
Mul(ArithmeticTerm, ArithmeticTerm, usize),
|
||||
IDiv(ArithmeticTerm, ArithmeticTerm, usize),
|
||||
RDiv(ArithmeticTerm, ArithmeticTerm, usize),
|
||||
Div(ArithmeticTerm, ArithmeticTerm, usize),
|
||||
Neg(ArithmeticTerm, usize)
|
||||
}
|
||||
|
||||
@@ -584,7 +667,7 @@ pub enum ControlInstruction {
|
||||
IsExecute(RegType),
|
||||
Proceed,
|
||||
ThrowCall,
|
||||
ThrowExecute,
|
||||
ThrowExecute,
|
||||
}
|
||||
|
||||
impl ControlInstruction {
|
||||
@@ -601,7 +684,7 @@ impl ControlInstruction {
|
||||
&ControlInstruction::Goto(_, _) => true,
|
||||
&ControlInstruction::Proceed => true,
|
||||
&ControlInstruction::IsCall(_) => true,
|
||||
&ControlInstruction::IsExecute(_) => true,
|
||||
&ControlInstruction::IsExecute(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,9 +128,11 @@ pub fn build_code_dir() -> (Code, CodeDir, OpDir)
|
||||
op_dir.insert((String::from("+"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((String::from("-"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((String::from("//"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((String::from("/"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((String::from("div"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((String::from("*"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((String::from("-"), Fixity::Pre), (FY, 200));
|
||||
op_dir.insert((String::from("rdiv"), Fixity::In), (YFX, 400));
|
||||
|
||||
// there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
|
||||
// (an extra register is needed for the predicate name)
|
||||
|
||||
@@ -212,8 +212,12 @@ impl fmt::Display for ArithmeticInstruction {
|
||||
write!(f, "sub {}, {}, @{}", a1, a2, t),
|
||||
&ArithmeticInstruction::Mul(ref a1, ref a2, ref t) =>
|
||||
write!(f, "mul {}, {}, @{}", a1, a2, t),
|
||||
&ArithmeticInstruction::Div(ref a1, ref a2, ref t) =>
|
||||
write!(f, "div {}, {}, @{}", a1, a2, t),
|
||||
&ArithmeticInstruction::IDiv(ref a1, ref a2, ref t) =>
|
||||
write!(f, "idiv {}, {}, @{}", a1, a2, t),
|
||||
&ArithmeticInstruction::RDiv(ref a1, ref a2, ref t) =>
|
||||
write!(f, "rdiv {}, {}, @{}", a1, a2, t),
|
||||
&ArithmeticInstruction::Neg(ref a, ref t) =>
|
||||
write!(f, "neg {}, @{}", a, t)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use prolog::heapview::*;
|
||||
use prolog::and_stack::*;
|
||||
use prolog::num::Zero;
|
||||
use prolog::num::bigint::BigInt;
|
||||
use prolog::num::rational::Ratio;
|
||||
use prolog::or_stack::*;
|
||||
use prolog::ordered_float::OrderedFloat;
|
||||
use prolog::fixtures::*;
|
||||
@@ -610,7 +611,7 @@ macro_rules! try_or_fail {
|
||||
match $e {
|
||||
Ok(val) => val,
|
||||
Err(msg) => {
|
||||
$s.throw_exception(string!(msg));
|
||||
$s.throw_exception(msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -841,7 +842,23 @@ impl MachineState {
|
||||
};
|
||||
}
|
||||
|
||||
fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, &'static str> {
|
||||
fn get_rational(&self, at: &ArithmeticTerm) -> Result<Ratio<BigInt>, Vec<HeapCellValue>> {
|
||||
let n = self.get_number(at)?;
|
||||
|
||||
match n {
|
||||
Number::Rational(r) => Ok(r),
|
||||
Number::Float(fl) =>
|
||||
if let Some(r) = Ratio::from_float(fl.into_inner()) {
|
||||
Ok(r)
|
||||
} else {
|
||||
Err(functor!("instantiation_error", 1, [atom!("(is)/2")]))
|
||||
},
|
||||
Number::Integer(bi) =>
|
||||
Ok(Ratio::from_integer(bi))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, Vec<HeapCellValue>> {
|
||||
match at {
|
||||
&ArithmeticTerm::Reg(r) => {
|
||||
let addr = self[r].clone();
|
||||
@@ -852,8 +869,10 @@ impl MachineState {
|
||||
Ok(Number::Integer(bi)),
|
||||
Addr::Con(Constant::Float(fl)) =>
|
||||
Ok(Number::Float(fl)),
|
||||
Addr::Con(Constant::Rational(r)) =>
|
||||
Ok(Number::Rational(r)),
|
||||
_ =>
|
||||
Err("is/2: variable not instantiated to number.")
|
||||
Err(functor!("instantiation_error", 1, [atom!("(is)/2")]))
|
||||
}
|
||||
},
|
||||
&ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()),
|
||||
@@ -885,6 +904,20 @@ impl MachineState {
|
||||
self.interms[t - 1] = n1 * n2;
|
||||
self.p += 1;
|
||||
},
|
||||
&ArithmeticInstruction::RDiv(ref a1, ref a2, t) => {
|
||||
let r1 = try_or_fail!(self, self.get_rational(a1));
|
||||
let r2 = try_or_fail!(self, self.get_rational(a2));
|
||||
|
||||
if r2 == Ratio::zero() {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
1,
|
||||
[atom!("zero_divisor")]));
|
||||
return;
|
||||
}
|
||||
|
||||
self.interms[t - 1] = Number::Rational(r1 / r2);
|
||||
self.p += 1;
|
||||
},
|
||||
&ArithmeticInstruction::IDiv(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
@@ -914,6 +947,20 @@ impl MachineState {
|
||||
|
||||
self.interms[t - 1] = - n1;
|
||||
self.p += 1;
|
||||
},
|
||||
&ArithmeticInstruction::Div(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
if n2.is_zero() {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
1,
|
||||
[atom!("zero_divisor")]));
|
||||
return;
|
||||
}
|
||||
|
||||
self.interms[t - 1] = n1 / n2;
|
||||
self.p += 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,12 +28,6 @@ macro_rules! arith {
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! string {
|
||||
($str:expr) => {
|
||||
vec![HeapCellValue::Con(Constant::String(String::from($str)))]
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! functor {
|
||||
($name:expr, $len:expr, [$($args:expr),*]) => {{
|
||||
if $len > 0 {
|
||||
|
||||
Reference in New Issue
Block a user