summaryrefslogtreecommitdiff
path: root/dhall/src/syntax
diff options
context:
space:
mode:
authorNadrieril Feneanar2019-12-20 19:39:16 +0000
committerGitHub2019-12-20 19:39:16 +0000
commitde0dd59204e979e29445d634a0739394110261ef (patch)
treea75ce010c7ea771a03cb51cc2b828dad6ea1a9f7 /dhall/src/syntax
parent91ef0cf697d56c91a8d15937aa4669dc221cd6c1 (diff)
parent64cca1837cc97b7679c4e2ffd54a22ad50f05cfd (diff)
Merge pull request #118 from Nadrieril/clarify-types
Clarify naming and file organization
Diffstat (limited to '')
-rw-r--r--dhall/src/syntax/ast/expr.rs (renamed from dhall/src/syntax/core/expr.rs)203
-rw-r--r--dhall/src/syntax/ast/import.rs (renamed from dhall/src/syntax/core/import.rs)0
-rw-r--r--dhall/src/syntax/ast/label.rs (renamed from dhall/src/syntax/core/label.rs)0
-rw-r--r--dhall/src/syntax/ast/map.rs (renamed from dhall/src/syntax/core/map.rs)0
-rw-r--r--dhall/src/syntax/ast/mod.rs (renamed from dhall/src/syntax/core/mod.rs)1
-rw-r--r--dhall/src/syntax/ast/span.rs (renamed from dhall/src/syntax/core/span.rs)0
-rw-r--r--dhall/src/syntax/ast/text.rs (renamed from dhall/src/syntax/core/text.rs)0
-rw-r--r--dhall/src/syntax/ast/visitor.rs (renamed from dhall/src/syntax/core/visitor.rs)47
-rw-r--r--dhall/src/syntax/binary/decode.rs19
-rw-r--r--dhall/src/syntax/binary/encode.rs16
-rw-r--r--dhall/src/syntax/core/context.rs80
-rw-r--r--dhall/src/syntax/mod.rs7
-rw-r--r--dhall/src/syntax/text/parser.rs29
-rw-r--r--dhall/src/syntax/text/printer.rs275
14 files changed, 300 insertions, 377 deletions
diff --git a/dhall/src/syntax/core/expr.rs b/dhall/src/syntax/ast/expr.rs
index 5b9f401..48c48d8 100644
--- a/dhall/src/syntax/core/expr.rs
+++ b/dhall/src/syntax/ast/expr.rs
@@ -1,51 +1,15 @@
use crate::syntax::map::{DupTreeMap, DupTreeSet};
-use crate::syntax::visitor::{self, ExprFMutVisitor, ExprFVisitor};
+use crate::syntax::visitor::{self, ExprKindMutVisitor, ExprKindVisitor};
use crate::syntax::*;
pub type Integer = isize;
pub type Natural = usize;
pub type Double = NaiveDouble;
-pub fn trivial_result<T>(x: Result<T, !>) -> T {
- match x {
- Ok(x) => x,
- Err(e) => e,
- }
-}
-
/// Double with bitwise equality
#[derive(Debug, Copy, Clone)]
pub struct NaiveDouble(f64);
-impl PartialEq for NaiveDouble {
- fn eq(&self, other: &Self) -> bool {
- self.0.to_bits() == other.0.to_bits()
- }
-}
-
-impl Eq for NaiveDouble {}
-
-impl std::hash::Hash for NaiveDouble {
- fn hash<H>(&self, state: &mut H)
- where
- H: std::hash::Hasher,
- {
- self.0.to_bits().hash(state)
- }
-}
-
-impl From<f64> for NaiveDouble {
- fn from(x: f64) -> Self {
- NaiveDouble(x)
- }
-}
-
-impl From<NaiveDouble> for f64 {
- fn from(x: NaiveDouble) -> f64 {
- x.0
- }
-}
-
/// Constants for a pure type system
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Const {
@@ -62,18 +26,6 @@ pub enum Const {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct V<Label>(pub Label, pub usize);
-// This is only for the specific `Label` type, not generic
-impl From<Label> for V<Label> {
- fn from(x: Label) -> V<Label> {
- V(x, 0)
- }
-}
-impl<'a> From<&'a Label> for V<Label> {
- fn from(x: &'a Label) -> V<Label> {
- V(x.clone(), 0)
- }
-}
-
// Definition order must match precedence order for
// pretty-printing to work correctly
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -142,33 +94,19 @@ pub enum Builtin {
// Each node carries an annotation.
#[derive(Debug, Clone)]
-pub struct Expr<Embed>(Box<(RawExpr<Embed>, Span)>);
-
-pub type RawExpr<Embed> = ExprF<Expr<Embed>, Embed>;
-
-impl<Embed: PartialEq> std::cmp::PartialEq for Expr<Embed> {
- fn eq(&self, other: &Self) -> bool {
- self.0.as_ref().0 == other.0.as_ref().0
- }
+pub struct Expr<Embed> {
+ kind: Box<ExprKind<Expr<Embed>, Embed>>,
+ span: Span,
}
-impl<Embed: Eq> std::cmp::Eq for Expr<Embed> {}
-
-impl<Embed: std::hash::Hash> std::hash::Hash for Expr<Embed> {
- fn hash<H>(&self, state: &mut H)
- where
- H: std::hash::Hasher,
- {
- (self.0).0.hash(state)
- }
-}
+pub type UnspannedExpr<Embed> = ExprKind<Expr<Embed>, Embed>;
/// Syntax tree for expressions
// Having the recursion out of the enum definition enables writing
// much more generic code and improves pattern-matching behind
// smart pointers.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum ExprF<SubExpr, Embed> {
+pub enum ExprKind<SubExpr, Embed> {
Const(Const),
/// `x`
/// `x@n`
@@ -231,12 +169,12 @@ pub enum ExprF<SubExpr, Embed> {
Embed(Embed),
}
-impl<SE, E> ExprF<SE, E> {
+impl<SE, E> ExprKind<SE, E> {
pub fn traverse_ref_with_special_handling_of_binders<'a, SE2, Err>(
&'a self,
visit_subexpr: impl FnMut(&'a SE) -> Result<SE2, Err>,
visit_under_binder: impl FnOnce(&'a Label, &'a SE) -> Result<SE2, Err>,
- ) -> Result<ExprF<SE2, E>, Err>
+ ) -> Result<ExprKind<SE2, E>, Err>
where
E: Clone,
{
@@ -250,7 +188,7 @@ impl<SE, E> ExprF<SE, E> {
fn traverse_ref<'a, SE2, Err>(
&'a self,
visit_subexpr: impl FnMut(&'a SE) -> Result<SE2, Err>,
- ) -> Result<ExprF<SE2, E>, Err>
+ ) -> Result<ExprKind<SE2, E>, Err>
where
E: Clone,
{
@@ -268,7 +206,7 @@ impl<SE, E> ExprF<SE, E> {
&'a self,
mut map_subexpr: impl FnMut(&'a SE) -> SE2,
mut map_under_binder: impl FnMut(&'a Label, &'a SE) -> SE2,
- ) -> ExprF<SE2, E>
+ ) -> ExprKind<SE2, E>
where
E: Clone,
{
@@ -281,7 +219,7 @@ impl<SE, E> ExprF<SE, E> {
pub fn map_ref<'a, SE2>(
&'a self,
mut map_subexpr: impl FnMut(&'a SE) -> SE2,
- ) -> ExprF<SE2, E>
+ ) -> ExprKind<SE2, E>
where
E: Clone,
{
@@ -294,22 +232,25 @@ impl<SE, E> ExprF<SE, E> {
}
impl<E> Expr<E> {
- pub fn as_ref(&self) -> &RawExpr<E> {
- &self.0.as_ref().0
- }
- pub fn as_mut(&mut self) -> &mut RawExpr<E> {
- &mut self.0.as_mut().0
+ pub fn as_ref(&self) -> &UnspannedExpr<E> {
+ &self.kind
}
pub fn span(&self) -> Span {
- self.0.as_ref().1.clone()
+ self.span.clone()
}
- pub fn new(x: RawExpr<E>, n: Span) -> Self {
- Expr(Box::new((x, n)))
+ pub fn new(kind: UnspannedExpr<E>, span: Span) -> Self {
+ Expr {
+ kind: Box::new(kind),
+ span,
+ }
}
- pub fn rewrap<E2>(&self, x: RawExpr<E2>) -> Expr<E2> {
- Expr(Box::new((x, (self.0).1.clone())))
+ pub fn rewrap<E2>(&self, kind: UnspannedExpr<E2>) -> Expr<E2> {
+ Expr {
+ kind: Box::new(kind),
+ span: self.span.clone(),
+ }
}
pub fn traverse_resolve_mut<Err, F1>(
@@ -320,21 +261,21 @@ impl<E> Expr<E> {
E: Clone,
F1: FnMut(Import<Expr<E>>) -> Result<E, Err>,
{
- match self.as_mut() {
- ExprF::BinOp(BinOp::ImportAlt, l, r) => {
- let garbage_expr = ExprF::BoolLit(false);
+ match self.kind.as_mut() {
+ ExprKind::BinOp(BinOp::ImportAlt, l, r) => {
+ let garbage_expr = ExprKind::BoolLit(false);
let new_self = if l.traverse_resolve_mut(f).is_ok() {
l
} else {
r.traverse_resolve_mut(f)?;
r
};
- *self.as_mut() =
- std::mem::replace(new_self.as_mut(), garbage_expr);
+ *self.kind =
+ std::mem::replace(new_self.kind.as_mut(), garbage_expr);
}
_ => {
- self.as_mut().traverse_mut(|e| e.traverse_resolve_mut(f))?;
- if let ExprF::Import(import) = self.as_mut() {
+ self.kind.traverse_mut(|e| e.traverse_resolve_mut(f))?;
+ if let ExprKind::Import(import) = self.kind.as_mut() {
let garbage_import = Import {
mode: ImportMode::Code,
location: ImportLocation::Missing,
@@ -342,7 +283,7 @@ impl<E> Expr<E> {
};
// Move out of &mut import
let import = std::mem::replace(import, garbage_import);
- *self.as_mut() = ExprF::Embed(f(import)?);
+ *self.kind = ExprKind::Embed(f(import)?);
}
}
}
@@ -350,16 +291,6 @@ impl<E> Expr<E> {
}
}
-/// Add an isize to an usize
-/// Returns `None` on over/underflow
-fn add_ui(u: usize, i: isize) -> Option<usize> {
- Some(if i < 0 {
- u.checked_sub(i.checked_neg()? as usize)?
- } else {
- u.checked_add(i as usize)?
- })
-}
-
impl<Label: PartialEq + Clone> V<Label> {
pub fn shift(&self, delta: isize, var: &V<Label>) -> Option<Self> {
let V(x, n) = var;
@@ -375,3 +306,73 @@ impl<Label: PartialEq + Clone> V<Label> {
self.shift(-1, &V(x.clone(), 0))
}
}
+
+pub fn trivial_result<T>(x: Result<T, !>) -> T {
+ match x {
+ Ok(x) => x,
+ Err(e) => e,
+ }
+}
+
+/// Add an isize to an usize
+/// Returns `None` on over/underflow
+fn add_ui(u: usize, i: isize) -> Option<usize> {
+ Some(if i < 0 {
+ u.checked_sub(i.checked_neg()? as usize)?
+ } else {
+ u.checked_add(i as usize)?
+ })
+}
+
+impl PartialEq for NaiveDouble {
+ fn eq(&self, other: &Self) -> bool {
+ self.0.to_bits() == other.0.to_bits()
+ }
+}
+
+impl Eq for NaiveDouble {}
+
+impl std::hash::Hash for NaiveDouble {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: std::hash::Hasher,
+ {
+ self.0.to_bits().hash(state)
+ }
+}
+
+impl From<f64> for NaiveDouble {
+ fn from(x: f64) -> Self {
+ NaiveDouble(x)
+ }
+}
+
+impl From<NaiveDouble> for f64 {
+ fn from(x: NaiveDouble) -> f64 {
+ x.0
+ }
+}
+
+/// This is only for the specific `Label` type, not generic
+impl From<Label> for V<Label> {
+ fn from(x: Label) -> V<Label> {
+ V(x, 0)
+ }
+}
+
+impl<Embed: PartialEq> std::cmp::PartialEq for Expr<Embed> {
+ fn eq(&self, other: &Self) -> bool {
+ self.kind == other.kind
+ }
+}
+
+impl<Embed: Eq> std::cmp::Eq for Expr<Embed> {}
+
+impl<Embed: std::hash::Hash> std::hash::Hash for Expr<Embed> {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: std::hash::Hasher,
+ {
+ self.kind.hash(state)
+ }
+}
diff --git a/dhall/src/syntax/core/import.rs b/dhall/src/syntax/ast/import.rs
index da3e99b..da3e99b 100644
--- a/dhall/src/syntax/core/import.rs
+++ b/dhall/src/syntax/ast/import.rs
diff --git a/dhall/src/syntax/core/label.rs b/dhall/src/syntax/ast/label.rs
index 43c3f53..43c3f53 100644
--- a/dhall/src/syntax/core/label.rs
+++ b/dhall/src/syntax/ast/label.rs
diff --git a/dhall/src/syntax/core/map.rs b/dhall/src/syntax/ast/map.rs
index c4c6126..c4c6126 100644
--- a/dhall/src/syntax/core/map.rs
+++ b/dhall/src/syntax/ast/map.rs
diff --git a/dhall/src/syntax/core/mod.rs b/dhall/src/syntax/ast/mod.rs
index 66bf229..1950154 100644
--- a/dhall/src/syntax/core/mod.rs
+++ b/dhall/src/syntax/ast/mod.rs
@@ -8,6 +8,5 @@ mod span;
pub use span::*;
mod text;
pub use text::*;
-pub mod context;
pub mod map;
pub mod visitor;
diff --git a/dhall/src/syntax/core/span.rs b/dhall/src/syntax/ast/span.rs
index f9c7008..f9c7008 100644
--- a/dhall/src/syntax/core/span.rs
+++ b/dhall/src/syntax/ast/span.rs
diff --git a/dhall/src/syntax/core/text.rs b/dhall/src/syntax/ast/text.rs
index fb390ee..fb390ee 100644
--- a/dhall/src/syntax/core/text.rs
+++ b/dhall/src/syntax/ast/text.rs
diff --git a/dhall/src/syntax/core/visitor.rs b/dhall/src/syntax/ast/visitor.rs
index b76d037..b557995 100644
--- a/dhall/src/syntax/core/visitor.rs
+++ b/dhall/src/syntax/ast/visitor.rs
@@ -1,7 +1,7 @@
use crate::syntax::*;
use std::iter::FromIterator;
-/// A visitor trait that can be used to traverse `ExprF`s. We need this pattern so that Rust lets
+/// A visitor trait that can be used to traverse `ExprKind`s. We need this pattern so that Rust lets
/// us have as much mutability as we can.
/// For example, `traverse_ref_with_special_handling_of_binders` cannot be made using only
/// `traverse_ref`, because `traverse_ref` takes a `FnMut` so we would need to pass multiple
@@ -9,7 +9,7 @@ use std::iter::FromIterator;
/// preventing exactly this ! So we have to be more clever. The visitor pattern allows us to have
/// only one mutable thing the whole time: the visitor itself. The visitor can then carry around
/// multiple closures or just one, and Rust is ok with either. See for example TraverseRefVisitor.
-pub trait ExprFVisitor<'a, SE1, SE2, E1, E2>: Sized {
+pub trait ExprKindVisitor<'a, SE1, SE2, E1, E2>: Sized {
type Error;
fn visit_subexpr(&mut self, subexpr: &'a SE1) -> Result<SE2, Self::Error>;
@@ -25,14 +25,14 @@ pub trait ExprFVisitor<'a, SE1, SE2, E1, E2>: Sized {
fn visit(
self,
- input: &'a ExprF<SE1, E1>,
- ) -> Result<ExprF<SE2, E2>, Self::Error> {
+ input: &'a ExprKind<SE1, E1>,
+ ) -> Result<ExprKind<SE2, E2>, Self::Error> {
visit_ref(self, input)
}
}
-/// Like `ExprFVisitor`, but by mutable reference
-pub trait ExprFMutVisitor<'a, SE, E>: Sized {
+/// Like `ExprKindVisitor`, but by mutable reference
+pub trait ExprKindMutVisitor<'a, SE, E>: Sized {
type Error;
fn visit_subexpr(&mut self, subexpr: &'a mut SE)
@@ -49,17 +49,17 @@ pub trait ExprFMutVisitor<'a, SE, E>: Sized {
self.visit_subexpr(subexpr)
}
- fn visit(self, input: &'a mut ExprF<SE, E>) -> Result<(), Self::Error> {
+ fn visit(self, input: &'a mut ExprKind<SE, E>) -> Result<(), Self::Error> {
visit_mut(self, input)
}
}
fn visit_ref<'a, V, SE1, SE2, E1, E2>(
mut v: V,
- input: &'a ExprF<SE1, E1>,
-) -> Result<ExprF<SE2, E2>, V::Error>
+ input: &'a ExprKind<SE1, E1>,
+) -> Result<ExprKind<SE2, E2>, V::Error>
where
- V: ExprFVisitor<'a, SE1, SE2, E1, E2>,
+ V: ExprKindVisitor<'a, SE1, SE2, E1, E2>,
{
fn vec<'a, T, U, Err, F: FnMut(&'a T) -> Result<U, Err>>(
x: &'a [T],
@@ -83,7 +83,7 @@ where
where
SE1: 'a,
T: FromIterator<(Label, SE2)>,
- V: ExprFVisitor<'a, SE1, SE2, E1, E2>,
+ V: ExprKindVisitor<'a, SE1, SE2, E1, E2>,
{
x.into_iter()
.map(|(k, x)| Ok((k.clone(), v.visit_subexpr(x)?)))
@@ -96,7 +96,7 @@ where
where
SE1: 'a,
T: FromIterator<(Label, Option<SE2>)>,
- V: ExprFVisitor<'a, SE1, SE2, E1, E2>,
+ V: ExprKindVisitor<'a, SE1, SE2, E1, E2>,
{
x.into_iter()
.map(|(k, x)| {
@@ -111,7 +111,7 @@ where
.collect()
}
- use crate::syntax::ExprF::*;
+ use crate::syntax::ExprKind::*;
Ok(match input {
Var(v) => Var(v.clone()),
Lam(l, t, e) => {
@@ -172,14 +172,14 @@ where
fn visit_mut<'a, V, SE, E>(
mut v: V,
- input: &'a mut ExprF<SE, E>,
+ input: &'a mut ExprKind<SE, E>,
) -> Result<(), V::Error>
where
- V: ExprFMutVisitor<'a, SE, E>,
+ V: ExprKindMutVisitor<'a, SE, E>,
{
fn vec<'a, V, SE, E>(v: &mut V, x: &'a mut Vec<SE>) -> Result<(), V::Error>
where
- V: ExprFMutVisitor<'a, SE, E>,
+ V: ExprKindMutVisitor<'a, SE, E>,
{
for x in x {
v.visit_subexpr(x)?;
@@ -191,7 +191,7 @@ where
x: &'a mut Option<SE>,
) -> Result<(), V::Error>
where
- V: ExprFMutVisitor<'a, SE, E>,
+ V: ExprKindMutVisitor<'a, SE, E>,
{
if let Some(x) = x {
v.visit_subexpr(x)?;
@@ -204,7 +204,7 @@ where
) -> Result<(), V::Error>
where
SE: 'a,
- V: ExprFMutVisitor<'a, SE, E>,
+ V: ExprKindMutVisitor<'a, SE, E>,
{
for (_, x) in x {
v.visit_subexpr(x)?;
@@ -217,7 +217,7 @@ where
) -> Result<(), V::Error>
where
SE: 'a,
- V: ExprFMutVisitor<'a, SE, E>,
+ V: ExprKindMutVisitor<'a, SE, E>,
{
for (_, x) in x {
opt(&mut v, x)?;
@@ -225,7 +225,7 @@ where
Ok(())
}
- use crate::syntax::ExprF::*;
+ use crate::syntax::ExprKind::*;
match input {
Var(_) | Const(_) | Builtin(_) | BoolLit(_) | NaturalLit(_)
| IntegerLit(_) | DoubleLit(_) => {}
@@ -293,7 +293,7 @@ pub struct TraverseRefWithBindersVisitor<F1, F2> {
pub visit_under_binder: F2,
}
-impl<'a, SE, E, SE2, Err, F1, F2> ExprFVisitor<'a, SE, SE2, E, E>
+impl<'a, SE, E, SE2, Err, F1, F2> ExprKindVisitor<'a, SE, SE2, E, E>
for TraverseRefWithBindersVisitor<F1, F2>
where
SE: 'a,
@@ -322,7 +322,7 @@ pub struct TraverseRefVisitor<F1> {
pub visit_subexpr: F1,
}
-impl<'a, SE, E, SE2, Err, F1> ExprFVisitor<'a, SE, SE2, E, E>
+impl<'a, SE, E, SE2, Err, F1> ExprKindVisitor<'a, SE, SE2, E, E>
for TraverseRefVisitor<F1>
where
SE: 'a,
@@ -343,7 +343,8 @@ pub struct TraverseMutVisitor<F1> {
pub visit_subexpr: F1,
}
-impl<'a, SE, E, Err, F1> ExprFMutVisitor<'a, SE, E> for TraverseMutVisitor<F1>
+impl<'a, SE, E, Err, F1> ExprKindMutVisitor<'a, SE, E>
+ for TraverseMutVisitor<F1>
where
SE: 'a,
E: 'a,
diff --git a/dhall/src/syntax/binary/decode.rs b/dhall/src/syntax/binary/decode.rs
index 46c9921..254ab07 100644
--- a/dhall/src/syntax/binary/decode.rs
+++ b/dhall/src/syntax/binary/decode.rs
@@ -2,12 +2,13 @@ use itertools::Itertools;
use serde_cbor::value::value as cbor;
use std::iter::FromIterator;
-use crate::semantics::error::DecodeError;
+use crate::error::DecodeError;
use crate::semantics::phase::DecodedExpr;
use crate::syntax;
use crate::syntax::{
- Expr, ExprF, FilePath, FilePrefix, Hash, ImportLocation, ImportMode,
- Integer, InterpolatedText, Label, Natural, RawExpr, Scheme, Span, URL, V,
+ Expr, ExprKind, FilePath, FilePrefix, Hash, ImportLocation, ImportMode,
+ Integer, InterpolatedText, Label, Natural, Scheme, Span, UnspannedExpr,
+ URL, V,
};
pub(crate) fn decode(data: &[u8]) -> Result<DecodedExpr, DecodeError> {
@@ -18,17 +19,17 @@ pub(crate) fn decode(data: &[u8]) -> Result<DecodedExpr, DecodeError> {
}
// Should probably rename this
-fn rc<E>(x: RawExpr<E>) -> Expr<E> {
+fn rc<E>(x: UnspannedExpr<E>) -> Expr<E> {
Expr::new(x, Span::Decoded)
}
fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> {
use cbor::Value::*;
use syntax::{BinOp, Builtin, Const};
- use ExprF::*;
+ use ExprKind::*;
Ok(rc(match data {
String(s) => match Builtin::parse(s) {
- Some(b) => ExprF::Builtin(b),
+ Some(b) => ExprKind::Builtin(b),
None => match s.as_str() {
"True" => BoolLit(true),
"False" => BoolLit(false),
@@ -123,7 +124,7 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> {
}
[U64(4), t] => {
let t = cbor_value_to_dhall(&t)?;
- EmptyListLit(rc(App(rc(ExprF::Builtin(Builtin::List)), t)))
+ EmptyListLit(rc(App(rc(ExprKind::Builtin(Builtin::List)), t)))
}
[U64(4), Null, rest @ ..] => {
let rest = rest
@@ -139,14 +140,14 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> {
// Old-style optional literals
[U64(5), t] => {
let t = cbor_value_to_dhall(&t)?;
- App(rc(ExprF::Builtin(Builtin::OptionalNone)), t)
+ App(rc(ExprKind::Builtin(Builtin::OptionalNone)), t)
}
[U64(5), t, x] => {
let x = cbor_value_to_dhall(&x)?;
let t = cbor_value_to_dhall(&t)?;
Annot(
rc(SomeLit(x)),
- rc(App(rc(ExprF::Builtin(Builtin::Optional)), t)),
+ rc(App(rc(ExprKind::Builtin(Builtin::Optional)), t)),
)
}
[U64(6), x, y] => {
diff --git a/dhall/src/syntax/binary/encode.rs b/dhall/src/syntax/binary/encode.rs
index 8e13efd..25a545c 100644
--- a/dhall/src/syntax/binary/encode.rs
+++ b/dhall/src/syntax/binary/encode.rs
@@ -1,12 +1,12 @@
use serde_cbor::value::value as cbor;
use std::vec;
-use crate::semantics::error::EncodeError;
+use crate::error::EncodeError;
use crate::syntax;
use crate::syntax::map::DupTreeMap;
use crate::syntax::{
- Expr, ExprF, FilePrefix, Hash, Import, ImportLocation, ImportMode, Label,
- Scheme, V,
+ Expr, ExprKind, FilePrefix, Hash, Import, ImportLocation, ImportMode,
+ Label, Scheme, V,
};
/// Warning: will fail if `expr` contains an `Embed` node.
@@ -46,7 +46,7 @@ where
use cbor::Value::{String, I64, U64};
use std::iter::once;
use syntax::Builtin;
- use syntax::ExprF::*;
+ use syntax::ExprKind::*;
use self::Serialize::{RecordMap, UnionMap};
fn expr<E>(x: &Expr<E>) -> self::Serialize<'_, E> {
@@ -110,7 +110,9 @@ where
SomeLit(x) => ser_seq!(ser; tag(5), null(), expr(x)),
EmptyListLit(x) => match x.as_ref() {
App(f, a) => match f.as_ref() {
- ExprF::Builtin(Builtin::List) => ser_seq!(ser; tag(4), expr(a)),
+ ExprKind::Builtin(Builtin::List) => {
+ ser_seq!(ser; tag(4), expr(a))
+ }
_ => ser_seq!(ser; tag(28), expr(x)),
},
_ => ser_seq!(ser; tag(28), expr(x)),
@@ -284,7 +286,7 @@ fn collect_nested_applications<'a, E>(
) -> (&'a Expr<E>, Vec<&'a Expr<E>>) {
fn go<'a, E>(e: &'a Expr<E>, vec: &mut Vec<&'a Expr<E>>) -> &'a Expr<E> {
match e.as_ref() {
- ExprF::App(f, a) => {
+ ExprKind::App(f, a) => {
vec.push(a);
go(f, vec)
}
@@ -306,7 +308,7 @@ fn collect_nested_lets<'a, E>(
vec: &mut Vec<LetBinding<'a, E>>,
) -> &'a Expr<E> {
match e.as_ref() {
- ExprF::Let(l, t, v, e) => {
+ ExprKind::Let(l, t, v, e) => {
vec.push((l, t, v));
go(e, vec)
}
diff --git a/dhall/src/syntax/core/context.rs b/dhall/src/syntax/core/context.rs
deleted file mode 100644
index 6844baa..0000000
--- a/dhall/src/syntax/core/context.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-use std::cmp::Eq;
-use std::collections::HashMap;
-use std::hash::Hash;
-
-/// A `(Context a)` associates `Text` labels with values of type `a`
-///
-/// The `Context` is used for type-checking when `(a = Expr)`
-///
-/// * You create a `Context` using `empty` and `insert`
-/// * You transform a `Context` using `fmap`
-/// * You consume a `Context` using `lookup` and `toList`
-///
-/// The difference between a `Context` and a `Map` is that a `Context` lets you
-/// have multiple ordered occurrences of the same key and you can query for the
-/// `n`th occurrence of a given key.
-///
-#[derive(Debug, Clone)]
-pub struct Context<K: Eq + Hash, T>(HashMap<K, Vec<T>>);
-
-impl<K: Hash + Eq + Clone, T> Context<K, T> {
- /// An empty context with no key-value pairs
- pub fn new() -> Self {
- Context(HashMap::new())
- }
-
- /// Look up a key by name and index
- ///
- /// ```c
- /// lookup _ _ empty = Nothing
- /// lookup k 0 (insert k v c) = Just v
- /// lookup k n (insert k v c) = lookup k (n - 1) c -- 1 <= n
- /// lookup k n (insert j v c) = lookup k n c -- k /= j
- /// ```
- pub fn lookup<'a>(&'a self, k: &K, n: usize) -> Option<&'a T> {
- self.0.get(k).and_then(|v| {
- if n < v.len() {
- v.get(v.len() - 1 - n)
- } else {
- None
- }
- })
- }
-
- pub fn map<U, F: Fn(&K, &T) -> U>(&self, f: F) -> Context<K, U> {
- Context(
- self.0
- .iter()
- .map(|(k, vs)| {
- ((*k).clone(), vs.iter().map(|v| f(k, v)).collect())
- })
- .collect(),
- )
- }
-
- pub fn lookup_all<'a>(&'a self, k: &K) -> impl Iterator<Item = &T> {
- self.0.get(k).into_iter().flat_map(|v| v.iter())
- }
-
- pub fn iter(&self) -> impl Iterator<Item = (&K, &T)> {
- self.0
- .iter()
- .flat_map(|(k, vs)| vs.iter().map(move |v| (k, v)))
- }
-
- pub fn iter_keys(&self) -> impl Iterator<Item = (&K, &Vec<T>)> {
- self.0.iter()
- }
-}
-
-impl<K: Hash + Eq + Clone, T: Clone> Context<K, T> {
- /// Add a key-value pair to the `Context`
- pub fn insert(&self, k: K, v: T) -> Self {
- let mut ctx = (*self).clone();
- {
- let m = ctx.0.entry(k).or_insert_with(Vec::new);
- m.push(v);
- }
- ctx
- }
-}
diff --git a/dhall/src/syntax/mod.rs b/dhall/src/syntax/mod.rs
index a82e827..512a026 100644
--- a/dhall/src/syntax/mod.rs
+++ b/dhall/src/syntax/mod.rs
@@ -5,10 +5,9 @@
clippy::type_complexity
)]
-mod core;
-pub use crate::syntax::core::context;
-pub use crate::syntax::core::visitor;
-pub use crate::syntax::core::*;
+mod ast;
+pub use crate::syntax::ast::visitor;
+pub use crate::syntax::ast::*;
pub use crate::syntax::text::parser::*;
pub use crate::syntax::text::printer::*;
pub mod binary;
diff --git a/dhall/src/syntax/text/parser.rs b/dhall/src/syntax/text/parser.rs
index f6b6577..90cb4b1 100644
--- a/dhall/src/syntax/text/parser.rs
+++ b/dhall/src/syntax/text/parser.rs
@@ -7,13 +7,12 @@ use pest_consume::{match_nodes, Parser};
use crate::semantics::phase::Normalized;
use crate::syntax;
-use crate::syntax::core;
use crate::syntax::map::{DupTreeMap, DupTreeSet};
-use crate::syntax::ExprF::*;
+use crate::syntax::ExprKind::*;
use crate::syntax::{
- FilePath, FilePrefix, Hash, ImportLocation, ImportMode, InterpolatedText,
- InterpolatedTextContents, Label, NaiveDouble, RawExpr, Scheme, Span, URL,
- V,
+ Double, FilePath, FilePrefix, Hash, ImportLocation, ImportMode, Integer,
+ InterpolatedText, InterpolatedTextContents, Label, NaiveDouble, Natural,
+ Scheme, Span, UnspannedExpr, URL, V,
};
// This file consumes the parse tree generated by pest and turns it into
@@ -77,10 +76,14 @@ impl crate::syntax::Builtin {
fn input_to_span(input: ParseInput) -> Span {
Span::make(input.user_data().clone(), input.as_pair().as_span())
}
-fn spanned(input: ParseInput, x: RawExpr<Normalized>) -> Expr {
+fn spanned(input: ParseInput, x: UnspannedExpr<Normalized>) -> Expr {
Expr::new(x, input_to_span(input))
}
-fn spanned_union(span1: Span, span2: Span, x: RawExpr<Normalized>) -> Expr {
+fn spanned_union(
+ span1: Span,
+ span2: Span,
+ x: UnspannedExpr<Normalized>,
+) -> Expr {
Expr::new(x, span1.union(&span2))
}
@@ -349,20 +352,20 @@ impl DhallParser {
}
#[alias(double_literal)]
- fn NaN(_input: ParseInput) -> ParseResult<core::Double> {
+ fn NaN(_input: ParseInput) -> ParseResult<Double> {
Ok(std::f64::NAN.into())
}
#[alias(double_literal)]
- fn minus_infinity_literal(_input: ParseInput) -> ParseResult<core::Double> {
+ fn minus_infinity_literal(_input: ParseInput) -> ParseResult<Double> {
Ok(std::f64::NEG_INFINITY.into())
}
#[alias(double_literal)]
- fn plus_infinity_literal(_input: ParseInput) -> ParseResult<core::Double> {
+ fn plus_infinity_literal(_input: ParseInput) -> ParseResult<Double> {
Ok(std::f64::INFINITY.into())
}
#[alias(double_literal)]
- fn numeric_double_literal(input: ParseInput) -> ParseResult<core::Double> {
+ fn numeric_double_literal(input: ParseInput) -> ParseResult<Double> {
let s = input.as_str().trim();
match s.parse::<f64>() {
Ok(x) if x.is_infinite() => Err(input.error(format!(
@@ -374,7 +377,7 @@ impl DhallParser {
}
}
- fn natural_literal(input: ParseInput) -> ParseResult<core::Natural> {
+ fn natural_literal(input: ParseInput) -> ParseResult<Natural> {
input
.as_str()
.trim()
@@ -382,7 +385,7 @@ impl DhallParser {
.map_err(|e| input.error(format!("{}", e)))
}
- fn integer_literal(input: ParseInput) -> ParseResult<core::Integer> {
+ fn integer_literal(input: ParseInput) -> ParseResult<Integer> {
input
.as_str()
.trim()
diff --git a/dhall/src/syntax/text/printer.rs b/dhall/src/syntax/text/printer.rs
index 8df456b..78942ed 100644
--- a/dhall/src/syntax/text/printer.rs
+++ b/dhall/src/syntax/text/printer.rs
@@ -2,10 +2,137 @@ use crate::syntax::*;
use itertools::Itertools;
use std::fmt::{self, Display};
+// There is a one-to-one correspondence between the formatter and the grammar. Each phase is
+// named after a corresponding grammar group, and the structure of the formatter reflects
+// the relationship between the corresponding grammar rules. This leads to the nice property
+// of automatically getting all the parentheses and precedences right.
+#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
+enum PrintPhase {
+ Base,
+ Operator,
+ BinOp(ast::BinOp),
+ App,
+ Import,
+ Primitive,
+}
+
+// Wraps an Expr with a phase, so that phase selection can be done separate from the actual
+// printing.
+#[derive(Clone)]
+struct PhasedExpr<'a, E>(&'a Expr<E>, PrintPhase);
+
+impl<'a, E: Display + Clone> PhasedExpr<'a, E> {
+ fn phase(self, phase: PrintPhase) -> PhasedExpr<'a, E> {
+ PhasedExpr(self.0, phase)
+ }
+}
+
+impl<E: Display + Clone> UnspannedExpr<E> {
+ // Annotate subexpressions with the appropriate phase, defaulting to Base
+ fn annotate_with_phases<'a>(&'a self) -> ExprKind<PhasedExpr<'a, E>, E> {
+ use crate::syntax::ExprKind::*;
+ use PrintPhase::*;
+ let with_base = self.map_ref(|e| PhasedExpr(e, Base));
+ match with_base {
+ Pi(a, b, c) => {
+ if &String::from(&a) == "_" {
+ Pi(a, b.phase(Operator), c)
+ } else {
+ Pi(a, b, c)
+ }
+ }
+ Merge(a, b, c) => Merge(
+ a.phase(PrintPhase::Import),
+ b.phase(PrintPhase::Import),
+ c.map(|x| x.phase(PrintPhase::App)),
+ ),
+ ToMap(a, b) => ToMap(
+ a.phase(PrintPhase::Import),
+ b.map(|x| x.phase(PrintPhase::App)),
+ ),
+ Annot(a, b) => Annot(a.phase(Operator), b),
+ ExprKind::BinOp(op, a, b) => ExprKind::BinOp(
+ op,
+ a.phase(PrintPhase::BinOp(op)),
+ b.phase(PrintPhase::BinOp(op)),
+ ),
+ SomeLit(e) => SomeLit(e.phase(PrintPhase::Import)),
+ ExprKind::App(f, a) => ExprKind::App(
+ f.phase(PrintPhase::Import),
+ a.phase(PrintPhase::Import),
+ ),
+ Field(a, b) => Field(a.phase(Primitive), b),
+ Projection(e, ls) => Projection(e.phase(Primitive), ls),
+ ProjectionByExpr(a, b) => ProjectionByExpr(a.phase(Primitive), b),
+ e => e,
+ }
+ }
+
+ fn fmt_phase(
+ &self,
+ f: &mut fmt::Formatter,
+ phase: PrintPhase,
+ ) -> Result<(), fmt::Error> {
+ use crate::syntax::ExprKind::*;
+
+ let needs_paren = match self {
+ Lam(_, _, _)
+ | BoolIf(_, _, _)
+ | Pi(_, _, _)
+ | Let(_, _, _, _)
+ | EmptyListLit(_)
+ | NEListLit(_)
+ | SomeLit(_)
+ | Merge(_, _, _)
+ | ToMap(_, _)
+ | Annot(_, _) => phase > PrintPhase::Base,
+ // Precedence is magically handled by the ordering of BinOps.
+ ExprKind::BinOp(op, _, _) => phase > PrintPhase::BinOp(*op),
+ ExprKind::App(_, _) => phase > PrintPhase::App,
+ Field(_, _) | Projection(_, _) | ProjectionByExpr(_, _) => {
+ phase > PrintPhase::Import
+ }
+ _ => false,
+ };
+
+ if needs_paren {
+ f.write_str("(")?;
+ }
+ self.annotate_with_phases().fmt(f)?;
+ if needs_paren {
+ f.write_str(")")?;
+ }
+
+ Ok(())
+ }
+}
+
+fn fmt_list<T, I, F>(
+ open: &str,
+ sep: &str,
+ close: &str,
+ it: I,
+ f: &mut fmt::Formatter,
+ func: F,
+) -> Result<(), fmt::Error>
+where
+ I: IntoIterator<Item = T>,
+ F: Fn(T, &mut fmt::Formatter) -> Result<(), fmt::Error>,
+{
+ f.write_str(open)?;
+ for (i, x) in it.into_iter().enumerate() {
+ if i > 0 {
+ f.write_str(sep)?;
+ }
+ func(x, f)?;
+ }
+ f.write_str(close)
+}
+
/// Generic instance that delegates to subexpressions
-impl<SE: Display + Clone, E: Display> Display for ExprF<SE, E> {
+impl<SE: Display + Clone, E: Display> Display for ExprKind<SE, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- use crate::syntax::ExprF::*;
+ use crate::syntax::ExprKind::*;
match self {
Lam(a, b, c) => {
write!(f, "λ({} : {}) → {}", a, b, c)?;
@@ -53,10 +180,10 @@ impl<SE: Display + Clone, E: Display> Display for ExprF<SE, E> {
Assert(a) => {
write!(f, "assert : {}", a)?;
}
- ExprF::BinOp(op, a, b) => {
+ ExprKind::BinOp(op, a, b) => {
write!(f, "{} {} {}", a, op, b)?;
}
- ExprF::App(a, b) => {
+ ExprKind::App(a, b) => {
write!(f, "{} {}", a, b)?;
}
Field(a, b) => {
@@ -104,147 +231,16 @@ impl<SE: Display + Clone, E: Display> Display for ExprF<SE, E> {
}
}
-// There is a one-to-one correspondence between the formatter and the grammar. Each phase is
-// named after a corresponding grammar group, and the structure of the formatter reflects
-// the relationship between the corresponding grammar rules. This leads to the nice property
-// of automatically getting all the parentheses and precedences right.
-#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
-enum PrintPhase {
- Base,
- Operator,
- BinOp(core::BinOp),
- App,
- Import,
- Primitive,
-}
-
-// Wraps an Expr with a phase, so that phase selsction can be done
-// separate from the actual printing
-#[derive(Clone)]
-struct PhasedExpr<'a, A>(&'a Expr<A>, PrintPhase);
-
-impl<'a, A: Display + Clone> Display for PhasedExpr<'a, A> {
- fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- self.0.as_ref().fmt_phase(f, self.1)
- }
-}
-
-impl<'a, A: Display + Clone> PhasedExpr<'a, A> {
- fn phase(self, phase: PrintPhase) -> PhasedExpr<'a, A> {
- PhasedExpr(self.0, phase)
- }
-}
-
-impl<A: Display + Clone> RawExpr<A> {
- fn fmt_phase(
- &self,
- f: &mut fmt::Formatter,
- phase: PrintPhase,
- ) -> Result<(), fmt::Error> {
- use crate::syntax::ExprF::*;
- use PrintPhase::*;
-
- let needs_paren = match self {
- Lam(_, _, _)
- | BoolIf(_, _, _)
- | Pi(_, _, _)
- | Let(_, _, _, _)
- | EmptyListLit(_)
- | NEListLit(_)
- | SomeLit(_)
- | Merge(_, _, _)
- | ToMap(_, _)
- | Annot(_, _)
- if phase > Base =>
- {
- true
- }
- // Precedence is magically handled by the ordering of BinOps.
- ExprF::BinOp(op, _, _) if phase > PrintPhase::BinOp(*op) => true,
- ExprF::App(_, _) if phase > PrintPhase::App => true,
- Field(_, _) | Projection(_, _) | ProjectionByExpr(_, _)
- if phase > PrintPhase::Import =>
- {
- true
- }
- _ => false,
- };
-
- // Annotate subexpressions with the appropriate phase, defaulting to Base
- let phased_self = match self.map_ref(|e| PhasedExpr(e, Base)) {
- Pi(a, b, c) => {
- if &String::from(&a) == "_" {
- Pi(a, b.phase(Operator), c)
- } else {
- Pi(a, b, c)
- }
- }
- Merge(a, b, c) => Merge(
- a.phase(PrintPhase::Import),
- b.phase(PrintPhase::Import),
- c.map(|x| x.phase(PrintPhase::App)),
- ),
- ToMap(a, b) => ToMap(
- a.phase(PrintPhase::Import),
- b.map(|x| x.phase(PrintPhase::App)),
- ),
- Annot(a, b) => Annot(a.phase(Operator), b),
- ExprF::BinOp(op, a, b) => ExprF::BinOp(
- op,
- a.phase(PrintPhase::BinOp(op)),
- b.phase(PrintPhase::BinOp(op)),
- ),
- SomeLit(e) => SomeLit(e.phase(PrintPhase::Import)),
- ExprF::App(f, a) => ExprF::App(
- f.phase(PrintPhase::Import),
- a.phase(PrintPhase::Import),
- ),
- Field(a, b) => Field(a.phase(Primitive), b),
- Projection(e, ls) => Projection(e.phase(Primitive), ls),
- ProjectionByExpr(a, b) => ProjectionByExpr(a.phase(Primitive), b),
- e => e,
- };
-
- if needs_paren {
- f.write_str("(")?;
- }
-
- // Uses the ExprF<PhasedExpr<_>, _> instance
- phased_self.fmt(f)?;
-
- if needs_paren {
- f.write_str(")")?;
- }
- Ok(())
- }
-}
-
-impl<A: Display + Clone> Display for Expr<A> {
+impl<E: Display + Clone> Display for Expr<E> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.as_ref().fmt_phase(f, PrintPhase::Base)
}
}
-fn fmt_list<T, I, F>(
- open: &str,
- sep: &str,
- close: &str,
- it: I,
- f: &mut fmt::Formatter,
- func: F,
-) -> Result<(), fmt::Error>
-where
- I: IntoIterator<Item = T>,
- F: Fn(T, &mut fmt::Formatter) -> Result<(), fmt::Error>,
-{
- f.write_str(open)?;
- for (i, x) in it.into_iter().enumerate() {
- if i > 0 {
- f.write_str(sep)?;
- }
- func(x, f)?;
+impl<'a, E: Display + Clone> Display for PhasedExpr<'a, E> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ self.0.as_ref().fmt_phase(f, self.1)
}
- f.write_str(close)
}
impl<SubExpr: Display> Display for InterpolatedText<SubExpr> {
@@ -361,6 +357,7 @@ impl Display for Hash {
}
}
}
+
impl<SubExpr: Display> Display for Import<SubExpr> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use FilePrefix::*;