diff options
author | Nadrieril Feneanar | 2019-08-07 23:12:47 +0200 |
---|---|---|
committer | GitHub | 2019-08-07 23:12:47 +0200 |
commit | 674fbdc33c788156f76d263b044dccc48c810870 (patch) | |
tree | 725eaa49a4f2236d44470279296969b66ba0bbc8 /dhall_syntax/src/core | |
parent | 8ec422f2319360f986950fcb9aae4bcf65a9c1e2 (diff) | |
parent | e81ab9a553bf82f20fa0b0344926258176a21dac (diff) |
Merge pull request #95 from Nadrieril/catchup-spec
A lot more catching up on the spec
Diffstat (limited to 'dhall_syntax/src/core')
-rw-r--r-- | dhall_syntax/src/core/expr.rs | 52 | ||||
-rw-r--r-- | dhall_syntax/src/core/import.rs | 2 | ||||
-rw-r--r-- | dhall_syntax/src/core/map.rs | 95 | ||||
-rw-r--r-- | dhall_syntax/src/core/visitor.rs | 32 |
4 files changed, 165 insertions, 16 deletions
diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs index da9465d..b293357 100644 --- a/dhall_syntax/src/core/expr.rs +++ b/dhall_syntax/src/core/expr.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use crate::map::DupTreeMap; +use crate::map::{DupTreeMap, DupTreeSet}; use crate::visitor; use crate::*; @@ -119,6 +119,7 @@ pub enum Builtin { NaturalOdd, NaturalToInteger, NaturalShow, + NaturalSubtract, IntegerToDouble, IntegerShow, DoubleShow, @@ -190,14 +191,10 @@ pub enum ExprF<SubExpr, Embed> { DoubleLit(Double), /// `"Some ${interpolated} text"` TextLit(InterpolatedText<SubExpr>), - /// `[] : List t` + /// `[] : t` EmptyListLit(SubExpr), /// `[x, y, z]` NEListLit(Vec<SubExpr>), - /// Deprecated Optional literal form - /// `[] : Optional a` - /// `[x] : Optional a` - OldOptionalLit(Option<SubExpr>, SubExpr), /// `Some e` SomeLit(SubExpr), /// `{ k1 : t1, k2 : t1 }` @@ -206,14 +203,12 @@ pub enum ExprF<SubExpr, Embed> { RecordLit(DupTreeMap<Label, SubExpr>), /// `< k1 : t1, k2 >` UnionType(DupTreeMap<Label, Option<SubExpr>>), - /// `< k1 = t1, k2 : t2, k3 >` - UnionLit(Label, SubExpr, DupTreeMap<Label, Option<SubExpr>>), /// `merge x y : t` Merge(SubExpr, SubExpr, Option<SubExpr>), /// `e.x` Field(SubExpr, Label), /// `e.{ x, y, z }` - Projection(SubExpr, Vec<Label>), + Projection(SubExpr, DupTreeSet<Label>), /// Embeds an import or the result of resolving the import Embed(Embed), } @@ -311,6 +306,35 @@ impl<N, E> Expr<N, E> { { trivial_result(self.traverse_embed(|x| Ok(map_embed(x)))) } + + pub fn traverse_resolve<E2, Err>( + &self, + visit_embed: impl FnMut(&E) -> Result<E2, Err>, + ) -> Result<Expr<N, E2>, Err> + where + N: Clone, + { + self.traverse_resolve_with_visitor(&mut visitor::ResolveVisitor( + visit_embed, + )) + } + + pub(crate) fn traverse_resolve_with_visitor<E2, Err, F1>( + &self, + visitor: &mut visitor::ResolveVisitor<F1>, + ) -> Result<Expr<N, E2>, Err> + where + N: Clone, + F1: FnMut(&E) -> Result<E2, Err>, + { + match self { + ExprF::BinOp(BinOp::ImportAlt, l, r) => l + .as_ref() + .traverse_resolve_with_visitor(visitor) + .or(r.as_ref().traverse_resolve_with_visitor(visitor)), + _ => self.visit(visitor), + } + } } impl Expr<X, X> { @@ -387,6 +411,16 @@ impl<N, E> SubExpr<N, E> { )), } } + + pub fn traverse_resolve<E2, Err>( + &self, + visit_embed: impl FnMut(&E) -> Result<E2, Err>, + ) -> Result<SubExpr<N, E2>, Err> + where + N: Clone, + { + Ok(self.rewrap(self.as_ref().traverse_resolve(visit_embed)?)) + } } impl SubExpr<X, X> { diff --git a/dhall_syntax/src/core/import.rs b/dhall_syntax/src/core/import.rs index c328e34..d41eae2 100644 --- a/dhall_syntax/src/core/import.rs +++ b/dhall_syntax/src/core/import.rs @@ -26,6 +26,7 @@ pub struct URL { pub authority: String, pub path: Vec<String>, pub query: Option<String>, + // TODO: implement inline headers pub headers: Option<Box<ImportHashed>>, } @@ -40,6 +41,7 @@ pub enum Scheme { pub enum ImportMode { Code, RawText, + Location, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/dhall_syntax/src/core/map.rs b/dhall_syntax/src/core/map.rs index 63f19cd..6a0ebda 100644 --- a/dhall_syntax/src/core/map.rs +++ b/dhall_syntax/src/core/map.rs @@ -1,5 +1,6 @@ /// A sorted map that allows multiple values for each key. pub use dup_tree_map::DupTreeMap; +pub use dup_tree_set::DupTreeSet; mod one_or_more { use either::Either; @@ -232,3 +233,97 @@ mod dup_tree_map { // unsafe impl<K, V> iter::TrustedLen for IntoIter<K, V> {} } + +mod dup_tree_set { + use super::DupTreeMap; + use std::iter; + + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct DupTreeSet<K> { + map: DupTreeMap<K, ()>, + } + + pub type Iter<'a, K> = iter::Map< + super::dup_tree_map::Iter<'a, K, ()>, + for<'b> fn((&'b K, &'b ())) -> &'b K, + >; + pub type IntoIter<K> = + iter::Map<super::dup_tree_map::IntoIter<K, ()>, fn((K, ())) -> K>; + + impl<K> DupTreeSet<K> { + pub fn new() -> Self + where + K: Ord, + { + DupTreeSet { + map: DupTreeMap::new(), + } + } + + pub fn len(&self) -> usize { + self.map.len() + } + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + + pub fn iter(&self) -> Iter<'_, K> + where + K: Ord, + { + fn foo<'a, K>((k, ()): (&'a K, &'a ())) -> &'a K { + k + } + self.map.iter().map(foo) + } + } + + impl<K> Default for DupTreeSet<K> + where + K: Ord, + { + fn default() -> Self { + Self::new() + } + } + + impl<K> IntoIterator for DupTreeSet<K> + where + K: Ord + Clone, + { + type Item = K; + type IntoIter = IntoIter<K>; + + fn into_iter(self) -> Self::IntoIter { + fn foo<K>((k, ()): (K, ())) -> K { + k + } + self.map.into_iter().map(foo) + } + } + + impl<'a, K> IntoIterator for &'a DupTreeSet<K> + where + K: Ord, + { + type Item = &'a K; + type IntoIter = Iter<'a, K>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } + } + + impl<K> iter::FromIterator<K> for DupTreeSet<K> + where + K: Ord, + { + fn from_iter<T>(iter: T) -> Self + where + T: IntoIterator<Item = K>, + { + let map = iter.into_iter().map(|k| (k, ())).collect(); + DupTreeSet { map } + } + } +} diff --git a/dhall_syntax/src/core/visitor.rs b/dhall_syntax/src/core/visitor.rs index 99a9c11..68ad956 100644 --- a/dhall_syntax/src/core/visitor.rs +++ b/dhall_syntax/src/core/visitor.rs @@ -137,17 +137,10 @@ where ), EmptyListLit(t) => EmptyListLit(v.visit_subexpr(t)?), NEListLit(es) => NEListLit(vec(es, |e| v.visit_subexpr(e))?), - OldOptionalLit(x, t) => OldOptionalLit( - opt(x, |e| v.visit_subexpr(e))?, - v.visit_subexpr(t)?, - ), SomeLit(e) => SomeLit(v.visit_subexpr(e)?), RecordType(kts) => RecordType(dupmap(kts, v)?), RecordLit(kvs) => RecordLit(dupmap(kvs, v)?), UnionType(kts) => UnionType(optdupmap(kts, v)?), - UnionLit(k, x, kts) => { - UnionLit(k.clone(), v.visit_subexpr(x)?, optdupmap(kts, v)?) - } Merge(x, y, t) => Merge( v.visit_subexpr(x)?, v.visit_subexpr(y)?, @@ -362,6 +355,31 @@ where } } +pub struct ResolveVisitor<F1>(pub F1); + +impl<'a, 'b, N, E, E2, Err, F1> + ExprFFallibleVisitor<'a, SubExpr<N, E>, SubExpr<N, E2>, E, E2> + for &'b mut ResolveVisitor<F1> +where + N: Clone + 'a, + F1: FnMut(&E) -> Result<E2, Err>, +{ + type Error = Err; + + fn visit_subexpr( + &mut self, + subexpr: &'a SubExpr<N, E>, + ) -> Result<SubExpr<N, E2>, Self::Error> { + Ok(subexpr.rewrap( + subexpr + .as_ref() + .traverse_resolve_with_visitor(&mut **self)?, + )) + } + fn visit_embed(self, embed: &'a E) -> Result<E2, Self::Error> { + (self.0)(embed) + } +} pub struct NoteAbsurdVisitor; impl<'a, 'b, N, E> |