diff options
author | Nadrieril | 2019-03-08 00:07:09 +0100 |
---|---|---|
committer | Nadrieril | 2019-03-08 00:07:09 +0100 |
commit | 16ce1082465a11bf76df5f59530cde02bddc4f21 (patch) | |
tree | 7e0af011578a46d3916386b99ade2b920481a4d8 /dhall_core/src | |
parent | d8c8514c6a903b155345f419cb56daa91d27c141 (diff) |
Make Expr generic in its type of labels
Diffstat (limited to 'dhall_core/src')
-rw-r--r-- | dhall_core/src/core.rs | 107 | ||||
-rw-r--r-- | dhall_core/src/parser.rs | 78 |
2 files changed, 93 insertions, 92 deletions
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index f2177b1..cbf0654 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -104,7 +104,7 @@ pub struct Import { /// appear as a numeric suffix. /// #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct V<'i>(pub &'i str, pub usize); +pub struct V<Label>(pub Label, pub usize); #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum BinOp { @@ -135,41 +135,42 @@ pub enum BinOp { } /// Syntax tree for expressions +pub type Expr<'i, S, A> = Expr_<&'i str, S, A>; #[derive(Debug, Clone, PartialEq)] -pub enum Expr<'i, S, A> { +pub enum Expr_<Label, Note, Embed> { /// `Const c ~ c` Const(Const), /// `Var (V x 0) ~ x`<br> /// `Var (V x n) ~ x@n` - Var(V<'i>), + Var(V<Label>), /// `Lam x A b ~ λ(x : A) -> b` - Lam(&'i str, Box<Expr<'i, S, A>>, Box<Expr<'i, S, A>>), + Lam(Label, Box<Expr_<Label, Note, Embed>>, Box<Expr_<Label, Note, Embed>>), /// `Pi "_" A B ~ A -> B` /// `Pi x A B ~ ∀(x : A) -> B` - Pi(&'i str, Box<Expr<'i, S, A>>, Box<Expr<'i, S, A>>), + Pi(Label, Box<Expr_<Label, Note, Embed>>, Box<Expr_<Label, Note, Embed>>), /// `App f A ~ f A` - App(Box<Expr<'i, S, A>>, Box<Expr<'i, S, A>>), + App(Box<Expr_<Label, Note, Embed>>, Box<Expr_<Label, Note, Embed>>), /// `Let x Nothing r e ~ let x = r in e` /// `Let x (Just t) r e ~ let x : t = r in e` Let( - &'i str, - Option<Box<Expr<'i, S, A>>>, - Box<Expr<'i, S, A>>, - Box<Expr<'i, S, A>>, + Label, + Option<Box<Expr_<Label, Note, Embed>>>, + Box<Expr_<Label, Note, Embed>>, + Box<Expr_<Label, Note, Embed>>, ), /// `Annot x t ~ x : t` - Annot(Box<Expr<'i, S, A>>, Box<Expr<'i, S, A>>), + Annot(Box<Expr_<Label, Note, Embed>>, Box<Expr_<Label, Note, Embed>>), /// Built-in values Builtin(Builtin), // Binary operations - BinOp(BinOp, Box<Expr<'i, S, A>>, Box<Expr<'i, S, A>>), + BinOp(BinOp, Box<Expr_<Label, Note, Embed>>, Box<Expr_<Label, Note, Embed>>), /// `BoolLit b ~ b` BoolLit(bool), /// `BoolIf x y z ~ if x then y else z` BoolIf( - Box<Expr<'i, S, A>>, - Box<Expr<'i, S, A>>, - Box<Expr<'i, S, A>>, + Box<Expr_<Label, Note, Embed>>, + Box<Expr_<Label, Note, Embed>>, + Box<Expr_<Label, Note, Embed>>, ), /// `NaturalLit n ~ +n` NaturalLit(Natural), @@ -180,34 +181,34 @@ pub enum Expr<'i, S, A> { /// `TextLit t ~ t` TextLit(Builder), /// `ListLit t [x, y, z] ~ [x, y, z] : List t` - ListLit(Option<Box<Expr<'i, S, A>>>, Vec<Expr<'i, S, A>>), + ListLit(Option<Box<Expr_<Label, Note, Embed>>>, Vec<Expr_<Label, Note, Embed>>), /// `OptionalLit t [e] ~ [e] : Optional t` /// `OptionalLit t [] ~ [] : Optional t` - OptionalLit(Option<Box<Expr<'i, S, A>>>, Vec<Expr<'i, S, A>>), + OptionalLit(Option<Box<Expr_<Label, Note, Embed>>>, Vec<Expr_<Label, Note, Embed>>), /// `Record [(k1, t1), (k2, t2)] ~ { k1 : t1, k2 : t1 }` - Record(BTreeMap<&'i str, Expr<'i, S, A>>), + Record(BTreeMap<Label, Expr_<Label, Note, Embed>>), /// `RecordLit [(k1, v1), (k2, v2)] ~ { k1 = v1, k2 = v2 }` - RecordLit(BTreeMap<&'i str, Expr<'i, S, A>>), + RecordLit(BTreeMap<Label, Expr_<Label, Note, Embed>>), /// `Union [(k1, t1), (k2, t2)] ~ < k1 : t1, k2 : t2 >` - Union(BTreeMap<&'i str, Expr<'i, S, A>>), + Union(BTreeMap<Label, Expr_<Label, Note, Embed>>), /// `UnionLit (k1, v1) [(k2, t2), (k3, t3)] ~ < k1 = t1, k2 : t2, k3 : t3 >` UnionLit( - &'i str, - Box<Expr<'i, S, A>>, - BTreeMap<&'i str, Expr<'i, S, A>>, + Label, + Box<Expr_<Label, Note, Embed>>, + BTreeMap<Label, Expr_<Label, Note, Embed>>, ), /// `Merge x y t ~ merge x y : t` Merge( - Box<Expr<'i, S, A>>, - Box<Expr<'i, S, A>>, - Option<Box<Expr<'i, S, A>>>, + Box<Expr_<Label, Note, Embed>>, + Box<Expr_<Label, Note, Embed>>, + Option<Box<Expr_<Label, Note, Embed>>>, ), /// `Field e x ~ e.x` - Field(Box<Expr<'i, S, A>>, &'i str), - /// `Note S x ~ e` - Note(S, Box<Expr<'i, S, A>>), - /// `Embed path ~ path` - Embed(A), + Field(Box<Expr_<Label, Note, Embed>>, Label), + /// Annotation on the AST. Unused for now but could hold e.g. file location information + Note(Note, Box<Expr_<Label, Note, Embed>>), + /// Embeds an import or the result of resolving the import + Embed(Embed), } /// Built-ins @@ -242,7 +243,7 @@ pub enum Builtin { TextShow, } -impl<'i> From<&'i str> for V<'i> { +impl<'i> From<&'i str> for V<&'i str> { fn from(s: &'i str) -> Self { V(s, 0) } @@ -250,13 +251,13 @@ impl<'i> From<&'i str> for V<'i> { impl<'i, S, A> From<&'i str> for Expr<'i, S, A> { fn from(s: &'i str) -> Self { - Expr::Var(s.into()) + Expr_::Var(s.into()) } } impl<'i, S, A> From<Builtin> for Expr<'i, S, A> { fn from(t: Builtin) -> Self { - Expr::Builtin(t) + Expr_::Builtin(t) } } @@ -291,21 +292,21 @@ impl<'i, S, A> Expr<'i, S, A> { pub fn bool_lit(&self) -> Option<bool> { match *self { - Expr::BoolLit(v) => Some(v), + Expr_::BoolLit(v) => Some(v), _ => None, } } pub fn natural_lit(&self) -> Option<usize> { match *self { - Expr::NaturalLit(v) => Some(v), + Expr_::NaturalLit(v) => Some(v), _ => None, } } pub fn text_lit(&self) -> Option<String> { match *self { - Expr::TextLit(ref t) => Some(t.clone()), // FIXME? + Expr_::TextLit(ref t) => Some(t.clone()), // FIXME? _ => None, } } @@ -324,7 +325,7 @@ impl<'i, S, A> Expr<'i, S, A> { impl<'i, S, A: Display> Display for Expr<'i, S, A> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { // buildExprA - use crate::Expr::*; + use crate::Expr_::*; match self { &Annot(ref a, ref b) => { a.fmt_b(f)?; @@ -339,7 +340,7 @@ impl<'i, S, A: Display> Display for Expr<'i, S, A> { impl<'i, S, A: Display> Expr<'i, S, A> { fn fmt_b(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use crate::Expr::*; + use crate::Expr_::*; match self { &Lam(a, ref b, ref c) => { write!(f, "λ({} : ", a)?; @@ -423,7 +424,7 @@ impl<'i, S, A: Display> Expr<'i, S, A> { fn fmt_c(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { use crate::BinOp::*; - use crate::Expr::*; + use crate::Expr_::*; match self { // FIXME precedence &BinOp(BoolOr, ref a, ref b) => { @@ -472,7 +473,7 @@ impl<'i, S, A: Display> Expr<'i, S, A> { } fn fmt_d(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use crate::Expr::*; + use crate::Expr_::*; match self { &App(ref a, ref b) => { a.fmt_d(f)?; @@ -485,7 +486,7 @@ impl<'i, S, A: Display> Expr<'i, S, A> { } fn fmt_e(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use crate::Expr::*; + use crate::Expr_::*; match self { &Field(ref a, b) => { a.fmt_e(f)?; @@ -497,7 +498,7 @@ impl<'i, S, A: Display> Expr<'i, S, A> { } fn fmt_f(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use crate::Expr::*; + use crate::Expr_::*; match self { &Var(a) => a.fmt(f), &Const(k) => k.fmt(f), @@ -632,7 +633,7 @@ impl Builtin { } } -impl<'i> Display for V<'i> { +impl<'i> Display for V<&'i str> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { let V(x, n) = *self; f.write_str(x)?; @@ -653,7 +654,7 @@ where Et: Into<Expr<'i, S, A>>, Ev: Into<Expr<'i, S, A>>, { - Expr::Pi(var.into(), bx(ty.into()), bx(value.into())) + Expr_::Pi(var.into(), bx(ty.into()), bx(value.into())) } pub fn app<'i, S, A, Ef, Ex>(f: Ef, x: Ex) -> Expr<'i, S, A> @@ -661,7 +662,7 @@ where Ef: Into<Expr<'i, S, A>>, Ex: Into<Expr<'i, S, A>>, { - Expr::App(bx(f.into()), bx(x.into())) + Expr_::App(bx(f.into()), bx(x.into())) } pub type Builder = String; @@ -706,7 +707,7 @@ where F2: FnOnce(&S) -> T, F3: FnOnce(&A) -> B, { - use crate::Expr::*; + use crate::Expr_::*; let bxmap = |x: &Expr<'i, S, A>| -> Box<Expr<'i, T, B>> { bx(map(x)) }; let opt = |x| map_opt_box(x, &map); match *e { @@ -844,10 +845,10 @@ where /// pub fn shift<'i, S, T, A: Clone>( d: isize, - v: V, + v: V<&'i str>, e: &Expr<'i, S, A>, ) -> Expr<'i, T, A> { - use crate::Expr::*; + use crate::Expr_::*; let V(x, n) = v; match *e { Const(a) => Const(a), @@ -924,7 +925,7 @@ pub fn shift<'i, S, T, A: Clone>( fn shift_op2<'i, S, T, A, F>( f: F, d: isize, - v: V, + v: V<&'i str>, a: &Expr<'i, S, A>, b: &Expr<'i, S, A>, ) -> Expr<'i, T, A> @@ -942,7 +943,7 @@ where /// ``` /// pub fn subst<'i, S, T, A>( - v: V<'i>, + v: V<&'i str>, e: &Expr<'i, S, A>, b: &Expr<'i, T, A>, ) -> Expr<'i, S, A> @@ -950,7 +951,7 @@ where S: Clone, A: Clone, { - use crate::Expr::*; + use crate::Expr_::*; let V(x, n) = v; match *b { Const(a) => Const(a), @@ -1029,7 +1030,7 @@ where fn subst_op2<'i, S, T, A, F>( f: F, - v: V<'i>, + v: V<&'i str>, e: &Expr<'i, S, A>, a: &Expr<'i, T, A>, b: &Expr<'i, T, A>, diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index 34327b1..d72b6bd 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -539,7 +539,7 @@ rule!(import_raw<BoxExpr<'a>>; // TODO: handle "as Text" children!(import: import_hashed_raw) => { let (location, hash) = import; - bx(Expr::Embed(Import { + bx(Expr_::Embed(Import { mode: ImportMode::Code, hash, location, @@ -586,19 +586,19 @@ rule_group!(expression<BoxExpr<'a>>; rule!(lambda_expression<BoxExpr<'a>>; children!(label: str, typ: expression, body: expression) => { - bx(Expr::Lam(label, typ, body)) + bx(Expr_::Lam(label, typ, body)) } ); rule!(ifthenelse_expression<BoxExpr<'a>>; children!(cond: expression, left: expression, right: expression) => { - bx(Expr::BoolIf(cond, left, right)) + bx(Expr_::BoolIf(cond, left, right)) } ); rule!(let_expression<BoxExpr<'a>>; children!(bindings*: let_binding, final_expr: expression) => { - bindings.fold(final_expr, |acc, x| bx(Expr::Let(x.0, x.1, x.2, acc))) + bindings.fold(final_expr, |acc, x| bx(Expr_::Let(x.0, x.1, x.2, acc))) } ); @@ -608,27 +608,27 @@ rule!(let_binding<(&'a str, Option<BoxExpr<'a>>, BoxExpr<'a>)>; rule!(forall_expression<BoxExpr<'a>>; children!(label: str, typ: expression, body: expression) => { - bx(Expr::Pi(label, typ, body)) + bx(Expr_::Pi(label, typ, body)) } ); rule!(arrow_expression<BoxExpr<'a>>; children!(typ: expression, body: expression) => { - bx(Expr::Pi("_", typ, body)) + bx(Expr_::Pi("_", typ, body)) } ); rule!(merge_expression<BoxExpr<'a>>; children!(x: expression, y: expression, z?: expression) => { - bx(Expr::Merge(x, y, z)) + bx(Expr_::Merge(x, y, z)) } ); rule!(empty_collection<BoxExpr<'a>>; children!(x: str, y: expression) => { match x { - "Optional" => bx(Expr::OptionalLit(Some(y), vec![])), - "List" => bx(Expr::ListLit(Some(y), vec![])), + "Optional" => bx(Expr_::OptionalLit(Some(y), vec![])), + "List" => bx(Expr_::ListLit(Some(y), vec![])), _ => unreachable!(), } } @@ -636,7 +636,7 @@ rule!(empty_collection<BoxExpr<'a>>; rule!(non_empty_optional<BoxExpr<'a>>; children!(x: expression, _y: str, z: expression) => { - bx(Expr::OptionalLit(Some(z), vec![*x])) + bx(Expr_::OptionalLit(Some(z), vec![*x])) } ); @@ -644,7 +644,7 @@ macro_rules! binop { ($rule:ident, $op:ident) => { rule!($rule<BoxExpr<'a>>; children!(first: expression, rest*: expression) => { - rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::$op, acc, e))) + rest.fold(first, |acc, e| bx(Expr_::BinOp(BinOp::$op, acc, e))) } ); }; @@ -652,7 +652,7 @@ macro_rules! binop { rule!(annotated_expression<BoxExpr<'a>>; children!(e: expression, annot: expression) => { - bx(Expr::Annot(e, annot)) + bx(Expr_::Annot(e, annot)) }, children!(e: expression) => e, ); @@ -672,61 +672,61 @@ binop!(not_equal_expression, BoolNE); rule!(application_expression<BoxExpr<'a>>; children!(first: expression, rest*: expression) => { - rest.fold(first, |acc, e| bx(Expr::App(acc, e))) + rest.fold(first, |acc, e| bx(Expr_::App(acc, e))) } ); rule!(selector_expression_raw<BoxExpr<'a>>; children!(first: expression, rest*: str) => { - rest.fold(first, |acc, e| bx(Expr::Field(acc, e))) + rest.fold(first, |acc, e| bx(Expr_::Field(acc, e))) } ); rule!(literal_expression_raw<BoxExpr<'a>>; - children!(n: double_literal_raw) => bx(Expr::DoubleLit(n)), - children!(n: minus_infinity_literal) => bx(Expr::DoubleLit(std::f64::NEG_INFINITY)), - children!(n: plus_infinity_literal) => bx(Expr::DoubleLit(std::f64::INFINITY)), - children!(n: NaN_raw) => bx(Expr::DoubleLit(std::f64::NAN)), - children!(n: natural_literal_raw) => bx(Expr::NaturalLit(n)), - children!(n: integer_literal_raw) => bx(Expr::IntegerLit(n)), - children!(s: double_quote_literal) => bx(Expr::TextLit(s)), - children!(s: single_quote_literal) => bx(Expr::TextLit(s)), + children!(n: double_literal_raw) => bx(Expr_::DoubleLit(n)), + children!(n: minus_infinity_literal) => bx(Expr_::DoubleLit(std::f64::NEG_INFINITY)), + children!(n: plus_infinity_literal) => bx(Expr_::DoubleLit(std::f64::INFINITY)), + children!(n: NaN_raw) => bx(Expr_::DoubleLit(std::f64::NAN)), + children!(n: natural_literal_raw) => bx(Expr_::NaturalLit(n)), + children!(n: integer_literal_raw) => bx(Expr_::IntegerLit(n)), + children!(s: double_quote_literal) => bx(Expr_::TextLit(s)), + children!(s: single_quote_literal) => bx(Expr_::TextLit(s)), children!(e: expression) => e, ); rule!(identifier_raw<BoxExpr<'a>>; children!(name: str, idx?: natural_literal_raw) => { match Builtin::parse(name) { - Some(b) => bx(Expr::Builtin(b)), + Some(b) => bx(Expr_::Builtin(b)), None => match name { - "True" => bx(Expr::BoolLit(true)), - "False" => bx(Expr::BoolLit(false)), - "Type" => bx(Expr::Const(Const::Type)), - "Kind" => bx(Expr::Const(Const::Kind)), - name => bx(Expr::Var(V(name, idx.unwrap_or(0)))), + "True" => bx(Expr_::BoolLit(true)), + "False" => bx(Expr_::BoolLit(false)), + "Type" => bx(Expr_::Const(Const::Type)), + "Kind" => bx(Expr_::Const(Const::Kind)), + name => bx(Expr_::Var(V(name, idx.unwrap_or(0)))), } } } ); rule!(empty_record_literal<BoxExpr<'a>>; - children!() => bx(Expr::RecordLit(BTreeMap::new())) + children!() => bx(Expr_::RecordLit(BTreeMap::new())) ); rule!(empty_record_type<BoxExpr<'a>>; - children!() => bx(Expr::Record(BTreeMap::new())) + children!() => bx(Expr_::Record(BTreeMap::new())) ); rule!(non_empty_record_type_or_literal<BoxExpr<'a>>; children!(first_label: str, rest: non_empty_record_type) => { let (first_expr, mut map) = rest; map.insert(first_label, *first_expr); - bx(Expr::Record(map)) + bx(Expr_::Record(map)) }, children!(first_label: str, rest: non_empty_record_literal) => { let (first_expr, mut map) = rest; map.insert(first_label, *first_expr); - bx(Expr::RecordLit(map)) + bx(Expr_::RecordLit(map)) }, ); @@ -754,12 +754,12 @@ rule!(non_empty_record_literal<(BoxExpr<'a>, BTreeMap<&'a str, ParsedExpr<'a>>)> rule!(union_type_or_literal<BoxExpr<'a>>; children!(_e: empty_union_type) => { - bx(Expr::Union(BTreeMap::new())) + bx(Expr_::Union(BTreeMap::new())) }, children!(x: non_empty_union_type_or_literal) => { match x { - (Some((l, e)), entries) => bx(Expr::UnionLit(l, e, entries)), - (None, entries) => bx(Expr::Union(entries)), + (Some((l, e)), entries) => bx(Expr_::UnionLit(l, e, entries)), + (None, entries) => bx(Expr_::Union(entries)), } }, ); @@ -799,7 +799,7 @@ rule!(union_type_entry<(&'a str, BoxExpr<'a>)>; rule!(non_empty_list_literal_raw<BoxExpr<'a>>; children!(items*: expression) => { - bx(Expr::ListLit(None, items.map(|x| *x).collect())) + bx(Expr_::ListLit(None, items.map(|x| *x).collect())) } ); @@ -807,17 +807,17 @@ rule!(final_expression<BoxExpr<'a>>; children!(e: expression, _eoi: EOI) => e ); -pub fn parse_expr(s: &str) -> ParseResult<BoxExpr> { +pub fn parse_expr<'i>(s: &'i str) -> ParseResult<BoxExpr<'i>> { let pairs = DhallParser::parse(Rule::final_expression, s)?; // Match the only item in the pairs iterator match_iter!(@panic; pairs; (p) => expression(p)) - // Ok(bx(Expr::BoolLit(false))) + // Ok(bx(Expr_::BoolLit(false))) } #[test] fn test_parse() { use crate::core::BinOp::*; - use crate::core::Expr::*; + use crate::core::Expr_::*; // let expr = r#"{ x = "foo", y = 4 }.x"#; // let expr = r#"(1 + 2) * 3"#; let expr = r#"if True then 1 + 3 * 5 else 2"#; |