From fd417da04f7ca4b995de7f6510abafd3e9c31307 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 6 Jun 2023 21:13:59 +0200 Subject: Improve value casting infrastructure --- src/eval/args.rs | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'src/eval/args.rs') diff --git a/src/eval/args.rs b/src/eval/args.rs index bea2baa1..da29eeaf 100644 --- a/src/eval/args.rs +++ b/src/eval/args.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Debug, Formatter}; use ecow::{eco_format, EcoVec}; -use super::{Array, Cast, Dict, Str, Value}; +use super::{Array, Dict, FromValue, IntoValue, Str, Value}; use crate::diag::{bail, At, SourceResult}; use crate::syntax::{Span, Spanned}; use crate::util::pretty_array_like; @@ -29,10 +29,14 @@ pub struct Arg { impl Args { /// Create positional arguments from a span and values. - pub fn new(span: Span, values: impl IntoIterator) -> Self { + pub fn new(span: Span, values: impl IntoIterator) -> Self { let items = values .into_iter() - .map(|value| Arg { span, name: None, value: Spanned::new(value, span) }) + .map(|value| Arg { + span, + name: None, + value: Spanned::new(value.into_value(), span), + }) .collect(); Self { span, items } } @@ -49,13 +53,13 @@ impl Args { /// Consume and cast the first positional argument if there is one. pub fn eat(&mut self) -> SourceResult> where - T: Cast>, + T: FromValue>, { for (i, slot) in self.items.iter().enumerate() { if slot.name.is_none() { let value = self.items.remove(i).value; let span = value.span; - return T::cast(value).at(span).map(Some); + return T::from_value(value).at(span).map(Some); } } Ok(None) @@ -87,24 +91,24 @@ impl Args { /// left. pub fn expect(&mut self, what: &str) -> SourceResult where - T: Cast>, + T: FromValue>, { match self.eat()? { Some(v) => Ok(v), - None => bail!(self.span, "missing argument: {}", what), + None => bail!(self.span, "missing argument: {what}"), } } /// Find and consume the first castable positional argument. pub fn find(&mut self) -> SourceResult> where - T: Cast>, + T: FromValue>, { for (i, slot) in self.items.iter().enumerate() { - if slot.name.is_none() && T::is(&slot.value) { + if slot.name.is_none() && T::castable(&slot.value.v) { let value = self.items.remove(i).value; let span = value.span; - return T::cast(value).at(span).map(Some); + return T::from_value(value).at(span).map(Some); } } Ok(None) @@ -113,7 +117,7 @@ impl Args { /// Find and consume all castable positional arguments. pub fn all(&mut self) -> SourceResult> where - T: Cast>, + T: FromValue>, { let mut list = vec![]; while let Some(value) = self.find()? { @@ -126,7 +130,7 @@ impl Args { /// error if the conversion fails. pub fn named(&mut self, name: &str) -> SourceResult> where - T: Cast>, + T: FromValue>, { // 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. @@ -136,7 +140,7 @@ impl Args { if self.items[i].name.as_deref() == Some(name) { let value = self.items.remove(i).value; let span = value.span; - found = Some(T::cast(value).at(span)?); + found = Some(T::from_value(value).at(span)?); } else { i += 1; } @@ -147,7 +151,7 @@ impl Args { /// Same as named, but with fallback to find. pub fn named_or_find(&mut self, name: &str) -> SourceResult> where - T: Cast>, + T: FromValue>, { match self.named(name)? { Some(value) => Ok(Some(value)), @@ -167,13 +171,10 @@ impl Args { /// argument. pub fn finish(self) -> SourceResult<()> { if let Some(arg) = self.items.first() { - bail!( - arg.span, - match &arg.name { - Some(name) => eco_format!("unexpected argument: {}", name), - _ => eco_format!("unexpected argument"), - } - ) + match &arg.name { + Some(name) => bail!(arg.span, "unexpected argument: {name}"), + _ => bail!(arg.span, "unexpected argument"), + } } Ok(()) } -- cgit v1.2.3