diff options
Diffstat (limited to 'dhall')
-rw-r--r-- | dhall/src/syntax/binary.rs | 1 | ||||
-rw-r--r-- | dhall/src/syntax/parser.rs | 152 |
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, |