diff options
-rw-r--r-- | dhall_proc_macros/src/make_parser.rs | 83 | ||||
-rw-r--r-- | dhall_syntax/src/core/expr.rs | 9 | ||||
-rw-r--r-- | dhall_syntax/src/parser.rs | 140 |
3 files changed, 130 insertions, 102 deletions
diff --git a/dhall_proc_macros/src/make_parser.rs b/dhall_proc_macros/src/make_parser.rs index 63ce779..268a639 100644 --- a/dhall_proc_macros/src/make_parser.rs +++ b/dhall_proc_macros/src/make_parser.rs @@ -2,26 +2,25 @@ use quote::quote; use syn::parse::{ParseStream, Result}; use syn::spanned::Spanned; use syn::{ - parse_quote, Error, Expr, Ident, ImplItem, ImplItemMethod, ItemImpl, - ReturnType, Token, + parse_quote, Error, Expr, FnArg, Ident, ImplItem, ImplItemMethod, ItemImpl, + Pat, Token, }; -fn apply_special_attrs( - rule_enum: &Ident, - function: &mut ImplItemMethod, -) -> Result<()> { +fn apply_special_attrs(function: &mut ImplItemMethod) -> Result<()> { + *function = parse_quote!( + #[allow(non_snake_case, dead_code)] + #function + ); + let recognized_attrs: Vec<_> = function .attrs .drain_filter(|attr| attr.path.is_ident("prec_climb")) .collect(); let name = function.sig.ident.clone(); - let output_type = match &function.sig.output { - ReturnType::Default => parse_quote!(()), - ReturnType::Type(_, t) => (**t).clone(), - }; if recognized_attrs.is_empty() { + // do nothing } else if recognized_attrs.len() > 1 { return Err(Error::new( recognized_attrs[1].span(), @@ -37,28 +36,50 @@ fn apply_special_attrs( Ok((child_rule, climber)) })?; - *function = parse_quote!( - fn #name<'a>( - input: ParseInput<'a, #rule_enum>, - ) -> #output_type { - #[allow(non_snake_case, dead_code)] - #function - - #climber.climb( - input.pair.clone().into_inner(), - |p| Self::#child_rule(input.with_pair(p)), - |l, op, r| { - #name(input.clone(), l?, op, r?) - }, - ) + // Get the name of the first (`input`) function argument + let first_arg = function.sig.inputs.first().ok_or_else(|| { + Error::new( + function.sig.inputs.span(), + "a prec_climb function needs 4 arguments", + ) + })?; + let first_arg = match &first_arg { + FnArg::Receiver(_) => return Err(Error::new( + first_arg.span(), + "a prec_climb function should not have a `self` argument", + )), + FnArg::Typed(first_arg) => match &*first_arg.pat{ + Pat::Ident(ident) => &ident.ident, + _ => return Err(Error::new( + first_arg.span(), + "this argument should be a plain identifier instead of a pattern", + )), } - ); - } + }; - *function = parse_quote!( - #[allow(non_snake_case, dead_code)] - #function - ); + function.block = parse_quote!({ + #function + + #climber.climb( + #first_arg.pair.clone().into_inner(), + |p| Self::#child_rule(#first_arg.with_pair(p)), + |l, op, r| { + #name(#first_arg.clone(), l?, op, r?) + }, + ) + }); + // Remove the 3 last arguments to keep only the `input` one + function.sig.inputs.pop(); + function.sig.inputs.pop(); + function.sig.inputs.pop(); + // Check that an argument remains + function.sig.inputs.first().ok_or_else(|| { + Error::new( + function.sig.inputs.span(), + "a prec_climb function needs 4 arguments", + ) + })?; + } Ok(()) } @@ -73,7 +94,7 @@ pub fn make_parser( imp.items .iter_mut() .map(|item| match item { - ImplItem::Method(m) => apply_special_attrs(&rule_enum, m), + ImplItem::Method(m) => apply_special_attrs(m), _ => Ok(()), }) .collect::<Result<()>>()?; diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs index 51b6c47..eeee4d8 100644 --- a/dhall_syntax/src/core/expr.rs +++ b/dhall_syntax/src/core/expr.rs @@ -381,15 +381,10 @@ pub fn rc<E>(x: RawExpr<E>) -> Expr<E> { Expr::from_expr_no_span(x) } -pub(crate) fn spanned( - span: Span, - x: crate::parser::ParsedRawExpr, -) -> crate::parser::ParsedExpr { +pub(crate) fn spanned<E>(span: Span, x: RawExpr<E>) -> Expr<E> { Expr::new(x, span) } -pub(crate) fn unspanned( - x: crate::parser::ParsedRawExpr, -) -> crate::parser::ParsedExpr { +pub(crate) fn unspanned<E>(x: RawExpr<E>) -> Expr<E> { Expr::from_expr_no_span(x) } diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs index b1e429b..c2ba19a 100644 --- a/dhall_syntax/src/parser.rs +++ b/dhall_syntax/src/parser.rs @@ -18,10 +18,8 @@ use crate::*; // their own crate because they are quite general and useful. For now they // are here and hopefully you can figure out how they work. -pub(crate) type ParsedRawExpr = RawExpr<!>; -pub(crate) type ParsedExpr = Expr<!>; -type ParsedText = InterpolatedText<ParsedExpr>; -type ParsedTextContents = InterpolatedTextContents<ParsedExpr>; +type ParsedText<E> = InterpolatedText<Expr<E>>; +type ParsedTextContents<E> = InterpolatedTextContents<Expr<E>>; pub type ParseError = pest::error::Error<Rule>; @@ -162,7 +160,7 @@ impl crate::Builtin { // Trim the shared indent off of a vec of lines, as defined by the Dhall semantics of multiline // literals. -fn trim_indent(lines: &mut Vec<ParsedText>) { +fn trim_indent<E: Clone>(lines: &mut Vec<ParsedText<E>>) { let is_indent = |c: char| c == ' ' || c == '\t'; // There is at least one line so this is safe @@ -250,9 +248,9 @@ impl Parsers { )) } - fn double_quote_literal( + fn double_quote_literal<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ParsedText> { + ) -> ParseResult<ParsedText<E>> { Ok(parse_children!(input; [double_quote_chunk(chunks)..] => { chunks.collect() @@ -260,9 +258,9 @@ impl Parsers { )) } - fn double_quote_chunk( + fn double_quote_chunk<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ParsedTextContents> { + ) -> ParseResult<ParsedTextContents<E>> { Ok(parse_children!(input; [interpolation(e)] => { InterpolatedTextContents::Expr(e) @@ -351,17 +349,17 @@ impl Parsers { Ok(input.as_str()) } - fn single_quote_literal( + fn single_quote_literal<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ParsedText> { + ) -> ParseResult<ParsedText<E>> { Ok(parse_children!(input; [single_quote_continue(lines)] => { - let newline: ParsedText = "\n".to_string().into(); + let newline: ParsedText<E> = "\n".to_string().into(); - let mut lines: Vec<ParsedText> = lines + let mut lines: Vec<ParsedText<E>> = lines .into_iter() .rev() - .map(|l| l.into_iter().rev().collect::<ParsedText>()) + .map(|l| l.into_iter().rev().collect::<ParsedText<E>>()) .collect(); trim_indent(&mut lines); @@ -370,7 +368,7 @@ impl Parsers { .into_iter() .intersperse(newline) .flat_map(InterpolatedText::into_iter) - .collect::<ParsedText>() + .collect::<ParsedText<E>>() } )) } @@ -387,16 +385,18 @@ impl Parsers { ) -> ParseResult<&'a str> { Ok("${") } - fn interpolation(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn interpolation<E: Clone>( + input: ParseInput<Rule>, + ) -> ParseResult<Expr<E>> { Ok(parse_children!(input; [expression(e)] => e )) } // Returns a vec of lines in reversed order, where each line is also in reversed order. - fn single_quote_continue( + fn single_quote_continue<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<Vec<Vec<ParsedTextContents>>> { + ) -> ParseResult<Vec<Vec<ParsedTextContents<E>>>> { Ok(parse_children!(input; [interpolation(c), single_quote_continue(lines)] => { let c = InterpolatedTextContents::Expr(c); @@ -435,7 +435,7 @@ impl Parsers { )) } - fn builtin(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn builtin<E: Clone>(input: ParseInput<Rule>) -> ParseResult<Expr<E>> { let s = input.as_str(); let span = input.as_span(); Ok(spanned( @@ -506,7 +506,7 @@ impl Parsers { .map_err(|e| input.error(format!("{}", e))) } - fn identifier(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn identifier<E: Clone>(input: ParseInput<Rule>) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(parse_children!(input; [variable(v)] => { @@ -620,7 +620,9 @@ impl Parsers { }) } - fn http_raw(input: ParseInput<Rule>) -> ParseResult<URL<ParsedExpr>> { + fn http_raw<E: Clone>( + input: ParseInput<Rule>, + ) -> ParseResult<URL<Expr<E>>> { Ok(parse_children!(input; [scheme(sch), authority(auth), path(p)] => URL { scheme: sch, @@ -647,7 +649,7 @@ impl Parsers { Ok(input.as_str().to_owned()) } - fn http(input: ParseInput<Rule>) -> ParseResult<URL<ParsedExpr>> { + fn http<E: Clone>(input: ParseInput<Rule>) -> ParseResult<URL<Expr<E>>> { Ok(parse_children!(input; [http_raw(url)] => url, [http_raw(url), import_expression(e)] => @@ -696,9 +698,9 @@ impl Parsers { Ok(()) } - fn import_type( + fn import_type<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ImportLocation<ParsedExpr>> { + ) -> ParseResult<ImportLocation<Expr<E>>> { Ok(parse_children!(input; [missing(_)] => { ImportLocation::Missing @@ -725,9 +727,9 @@ impl Parsers { Ok(Hash::SHA256(hex::decode(hash).unwrap())) } - fn import_hashed( + fn import_hashed<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<crate::Import<ParsedExpr>> { + ) -> ParseResult<crate::Import<Expr<E>>> { Ok(parse_children!(input; [import_type(location)] => crate::Import {mode: ImportMode::Code, location, hash: None }, @@ -743,7 +745,7 @@ impl Parsers { Ok(()) } - fn import(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn import<E: Clone>(input: ParseInput<Rule>) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(parse_children!(input; [import_hashed(imp)] => { @@ -792,7 +794,9 @@ impl Parsers { Ok(()) } - fn empty_list_literal(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn empty_list_literal<E: Clone>( + input: ParseInput<Rule>, + ) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(parse_children!(input; [application_expression(e)] => { @@ -801,7 +805,7 @@ impl Parsers { )) } - fn expression(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn expression<E: Clone>(input: ParseInput<Rule>) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(parse_children!(input; [lambda(()), label(l), expression(typ), @@ -843,9 +847,9 @@ impl Parsers { )) } - fn let_binding( + fn let_binding<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<(Label, Option<ParsedExpr>, ParsedExpr)> { + ) -> ParseResult<(Label, Option<Expr<E>>, Expr<E>)> { Ok(parse_children!(input; [label(name), expression(annot), expression(expr)] => (name, Some(annot), expr), @@ -862,12 +866,12 @@ impl Parsers { } #[prec_climb(application_expression, PRECCLIMBER)] - fn operator_expression( + fn operator_expression<E: Clone>( input: ParseInput<Rule>, - l: ParsedExpr, + l: Expr<E>, op: Pair<Rule>, - r: ParsedExpr, - ) -> ParseResult<ParsedExpr> { + r: Expr<E>, + ) -> ParseResult<Expr<E>> { use crate::BinOp::*; use Rule::*; let op = match op.as_rule() { @@ -894,9 +898,9 @@ impl Parsers { Ok(()) } - fn application_expression( + fn application_expression<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ParsedExpr> { + ) -> ParseResult<Expr<E>> { Ok(parse_children!(input; [first_application_expression(e)] => e, [first_application_expression(first), @@ -906,9 +910,9 @@ impl Parsers { )) } - fn first_application_expression( + fn first_application_expression<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ParsedExpr> { + ) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(parse_children!(input; [Some_(()), import_expression(e)] => { @@ -924,14 +928,18 @@ impl Parsers { )) } - fn import_expression(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn import_expression<E: Clone>( + input: ParseInput<Rule>, + ) -> ParseResult<Expr<E>> { Ok(parse_children!(input; [selector_expression(e)] => e, [import(e)] => e, )) } - fn selector_expression(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn selector_expression<E: Clone>( + input: ParseInput<Rule>, + ) -> ParseResult<Expr<E>> { Ok(parse_children!(input; [primitive_expression(e)] => e, [primitive_expression(first), selector(rest)..] => { @@ -949,7 +957,7 @@ impl Parsers { Ok(parse_children!(input; [label(l)] => Either::Left(l), [labels(ls)] => Either::Right(ls), - [expression(_e)] => unimplemented!("selection by expression"), // TODO + // [expression(_e)] => unimplemented!("selection by expression"), // TODO )) } @@ -959,9 +967,9 @@ impl Parsers { )) } - fn primitive_expression( + fn primitive_expression<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ParsedExpr> { + ) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(parse_children!(input; [double_literal(n)] => spanned(span, DoubleLit(n)), @@ -979,21 +987,23 @@ impl Parsers { )) } - fn empty_record_literal( + fn empty_record_literal<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ParsedExpr> { + ) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(spanned(span, RecordLit(Default::default()))) } - fn empty_record_type(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn empty_record_type<E: Clone>( + input: ParseInput<Rule>, + ) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(spanned(span, RecordType(Default::default()))) } - fn non_empty_record_type_or_literal( + fn non_empty_record_type_or_literal<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ParsedExpr> { + ) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(parse_children!(input; [label(first_label), non_empty_record_type(rest)] => { @@ -1009,9 +1019,9 @@ impl Parsers { )) } - fn non_empty_record_type( + fn non_empty_record_type<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<(ParsedExpr, DupTreeMap<Label, ParsedExpr>)> { + ) -> ParseResult<(Expr<E>, DupTreeMap<Label, Expr<E>>)> { Ok(parse_children!(input; [expression(expr), record_type_entry(entries)..] => { (expr, entries.collect()) @@ -1019,17 +1029,17 @@ impl Parsers { )) } - fn record_type_entry( + fn record_type_entry<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<(Label, ParsedExpr)> { + ) -> ParseResult<(Label, Expr<E>)> { Ok(parse_children!(input; [label(name), expression(expr)] => (name, expr) )) } - fn non_empty_record_literal( + fn non_empty_record_literal<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<(ParsedExpr, DupTreeMap<Label, ParsedExpr>)> { + ) -> ParseResult<(Expr<E>, DupTreeMap<Label, Expr<E>>)> { Ok(parse_children!(input; [expression(expr), record_literal_entry(entries)..] => { (expr, entries.collect()) @@ -1037,15 +1047,15 @@ impl Parsers { )) } - fn record_literal_entry( + fn record_literal_entry<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<(Label, ParsedExpr)> { + ) -> ParseResult<(Label, Expr<E>)> { Ok(parse_children!(input; [label(name), expression(expr)] => (name, expr) )) } - fn union_type(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn union_type<E: Clone>(input: ParseInput<Rule>) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(parse_children!(input; [empty_union_type(_)] => { @@ -1061,18 +1071,18 @@ impl Parsers { Ok(()) } - fn union_type_entry( + fn union_type_entry<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<(Label, Option<ParsedExpr>)> { + ) -> ParseResult<(Label, Option<Expr<E>>)> { Ok(parse_children!(input; [label(name), expression(expr)] => (name, Some(expr)), [label(name)] => (name, None), )) } - fn non_empty_list_literal( + fn non_empty_list_literal<E: Clone>( input: ParseInput<Rule>, - ) -> ParseResult<ParsedExpr> { + ) -> ParseResult<Expr<E>> { let span = input.as_span(); Ok(parse_children!(input; [expression(items)..] => spanned( @@ -1082,14 +1092,16 @@ impl Parsers { )) } - fn final_expression(input: ParseInput<Rule>) -> ParseResult<ParsedExpr> { + fn final_expression<E: Clone>( + input: ParseInput<Rule>, + ) -> ParseResult<Expr<E>> { Ok(parse_children!(input; [expression(e), EOI(_)] => e )) } } -pub fn parse_expr(s: &str) -> ParseResult<ParsedExpr> { +pub fn parse_expr<E: Clone>(s: &str) -> ParseResult<Expr<E>> { let input = ParseInput::parse(s, Rule::final_expression)?; Parsers::final_expression(input) } |