use super::*; /// The arguments passed to a function. #[derive(Debug, Clone, PartialEq)] pub struct FuncArgs { pub pos: Vec>, pub key: Vec>, } impl FuncArgs { /// Create an empty collection of arguments. pub fn new() -> FuncArgs { FuncArgs { pos: vec![], key: vec![], } } /// Add a positional argument. pub fn add_pos(&mut self, arg: Spanned) { self.pos.push(arg); } /// Add a keyword argument. pub fn add_key(&mut self, arg: Spanned) { self.key.push(arg); } /// Force-extract the first positional argument. pub fn get_pos(&mut self) -> ParseResult { expect(self.get_pos_opt()) } /// Extract the first positional argument. pub fn get_pos_opt(&mut self) -> ParseResult> { Ok(if !self.pos.is_empty() { let spanned = self.pos.remove(0); Some(E::from_expr(spanned)?) } else { None }) } /// Iterator over positional arguments. pub fn pos(&mut self) -> std::vec::IntoIter> { let vec = std::mem::replace(&mut self.pos, vec![]); vec.into_iter() } /// Force-extract a keyword argument. pub fn get_key(&mut self, name: &str) -> ParseResult { expect(self.get_key_opt(name)) } /// Extract a keyword argument. pub fn get_key_opt(&mut self, name: &str) -> ParseResult> { Ok(if let Some(index) = self.key.iter().position(|arg| arg.v.key.v.0 == name) { let value = self.key.swap_remove(index).v.value; Some(E::from_expr(value)?) } else { None }) } /// Extract any keyword argument. pub fn get_key_next(&mut self) -> Option> { self.key.pop() } /// Iterator over all keyword arguments. pub fn keys(&mut self) -> std::vec::IntoIter> { let vec = std::mem::replace(&mut self.key, vec![]); vec.into_iter() } /// Clear the argument lists. pub fn clear(&mut self) { self.pos.clear(); self.key.clear(); } /// Whether both the positional and keyword argument lists are empty. pub fn is_empty(&self) -> bool { self.pos.is_empty() && self.key.is_empty() } } /// Extract the option expression kind from the option or return an error. fn expect(opt: ParseResult>) -> ParseResult { match opt { Ok(Some(spanned)) => Ok(spanned), Ok(None) => error!("expected {}", E::NAME), Err(e) => Err(e), } } /// A positional argument passed to a function. pub type PosArg = Expression; /// A keyword argument passed to a function. #[derive(Debug, Clone, PartialEq)] pub struct KeyArg { pub key: Spanned, pub value: Spanned, } /// Either a positional or keyword argument. #[derive(Debug, Clone, PartialEq)] pub enum DynArg { Pos(Spanned), Key(Spanned), } /// An argument or return value. #[derive(Clone, PartialEq)] pub enum Expression { Ident(Ident), Str(String), Num(f64), Size(Size), Bool(bool), } impl Display for Expression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { use Expression::*; match self { Ident(i) => write!(f, "{}", i), Str(s) => write!(f, "{:?}", s), Num(n) => write!(f, "{}", n), Size(s) => write!(f, "{}", s), Bool(b) => write!(f, "{}", b), } } } debug_display!(Expression); pub struct Tuple; pub struct Object; /// An identifier. #[derive(Clone, PartialEq)] pub struct Ident(pub String); impl Ident { pub fn new(ident: S) -> Option where S: AsRef + Into { if is_identifier(ident.as_ref()) { Some(Ident(ident.into())) } else { None } } pub fn as_str(&self) -> &str { self.0.as_str() } } impl Display for Ident { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{}", self.0) } } debug_display!(Ident); /// Kinds of expressions. pub trait ExpressionKind: Sized { const NAME: &'static str; /// Create from expression. fn from_expr(expr: Spanned) -> ParseResult; } macro_rules! kind { ($type:ty, $name:expr, $($patterns:tt)*) => { impl ExpressionKind for $type { const NAME: &'static str = $name; fn from_expr(expr: Spanned) -> ParseResult { #[allow(unreachable_patterns)] Ok(match expr.v { $($patterns)*, _ => error!("expected {}", Self::NAME), }) } } }; } kind!(Expression, "expression", e => e); kind!(Ident, "identifier", Expression::Ident(ident) => ident); kind!(String, "string", Expression::Str(string) => string); kind!(f64, "number", Expression::Num(num) => num); kind!(bool, "boolean", Expression::Bool(boolean) => boolean); kind!(Size, "size", Expression::Size(size) => size); kind!(ScaleSize, "number or size", Expression::Size(size) => ScaleSize::Absolute(size), Expression::Num(scale) => ScaleSize::Scaled(scale as f32) ); impl ExpressionKind for Spanned where T: ExpressionKind { const NAME: &'static str = T::NAME; fn from_expr(expr: Spanned) -> ParseResult> { let span = expr.span; T::from_expr(expr) .map(|v| Spanned::new(v, span)) } } impl ExpressionKind for Option where T: ExpressionKind { const NAME: &'static str = T::NAME; fn from_expr(expr: Spanned) -> ParseResult> { if let Expression::Ident(ident) = &expr.v { match ident.as_str() { "default" | "none" => return Ok(None), _ => {}, } } T::from_expr(expr).map(|v| Some(v)) } }