From ecf0ff4d054f11c79ec0ddbbdf45f3dfcf9fc8d7 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 23 Oct 2019 00:14:43 +0200 Subject: =?UTF-8?q?Introduce=20a=20set=20of=20macros=20for=20writing=20fun?= =?UTF-8?q?ctions=20more=20concisely=20=F0=9F=8E=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/func.rs | 172 ------------------------------------------------------------ 1 file changed, 172 deletions(-) delete mode 100644 src/func.rs (limited to 'src/func.rs') diff --git a/src/func.rs b/src/func.rs deleted file mode 100644 index 05bbe83d..00000000 --- a/src/func.rs +++ /dev/null @@ -1,172 +0,0 @@ -//! Dynamic typesetting functions. - -use std::any::Any; -use std::collections::HashMap; -use std::fmt::{self, Debug, Formatter}; - -use crate::layout::{Layout, LayoutContext, Alignment, LayoutResult, MultiLayout}; -use crate::parsing::{ParseContext, ParseResult}; -use crate::style::TextStyle; -use crate::syntax::{FuncHeader, SyntaxTree}; - -/// Typesetting function types. -/// -/// These types have to be able to parse tokens into themselves and store the -/// relevant information from the parsing to do their role in typesetting later. -/// -/// The trait `FunctionBounds` is automatically implemented for types which can -/// be used as functions, that is they fulfill the bounds `Debug + PartialEq + -/// 'static`. -pub trait Function: FunctionBounds { - /// Parse the header and body into this function given a context. - fn parse(header: &FuncHeader, body: Option<&str>, ctx: ParseContext) -> ParseResult - where Self: Sized; - - /// Layout this function given a context. - /// - /// Returns optionally the resulting layout and a new context if changes to - /// the context should be made. - fn layout(&self, ctx: LayoutContext) -> LayoutResult; -} - -impl PartialEq for dyn Function { - fn eq(&self, other: &dyn Function) -> bool { - self.help_eq(other) - } -} - -/// A helper trait that describes requirements for types that can implement -/// [`Function`]. -/// -/// Automatically implemented for all types which fulfill to the bounds `Debug + -/// PartialEq + 'static`. There should be no need to implement this manually. -pub trait FunctionBounds: Debug { - /// Cast self into `Any`. - fn help_cast_as_any(&self) -> &dyn Any; - - /// Compare self with another function. - fn help_eq(&self, other: &dyn Function) -> bool; -} - -impl FunctionBounds for T -where T: Debug + PartialEq + 'static -{ - fn help_cast_as_any(&self) -> &dyn Any { - self - } - - fn help_eq(&self, other: &dyn Function) -> bool { - if let Some(other) = other.help_cast_as_any().downcast_ref::() { - self == other - } else { - false - } - } -} - -/// A sequence of commands requested for execution by a function. -#[derive(Debug)] -pub struct CommandList<'a> { - pub commands: Vec>, -} - -impl<'a> CommandList<'a> { - /// Create an empty command list. - pub fn new() -> CommandList<'a> { - CommandList { commands: vec![] } - } - - /// Create a command list with commands from a vector. - pub fn from_vec(commands: Vec>) -> CommandList<'a> { - CommandList { commands } - } - - /// Add a command to the sequence. - pub fn add(&mut self, command: Command<'a>) { - self.commands.push(command); - } - - /// Whether there are any commands in this sequence. - pub fn is_empty(&self) -> bool { - self.commands.is_empty() - } -} - -impl<'a> IntoIterator for CommandList<'a> { - type Item = Command<'a>; - type IntoIter = std::vec::IntoIter>; - - fn into_iter(self) -> Self::IntoIter { - self.commands.into_iter() - } -} - -impl<'a> IntoIterator for &'a CommandList<'a> { - type Item = &'a Command<'a>; - type IntoIter = std::slice::Iter<'a, Command<'a>>; - - fn into_iter(self) -> Self::IntoIter { - self.commands.iter() - } -} - -/// Commands requested for execution by functions. -#[derive(Debug)] -pub enum Command<'a> { - Layout(&'a SyntaxTree), - Add(Layout), - AddMany(MultiLayout), - AddFlex(Layout), - SetAlignment(Alignment), - SetStyle(TextStyle), - FinishLayout, - FinishFlexRun, -} - -macro_rules! commands { - ($($x:expr),*$(,)*) => ({ - $crate::func::CommandList::from_vec(vec![$($x,)*]) - }); -} - -/// A map from identifiers to functions. -pub struct Scope { - parsers: HashMap>, -} - -/// A function which parses a function invocation into a function type. -type ParseFunc = dyn Fn(&FuncHeader, Option<&str>, ParseContext) -> ParseResult>; - -impl Scope { - /// Create a new empty scope. - pub fn new() -> Scope { - Scope { - parsers: HashMap::new(), - } - } - - /// Create a new scope with the standard functions contained. - pub fn with_std() -> Scope { - crate::library::std() - } - - /// Add a function type to the scope giving it a name. - pub fn add(&mut self, name: &str) { - self.parsers.insert( - name.to_owned(), - Box::new(|h, b, c| F::parse(h, b, c).map(|func| Box::new(func) as Box)), - ); - } - - /// Return the parser with the given name if there is one. - pub(crate) fn get_parser(&self, name: &str) -> Option<&ParseFunc> { - self.parsers.get(name).map(|x| &**x) - } -} - -impl Debug for Scope { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "Scope ")?; - write!(f, "{:?}", self.parsers.keys()) - } -} -- cgit v1.2.3