diff options
Diffstat (limited to '')
-rw-r--r-- | dhall/src/syntax/text/parser.rs | 29 | ||||
-rw-r--r-- | dhall/src/syntax/text/printer.rs | 275 |
2 files changed, 152 insertions, 152 deletions
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::*; |