From 8d527e88168885ab754a039219d0ae682fa4508b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 21 Mar 2019 21:27:36 +0100 Subject: Follow the spec for handling Doubles --- dhall/src/binary.rs | 2 +- dhall/tests/parser.rs | 2 +- dhall_core/src/core.rs | 28 ++++++++++++++++++++++++++-- dhall_core/src/parser.rs | 9 +++++---- dhall_core/src/printer.rs | 18 +++++++++++++++++- dhall_core/src/text.rs | 2 +- 6 files changed, 51 insertions(+), 10 deletions(-) diff --git a/dhall/src/binary.rs b/dhall/src/binary.rs index e8fcdab..8c5b902 100644 --- a/dhall/src/binary.rs +++ b/dhall/src/binary.rs @@ -34,7 +34,7 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result { }, }, U64(n) => Var(V(Label::from("_"), *n as usize)), - F64(x) => DoubleLit(*x), + F64(x) => DoubleLit((*x).into()), Bool(b) => BoolLit(*b), Array(vec) => match vec.as_slice() { [String(l), U64(n)] => { diff --git a/dhall/tests/parser.rs b/dhall/tests/parser.rs index 678c198..4fa0ff7 100644 --- a/dhall/tests/parser.rs +++ b/dhall/tests/parser.rs @@ -18,7 +18,7 @@ parser_success!(spec_parser_success_annotations, "annotations"); parser_success!(spec_parser_success_blockComment, "blockComment"); parser_success!(spec_parser_success_builtins, "builtins"); // parser_success!(spec_parser_success_collectionImportType, "collectionImportType"); -// parser_success!(spec_parser_success_double, "double"); +parser_success!(spec_parser_success_double, "double"); parser_success!(spec_parser_success_doubleQuotedString, "doubleQuotedString"); // parser_success!(spec_parser_success_environmentVariables, "environmentVariables"); // parser_success!(spec_parser_success_escapedDoubleQuotedString, "escapedDoubleQuotedString"); diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index 52fc0cf..9f26b65 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -3,15 +3,39 @@ use crate::*; use std::collections::BTreeMap; use std::rc::Rc; -pub type Double = f64; pub type Int = isize; pub type Integer = isize; pub type Natural = usize; +pub type Double = NaiveDouble; /// An empty type #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum X {} +/// Double with bitwise equality +#[derive(Debug, Copy, Clone)] +pub struct NaiveDouble(f64); + +impl PartialEq for NaiveDouble { + fn eq(&self, other: &Self) -> bool { + return self.0.to_bits() == other.0.to_bits(); + } +} + +impl Eq for NaiveDouble {} + +impl From for NaiveDouble { + fn from(x: f64) -> Self { + NaiveDouble(x) + } +} + +impl From for f64 { + fn from(x: NaiveDouble) -> f64 { + x.0 + } +} + /// Constants for a pure type system /// /// The only axiom is: @@ -147,7 +171,7 @@ pub type DhallExpr = ResolvedExpr; pub type SubExpr = Rc>; /// Syntax tree for expressions -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Expr { /// `Const c ~ c` Const(Const), diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index b07094d..7de75d2 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -348,7 +348,8 @@ make_parser! { rule!(double_literal_raw; raw_pair!(pair) => { pair.as_str().trim() - .parse() + .parse::() + .map(NaiveDouble::from) .map_err(|e: std::num::ParseFloatError| custom_parse_error(&pair, format!("{}", e)))? } ); @@ -599,9 +600,9 @@ make_parser! { rule!(literal_expression_raw as expression; children!( [double_literal_raw(n)] => bx(Expr::DoubleLit(n)), - [minus_infinity_literal(n)] => bx(Expr::DoubleLit(std::f64::NEG_INFINITY)), - [plus_infinity_literal(n)] => bx(Expr::DoubleLit(std::f64::INFINITY)), - [NaN_raw(n)] => bx(Expr::DoubleLit(std::f64::NAN)), + [minus_infinity_literal(n)] => bx(Expr::DoubleLit(std::f64::NEG_INFINITY.into())), + [plus_infinity_literal(n)] => bx(Expr::DoubleLit(std::f64::INFINITY.into())), + [NaN_raw(n)] => bx(Expr::DoubleLit(std::f64::NAN.into())), [natural_literal_raw(n)] => bx(Expr::NaturalLit(n)), [integer_literal_raw(n)] => bx(Expr::IntegerLit(n)), [double_quote_literal(s)] => bx(Expr::TextLit(s)), diff --git a/dhall_core/src/printer.rs b/dhall_core/src/printer.rs index b72f32b..e43f1be 100644 --- a/dhall_core/src/printer.rs +++ b/dhall_core/src/printer.rs @@ -183,7 +183,23 @@ impl Expr { a.fmt(f) } &IntegerLit(a) => a.fmt(f), - &DoubleLit(a) => a.fmt(f), + &DoubleLit(a) => { + let a = f64::from(*a); + if a == std::f64::INFINITY { + f.write_str("Infinity") + } else if a == std::f64::NEG_INFINITY { + f.write_str("-Infinity") + } else if a.is_nan() { + f.write_str("NaN") + } else { + let s = format!("{}", a); + if s.contains("e") || s.contains(".") { + f.write_str(&s) + } else { + write!(f, "{}.0", s) + } + } + } &TextLit(ref a) => { f.write_str("\"")?; for x in a.iter() { diff --git a/dhall_core/src/text.rs b/dhall_core/src/text.rs index cd5fef3..eb0d39c 100644 --- a/dhall_core/src/text.rs +++ b/dhall_core/src/text.rs @@ -3,7 +3,7 @@ use std::iter::FromIterator; use std::ops::Add; use std::rc::Rc; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct InterpolatedText { head: String, tail: Vec<(Rc>, String)>, -- cgit v1.2.3