summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall/src/imports.rs2
-rw-r--r--dhall/src/main.rs4
-rw-r--r--dhall_core/src/core.rs57
-rw-r--r--dhall_core/src/grammar_util.rs4
-rw-r--r--dhall_core/src/lib.rs1
-rw-r--r--dhall_core/src/parser.rs104
-rw-r--r--dhall_generator/src/lib.rs4
7 files changed, 110 insertions, 66 deletions
diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs
index 9ae66a7..d9f0b33 100644
--- a/dhall/src/imports.rs
+++ b/dhall/src/imports.rs
@@ -75,7 +75,7 @@ pub fn load_dhall_file(
let mut buffer = String::new();
File::open(f)?.read_to_string(&mut buffer)?;
let expr = parser::parse_expr(&*buffer)?;
- let expr = expr.take_ownership_of_labels();
+ let expr = expr.map_label(&|l| String::from(l.clone()));
let expr = if resolve_imports {
let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned());
let resolve = |import: &Import| -> Expr<String, X, X> {
diff --git a/dhall/src/main.rs b/dhall/src/main.rs
index d072fe7..db69a46 100644
--- a/dhall/src/main.rs
+++ b/dhall/src/main.rs
@@ -65,8 +65,8 @@ fn main() {
}
};
- let expr: Expr<String, _, _> =
- imports::panic_imports(&expr.take_ownership_of_labels());
+ let expr: Expr<Label, _, _> =
+ imports::panic_imports(&expr);
let type_expr = match typecheck::type_of(&expr) {
Err(e) => {
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs
index eed9e0c..7bd1318 100644
--- a/dhall_core/src/core.rs
+++ b/dhall_core/src/core.rs
@@ -68,6 +68,41 @@ pub struct Import {
pub hash: Option<()>,
}
+// The type for labels throughout the AST
+// It owns the data because otherwise lifetimes would make recursive imports impossible
+#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct Label(String);
+
+impl From<String> for Label {
+ fn from(s: String) -> Self {
+ Label(s)
+ }
+}
+
+impl From<&'static str> for Label {
+ fn from(s: &'static str) -> Self {
+ Label(s.to_owned())
+ }
+}
+
+impl From<Label> for String {
+ fn from(x: Label) -> String {
+ x.0
+ }
+}
+
+impl Display for Label {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ self.0.fmt(f)
+ }
+}
+
+impl Label {
+ pub fn from_str<'a>(s: &'a str) -> Label {
+ s.to_owned().into()
+ }
+}
+
/// Label for a bound variable
///
/// The `String` field is the variable's name (i.e. \"`x`\").
@@ -268,7 +303,6 @@ pub trait StringLike:
+ Hash
+ Ord
+ Eq
- + Default
+ Into<String>
+ From<String>
+ From<&'static str>
@@ -282,7 +316,6 @@ impl<T> StringLike for T where
+ Hash
+ Ord
+ Eq
- + Default
+ Into<String>
+ From<String>
+ From<&'static str>
@@ -340,6 +373,18 @@ impl<Label: StringLike, S, A> Expr<Label, S, A> {
self.map_shallow(recurse, |x| x.clone(), map_embed, |x| x.clone())
}
+ pub fn map_label<L2: StringLike, F>(&self, map_label: &F) -> Expr<L2, S, A>
+ where
+ A: Clone,
+ S: Clone,
+ F: Fn(&Label) -> L2,
+ {
+ let recurse = |e: &Expr<Label, S, A>| -> Expr<L2, S, A> {
+ e.map_label(map_label)
+ };
+ self.map_shallow(recurse, |x| x.clone(), |x| x.clone(), map_label)
+ }
+
pub fn bool_lit(&self) -> Option<bool> {
match *self {
Expr::BoolLit(v) => Some(v),
@@ -362,11 +407,11 @@ impl<Label: StringLike, S, A> Expr<Label, S, A> {
}
}
-impl<'i, S: Clone, A: Clone> Expr<&'i str, S, A> {
- pub fn take_ownership_of_labels<L: StringLike + From<String>>(
+impl<S: Clone, A: Clone> Expr<&'static str, S, A> {
+ pub fn take_ownership_of_labels<L: StringLike>(
&self,
) -> Expr<L, S, A> {
- let recurse = |e: &Expr<&'i str, S, A>| -> Expr<L, S, A> {
+ let recurse = |e: &Expr<&'static str, S, A>| -> Expr<L, S, A> {
e.take_ownership_of_labels()
};
map_shallow(
@@ -787,7 +832,7 @@ where
S: Clone,
T: Clone,
Label1:
- Display + fmt::Debug + Clone + Hash + Ord + Eq + Into<String> + Default,
+ Display + fmt::Debug + Clone + Hash + Ord + Eq + Into<String>,
Label2: StringLike,
F1: Fn(&Expr<Label1, S, A>) -> Expr<Label2, T, B>,
F2: FnOnce(&S) -> T,
diff --git a/dhall_core/src/grammar_util.rs b/dhall_core/src/grammar_util.rs
deleted file mode 100644
index 2547e94..0000000
--- a/dhall_core/src/grammar_util.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-use crate::core::{Expr, Import, X};
-
-pub type ParsedExpr<'i> = Expr<&'i str, X, Import>;
-pub type BoxExpr<'i> = Box<ParsedExpr<'i>>;
diff --git a/dhall_core/src/lib.rs b/dhall_core/src/lib.rs
index bd53603..386d6bc 100644
--- a/dhall_core/src/lib.rs
+++ b/dhall_core/src/lib.rs
@@ -4,5 +4,4 @@
pub mod core;
pub use crate::core::*;
pub mod context;
-mod grammar_util;
pub mod parser;
diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs
index 0ba1586..7073a93 100644
--- a/dhall_core/src/parser.rs
+++ b/dhall_core/src/parser.rs
@@ -7,7 +7,9 @@ use dhall_parser::{DhallParser, Rule};
use crate::core;
use crate::core::*;
-use crate::grammar_util::{BoxExpr, ParsedExpr};
+
+pub type ParsedExpr = Expr<Label, X, Import>;
+pub type BoxExpr = Box<ParsedExpr>;
pub type ParseError = pest::error::Error<Rule>;
@@ -418,6 +420,8 @@ named!(str<&'a str>; captured_str!(s) => s.trim());
named!(raw_str<&'a str>; captured_str!(s) => s);
+named!(label<Label>; captured_str!(s) => Label::from(s.trim().to_owned()));
+
// TODO: parse escapes and interpolation
rule!(double_quote_literal<String>;
children!(strs*: raw_str) => {
@@ -537,7 +541,7 @@ rule!(import_hashed_raw<(ImportLocation, Option<()>)>;
}
);
-rule!(import_raw<BoxExpr<'a>>;
+rule!(import_raw<BoxExpr>;
// TODO: handle "as Text"
children!(import: import_hashed_raw) => {
let (location, hash) = import;
@@ -549,7 +553,7 @@ rule!(import_raw<BoxExpr<'a>>;
}
);
-rule_group!(expression<BoxExpr<'a>>;
+rule_group!(expression<BoxExpr>;
identifier_raw,
lambda_expression,
ifthenelse_expression,
@@ -586,47 +590,47 @@ rule_group!(expression<BoxExpr<'a>>;
final_expression
);
-rule!(lambda_expression<BoxExpr<'a>>;
- children!(label: str, typ: expression, body: expression) => {
- bx(Expr::Lam(label, typ, body))
+rule!(lambda_expression<BoxExpr>;
+ children!(l: label, typ: expression, body: expression) => {
+ bx(Expr::Lam(l, typ, body))
}
);
-rule!(ifthenelse_expression<BoxExpr<'a>>;
+rule!(ifthenelse_expression<BoxExpr>;
children!(cond: expression, left: expression, right: expression) => {
bx(Expr::BoolIf(cond, left, right))
}
);
-rule!(let_expression<BoxExpr<'a>>;
+rule!(let_expression<BoxExpr>;
children!(bindings*: let_binding, final_expr: expression) => {
bindings.fold(final_expr, |acc, x| bx(Expr::Let(x.0, x.1, x.2, acc)))
}
);
-rule!(let_binding<(&'a str, Option<BoxExpr<'a>>, BoxExpr<'a>)>;
- children!(name: str, annot?: expression, expr: expression) => (name, annot, expr)
+rule!(let_binding<(Label, Option<BoxExpr>, BoxExpr)>;
+ children!(name: label, annot?: expression, expr: expression) => (name, annot, expr)
);
-rule!(forall_expression<BoxExpr<'a>>;
- children!(label: str, typ: expression, body: expression) => {
- bx(Expr::Pi(label, typ, body))
+rule!(forall_expression<BoxExpr>;
+ children!(l: label, typ: expression, body: expression) => {
+ bx(Expr::Pi(l, typ, body))
}
);
-rule!(arrow_expression<BoxExpr<'a>>;
+rule!(arrow_expression<BoxExpr>;
children!(typ: expression, body: expression) => {
- bx(Expr::Pi("_", typ, body))
+ bx(Expr::Pi("_".into(), typ, body))
}
);
-rule!(merge_expression<BoxExpr<'a>>;
+rule!(merge_expression<BoxExpr>;
children!(x: expression, y: expression, z?: expression) => {
bx(Expr::Merge(x, y, z))
}
);
-rule!(empty_collection<BoxExpr<'a>>;
+rule!(empty_collection<BoxExpr>;
children!(x: str, y: expression) => {
match x {
"Optional" => bx(Expr::OptionalLit(Some(y), vec![])),
@@ -636,7 +640,7 @@ rule!(empty_collection<BoxExpr<'a>>;
}
);
-rule!(non_empty_optional<BoxExpr<'a>>;
+rule!(non_empty_optional<BoxExpr>;
children!(x: expression, _y: str, z: expression) => {
bx(Expr::OptionalLit(Some(z), vec![*x]))
}
@@ -644,7 +648,7 @@ rule!(non_empty_optional<BoxExpr<'a>>;
macro_rules! binop {
($rule:ident, $op:ident) => {
- rule!($rule<BoxExpr<'a>>;
+ rule!($rule<BoxExpr>;
children!(first: expression, rest*: expression) => {
rest.fold(first, |acc, e| bx(Expr::BinOp(BinOp::$op, acc, e)))
}
@@ -652,7 +656,7 @@ macro_rules! binop {
};
}
-rule!(annotated_expression<BoxExpr<'a>>;
+rule!(annotated_expression<BoxExpr>;
children!(e: expression, annot: expression) => {
bx(Expr::Annot(e, annot))
},
@@ -672,19 +676,19 @@ binop!(times_expression, NaturalTimes);
binop!(equal_expression, BoolEQ);
binop!(not_equal_expression, BoolNE);
-rule!(application_expression<BoxExpr<'a>>;
+rule!(application_expression<BoxExpr>;
children!(first: expression, rest*: expression) => {
rest.fold(first, |acc, e| bx(Expr::App(acc, e)))
}
);
-rule!(selector_expression_raw<BoxExpr<'a>>;
- children!(first: expression, rest*: str) => {
+rule!(selector_expression_raw<BoxExpr>;
+ children!(first: expression, rest*: label) => {
rest.fold(first, |acc, e| bx(Expr::Field(acc, e)))
}
);
-rule!(literal_expression_raw<BoxExpr<'a>>;
+rule!(literal_expression_raw<BoxExpr>;
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)),
@@ -696,7 +700,7 @@ rule!(literal_expression_raw<BoxExpr<'a>>;
children!(e: expression) => e,
);
-rule!(identifier_raw<BoxExpr<'a>>;
+rule!(identifier_raw<BoxExpr>;
children!(name: str, idx?: natural_literal_raw) => {
match Builtin::parse(name) {
Some(b) => bx(Expr::Builtin(b)),
@@ -705,40 +709,40 @@ rule!(identifier_raw<BoxExpr<'a>>;
"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)))),
+ name => bx(Expr::Var(V(Label::from(name.to_owned()), idx.unwrap_or(0)))),
}
}
}
);
-rule!(empty_record_literal<BoxExpr<'a>>;
+rule!(empty_record_literal<BoxExpr>;
children!() => bx(Expr::RecordLit(BTreeMap::new()))
);
-rule!(empty_record_type<BoxExpr<'a>>;
+rule!(empty_record_type<BoxExpr>;
children!() => bx(Expr::Record(BTreeMap::new()))
);
-rule!(non_empty_record_type_or_literal<BoxExpr<'a>>;
- children!(first_label: str, rest: non_empty_record_type) => {
+rule!(non_empty_record_type_or_literal<BoxExpr>;
+ children!(first_label: label, rest: non_empty_record_type) => {
let (first_expr, mut map) = rest;
map.insert(first_label, *first_expr);
bx(Expr::Record(map))
},
- children!(first_label: str, rest: non_empty_record_literal) => {
+ children!(first_label: label, rest: non_empty_record_literal) => {
let (first_expr, mut map) = rest;
map.insert(first_label, *first_expr);
bx(Expr::RecordLit(map))
},
);
-rule!(non_empty_record_type<(BoxExpr<'a>, BTreeMap<&'a str, ParsedExpr<'a>>)>;
+rule!(non_empty_record_type<(BoxExpr, BTreeMap<Label, ParsedExpr>)>;
self!(x: partial_record_entries) => x
);
-named!(partial_record_entries<(BoxExpr<'a>, BTreeMap<&'a str, ParsedExpr<'a>>)>;
+named!(partial_record_entries<(BoxExpr, BTreeMap<Label, ParsedExpr>)>;
children!(expr: expression, entries*: record_entry) => {
- let mut map: BTreeMap<&str, ParsedExpr> = BTreeMap::new();
+ let mut map: BTreeMap<Label, ParsedExpr> = BTreeMap::new();
for (n, e) in entries {
map.insert(n, *e);
}
@@ -746,15 +750,15 @@ named!(partial_record_entries<(BoxExpr<'a>, BTreeMap<&'a str, ParsedExpr<'a>>)>;
}
);
-named!(record_entry<(&'a str, BoxExpr<'a>)>;
- children!(name: str, expr: expression) => (name, expr)
+named!(record_entry<(Label, BoxExpr)>;
+ children!(name: label, expr: expression) => (name, expr)
);
-rule!(non_empty_record_literal<(BoxExpr<'a>, BTreeMap<&'a str, ParsedExpr<'a>>)>;
+rule!(non_empty_record_literal<(BoxExpr, BTreeMap<Label, ParsedExpr>)>;
self!(x: partial_record_entries) => x
);
-rule!(union_type_or_literal<BoxExpr<'a>>;
+rule!(union_type_or_literal<BoxExpr>;
children!(_e: empty_union_type) => {
bx(Expr::Union(BTreeMap::new()))
},
@@ -769,25 +773,25 @@ rule!(union_type_or_literal<BoxExpr<'a>>;
rule!(empty_union_type<()>; children!() => ());
rule!(non_empty_union_type_or_literal
- <(Option<(&'a str, BoxExpr<'a>)>, BTreeMap<&'a str, ParsedExpr<'a>>)>;
- children!(label: str, e: expression, entries: union_type_entries) => {
- (Some((label, e)), entries)
+ <(Option<(Label, BoxExpr)>, BTreeMap<Label, ParsedExpr>)>;
+ children!(l: label, e: expression, entries: union_type_entries) => {
+ (Some((l, e)), entries)
},
- children!(l: str, e: expression, rest: non_empty_union_type_or_literal) => {
+ children!(l: label, e: expression, rest: non_empty_union_type_or_literal) => {
let (x, mut entries) = rest;
entries.insert(l, *e);
(x, entries)
},
- children!(l: str, e: expression) => {
+ children!(l: label, e: expression) => {
let mut entries = BTreeMap::new();
entries.insert(l, *e);
(None, entries)
},
);
-rule!(union_type_entries<BTreeMap<&'a str, ParsedExpr<'a>>>;
+rule!(union_type_entries<BTreeMap<Label, ParsedExpr>>;
children!(entries*: union_type_entry) => {
- let mut map: BTreeMap<&str, ParsedExpr> = BTreeMap::new();
+ let mut map: BTreeMap<Label, ParsedExpr> = BTreeMap::new();
for (n, e) in entries {
map.insert(n, *e);
}
@@ -795,21 +799,21 @@ rule!(union_type_entries<BTreeMap<&'a str, ParsedExpr<'a>>>;
}
);
-rule!(union_type_entry<(&'a str, BoxExpr<'a>)>;
- children!(name: str, expr: expression) => (name, expr)
+rule!(union_type_entry<(Label, BoxExpr)>;
+ children!(name: label, expr: expression) => (name, expr)
);
-rule!(non_empty_list_literal_raw<BoxExpr<'a>>;
+rule!(non_empty_list_literal_raw<BoxExpr>;
children!(items*: expression) => {
bx(Expr::ListLit(None, items.map(|x| *x).collect()))
}
);
-rule!(final_expression<BoxExpr<'a>>;
+rule!(final_expression<BoxExpr>;
children!(e: expression, _eoi: EOI) => e
);
-pub fn parse_expr<'i>(s: &'i str) -> ParseResult<BoxExpr<'i>> {
+pub fn parse_expr<'i>(s: &'i str) -> ParseResult<BoxExpr> {
let pairs = DhallParser::parse(Rule::final_expression, s)?;
// Match the only item in the pairs iterator
match_iter!(@panic; pairs; (p) => expression(p))
diff --git a/dhall_generator/src/lib.rs b/dhall_generator/src/lib.rs
index d1a8bdf..e66ab2c 100644
--- a/dhall_generator/src/lib.rs
+++ b/dhall_generator/src/lib.rs
@@ -11,8 +11,8 @@ pub fn dhall_expr(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let expr: Box<Expr<_, X, Import>> = parser::parse_expr(&input_str).unwrap();
let no_import =
|_: &Import| -> X { panic!("Don't use import in dhall!()") };
- let expr = expr.take_ownership_of_labels().map_embed(&no_import);
- let output = dhall_to_tokenstream::<String>(&expr, &Context::new());
+ let expr = expr.map_embed(&no_import);
+ let output = dhall_to_tokenstream::<Label>(&expr, &Context::new());
output.into()
}