From da80ef06a91e3869cc3c1d4dbd07259c408ff490 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 9 Apr 2020 23:09:47 +0100 Subject: Move Label escaping out of its Display impl --- dhall/src/syntax/text/printer.rs | 54 +++++++++++++--------- .../success/regression/ToMapQuotedFieldsA.dhall | 1 + .../success/regression/ToMapQuotedFieldsB.dhall | 1 + serde_dhall/tests/de.rs | 16 ++++++- 4 files changed, 49 insertions(+), 23 deletions(-) create mode 100644 dhall/tests/normalization/success/regression/ToMapQuotedFieldsA.dhall create mode 100644 dhall/tests/normalization/success/regression/ToMapQuotedFieldsB.dhall diff --git a/dhall/src/syntax/text/printer.rs b/dhall/src/syntax/text/printer.rs index 9e90660..ccba385 100644 --- a/dhall/src/syntax/text/printer.rs +++ b/dhall/src/syntax/text/printer.rs @@ -146,6 +146,21 @@ where f.write_str(close) } +fn fmt_label(label: &Label, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + // TODO: distinguish between reserved and nonreserved locations for quoting builtins + let s = String::from(label); + let is_reserved = match s.as_str() { + "let" | "in" | "if" | "then" | "else" | "Type" | "Kind" | "Sort" + | "True" | "False" | "Some" => true, + _ => Builtin::parse(&s).is_some(), + }; + if !is_reserved && s.chars().all(|c| c.is_ascii_alphanumeric()) { + write!(f, "{}", s) + } else { + write!(f, "`{}`", s) + } +} + /// Generic instance that delegates to subexpressions impl Display for ExprKind { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { @@ -153,16 +168,21 @@ impl Display for ExprKind { match self { Var(a) => a.fmt(f)?, Lam(a, b, c) => { - write!(f, "λ({} : {}) → {}", a, b, c)?; + write!(f, "λ(")?; + fmt_label(a, f)?; + write!(f, " : {}) → {}", b, c)?; } Pi(a, b, c) if &String::from(a) == "_" => { write!(f, "{} → {}", b, c)?; } Pi(a, b, c) => { - write!(f, "∀({} : {}) → {}", a, b, c)?; + write!(f, "∀(")?; + fmt_label(a, f)?; + write!(f, " : {}) → {}", b, c)?; } Let(a, b, c, d) => { - write!(f, "let {}", a)?; + write!(f, "let ")?; + fmt_label(a, f)?; if let Some(b) = b { write!(f, " : {}", b)?; } @@ -183,14 +203,16 @@ impl Display for ExprKind { } RecordLit(a) if a.is_empty() => f.write_str("{=}")?, RecordLit(a) => fmt_list("{ ", ", ", " }", a, f, |(k, v), f| { - write!(f, "{} = {}", k, v) + fmt_label(k, f)?; + write!(f, " = {}", v) })?, RecordType(a) if a.is_empty() => f.write_str("{}")?, RecordType(a) => fmt_list("{ ", ", ", " }", a, f, |(k, t), f| { - write!(f, "{} : {}", k, t) + fmt_label(k, f)?; + write!(f, " : {}", t) })?, UnionType(a) => fmt_list("< ", " | ", " >", a, f, |(k, v), f| { - write!(f, "{}", k)?; + fmt_label(k, f)?; if let Some(v) = v { write!(f, ": {}", v)?; } @@ -238,11 +260,12 @@ impl Display for OpKind { } } Field(a, b) => { - write!(f, "{}.{}", a, b)?; + write!(f, "{}.", a)?; + fmt_label(b, f)?; } Projection(e, ls) => { write!(f, "{}.", e)?; - fmt_list("{ ", ", ", " }", ls, f, Display::fmt)?; + fmt_list("{ ", ", ", " }", ls, f, fmt_label)?; } ProjectionByExpr(a, b) => { write!(f, "{}.({})", a, b)?; @@ -379,18 +402,7 @@ impl Display for NaiveDouble { 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" | "Some" => true, - _ => Builtin::parse(&s).is_some(), - }; - if !is_reserved && s.chars().all(|c| c.is_ascii_alphanumeric()) { - write!(f, "{}", s) - } else { - write!(f, "`{}`", s) - } + write!(f, "{}", String::from(self)) } } @@ -495,7 +507,7 @@ impl Display for Scheme { impl Display for V { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { let V(x, n) = self; - x.fmt(f)?; + fmt_label(x, f)?; if *n != 0 { write!(f, "@{}", n)?; } diff --git a/dhall/tests/normalization/success/regression/ToMapQuotedFieldsA.dhall b/dhall/tests/normalization/success/regression/ToMapQuotedFieldsA.dhall new file mode 100644 index 0000000..2b355fa --- /dev/null +++ b/dhall/tests/normalization/success/regression/ToMapQuotedFieldsA.dhall @@ -0,0 +1 @@ +toMap { `if` = 0, `foo%bar` = 1 } diff --git a/dhall/tests/normalization/success/regression/ToMapQuotedFieldsB.dhall b/dhall/tests/normalization/success/regression/ToMapQuotedFieldsB.dhall new file mode 100644 index 0000000..d71242b --- /dev/null +++ b/dhall/tests/normalization/success/regression/ToMapQuotedFieldsB.dhall @@ -0,0 +1 @@ +[ { mapKey = "foo%bar", mapValue = 1 }, { mapKey = "if", mapValue = 0 } ] diff --git a/serde_dhall/tests/de.rs b/serde_dhall/tests/de.rs index a5c42fd..41b4080 100644 --- a/serde_dhall/tests/de.rs +++ b/serde_dhall/tests/de.rs @@ -60,6 +60,9 @@ fn test_de_typed() { #[test] fn test_de_untyped() { + use std::collections::BTreeMap; + use std::collections::HashMap; + fn parse(s: &str) -> T { from_str(s).parse().unwrap() } @@ -70,7 +73,6 @@ fn test_de_untyped() { (1, "foo".to_owned(), 42) ); - use std::collections::HashMap; let mut expected_map = HashMap::new(); expected_map.insert("x".to_string(), 1); expected_map.insert("y".to_string(), 2); @@ -79,7 +81,17 @@ fn test_de_untyped() { expected_map ); - use std::collections::BTreeMap; + let mut expected_map = HashMap::new(); + expected_map.insert("if".to_string(), 1); + expected_map.insert("FOO_BAR".to_string(), 2); + expected_map.insert("baz-kux".to_string(), 3); + assert_eq!( + parse::>( + "{ `if` = 1, FOO_BAR = 2, baz-kux = 3 }" + ), + expected_map + ); + let mut expected_map = BTreeMap::new(); expected_map.insert("x".to_string(), 1); expected_map.insert("y".to_string(), 2); -- cgit v1.2.3