diff options
Diffstat (limited to 'src/func/args.rs')
| -rw-r--r-- | src/func/args.rs | 215 |
1 files changed, 0 insertions, 215 deletions
diff --git a/src/func/args.rs b/src/func/args.rs deleted file mode 100644 index d1d49b6a..00000000 --- a/src/func/args.rs +++ /dev/null @@ -1,215 +0,0 @@ -//! Parsing, storing and deduplication of function arguments. - -use super::prelude::*; -use Expression::*; - -/// Provides a convenient interface to parse the arguments to a function. -pub struct ArgParser<'a> { - args: &'a FuncArgs, - positional_index: usize, -} - -impl<'a> ArgParser<'a> { - pub fn new(args: &'a FuncArgs) -> ArgParser<'a> { - ArgParser { - args, - positional_index: 0, - } - } - - /// Get the next positional argument of the given type. - /// - /// If there are no more arguments or the type is wrong, - /// this will return an error. - pub fn get_pos<T>(&mut self) -> ParseResult<Spanned<T::Output>> - where T: Argument<'a> { - Self::expected(self.get_pos_opt::<T>()?) - } - - /// Get the next positional argument if there is any. - /// - /// If the argument is of the wrong type, this will return an error. - pub fn get_pos_opt<T>(&mut self) -> ParseResult<Option<Spanned<T::Output>>> - where T: Argument<'a> { - let arg = self.args.positional - .get(self.positional_index) - .map(T::from_expr) - .transpose(); - - if let Ok(Some(_)) = arg { - self.positional_index += 1; - } - - arg - } - - /// Get a keyword argument with the given key and type. - pub fn get_key<T>(&mut self, key: &str) -> ParseResult<Spanned<T::Output>> - where T: Argument<'a> { - Self::expected(self.get_key_opt::<T>(key)?) - } - - /// Get a keyword argument with the given key and type if it is present. - pub fn get_key_opt<T>(&mut self, key: &str) -> ParseResult<Option<Spanned<T::Output>>> - where T: Argument<'a> { - self.args.keyword.iter() - .find(|entry| entry.val.0.val == key) - .map(|entry| T::from_expr(&entry.val.1)) - .transpose() - } - - /// Assert that there are no positional arguments left. Returns an error - /// otherwise. - pub fn done(&self) -> ParseResult<()> { - if self.positional_index == self.args.positional.len() { - Ok(()) - } else { - error!(unexpected_argument); - } - } - - /// Covert an option to a result with an error on `None`. - fn expected<T>(val: Option<Spanned<T::Output>>) -> ParseResult<Spanned<T::Output>> - where T: Argument<'a> { - val.ok_or_else(|| error!(@"expected {}", T::ERROR_MESSAGE)) - } -} - -/// A kind of argument. -pub trait Argument<'a> { - type Output; - const ERROR_MESSAGE: &'static str; - - fn from_expr(expr: &'a Spanned<Expression>) -> ParseResult<Spanned<Self::Output>>; -} - -macro_rules! arg { - ($type:ident, $err:expr, $doc:expr, $output:ty, $wanted:pat => $converted:expr) => ( - #[doc = $doc] - #[doc = " argument for use with the [`ArgParser`]."] - pub struct $type; - impl<'a> Argument<'a> for $type { - type Output = $output; - const ERROR_MESSAGE: &'static str = $err; - - fn from_expr(expr: &'a Spanned<Expression>) -> ParseResult<Spanned<Self::Output>> { - #[allow(unreachable_code)] - match &expr.val { - $wanted => Ok(Spanned::new($converted, expr.span)), - _ => error!("expected {}", $err), - } - } - } - ); -} - -arg!(ArgExpr, "expression", "A generic expression", &'a Expression, expr => &expr); -arg!(ArgIdent, "identifier", "An identifier (e.g. `horizontal`)", &'a str, Ident(s) => s.as_str()); -arg!(ArgStr, "string", "A string (e.g. `\"Hello\"`)", &'a str, Str(s) => s.as_str()); -arg!(ArgNum, "number", "A number (e.g. `5.4`)", f64, Num(n) => *n); -arg!(ArgSize, "size", "A size (e.g. `12pt`)", crate::size::Size, Size(s) => *s); -arg!(ArgBool, "bool", "A boolean (`true` or `false`)", bool, Bool(b) => *b); - -/// An argument key which identifies a layouting axis. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum AxisKey { - Primary, - Secondary, - Vertical, - Horizontal, -} - -impl AxisKey { - /// The generic version of this axis key in the given system of axes. - pub fn generic(&self, axes: LayoutAxes) -> GenericAxisKind { - match self { - Primary => GenericAxisKind::Primary, - Secondary => GenericAxisKind::Secondary, - Vertical => axes.vertical(), - Horizontal => axes.horizontal(), - } - } - - /// The specific version of this axis key in the given system of axes. - pub fn specific(&self, axes: LayoutAxes) -> SpecificAxisKind { - match self { - Primary => axes.primary(), - Secondary => axes.secondary(), - Vertical => SpecificAxisKind::Vertical, - Horizontal => SpecificAxisKind::Horizontal, - } - } -} - -/// An argument key which identifies a target alignment. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum AlignmentKey { - Left, - Top, - Right, - Bottom, - Origin, - Center, - End, -} - -impl AlignmentKey { - /// The generic axis this alignment key corresopnds to in the given system - /// of layouting axes. Falls back to `default` if the alignment is generic. - pub fn axis(&self, axes: LayoutAxes, default: GenericAxisKind) -> GenericAxisKind { - use AlignmentKey::*; - match self { - Origin | Center | End => default, - Left | Right => axes.horizontal(), - Top | Bottom => axes.vertical(), - } - } - - /// The generic version of this alignment in the given system of layouting - /// axes. Returns an error if the alignment is invalid for the given axis. - pub fn generic(&self, axes: LayoutAxes, axis: GenericAxisKind) -> LayoutResult<Alignment> { - use AlignmentKey::*; - - let horizontal = axis == axes.horizontal(); - Ok(match self { - Origin => Alignment::Origin, - Center => Alignment::Center, - End => Alignment::End, - Left if horizontal => axes.left(), - Right if horizontal => axes.right(), - Top if !horizontal => axes.top(), - Bottom if !horizontal => axes.bottom(), - _ => error!( - "invalid alignment `{}` for {} axis", - format!("{:?}", self).to_lowercase(), - format!("{:?}", axis).to_lowercase() - ) - }) - } - - /// The specific version of this alignment in the given system of layouting - /// axes. - pub fn specific(&self, axes: LayoutAxes, axis: SpecificAxisKind) -> AlignmentKey { - use AlignmentKey::*; - match (self, axis) { - (Origin, SpecificAxisKind::Horizontal) => Left, - (End, SpecificAxisKind::Horizontal) => Right, - (Origin, SpecificAxisKind::Vertical) => Top, - (End, SpecificAxisKind::Vertical) => Bottom, - _ => *self, - } - } -} - -/// An argument key which identifies a margin or padding target. -/// -/// A is the axis type used. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum PaddingKey<A> { - /// All four sides should have the specified padding. - All, - /// Both sides of the given axis should have the specified padding. - Axis(A), - /// Only the given side of the given axis should have the specified padding. - AxisAligned(A, AlignmentKey), -} |
