summaryrefslogtreecommitdiff
path: root/src/eval/args.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-07-02 19:59:52 +0200
committerLaurenz <laurmaedje@gmail.com>2023-07-02 20:07:43 +0200
commitebfdb1dafa430786db10dad2ef7d5467c1bdbed1 (patch)
tree2bbc24ddb4124c4bb14dec0e536129d4de37b056 /src/eval/args.rs
parent3ab19185093d7709f824b95b979060ce125389d8 (diff)
Move everything into `crates/` directory
Diffstat (limited to 'src/eval/args.rs')
-rw-r--r--src/eval/args.rs216
1 files changed, 0 insertions, 216 deletions
diff --git a/src/eval/args.rs b/src/eval/args.rs
deleted file mode 100644
index da29eeaf..00000000
--- a/src/eval/args.rs
+++ /dev/null
@@ -1,216 +0,0 @@
-use std::fmt::{self, Debug, Formatter};
-
-use ecow::{eco_format, EcoVec};
-
-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;
-
-/// Evaluated arguments to a function.
-#[derive(Clone, PartialEq, Hash)]
-pub struct Args {
- /// The span of the whole argument list.
- pub span: Span,
- /// The positional and named arguments.
- pub items: EcoVec<Arg>,
-}
-
-/// An argument to a function call: `12` or `draw: false`.
-#[derive(Clone, PartialEq, Hash)]
-pub struct Arg {
- /// The span of the whole argument.
- pub span: Span,
- /// The name of the argument (`None` for positional arguments).
- pub name: Option<Str>,
- /// The value of the argument.
- pub value: Spanned<Value>,
-}
-
-impl Args {
- /// Create positional arguments from a span and values.
- 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.into_value(), span),
- })
- .collect();
- Self { span, items }
- }
-
- /// Push a positional argument.
- pub fn push(&mut self, span: Span, value: Value) {
- self.items.push(Arg {
- span: self.span,
- name: None,
- value: Spanned::new(value, span),
- })
- }
-
- /// Consume and cast the first positional argument if there is one.
- pub fn eat<T>(&mut self) -> SourceResult<Option<T>>
- where
- 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::from_value(value).at(span).map(Some);
- }
- }
- Ok(None)
- }
-
- /// Consume n positional arguments if possible.
- pub fn consume(&mut self, n: usize) -> SourceResult<Vec<Arg>> {
- let mut list = vec![];
-
- let mut i = 0;
- while i < self.items.len() && list.len() < n {
- if self.items[i].name.is_none() {
- list.push(self.items.remove(i));
- } else {
- i += 1;
- }
- }
-
- if list.len() < n {
- bail!(self.span, "not enough arguments");
- }
-
- Ok(list)
- }
-
- /// Consume and cast the first positional argument.
- ///
- /// Returns a `missing argument: {what}` error if no positional argument is
- /// left.
- pub fn expect<T>(&mut self, what: &str) -> SourceResult<T>
- where
- T: FromValue<Spanned<Value>>,
- {
- match self.eat()? {
- Some(v) => Ok(v),
- 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: FromValue<Spanned<Value>>,
- {
- for (i, slot) in self.items.iter().enumerate() {
- if slot.name.is_none() && T::castable(&slot.value.v) {
- let value = self.items.remove(i).value;
- let span = value.span;
- return T::from_value(value).at(span).map(Some);
- }
- }
- Ok(None)
- }
-
- /// Find and consume all castable positional arguments.
- pub fn all<T>(&mut self) -> SourceResult<Vec<T>>
- where
- T: FromValue<Spanned<Value>>,
- {
- 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) -> SourceResult<Option<T>>
- where
- 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.
- let mut i = 0;
- let mut found = None;
- while i < self.items.len() {
- if self.items[i].name.as_deref() == Some(name) {
- let value = self.items.remove(i).value;
- let span = value.span;
- found = Some(T::from_value(value).at(span)?);
- } else {
- i += 1;
- }
- }
- Ok(found)
- }
-
- /// Same as named, but with fallback to find.
- pub fn named_or_find<T>(&mut self, name: &str) -> SourceResult<Option<T>>
- where
- T: FromValue<Spanned<Value>>,
- {
- 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 {
- span: self.span,
- items: std::mem::take(&mut self.items),
- }
- }
-
- /// Return an "unexpected argument" error if there is any remaining
- /// argument.
- pub fn finish(self) -> SourceResult<()> {
- if let Some(arg) = self.items.first() {
- match &arg.name {
- Some(name) => bail!(arg.span, "unexpected argument: {name}"),
- _ => bail!(arg.span, "unexpected argument"),
- }
- }
- Ok(())
- }
-
- /// Extract the positional arguments as an array.
- pub fn to_pos(&self) -> Array {
- self.items
- .iter()
- .filter(|item| item.name.is_none())
- .map(|item| item.value.v.clone())
- .collect()
- }
-
- /// Extract the named arguments as a dictionary.
- pub fn to_named(&self) -> Dict {
- self.items
- .iter()
- .filter_map(|item| item.name.clone().map(|name| (name, item.value.v.clone())))
- .collect()
- }
-}
-
-impl Debug for Args {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- let pieces: Vec<_> =
- self.items.iter().map(|arg| eco_format!("{arg:?}")).collect();
- f.write_str(&pretty_array_like(&pieces, false))
- }
-}
-
-impl Debug for Arg {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- if let Some(name) = &self.name {
- f.write_str(name)?;
- f.write_str(": ")?;
- }
- Debug::fmt(&self.value.v, f)
- }
-}