diff options
Diffstat (limited to 'src/func')
| -rw-r--r-- | src/func/macros.rs | 136 | ||||
| -rw-r--r-- | src/func/mod.rs | 129 |
2 files changed, 0 insertions, 265 deletions
diff --git a/src/func/macros.rs b/src/func/macros.rs deleted file mode 100644 index 764f0836..00000000 --- a/src/func/macros.rs +++ /dev/null @@ -1,136 +0,0 @@ -//! Helper types and macros for creating custom functions. - - -#[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, _e, _d, _m) {Default::default() } $($r)*); - }; - (@parse($($a:tt)*) parse($h:ident, $b:ident, $c:ident, $e:ident, $d:ident) $($r:tt)* ) => { - function!(@parse($($a)*) parse($h, $b, $c, $e, $d, _metadata) $($r)*); - }; - (@parse($name:ident, $meta:ty) parse( - $header:ident, - $body:ident, - $ctx:ident, - $errors:ident, - $decos:ident, - $metadata:ident - ) $code:block $($r:tt)*) => { - impl $crate::func::Parse for $name { - type Meta = $meta; - - fn parse( - #[allow(unused)] mut header: FuncHeader, - #[allow(unused)] $body: Option<Spanned<&str>>, - #[allow(unused)] $ctx: ParseContext, - #[allow(unused)] $metadata: Self::Meta, - ) -> Parsed<Self> where Self: Sized { - let mut errors = vec![]; - let mut decorations = vec![]; - #[allow(unused)] let $header = &mut header; - #[allow(unused)] let $errors = &mut errors; - #[allow(unused)] let $decos = &mut decorations; - let output = $code; - - for arg in header.args.into_iter() { - errors.push(err!(arg.span(); "unexpected argument")); - } - - $crate::syntax::Parsed { output, errors, decorations } - } - } - - function!(@layout($name) $($r)*); - }; - - (@layout($name:ident) layout($this:ident, $ctx:ident, $errors:ident) $code:block) => { - impl $crate::syntax::Model for $name { - fn layout<'a, 'b, 'c, 't>( - #[allow(unused)] &'a $this, - #[allow(unused)] mut $ctx: $crate::layout::LayoutContext<'b, 'c>, - ) -> $crate::syntax::DynFuture<'t, $crate::layout::Layouted<$crate::func::Commands<'a>>> - where - 'a: 't, - 'b: 't, - 'c: 't, - Self: 't, - { - Box::pin(async move { - let mut errors = vec![]; - #[allow(unused)] let $errors = &mut errors; - let output = $code; - $crate::layout::Layouted { output, errors } - }) - } - } - }; -} - -/// Parse the body of a function. -/// -/// - If the function does not expect a body, use `parse!(nope: body, errors)`. -/// - If the function can have a body, use `parse!(opt: body, ctx, errors, decos)`. -#[macro_export] -macro_rules! body { - (opt: $body:expr, $ctx:expr, $errors:expr, $decos:expr) => ({ - $body.map(|body| { - // Since the body span starts at the opening bracket of the body, we - // need to add 1 column to find out the start position of body - // content. - let start = body.span.start + Position::new(0, 1); - let parsed = $crate::syntax::parse(start, body.v, $ctx); - $errors.extend(parsed.errors); - $decos.extend(parsed.decorations); - parsed.output - }) - }); - - (nope: $body:expr, $errors:expr) => { - if let Some(body) = $body { - $errors.push($crate::err!(body.span; "unexpected body")); - } - }; -} - -/// Construct an error with optional severity and span. -/// -/// # Examples -/// ``` -/// err!(span; "the wrong {}", value); -/// err!(@Warning: span; "non-fatal!"); -/// err!("no spans here ..."); -/// ``` -#[macro_export] -macro_rules! err { - (@$severity:ident: $span:expr; $($args:tt)*) => { - $crate::syntax::Spanned { v: err!(@Error: $($args)*), span: $span } - }; - - (@$severity:ident: $($args:tt)*) => { - $crate::error::Error { - message: format!($($args)*), - severity: $crate::error::Severity::$severity, - } - }; - - ($($tts:tt)*) => { err!(@Error: $($tts)*) }; -} diff --git a/src/func/mod.rs b/src/func/mod.rs deleted file mode 100644 index b3721d91..00000000 --- a/src/func/mod.rs +++ /dev/null @@ -1,129 +0,0 @@ -//! Dynamic typesetting functions. - -use std::collections::HashMap; -use std::fmt::{self, Debug, Formatter}; - -use self::prelude::*; - -#[macro_use] -mod macros; - -/// Useful imports for creating your own functions. -pub mod prelude { - pub use super::{Scope, Parse, Command, Commands}; - pub use crate::error::Error; - pub use crate::layout::prelude::*; - pub use crate::syntax::prelude::*; - pub use crate::size::{Size, Size2D, SizeBox, ValueBox, ScaleSize, FSize, PSize}; - pub use crate::style::{LayoutStyle, PageStyle, TextStyle}; - pub use Command::*; -} - -/// Parse a function from source code. -pub trait Parse { - type Meta: Clone; - - /// Parse the header and body into this function given a context. - fn parse( - header: FuncHeader, - body: Option<Spanned<&str>>, - ctx: ParseContext, - metadata: Self::Meta, - ) -> Parsed<Self> where Self: Sized; -} - -/// A function which parses the source of a function into a model type which -/// implements [`Model`]. -type Parser = dyn Fn( - FuncHeader, - Option<Spanned<&str>>, - ParseContext, -) -> Parsed<Box<dyn Model>>; - -/// A sequence of layouting commands. -pub type Commands<'a> = Vec<Command<'a>>; - -/// Layouting commands from functions to the typesetting engine. -#[derive(Debug)] -pub enum Command<'a> { - LayoutSyntaxModel(&'a SyntaxModel), - - Add(Layout), - AddMultiple(MultiLayout), - AddSpacing(Size, SpacingKind, GenericAxis), - - FinishLine, - FinishSpace, - BreakParagraph, - BreakPage, - - SetTextStyle(TextStyle), - SetPageStyle(PageStyle), - SetAlignment(LayoutAlignment), - SetAxes(LayoutAxes), -} - -/// A map from identifiers to function parsers. -pub struct Scope { - parsers: HashMap<String, Box<Parser>>, - fallback: Box<Parser> -} - -impl Scope { - /// Create a new empty scope with a fallback parser that is invoked when no - /// match is found. - pub fn new<F>() -> Scope - where F: Parse<Meta=()> + Model + 'static { - Scope { - parsers: HashMap::new(), - fallback: parser::<F>(()), - } - } - - /// Create a new scope with the standard functions contained. - pub fn with_std() -> Scope { - crate::library::std() - } - - /// Associate the given name with a type that is parseable into a function. - pub fn add<F>(&mut self, name: &str) - where F: Parse<Meta=()> + Model + 'static { - self.add_with_meta::<F>(name, ()); - } - - /// Add a parseable type with additional metadata that is given to the - /// parser (other than the default of `()`). - pub fn add_with_meta<F>(&mut self, name: &str, metadata: <F as Parse>::Meta) - where F: Parse + Model + 'static { - self.parsers.insert( - name.to_owned(), - parser::<F>(metadata), - ); - } - - /// Return the parser with the given name if there is one. - pub fn get_parser(&self, name: &str) -> Result<&Parser, &Parser> { - self.parsers.get(name) - .map(|x| &**x) - .ok_or_else(|| &*self.fallback) - } - - /// Return the fallback parser. - pub fn get_fallback_parser(&self) -> &Parser { - &*self.fallback - } -} - -impl Debug for Scope { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "Scope ")?; - write!(f, "{:?}", self.parsers.keys()) - } -} - -fn parser<F>(metadata: <F as Parse>::Meta) -> Box<Parser> where F: Parse + Model + 'static { - Box::new(move |h, b, c| { - F::parse(h, b, c, metadata.clone()) - .map(|model| Box::new(model) as Box<dyn Model>) - }) -} |
