diff options
Diffstat (limited to 'src/eval/func.rs')
| -rw-r--r-- | src/eval/func.rs | 44 |
1 files changed, 21 insertions, 23 deletions
diff --git a/src/eval/func.rs b/src/eval/func.rs index 6d405ca4..887f7989 100644 --- a/src/eval/func.rs +++ b/src/eval/func.rs @@ -162,10 +162,7 @@ impl Args { /// /// Returns a `missing argument: {what}` error if no positional argument is /// left. - pub fn expect<T>(&mut self, what: &str) -> TypResult<T> - where - T: Cast<Spanned<Value>>, - { + pub fn expect<T: Cast>(&mut self, what: &str) -> TypResult<T> { match self.eat()? { Some(v) => Ok(v), None => bail!(self.span, "missing argument: {}", what), @@ -173,10 +170,7 @@ impl Args { } /// Consume and cast the first positional argument if there is one. - pub fn eat<T>(&mut self) -> TypResult<Option<T>> - where - T: Cast<Spanned<Value>>, - { + pub fn eat<T: Cast>(&mut self) -> TypResult<Option<T>> { for (i, slot) in self.items.iter().enumerate() { if slot.name.is_none() { let value = self.items.remove(i).value; @@ -188,33 +182,29 @@ impl Args { } /// Find and consume the first castable positional argument. - pub fn find<T>(&mut self) -> Option<T> - where - T: Cast<Spanned<Value>>, - { + pub fn find<T: Cast>(&mut self) -> TypResult<Option<T>> { for (i, slot) in self.items.iter().enumerate() { if slot.name.is_none() && T::is(&slot.value) { let value = self.items.remove(i).value; - return T::cast(value).ok(); + let span = value.span; + return T::cast(value).at(span).map(Some); } } - None + Ok(None) } /// Find and consume all castable positional arguments. - pub fn all<T>(&mut self) -> impl Iterator<Item = T> + '_ - where - T: Cast<Spanned<Value>>, - { - std::iter::from_fn(move || self.find()) + pub fn all<T: Cast>(&mut self) -> TypResult<Vec<T>> { + let mut list = vec![]; + while let Some(value) = self.find()? { + list.push(value); + } + Ok(list) } /// Cast and remove the value for the given named argument, returning an /// error if the conversion fails. - pub fn named<T>(&mut self, name: &str) -> TypResult<Option<T>> - where - T: Cast<Spanned<Value>>, - { + pub fn named<T: Cast>(&mut self, name: &str) -> TypResult<Option<T>> { // We don't quit once we have a match because when multiple matches // exist, we want to remove all of them and use the last one. let mut i = 0; @@ -231,6 +221,14 @@ impl Args { Ok(found) } + /// Same as named, but with fallback to find. + pub fn named_or_find<T: Cast>(&mut self, name: &str) -> TypResult<Option<T>> { + match self.named(name)? { + Some(value) => Ok(Some(value)), + None => self.find(), + } + } + /// Take out all arguments into a new instance. pub fn take(&mut self) -> Self { Self { |
