diff --git a/implementations/rust/preserves-path/Cargo.toml b/implementations/rust/preserves-path/Cargo.toml index 57920d1..a87d58e 100644 --- a/implementations/rust/preserves-path/Cargo.toml +++ b/implementations/rust/preserves-path/Cargo.toml @@ -15,5 +15,6 @@ preserves-schema = { path = "../preserves-schema", version = "0.3.0" } preserves = { path = "../preserves", version = "0.16.0" } preserves-schema = { path = "../preserves-schema", version = "0.3.0" } +num = "0.4" regex = "1.5" thiserror = "1.0" diff --git a/implementations/rust/preserves-path/src/lib.rs b/implementations/rust/preserves-path/src/lib.rs index b60e243..58ab4fd 100644 --- a/implementations/rust/preserves-path/src/lib.rs +++ b/implementations/rust/preserves-path/src/lib.rs @@ -5,6 +5,9 @@ pub mod schemas; pub use crate::schemas::path; +use num::bigint::BigInt; +use num::traits::cast::ToPrimitive; + use preserves::value::AtomClass; use preserves::value::BinarySource; use preserves::value::BytesBinarySource; @@ -299,6 +302,7 @@ impl StepMaker for path::Filter { })), path::Filter::Regex { regex } => Ok(Node::new(RegexStep { regex: regex::Regex::new(regex)?, step })), path::Filter::Test { pred } => Ok(Node::new(TestStep { pred: compile_predicate(&**pred)?, step })), + path::Filter::Real => Ok(Node::new(RealStep { step })), path::Filter::Kind { kind } => Ok(Node::new(KindStep { kind: match &**kind { path::ValueKind::Boolean => ValueClass::Atomic(AtomClass::Boolean), @@ -387,6 +391,26 @@ impl Step for TestStep { delegate_finish_and_reset!(self, self.step); } +#[derive(Debug)] +struct RealStep { + step: Node, +} + +impl Step for RealStep { + fn accept(&mut self, path: Rc, value: &IOValue) { + match value.value() { + Value::SignedInteger(i) => if let Some(r) = BigInt::from(i).to_f64() { + self.step.accept(path, &IOValue::new(r)) + }, + Value::Float(f) => self.step.accept(path, &IOValue::new(f32::from(*f) as f64)), + Value::Double(_) => self.step.accept(path, value), + _ => (), + } + } + + delegate_finish_and_reset!(self, self.step); +} + #[derive(Debug)] struct VecCollector { accumulator: Vec, @@ -535,9 +559,8 @@ fn parse_step(tokens: &[IOValue]) -> Result, Co ".embedded" => Ok(Some((path::Step::Axis(Box::new(path::Axis::Embedded)), remainder))), "*" => Ok(Some((path::Step::Filter(Box::new(path::Filter::Nop)), remainder))), - "eq" => parse_comparison(remainder, path::Comparison::Eq), - "=" => parse_comparison(remainder, path::Comparison::Eq), - "ne" => parse_comparison(remainder, path::Comparison::Ne), + "eq" | "=" => parse_comparison(remainder, path::Comparison::Eq), + "ne" | "!=" => parse_comparison(remainder, path::Comparison::Ne), "lt" => parse_comparison(remainder, path::Comparison::Lt), "gt" => parse_comparison(remainder, path::Comparison::Gt), "le" => parse_comparison(remainder, path::Comparison::Le), @@ -561,6 +584,8 @@ fn parse_step(tokens: &[IOValue]) -> Result, Co })), remainder))) } + "real" => Ok(Some((path::Step::Filter(Box::new(path::Filter::Real)), remainder))), + "bool" => Ok(Some((path::Step::from(path::ValueKind::Boolean), remainder))), "float" => Ok(Some((path::Step::from(path::ValueKind::Float), remainder))), "double" => Ok(Some((path::Step::from(path::ValueKind::Double), remainder))), diff --git a/implementations/rust/preserves/Cargo.toml b/implementations/rust/preserves/Cargo.toml index 1ebd97b..96d6642 100644 --- a/implementations/rust/preserves/Cargo.toml +++ b/implementations/rust/preserves/Cargo.toml @@ -14,7 +14,7 @@ gitlab = { repository = "preserves/preserves" } [dependencies] base64 = "0.13" dtoa = "0.4" -num = "0.2" +num = "0.4" regex = "1.5" serde = { version = "1.0", features = ["derive"] } serde_bytes = "0.11" diff --git a/implementations/rust/preserves/src/value/repr.rs b/implementations/rust/preserves/src/value/repr.rs index a5f5b54..d7bb455 100644 --- a/implementations/rust/preserves/src/value/repr.rs +++ b/implementations/rust/preserves/src/value/repr.rs @@ -119,11 +119,11 @@ pub enum CompoundClass { } /// Single-precision IEEE 754 Value -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct Float(pub f32); /// Double-precision IEEE 754 Value -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct Double(pub f64); /// A Record `Value` -- INVARIANT: length always non-zero diff --git a/path/path.bin b/path/path.bin index 547251f..43733c0 100644 --- a/path/path.bin +++ b/path/path.bin @@ -1,5 +1,5 @@ ´łschema·łversion‘ł definitions·łAxis´łorµµ±values´łrec´łlitłvalues„´łtupleµ„„„„µ± descendants´łrec´łlitł descendants„´łtupleµ„„„„µ±at´łrec´łlitłat„´łtupleµ´łnamedłkeyłany„„„„„µ±label´łrec´łlitłlabel„´łtupleµ„„„„µ±keys´łrec´łlitłkeys„´łtupleµ„„„„µ±length´łrec´łlitłlength„´łtupleµ„„„„µ± annotations´łrec´łlitł annotations„´łtupleµ„„„„µ±embedded´łrec´łlitłembedded„´łtupleµ„„„„„„łStep´łorµµ±Axis´łrefµ„łAxis„„µ±Filter´łrefµ„łFilter„„„„łFilter´łorµµ±nop´łrec´łlitłnop„´łtupleµ„„„„µ±compare´łrec´łlitłcompare„´łtupleµ´łnamedłop´łrefµ„ł -Comparison„„´łnamedłliteralłany„„„„„µ±regex´łrec´łlitłregex„´łtupleµ´łnamedłregex´łatomłString„„„„„„µ±test´łrec´łlitłtest„´łtupleµ´łnamedłpred´łrefµ„ł Predicate„„„„„„µ±kind´łrec´łlitłkind„´łtupleµ´łnamedłkind´łrefµ„ł ValueKind„„„„„„„„łSelector´łseqof´łrefµ„łStep„„ł Predicate´łorµµ±Selector´łrefµ„łSelector„„µ±not´łrec´łlitłnot„´łtupleµ´łnamedłpred´łrefµ„ł Predicate„„„„„„µ±or´łrec´łlitłor„´łtupleµ´łnamedłpreds´łseqof´łrefµ„ł Predicate„„„„„„„µ±and´łrec´łlitłand„´łtupleµ´łnamedłpreds´łseqof´łrefµ„ł Predicate„„„„„„„„„ł ValueKind´łorµµ±Boolean´łlitłBoolean„„µ±Float´łlitłFloat„„µ±Double´łlitłDouble„„µ± SignedInteger´łlitł SignedInteger„„µ±String´łlitłString„„µ± +Comparison„„´łnamedłliteralłany„„„„„µ±regex´łrec´łlitłregex„´łtupleµ´łnamedłregex´łatomłString„„„„„„µ±test´łrec´łlitłtest„´łtupleµ´łnamedłpred´łrefµ„ł Predicate„„„„„„µ±real´łrec´łlitłreal„´łtupleµ„„„„µ±kind´łrec´łlitłkind„´łtupleµ´łnamedłkind´łrefµ„ł ValueKind„„„„„„„„łSelector´łseqof´łrefµ„łStep„„ł Predicate´łorµµ±Selector´łrefµ„łSelector„„µ±not´łrec´łlitłnot„´łtupleµ´łnamedłpred´łrefµ„ł Predicate„„„„„„µ±or´łrec´łlitłor„´łtupleµ´łnamedłpreds´łseqof´łrefµ„ł Predicate„„„„„„„µ±and´łrec´łlitłand„´łtupleµ´łnamedłpreds´łseqof´łrefµ„ł Predicate„„„„„„„„„ł ValueKind´łorµµ±Boolean´łlitłBoolean„„µ±Float´łlitłFloat„„µ±Double´łlitłDouble„„µ± SignedInteger´łlitł SignedInteger„„µ±String´łlitłString„„µ± ByteString´łlitł ByteString„„µ±Symbol´łlitłSymbol„„µ±Record´łlitłRecord„„µ±Sequence´łlitłSequence„„µ±Set´łlitłSet„„µ± Dictionary´łlitł diff --git a/path/path.prs b/path/path.prs index c6759e8..9d999e7 100644 --- a/path/path.prs +++ b/path/path.prs @@ -27,6 +27,7 @@ Filter = / / / +/ / . diff --git a/preserves-path.md b/preserves-path.md index 66037f4..7bdd091 100644 --- a/preserves-path.md +++ b/preserves-path.md @@ -66,6 +66,7 @@ Filters: narrow down a selection without moving eq literal ;; Matches values (equal to/less than/greater than/etc.) the literal = literal ne literal + != literal lt literal gt literal le literal @@ -78,6 +79,10 @@ Filters: narrow down a selection without moving ^ literal ;; Matches a record having a the literal as its label -- equivalent to [.^ = literal] + real ;; Promotes int and float to double, passes on double unchanged, rejects others + ;; Out-of-range ints (too big or too small) become various double infinities + ;; Converting high-magnitude ints causes loss of precision + bool ;; Type filters float double