diff options
Diffstat (limited to 'dhall_core')
-rw-r--r-- | dhall_core/src/core.rs | 126 | ||||
-rw-r--r-- | dhall_core/src/text.rs | 22 |
2 files changed, 102 insertions, 46 deletions
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index a9033f3..355f625 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -12,6 +12,13 @@ pub type Double = NaiveDouble; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum X {} +pub fn trivial_result<T>(x: Result<T, X>) -> T { + match x { + Ok(x) => x, + Err(e) => match e {}, + } +} + /// Double with bitwise equality #[derive(Debug, Copy, Clone)] pub struct NaiveDouble(f64); @@ -362,83 +369,122 @@ impl<SE, L, N, E> ExprF<SE, L, N, E> { } #[inline(always)] - pub fn map<SE2, L2, N2, E2, F1, F2, F3, F4, F5>( + pub fn traverse<SE2, L2, N2, E2, Err, F1, F2, F3, F4, F5>( self, map_subexpr: F1, map_under_binder: F2, map_note: F3, map_embed: F4, mut map_label: F5, - ) -> ExprF<SE2, L2, N2, E2> + ) -> Result<ExprF<SE2, L2, N2, E2>, Err> where L: Ord, L2: Ord, - F1: FnMut(SE) -> SE2, - F2: FnOnce(&L, SE) -> SE2, - F3: FnOnce(N) -> N2, - F4: FnOnce(E) -> E2, - F5: FnMut(L) -> L2, + F1: FnMut(SE) -> Result<SE2, Err>, + F2: FnOnce(&L, SE) -> Result<SE2, Err>, + F3: FnOnce(N) -> Result<N2, Err>, + F4: FnOnce(E) -> Result<E2, Err>, + F5: FnMut(L) -> Result<L2, Err>, { let mut map = map_subexpr; - fn vec<T, U, F: FnMut(T) -> U>(x: Vec<T>, f: F) -> Vec<U> { + fn vec<T, U, Err, F: FnMut(T) -> Result<U, Err>>( + x: Vec<T>, + f: F, + ) -> Result<Vec<U>, Err> { x.into_iter().map(f).collect() } - fn btmap<K, L, T, U, FK, FV>( + fn opt<T, U, Err, F: FnOnce(T) -> Result<U, Err>>( + x: Option<T>, + f: F, + ) -> Result<Option<U>, Err> { + Ok(match x { + Some(x) => Some(f(x)?), + None => None, + }) + } + fn btmap<K, L, T, U, Err, FK, FV>( x: BTreeMap<K, T>, mut fk: FK, mut fv: FV, - ) -> BTreeMap<L, U> + ) -> Result<BTreeMap<L, U>, Err> where K: Ord, L: Ord, - FK: FnMut(K) -> L, - FV: FnMut(T) -> U, + FK: FnMut(K) -> Result<L, Err>, + FV: FnMut(T) -> Result<U, Err>, { - x.into_iter().map(|(k, v)| (fk(k), fv(v))).collect() + x.into_iter().map(|(k, v)| Ok((fk(k)?, fv(v)?))).collect() } use crate::ExprF::*; - match self { - Var(V(l, n)) => Var(V(map_label(l), n)), + Ok(match self { + Var(V(l, n)) => Var(V(map_label(l)?, n)), Lam(l, t, b) => { - let b = map_under_binder(&l, b); - Lam(map_label(l), map(t), b) + let b = map_under_binder(&l, b)?; + Lam(map_label(l)?, map(t)?, b) } Pi(l, t, b) => { - let b = map_under_binder(&l, b); - Pi(map_label(l), map(t), b) + let b = map_under_binder(&l, b)?; + Pi(map_label(l)?, map(t)?, b) } Let(l, t, a, b) => { - let b = map_under_binder(&l, b); - Let(map_label(l), t.map(&mut map), map(a), b) + let b = map_under_binder(&l, b)?; + Let(map_label(l)?, opt(t, &mut map)?, map(a)?, b) } - App(f, args) => App(map(f), vec(args, map)), - Annot(x, t) => Annot(map(x), map(t)), + App(f, args) => App(map(f)?, vec(args, map)?), + Annot(x, t) => Annot(map(x)?, map(t)?), Const(k) => Const(k), Builtin(v) => Builtin(v), BoolLit(b) => BoolLit(b), NaturalLit(n) => NaturalLit(n), IntegerLit(n) => IntegerLit(n), DoubleLit(n) => DoubleLit(n), - TextLit(t) => TextLit(t.map(map)), - BinOp(o, x, y) => BinOp(o, map(x), map(y)), - BoolIf(b, t, f) => BoolIf(map(b), map(t), map(f)), - EmptyListLit(t) => EmptyListLit(map(t)), - NEListLit(es) => NEListLit(vec(es, map)), - EmptyOptionalLit(t) => EmptyOptionalLit(map(t)), - NEOptionalLit(e) => NEOptionalLit(map(e)), - RecordType(kts) => RecordType(btmap(kts, map_label, map)), - RecordLit(kvs) => RecordLit(btmap(kvs, map_label, map)), - UnionType(kts) => UnionType(btmap(kts, map_label, map)), + TextLit(t) => TextLit(t.traverse(map)?), + BinOp(o, x, y) => BinOp(o, map(x)?, map(y)?), + BoolIf(b, t, f) => BoolIf(map(b)?, map(t)?, map(f)?), + EmptyListLit(t) => EmptyListLit(map(t)?), + NEListLit(es) => NEListLit(vec(es, map)?), + EmptyOptionalLit(t) => EmptyOptionalLit(map(t)?), + NEOptionalLit(e) => NEOptionalLit(map(e)?), + RecordType(kts) => RecordType(btmap(kts, map_label, map)?), + RecordLit(kvs) => RecordLit(btmap(kvs, map_label, map)?), + UnionType(kts) => UnionType(btmap(kts, map_label, map)?), UnionLit(k, v, kvs) => { - UnionLit(map_label(k), map(v), btmap(kvs, map_label, map)) + UnionLit(map_label(k)?, map(v)?, btmap(kvs, map_label, map)?) } - Merge(x, y, t) => Merge(map(x), map(y), t.map(map)), - Field(e, l) => Field(map(e), map_label(l)), - Projection(e, ls) => Projection(map(e), vec(ls, map_label)), - Note(n, e) => Note(map_note(n), map(e)), - Embed(a) => Embed(map_embed(a)), - } + Merge(x, y, t) => Merge(map(x)?, map(y)?, opt(t, map)?), + Field(e, l) => Field(map(e)?, map_label(l)?), + Projection(e, ls) => Projection(map(e)?, vec(ls, map_label)?), + Note(n, e) => Note(map_note(n)?, map(e)?), + Embed(a) => Embed(map_embed(a)?), + }) + } + + #[inline(always)] + pub fn map<SE2, L2, N2, E2, F1, F2, F3, F4, F5>( + self, + mut map_subexpr: F1, + map_under_binder: F2, + map_note: F3, + map_embed: F4, + mut map_label: F5, + ) -> ExprF<SE2, L2, N2, E2> + where + L: Ord, + L2: Ord, + F1: FnMut(SE) -> SE2, + F2: FnOnce(&L, SE) -> SE2, + F3: FnOnce(N) -> N2, + F4: FnOnce(E) -> E2, + F5: FnMut(L) -> L2, + { + trivial_result(self.traverse( + |x| Ok(map_subexpr(x)), + |l, x| Ok(map_under_binder(l, x)), + |x| Ok(map_note(x)), + |x| Ok(map_embed(x)), + |x| Ok(map_label(x)), + )) } #[inline(always)] diff --git a/dhall_core/src/text.rs b/dhall_core/src/text.rs index 9500f32..7c0e2b4 100644 --- a/dhall_core/src/text.rs +++ b/dhall_core/src/text.rs @@ -34,18 +34,28 @@ pub enum InterpolatedTextContents<SubExpr> { } impl<SubExpr> InterpolatedText<SubExpr> { - pub fn map<SubExpr2, F>(self, mut f: F) -> InterpolatedText<SubExpr2> + pub fn traverse<SubExpr2, E, F>( + self, + mut f: F, + ) -> Result<InterpolatedText<SubExpr2>, E> where - F: FnMut(SubExpr) -> SubExpr2, + F: FnMut(SubExpr) -> Result<SubExpr2, E>, { - InterpolatedText { + Ok(InterpolatedText { head: self.head.clone(), tail: self .tail .into_iter() - .map(|(e, s)| (f(e), s.clone())) - .collect(), - } + .map(|(e, s)| Ok((f(e)?, s.clone()))) + .collect::<Result<_, _>>()?, + }) + } + + pub fn map<SubExpr2, F>(self, mut f: F) -> InterpolatedText<SubExpr2> + where + F: FnMut(SubExpr) -> SubExpr2, + { + crate::trivial_result(self.traverse(|e| Ok(f(e)))) } pub fn as_ref(&self) -> InterpolatedText<&SubExpr> { |