From 2467cd6272c13b618ad53c5dadff5b8c8e7885bf Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 4 Aug 2020 13:48:07 +0200 Subject: =?UTF-8?q?Refactor=20function=20parsing=20=E2=99=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/func.rs | 138 +++++++++++++----------------------------------------------- 1 file changed, 29 insertions(+), 109 deletions(-) (limited to 'src/func.rs') diff --git a/src/func.rs b/src/func.rs index 09870895..57dad103 100644 --- a/src/func.rs +++ b/src/func.rs @@ -2,25 +2,31 @@ /// Useful things for creating functions. pub mod prelude { + pub use async_trait::async_trait; pub use crate::layout::prelude::*; + pub use crate::layout::Commands; pub use crate::layout::Command::{self, *}; pub use crate::style::*; - pub use crate::syntax::prelude::*; - pub use super::{expect_no_body, parse_maybe_body, OptionExt}; + pub use crate::syntax::expr::*; + pub use crate::syntax::parsing::{ + parse, FuncArgs, FuncBody, FuncCall, FuncHeader, ParseState, + }; + pub use crate::syntax::span::{Span, SpanVec, Spanned}; + pub use crate::syntax::tree::{DynamicNode, SyntaxNode, SyntaxTree}; + pub use crate::syntax::value::*; + pub use crate::{Pass, Feedback}; + pub use super::*; } -use crate::syntax::parsing::{parse, ParseState}; -use crate::syntax::span::{Span, Spanned}; -use crate::syntax::tree::SyntaxTree; -use crate::Feedback; +use prelude::*; /// Extra methods on `Option`s used for function argument parsing. pub trait OptionExt: Sized { - /// Calls `f` with `val` if this is `Some(val)`. + /// Call `f` with `val` if this is `Some(val)`. fn with(self, f: impl FnOnce(T)); - /// Reports an error about a missing argument with the given name and span - /// if the option is `None`. + /// Report an error about a missing argument with the given name and span if + /// the option is `None`. fn or_missing(self, span: Span, arg: &str, f: &mut Feedback) -> Self; } @@ -39,8 +45,19 @@ impl OptionExt for Option { } } -/// Parses a function's body if there is one or returns `None` otherwise. -pub fn parse_maybe_body( +/// Generate `unexpected argument` errors for all remaining arguments. +pub fn drain_args(args: FuncArgs, f: &mut Feedback) { + for arg in args.pos.0 { + error!(@f, arg.span, "unexpected argument"); + } + + for arg in args.key.0 { + error!(@f, arg.span, "unexpected argument"); + } +} + +/// Parse a function's body if there is one or return `None` otherwise. +pub fn parse_body_maybe( body: Option>, state: &ParseState, f: &mut Feedback, @@ -52,106 +69,9 @@ pub fn parse_maybe_body( }) } -/// Generates an error if there is function body even though none was expected. +/// Generate an error if there is function body even though none was expected. pub fn expect_no_body(body: Option>, f: &mut Feedback) { if let Some(body) = body { error!(@f, body.span, "unexpected body"); } } - -/// Implement a custom function concisely. -/// -/// # Examples -/// Look at the source code of the `library` module for examples on how the -/// macro works. -#[macro_export] -macro_rules! function { - // Entry point. - ($(#[$outer:meta])* $v:vis $storage:ident $name:ident $($r:tt)*) => { - function!(@def($name) $(#[$outer])* $v $storage $name $($r)*); - }; - (@def($name:ident) $definition:item $($r:tt)*) => { - $definition - function!(@meta($name) $($r)*); - }; - - // Metadata. - (@meta($name:ident) type Meta = $meta:ty; $($r:tt)*) => { - function!(@parse($name, $meta) $($r)*); - }; - (@meta($name:ident) $($r:tt)*) => { - function!(@parse($name, ()) $($r)*); - }; - - // Parse trait. - (@parse($($a:tt)*) parse(default) $($r:tt)*) => { - function!(@parse($($a)*) parse(_h, _b, _c, _f, _m) { Default::default() } $($r)*); - }; - (@parse($($a:tt)*) parse($h:ident, $b:ident, $c:ident, $f:ident) $($r:tt)* ) => { - function!(@parse($($a)*) parse($h, $b, $c, $f, _metadata) $($r)*); - }; - (@parse($name:ident, $meta:ty) parse( - $header:ident, - $body:ident, - $state:ident, - $feedback:ident, - $metadata:ident - ) $code:block $($r:tt)*) => { - impl $crate::syntax::parsing::ParseCall for $name { - type Meta = $meta; - - fn parse( - #[allow(unused)] mut call: $crate::syntax::parsing::FuncCall, - #[allow(unused)] $state: &$crate::syntax::parsing::ParseState, - #[allow(unused)] $metadata: Self::Meta, - ) -> $crate::Pass - where - Self: Sized, - { - let mut feedback = $crate::Feedback::new(); - #[allow(unused)] let $header = &mut call.header; - #[allow(unused)] let $body = call.body; - #[allow(unused)] let $feedback = &mut feedback; - - let func = $code; - - for arg in call.header.args.pos.0 { - error!(@feedback, arg.span, "unexpected argument"); - } - - for arg in call.header.args.key.0 { - error!(@feedback, arg.span, "unexpected argument"); - } - - $crate::Pass::new(func, feedback) - } - } - - function!(@layout($name) $($r)*); - }; - - (@layout($name:ident) layout( - $this:ident, - $ctx:ident, - $feedback:ident - ) $code:block) => { - impl $crate::layout::Layout for $name { - fn layout<'a, 'b, 't>( - #[allow(unused)] &'a $this, - #[allow(unused)] mut $ctx: $crate::layout::LayoutContext<'b>, - ) -> $crate::DynFuture<'t, $crate::Pass<$crate::layout::Commands<'a>>> - where - 'a: 't, - 'b: 't, - Self: 't, - { - Box::pin(async move { - let mut feedback = $crate::Feedback::new(); - #[allow(unused)] let $feedback = &mut feedback; - let commands = $code; - $crate::Pass::new(commands, feedback) - }) - } - } - }; -} -- cgit v1.2.3