summaryrefslogtreecommitdiff
path: root/src/eval/args.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-06-06 21:13:59 +0200
committerLaurenz <laurmaedje@gmail.com>2023-06-06 22:06:16 +0200
commitfd417da04f7ca4b995de7f6510abafd3e9c31307 (patch)
tree3675529c75ca7363701ac8ea306de2cc1d3cbcb3 /src/eval/args.rs
parent168bdf35bd773e67343c965cb473492cc5cae9e7 (diff)
Improve value casting infrastructure
Diffstat (limited to 'src/eval/args.rs')
-rw-r--r--src/eval/args.rs43
1 files changed, 22 insertions, 21 deletions
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<Item = Value>) -> Self {
+ pub fn new<T: IntoValue>(span: Span, values: impl IntoIterator<Item = T>) -> 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<T>(&mut self) -> SourceResult<Option<T>>
where
- T: Cast<Spanned<Value>>,
+ T: FromValue<Spanned<Value>>,
{
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<T>(&mut self, what: &str) -> SourceResult<T>
where
- T: Cast<Spanned<Value>>,
+ T: FromValue<Spanned<Value>>,
{
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<T>(&mut self) -> SourceResult<Option<T>>
where
- T: Cast<Spanned<Value>>,
+ T: FromValue<Spanned<Value>>,
{
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<T>(&mut self) -> SourceResult<Vec<T>>
where
- T: Cast<Spanned<Value>>,
+ T: FromValue<Spanned<Value>>,
{
let mut list = vec![];
while let Some(value) = self.find()? {
@@ -126,7 +130,7 @@ impl Args {
/// error if the conversion fails.
pub fn named<T>(&mut self, name: &str) -> SourceResult<Option<T>>
where
- T: Cast<Spanned<Value>>,
+ T: FromValue<Spanned<Value>>,
{
// 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<T>(&mut self, name: &str) -> SourceResult<Option<T>>
where
- T: Cast<Spanned<Value>>,
+ T: FromValue<Spanned<Value>>,
{
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(())
}