summaryrefslogtreecommitdiff
path: root/dhall_core
diff options
context:
space:
mode:
authorNadrieril2019-03-08 00:07:09 +0100
committerNadrieril2019-03-08 00:07:09 +0100
commit16ce1082465a11bf76df5f59530cde02bddc4f21 (patch)
tree7e0af011578a46d3916386b99ade2b920481a4d8 /dhall_core
parentd8c8514c6a903b155345f419cb56daa91d27c141 (diff)
Make Expr generic in its type of labels
Diffstat (limited to 'dhall_core')
-rw-r--r--dhall_core/src/core.rs107
-rw-r--r--dhall_core/src/parser.rs78
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"#;