summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall/src/syntax/binary.rs1
-rw-r--r--dhall/src/syntax/parser.rs152
2 files changed, 66 insertions, 87 deletions
diff --git a/dhall/src/syntax/binary.rs b/dhall/src/syntax/binary.rs
index 9fe31ad..ad503ef 100644
--- a/dhall/src/syntax/binary.rs
+++ b/dhall/src/syntax/binary.rs
@@ -20,6 +20,7 @@ pub(crate) fn decode(data: &[u8]) -> Result<DecodedExpr, DecodeError> {
}
}
+/// Warning: will fail if `expr` contains an `Embed` node.
pub(crate) fn encode<E>(expr: &Expr<E>) -> Result<Vec<u8>, EncodeError> {
serde_cbor::ser::to_vec(&Serialize::Expr(expr))
.map_err(|e| EncodeError::CBORError(e))
diff --git a/dhall/src/syntax/parser.rs b/dhall/src/syntax/parser.rs
index 9aa9403..f6b6577 100644
--- a/dhall/src/syntax/parser.rs
+++ b/dhall/src/syntax/parser.rs
@@ -5,27 +5,35 @@ use std::rc::Rc;
use pest_consume::{match_nodes, Parser};
+use crate::semantics::phase::Normalized;
+use crate::syntax;
+use crate::syntax::core;
use crate::syntax::map::{DupTreeMap, DupTreeSet};
use crate::syntax::ExprF::*;
-use crate::syntax::*;
+use crate::syntax::{
+ FilePath, FilePrefix, Hash, ImportLocation, ImportMode, InterpolatedText,
+ InterpolatedTextContents, Label, NaiveDouble, RawExpr, Scheme, Span, URL,
+ V,
+};
// This file consumes the parse tree generated by pest and turns it into
// our own AST. All those custom macros should eventually moved into
// their own crate because they are quite general and useful. For now they
// are here and hopefully you can figure out how they work.
-type ParsedText<E> = InterpolatedText<Expr<E>>;
-type ParsedTextContents<E> = InterpolatedTextContents<Expr<E>>;
+type Expr = syntax::Expr<Normalized>;
+type ParsedText = InterpolatedText<Expr>;
+type ParsedTextContents = InterpolatedTextContents<Expr>;
type ParseInput<'input> = pest_consume::Node<'input, Rule, Rc<str>>;
pub type ParseError = pest::error::Error<Rule>;
pub type ParseResult<T> = Result<T, ParseError>;
#[derive(Debug)]
-enum Selector<E> {
+enum Selector {
Field(Label),
Projection(DupTreeSet<Label>),
- ProjectionByExpr(Expr<E>),
+ ProjectionByExpr(Expr),
}
impl crate::syntax::Builtin {
@@ -69,16 +77,16 @@ impl crate::syntax::Builtin {
fn input_to_span(input: ParseInput) -> Span {
Span::make(input.user_data().clone(), input.as_pair().as_span())
}
-fn spanned<E>(input: ParseInput, x: RawExpr<E>) -> Expr<E> {
+fn spanned(input: ParseInput, x: RawExpr<Normalized>) -> Expr {
Expr::new(x, input_to_span(input))
}
-fn spanned_union<E>(span1: Span, span2: Span, x: RawExpr<E>) -> Expr<E> {
+fn spanned_union(span1: Span, span2: Span, x: RawExpr<Normalized>) -> Expr {
Expr::new(x, span1.union(&span2))
}
// Trim the shared indent off of a vec of lines, as defined by the Dhall semantics of multiline
// literals.
-fn trim_indent<E: Clone>(lines: &mut Vec<ParsedText<E>>) {
+fn trim_indent(lines: &mut Vec<ParsedText>) {
let is_indent = |c: char| c == ' ' || c == '\t';
// There is at least one line so this is safe
@@ -164,9 +172,7 @@ impl DhallParser {
Ok(Label::from(input.as_str()))
}
- fn double_quote_literal<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ParsedText<E>> {
+ fn double_quote_literal(input: ParseInput) -> ParseResult<ParsedText> {
Ok(match_nodes!(input.into_children();
[double_quote_chunk(chunks)..] => {
chunks.collect()
@@ -174,9 +180,9 @@ impl DhallParser {
))
}
- fn double_quote_chunk<E: Clone>(
+ fn double_quote_chunk(
input: ParseInput,
- ) -> ParseResult<ParsedTextContents<E>> {
+ ) -> ParseResult<ParsedTextContents> {
Ok(match_nodes!(input.into_children();
[expression(e)] => {
InterpolatedTextContents::Expr(e)
@@ -261,18 +267,16 @@ impl DhallParser {
Ok(input.as_str().to_owned())
}
- fn single_quote_literal<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ParsedText<E>> {
+ fn single_quote_literal(input: ParseInput) -> ParseResult<ParsedText> {
Ok(match_nodes!(input.into_children();
[single_quote_continue(lines)] => {
- let newline: ParsedText<E> = "\n".to_string().into();
+ let newline: ParsedText = "\n".to_string().into();
// Reverse lines and chars in each line
- let mut lines: Vec<ParsedText<E>> = lines
+ let mut lines: Vec<ParsedText> = lines
.into_iter()
.rev()
- .map(|l| l.into_iter().rev().collect::<ParsedText<E>>())
+ .map(|l| l.into_iter().rev().collect::<ParsedText>())
.collect();
trim_indent(&mut lines);
@@ -281,7 +285,7 @@ impl DhallParser {
.into_iter()
.intersperse(newline)
.flat_map(InterpolatedText::into_iter)
- .collect::<ParsedText<E>>()
+ .collect::<ParsedText>()
}
))
}
@@ -298,9 +302,9 @@ impl DhallParser {
}
// Returns a vec of lines in reversed order, where each line is also in reversed order.
- fn single_quote_continue<E: Clone>(
+ fn single_quote_continue(
input: ParseInput,
- ) -> ParseResult<Vec<Vec<ParsedTextContents<E>>>> {
+ ) -> ParseResult<Vec<Vec<ParsedTextContents>>> {
Ok(match_nodes!(input.into_children();
[expression(e), single_quote_continue(lines)] => {
let c = InterpolatedTextContents::Expr(e);
@@ -326,7 +330,7 @@ impl DhallParser {
}
#[alias(expression)]
- fn builtin<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn builtin(input: ParseInput) -> ParseResult<Expr> {
let s = input.as_str();
let e = match crate::syntax::Builtin::parse(s) {
Some(b) => Builtin(b),
@@ -387,7 +391,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn identifier<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn identifier(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[variable(v)] => spanned(input, Var(v)),
[expression(e)] => e,
@@ -441,9 +445,7 @@ impl DhallParser {
}
#[alias(import_type)]
- fn local<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ImportLocation<Expr<E>>> {
+ fn local(input: ParseInput) -> ParseResult<ImportLocation<Expr>> {
Ok(match_nodes!(input.into_children();
[local_path((prefix, p))] => ImportLocation::Local(prefix, p),
))
@@ -482,7 +484,7 @@ impl DhallParser {
})
}
- fn http_raw<E: Clone>(input: ParseInput) -> ParseResult<URL<Expr<E>>> {
+ fn http_raw(input: ParseInput) -> ParseResult<URL<Expr>> {
Ok(match_nodes!(input.into_children();
[scheme(sch), authority(auth), path(p)] => URL {
scheme: sch,
@@ -510,9 +512,7 @@ impl DhallParser {
}
#[alias(import_type)]
- fn http<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ImportLocation<Expr<E>>> {
+ fn http(input: ParseInput) -> ParseResult<ImportLocation<Expr>> {
Ok(ImportLocation::Remote(match_nodes!(input.into_children();
[http_raw(url)] => url,
[http_raw(url), expression(e)] => URL { headers: Some(e), ..url },
@@ -520,9 +520,7 @@ impl DhallParser {
}
#[alias(import_type)]
- fn env<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ImportLocation<Expr<E>>> {
+ fn env(input: ParseInput) -> ParseResult<ImportLocation<Expr>> {
Ok(match_nodes!(input.into_children();
[environment_variable(v)] => ImportLocation::Env(v),
))
@@ -557,9 +555,7 @@ impl DhallParser {
}
#[alias(import_type)]
- fn missing<E: Clone>(
- _input: ParseInput,
- ) -> ParseResult<ImportLocation<Expr<E>>> {
+ fn missing(_input: ParseInput) -> ParseResult<ImportLocation<Expr>> {
Ok(ImportLocation::Missing)
}
@@ -573,9 +569,9 @@ impl DhallParser {
Ok(Hash::SHA256(hex::decode(hash).unwrap()))
}
- fn import_hashed<E: Clone>(
+ fn import_hashed(
input: ParseInput,
- ) -> ParseResult<crate::syntax::Import<Expr<E>>> {
+ ) -> ParseResult<crate::syntax::Import<Expr>> {
use crate::syntax::Import;
let mode = ImportMode::Code;
Ok(match_nodes!(input.into_children();
@@ -594,7 +590,7 @@ impl DhallParser {
}
#[alias(expression)]
- fn import<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn import(input: ParseInput) -> ParseResult<Expr> {
use crate::syntax::Import;
let import = match_nodes!(input.children();
[import_hashed(imp)] => {
@@ -630,13 +626,13 @@ impl DhallParser {
}
#[alias(expression)]
- fn empty_list_literal<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn empty_list_literal(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(e)] => spanned(input, EmptyListLit(e)),
))
}
- fn expression<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[lambda(()), label(l), expression(typ),
arrow(()), expression(body)] => {
@@ -681,9 +677,9 @@ impl DhallParser {
))
}
- fn let_binding<E: Clone>(
+ fn let_binding(
input: ParseInput,
- ) -> ParseResult<(Label, Option<Expr<E>>, Expr<E>, Span)> {
+ ) -> ParseResult<(Label, Option<Expr>, Expr, Span)> {
Ok(match_nodes!(input.children();
[label(name), expression(annot), expression(expr)] =>
(name, Some(annot), expr, input_to_span(input)),
@@ -694,11 +690,11 @@ impl DhallParser {
#[alias(expression, shortcut = true)]
#[prec_climb(expression, PRECCLIMBER)]
- fn operator_expression<E: Clone>(
- l: Expr<E>,
+ fn operator_expression(
+ l: Expr,
op: ParseInput,
- r: Expr<E>,
- ) -> ParseResult<Expr<E>> {
+ r: Expr,
+ ) -> ParseResult<Expr> {
use crate::syntax::BinOp::*;
use Rule::*;
let op = match op.as_rule() {
@@ -726,9 +722,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn application_expression<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn application_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(e)] => e,
[expression(first), expression(rest)..] => {
@@ -747,9 +741,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn first_application_expression<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn first_application_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[Some_(()), expression(e)] => {
spanned(input, SomeLit(e))
@@ -765,9 +757,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn selector_expression<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn selector_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(e)] => e,
[expression(first), selector(rest)..] => {
@@ -789,9 +779,7 @@ impl DhallParser {
))
}
- fn selector<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<(Selector<E>, Span)> {
+ fn selector(input: ParseInput) -> ParseResult<(Selector, Span)> {
let stor = match_nodes!(input.children();
[label(l)] => Selector::Field(l),
[labels(ls)] => Selector::Projection(ls),
@@ -807,9 +795,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn primitive_expression<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn primitive_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[double_literal(n)] => spanned(input, DoubleLit(n)),
[natural_literal(n)] => spanned(input, NaturalLit(n)),
@@ -821,21 +807,19 @@ impl DhallParser {
}
#[alias(expression)]
- fn empty_record_literal<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn empty_record_literal(input: ParseInput) -> ParseResult<Expr> {
Ok(spanned(input, RecordLit(Default::default())))
}
#[alias(expression)]
- fn empty_record_type<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn empty_record_type(input: ParseInput) -> ParseResult<Expr> {
Ok(spanned(input, RecordType(Default::default())))
}
#[alias(expression)]
- fn non_empty_record_type_or_literal<E: Clone>(
+ fn non_empty_record_type_or_literal(
input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ ) -> ParseResult<Expr> {
let e = match_nodes!(input.children();
[label(first_label), non_empty_record_type(rest)] => {
let (first_expr, mut map) = rest;
@@ -851,9 +835,9 @@ impl DhallParser {
Ok(spanned(input, e))
}
- fn non_empty_record_type<E: Clone>(
+ fn non_empty_record_type(
input: ParseInput,
- ) -> ParseResult<(Expr<E>, DupTreeMap<Label, Expr<E>>)> {
+ ) -> ParseResult<(Expr, DupTreeMap<Label, Expr>)> {
Ok(match_nodes!(input.into_children();
[expression(expr), record_type_entry(entries)..] => {
(expr, entries.collect())
@@ -861,17 +845,15 @@ impl DhallParser {
))
}
- fn record_type_entry<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<(Label, Expr<E>)> {
+ fn record_type_entry(input: ParseInput) -> ParseResult<(Label, Expr)> {
Ok(match_nodes!(input.into_children();
[label(name), expression(expr)] => (name, expr)
))
}
- fn non_empty_record_literal<E: Clone>(
+ fn non_empty_record_literal(
input: ParseInput,
- ) -> ParseResult<(Expr<E>, DupTreeMap<Label, Expr<E>>)> {
+ ) -> ParseResult<(Expr, DupTreeMap<Label, Expr>)> {
Ok(match_nodes!(input.into_children();
[expression(expr), record_literal_entry(entries)..] => {
(expr, entries.collect())
@@ -879,16 +861,14 @@ impl DhallParser {
))
}
- fn record_literal_entry<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<(Label, Expr<E>)> {
+ fn record_literal_entry(input: ParseInput) -> ParseResult<(Label, Expr)> {
Ok(match_nodes!(input.into_children();
[label(name), expression(expr)] => (name, expr)
))
}
#[alias(expression)]
- fn union_type<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn union_type(input: ParseInput) -> ParseResult<Expr> {
let map = match_nodes!(input.children();
[empty_union_type(_)] => Default::default(),
[union_type_entry(entries)..] => entries.collect(),
@@ -900,9 +880,9 @@ impl DhallParser {
Ok(())
}
- fn union_type_entry<E: Clone>(
+ fn union_type_entry(
input: ParseInput,
- ) -> ParseResult<(Label, Option<Expr<E>>)> {
+ ) -> ParseResult<(Label, Option<Expr>)> {
Ok(match_nodes!(input.children();
[label(name), expression(expr)] => (name, Some(expr)),
[label(name)] => (name, None),
@@ -910,9 +890,7 @@ impl DhallParser {
}
#[alias(expression)]
- fn non_empty_list_literal<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn non_empty_list_literal(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(items)..] => spanned(
input,
@@ -922,14 +900,14 @@ impl DhallParser {
}
#[alias(expression)]
- fn final_expression<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn final_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.into_children();
[expression(e), EOI(_)] => e
))
}
}
-pub fn parse_expr<E: Clone>(input_str: &str) -> ParseResult<Expr<E>> {
+pub fn parse_expr(input_str: &str) -> ParseResult<Expr> {
let rc_input_str = input_str.to_string().into();
let inputs = DhallParser::parse_with_userdata(
Rule::final_expression,