format

parent b14890b4
use num::bigint::ParseBigIntError;
use std::error::Error;
use std::fmt;
use num::bigint::ParseBigIntError;
/// Represents a partial computation that can be captured as part of an
/// error message.
......@@ -47,13 +47,10 @@ impl PartialComp {
impl fmt::Display for PartialComp {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
PartialComp::ToFloat(ref arg) => {
write!(f, "{} as float", arg)
PartialComp::ToFloat(ref arg) => write!(f, "{} as float", arg),
PartialComp::Unary { ref op, ref arg } => {
write!(f, "{} {}", op, arg)
}
PartialComp::Unary {
ref op,
ref arg,
} => write!(f, "{} {}", op, arg),
PartialComp::Binary {
ref op,
ref lhs,
......@@ -94,11 +91,9 @@ impl fmt::Display for CalcError {
UnrecognizedToken(ref token) => {
write!(f, "unrecognized token: {}", token)
}
UnexpectedToken(ref token, ref kind) => write!(
f,
"expected {} token, got {} instead",
kind, token
),
UnexpectedToken(ref token, ref kind) => {
write!(f, "expected {} token, got {} instead", kind, token)
}
UnknownAtom(ref atom) => {
write!(f, "unknown variable or function '{}'", atom)
}
......
......@@ -113,15 +113,9 @@ mod tests {
(" + 1 1", Value::dec(2)),
(" - * 4 7 14", Value::dec(14)),
(" << 2 16", Value::dec(131072)),
(
" / % * 4 18 17 3",
Value::Float(d128!(4.0) / d128!(3.0)),
),
(" / % * 4 18 17 3", Value::Float(d128!(4.0) / d128!(3.0))),
("* + 1 3 5", Value::dec(20)),
(
"+ / * 5 3 2 * + 1 3 5",
Value::Float(d128!(27.5)),
),
("+ / * 5 3 2 * + 1 3 5", Value::Float(d128!(27.5))),
("^ ^ ^ ^ ^ 4 3 2 3 4 2", Value::dec(0)),
("<< 3 >> 4 2", Value::dec(6)),
];
......
......@@ -262,11 +262,11 @@ impl Environment for DefaultEnvironment {
args: &[Value],
) -> Result<Value, CalcError> {
match atom {
"pi" => Ok(Value::Float(d128!(
3.1415926535897932384626433832795028
))),
"pi" => {
Ok(Value::Float(d128!(3.1415926535897932384626433832795028)))
}
"tau" => Ok(Value::Float(
d128!(3.1415926535897932384626433832795028) * d128!(2.0)
d128!(3.1415926535897932384626433832795028) * d128!(2.0),
)),
"log" => Ok(Value::Float(args[0].as_float()?.log10())),
// "sin" => Ok(Value::Float(args[0].as_float().sin())),
......
......@@ -146,7 +146,8 @@ pub fn tokenize(input: &str) -> Result<Vec<Token>, CalcError> {
} else {
match c.check_operator() {
OperatorState::Complete => {
tokens.push(c.operator_type()
tokens.push(c
.operator_type()
.ok_or_else(|| InvalidOperator(c))?);
chars.next();
}
......@@ -160,7 +161,8 @@ pub fn tokenize(input: &str) -> Result<Vec<Token>, CalcError> {
chars.next();
}
_ => {
tokens.push(c.operator_type()
tokens.push(c
.operator_type()
.ok_or_else(|| InvalidOperator(c))?);
}
}
......@@ -226,7 +228,8 @@ pub fn tokenize_polish(input: &str) -> Result<Vec<Token>, CalcError> {
} else {
match c.check_operator() {
OperatorState::Complete => {
let token = c.operator_type()
let token = c
.operator_type()
.ok_or_else(|| InvalidOperator(c))?;
if token != Token::OpenParen
&& token != Token::CloseParen
......@@ -250,7 +253,8 @@ pub fn tokenize_polish(input: &str) -> Result<Vec<Token>, CalcError> {
chars.next();
}
_ => {
let token = c.operator_type()
let token = c
.operator_type()
.ok_or_else(|| InvalidOperator(c))?;
if token != Token::OpenParen
&& token != Token::CloseParen
......
use num::{Zero, BigInt, BigUint, ToPrimitive};
use decimal::d128;
use error::{CalcError, PartialComp};
use num::{BigInt, BigUint, ToPrimitive, Zero};
use std::fmt;
use std::ops::*;
......@@ -53,17 +53,17 @@ pub enum Value {
}
pub mod ops {
use super::{CalcError, Integral, PartialComp, UIntegral};
use decimal::d128;
use num::{Integer, ToPrimitive, Zero};
use std::iter::repeat;
use num::{Zero, Integer, ToPrimitive};
use super::{UIntegral, Integral, CalcError, PartialComp};
macro_rules! bitwise_op {
($name:ident, $fun:expr) => {
pub fn $name(n: &Integral, m: &Integral) -> Integral {
bitwise(n, m, $fun)
}
}
};
}
fn equalize(left: &mut Vec<u8>, right: &mut Vec<u8>) {
......@@ -78,7 +78,11 @@ pub mod ops {
}
}
pub fn bitwise<F: Fn(u8, u8) -> u8>(n: &Integral, m: &Integral, fun: F) -> Integral {
pub fn bitwise<F: Fn(u8, u8) -> u8>(
n: &Integral,
m: &Integral,
fun: F,
) -> Integral {
let mut n_bytes = n.to_signed_bytes_le();
let mut m_bytes = m.to_signed_bytes_le();
equalize(&mut n_bytes, &mut m_bytes);
......@@ -96,10 +100,7 @@ pub mod ops {
pub fn not(n: Integral) -> Integral {
let bytes = n.to_signed_bytes_le();
let res: Vec<u8> = bytes
.iter()
.map(|n| !n)
.collect();
let res: Vec<u8> = bytes.iter().map(|n| !n).collect();
Integral::from_signed_bytes_le(&res)
}
......@@ -122,9 +123,9 @@ pub mod ops {
}
pub fn to_float(n: &Integral) -> Result<d128, CalcError> {
n.to_i64()
.map(Into::into)
.ok_or(CalcError::WouldTruncate(PartialComp::ToFloat(n.to_string())))
n.to_i64().map(Into::into).ok_or(CalcError::WouldTruncate(
PartialComp::ToFloat(n.to_string()),
))
}
}
......@@ -167,19 +168,22 @@ impl Value {
match (self, that) {
(Value::Integral(n, t1), Value::Integral(m, t2)) => {
Ok(Value::Integral(f(n, m)?, *t1 + t2))
},
}
(v1 @ Value::Float(_), v2 @ _) | (v1 @ _, v2 @ Value::Float(_)) => {
Err(CalcError::BadTypes(PartialComp::binary(
op, v1, v2,
)))
Err(CalcError::BadTypes(PartialComp::binary(op, v1, v2)))
}
}
}
/// Represents a computation that will cast integer types to floating
/// point. There might be a possible truncation when we convert a BigInt into a floating point,
/// so we have to be careful here.
pub fn castmap<F, G>(self, that: Value, f: F, g: G) -> Result<Value, CalcError>
/// point. There might be a possible truncation when we convert a BigInt
/// into a floating point, so we have to be careful here.
pub fn castmap<F, G>(
self,
that: Value,
f: F,
g: G,
) -> Result<Value, CalcError>
where
F: Fn(Integral, Integral) -> Integral,
G: Fn(d128, d128) -> d128,
......@@ -221,7 +225,6 @@ impl Value {
};
Ok(value)
}
}
impl fmt::Display for Value {
......@@ -366,21 +369,19 @@ impl Shl<Value> for Value {
type Output = Result<Self, CalcError>;
fn shl(self, that: Value) -> Self::Output {
self.intmap(
&that,
"<<",
|n, m| {
m.to_i64()
.map(|m| {
if m < 0 {
self.intmap(&that, "<<", |n, m| {
m.to_i64()
.map(|m| {
if m < 0 {
n >> ((-m) as usize)
} else {
} else {
n << (m as usize)
}
})
.ok_or(CalcError::WouldOverflow(PartialComp::binary("<<", &self, &that)))
}
)
}
})
.ok_or(CalcError::WouldOverflow(PartialComp::binary(
"<<", &self, &that,
)))
})
}
}
......@@ -388,23 +389,19 @@ impl Shr<Value> for Value {
type Output = Result<Self, CalcError>;
fn shr(self, that: Value) -> Self::Output {
self.intmap(
&that,
"<<",
|n, m| {
m.to_i64()
.map(|m| {
if m < 0 {
self.intmap(&that, "<<", |n, m| {
m.to_i64()
.map(|m| {
if m < 0 {
n << ((-m) as usize)
} else {
} else {
n >> (m as usize)
}
})
.ok_or(
CalcError::WouldOverflow(PartialComp::binary(">>", &self, &that))
)
}
)
}
})
.ok_or(CalcError::WouldOverflow(PartialComp::binary(
">>", &self, &that,
)))
})
}
}
......@@ -425,7 +422,8 @@ mod tests {
),
(
((Value::hex(24) * Value::dec(4)).unwrap()
* Value::Float(d128!(1) / d128!(48))).unwrap(),
* Value::Float(d128!(1) / d128!(48)))
.unwrap(),
Value::Float(d128!(2)),
),
];
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment