From 78e9e32e1357d50313287dd2a3c437132c83aeb6 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 15 Dec 2019 20:10:54 +0000 Subject: Move contents of dhall_syntax to dhall --- dhall_syntax/src/printer.rs | 500 -------------------------------------------- 1 file changed, 500 deletions(-) delete mode 100644 dhall_syntax/src/printer.rs (limited to 'dhall_syntax/src/printer.rs') diff --git a/dhall_syntax/src/printer.rs b/dhall_syntax/src/printer.rs deleted file mode 100644 index ce6ff97..0000000 --- a/dhall_syntax/src/printer.rs +++ /dev/null @@ -1,500 +0,0 @@ -use crate::*; -use itertools::Itertools; -use std::fmt::{self, Display}; - -/// Generic instance that delegates to subexpressions -impl Display for ExprF { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use crate::ExprF::*; - match self { - Lam(a, b, c) => { - write!(f, "λ({} : {}) → {}", a, b, c)?; - } - BoolIf(a, b, c) => { - write!(f, "if {} then {} else {}", a, b, c)?; - } - Pi(a, b, c) if &String::from(a) == "_" => { - write!(f, "{} → {}", b, c)?; - } - Pi(a, b, c) => { - write!(f, "∀({} : {}) → {}", a, b, c)?; - } - Let(a, b, c, d) => { - write!(f, "let {}", a)?; - if let Some(b) = b { - write!(f, " : {}", b)?; - } - write!(f, " = {} in {}", c, d)?; - } - EmptyListLit(t) => { - write!(f, "[] : {}", t)?; - } - NEListLit(es) => { - fmt_list("[", ", ", "]", es, f, Display::fmt)?; - } - SomeLit(e) => { - write!(f, "Some {}", e)?; - } - Merge(a, b, c) => { - write!(f, "merge {} {}", a, b)?; - if let Some(c) = c { - write!(f, " : {}", c)?; - } - } - ToMap(a, b) => { - write!(f, "toMap {}", a)?; - if let Some(b) = b { - write!(f, " : {}", b)?; - } - } - Annot(a, b) => { - write!(f, "{} : {}", a, b)?; - } - Assert(a) => { - write!(f, "assert : {}", a)?; - } - ExprF::BinOp(op, a, b) => { - write!(f, "{} {} {}", a, op, b)?; - } - ExprF::App(a, b) => { - write!(f, "{} {}", a, b)?; - } - Field(a, b) => { - write!(f, "{}.{}", a, b)?; - } - Projection(e, ls) => { - write!(f, "{}.", e)?; - fmt_list("{ ", ", ", " }", ls, f, Display::fmt)?; - } - ProjectionByExpr(a, b) => { - write!(f, "{}.({})", a, b)?; - } - Var(a) => a.fmt(f)?, - Const(k) => k.fmt(f)?, - Builtin(v) => v.fmt(f)?, - BoolLit(true) => f.write_str("True")?, - BoolLit(false) => f.write_str("False")?, - NaturalLit(a) => a.fmt(f)?, - IntegerLit(a) if *a >= 0 => { - f.write_str("+")?; - a.fmt(f)?; - } - IntegerLit(a) => a.fmt(f)?, - DoubleLit(a) => a.fmt(f)?, - TextLit(a) => a.fmt(f)?, - RecordType(a) if a.is_empty() => f.write_str("{}")?, - RecordType(a) => fmt_list("{ ", ", ", " }", a, f, |(k, t), f| { - write!(f, "{} : {}", k, t) - })?, - RecordLit(a) if a.is_empty() => f.write_str("{=}")?, - RecordLit(a) => fmt_list("{ ", ", ", " }", a, f, |(k, v), f| { - write!(f, "{} = {}", k, v) - })?, - UnionType(a) => fmt_list("< ", " | ", " >", a, f, |(k, v), f| { - write!(f, "{}", k)?; - if let Some(v) = v { - write!(f, ": {}", v)?; - } - Ok(()) - })?, - Import(a) => a.fmt(f)?, - Embed(a) => a.fmt(f)?, - } - Ok(()) - } -} - -// 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, 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 RawExpr { - fn fmt_phase( - &self, - f: &mut fmt::Formatter, - phase: PrintPhase, - ) -> Result<(), fmt::Error> { - use crate::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, _> instance - phased_self.fmt(f)?; - - if needs_paren { - f.write_str(")")?; - } - Ok(()) - } -} - -impl Display for Expr { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.as_ref().fmt_phase(f, PrintPhase::Base) - } -} - -fn fmt_list( - open: &str, - sep: &str, - close: &str, - it: I, - f: &mut fmt::Formatter, - func: F, -) -> Result<(), fmt::Error> -where - I: IntoIterator, - 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) -} - -impl Display for InterpolatedText { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.write_str("\"")?; - for x in self.iter() { - match x { - InterpolatedTextContents::Text(a) => { - for c in a.chars() { - match c { - '\\' => f.write_str("\\\\"), - '"' => f.write_str("\\\""), - '$' => f.write_str("\\u0024"), - '\u{0008}' => f.write_str("\\b"), - '\u{000C}' => f.write_str("\\f"), - '\n' => f.write_str("\\n"), - '\r' => f.write_str("\\r"), - '\t' => f.write_str("\\t"), - '\u{0000}'..='\u{001F}' => { - // Escape to an explicit "\u{XXXX}" form - let escaped: String = - c.escape_default().collect(); - // Print as "\uXXXX" - write!( - f, - "\\u{:0>4}", - &escaped[3..escaped.len() - 1] - ) - } - c => write!(f, "{}", c), - }?; - } - } - InterpolatedTextContents::Expr(e) => { - f.write_str("${ ")?; - e.fmt(f)?; - f.write_str(" }")?; - } - } - } - f.write_str("\"")?; - Ok(()) - } -} - -impl Display for Const { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - ::fmt(self, f) - } -} - -impl Display for BinOp { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use crate::BinOp::*; - f.write_str(match self { - BoolOr => "||", - TextAppend => "++", - NaturalPlus => "+", - BoolAnd => "&&", - RecursiveRecordMerge => "∧", - NaturalTimes => "*", - BoolEQ => "==", - BoolNE => "!=", - RecursiveRecordTypeMerge => "⩓", - ImportAlt => "?", - RightBiasedRecordMerge => "⫽", - ListAppend => "#", - Equivalence => "≡", - }) - } -} - -impl Display for NaiveDouble { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let v = f64::from(*self); - if v == std::f64::INFINITY { - f.write_str("Infinity") - } else if v == std::f64::NEG_INFINITY { - f.write_str("-Infinity") - } else if v.is_nan() { - f.write_str("NaN") - } else { - let s = format!("{}", v); - if s.contains('e') || s.contains('.') { - f.write_str(&s) - } else { - write!(f, "{}.0", s) - } - } - } -} - -impl Display for Label { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - // TODO: distinguish between reserved and nonreserved locations for quoting builtins - let s = String::from(self); - let is_reserved = match s.as_str() { - "let" | "in" | "if" | "then" | "else" | "Type" | "Kind" - | "Sort" | "True" | "False" => true, - _ => crate::Builtin::parse(&s).is_some(), - }; - if !is_reserved && s.chars().all(|c| c.is_ascii_alphanumeric()) { - write!(f, "{}", s) - } else { - write!(f, "`{}`", s) - } - } -} - -impl Display for Hash { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match self { - Hash::SHA256(hash) => write!(f, "sha256:{}", hex::encode(hash)), - } - } -} -impl Display for Import { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use FilePrefix::*; - use ImportLocation::*; - use ImportMode::*; - let quote_if_needed = |s: &str| -> String { - if s.chars().all(|c| c.is_ascii_alphanumeric()) { - s.to_string() - } else { - format!("\"{}\"", s) - } - }; - - match &self.location { - Local(prefix, path) => { - let prefix = match prefix { - Here => ".", - Parent => "..", - Home => "~", - Absolute => "", - }; - write!(f, "{}/", prefix)?; - let path: String = path - .file_path - .iter() - .map(|c| quote_if_needed(&*c)) - .join("/"); - f.write_str(&path)?; - } - Remote(url) => { - write!(f, "{}://{}/", url.scheme, url.authority,)?; - let path: String = url.path.file_path.iter().join("/"); - f.write_str(&path)?; - if let Some(q) = &url.query { - write!(f, "?{}", q)? - } - if let Some(h) = &url.headers { - write!(f, " using ({})", h)? - } - } - Env(s) => { - write!(f, "env:")?; - if s.chars().all(|c| c.is_ascii_alphanumeric()) { - write!(f, "{}", s)?; - } else { - write!(f, "\"")?; - for c in s.chars() { - match c { - '"' => f.write_str("\\\"")?, - '\\' => f.write_str("\\\\")?, - '\u{0007}' => f.write_str("\\a")?, - '\u{0008}' => f.write_str("\\b")?, - '\u{000C}' => f.write_str("\\f")?, - '\n' => f.write_str("\\n")?, - '\r' => f.write_str("\\r")?, - '\t' => f.write_str("\\t")?, - '\u{000B}' => f.write_str("\\v")?, - _ => write!(f, "{}", c)?, - } - } - write!(f, "\"")?; - } - } - Missing => { - write!(f, "missing")?; - } - } - if let Some(hash) = &self.hash { - write!(f, " ")?; - hash.fmt(f)?; - } - match self.mode { - Code => {} - RawText => write!(f, " as Text")?, - Location => write!(f, " as Location")?, - } - Ok(()) - } -} - -impl Display for Builtin { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use crate::Builtin::*; - f.write_str(match *self { - Bool => "Bool", - Natural => "Natural", - Integer => "Integer", - Double => "Double", - Text => "Text", - List => "List", - Optional => "Optional", - OptionalNone => "None", - NaturalBuild => "Natural/build", - NaturalFold => "Natural/fold", - NaturalIsZero => "Natural/isZero", - NaturalEven => "Natural/even", - NaturalOdd => "Natural/odd", - NaturalToInteger => "Natural/toInteger", - NaturalShow => "Natural/show", - NaturalSubtract => "Natural/subtract", - IntegerToDouble => "Integer/toDouble", - IntegerShow => "Integer/show", - DoubleShow => "Double/show", - ListBuild => "List/build", - ListFold => "List/fold", - ListLength => "List/length", - ListHead => "List/head", - ListLast => "List/last", - ListIndexed => "List/indexed", - ListReverse => "List/reverse", - OptionalFold => "Optional/fold", - OptionalBuild => "Optional/build", - TextShow => "Text/show", - }) - } -} - -impl Display for Scheme { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use crate::Scheme::*; - f.write_str(match *self { - HTTP => "http", - HTTPS => "https", - }) - } -} - -impl Display for V