diff --git a/implementations/rust/preserves-path/src/lib.rs b/implementations/rust/preserves-path/src/lib.rs index 58ab4fd..958603f 100644 --- a/implementations/rust/preserves-path/src/lib.rs +++ b/implementations/rust/preserves-path/src/lib.rs @@ -7,6 +7,7 @@ pub use crate::schemas::path; use num::bigint::BigInt; use num::traits::cast::ToPrimitive; +use num::traits::cast::FromPrimitive; use preserves::value::AtomClass; use preserves::value::BinarySource; @@ -303,6 +304,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::Int => Ok(Node::new(IntStep { step })), path::Filter::Kind { kind } => Ok(Node::new(KindStep { kind: match &**kind { path::ValueKind::Boolean => ValueClass::Atomic(AtomClass::Boolean), @@ -411,6 +413,28 @@ impl Step for RealStep { delegate_finish_and_reset!(self, self.step); } +#[derive(Debug)] +struct IntStep { + step: Node, +} + +impl Step for IntStep { + fn accept(&mut self, path: Rc, value: &IOValue) { + match value.value() { + Value::SignedInteger(_) => self.step.accept(path, value), + Value::Float(f) => if let Some(i) = BigInt::from_f32(f32::from(*f)) { + self.step.accept(path, &IOValue::new(i)) + }, + Value::Double(d) => if let Some(i) = BigInt::from_f64(f64::from(*d)) { + self.step.accept(path, &IOValue::new(i)) + }, + _ => (), + } + } + + delegate_finish_and_reset!(self, self.step); +} + #[derive(Debug)] struct VecCollector { accumulator: Vec, @@ -584,7 +608,8 @@ fn parse_step(tokens: &[IOValue]) -> Result, Co })), remainder))) } - "real" => Ok(Some((path::Step::Filter(Box::new(path::Filter::Real)), remainder))), + "~real" => Ok(Some((path::Step::Filter(Box::new(path::Filter::Real)), remainder))), + "~int" => Ok(Some((path::Step::Filter(Box::new(path::Filter::Int)), remainder))), "bool" => Ok(Some((path::Step::from(path::ValueKind::Boolean), remainder))), "float" => Ok(Some((path::Step::from(path::ValueKind::Float), remainder))), diff --git a/path/path.bin b/path/path.bin index 43733c0..5f9b5e5 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„„„„„„µ±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„„µ± +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µ„„„„µ±int´łrec´łlitłint„´ł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 9d999e7..828ddf2 100644 --- a/path/path.prs +++ b/path/path.prs @@ -28,6 +28,7 @@ Filter = / / / +/ / . diff --git a/preserves-path.md b/preserves-path.md index 7bdd091..bc3b50d 100644 --- a/preserves-path.md +++ b/preserves-path.md @@ -79,10 +79,13 @@ 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 + ~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 + ~int ;; Converts float and double to closest integer, where possible + ;; NaN and infinities are rejected + bool ;; Type filters float double