microcad_lang/value/
argument_value_list.rs

1// Copyright © 2024-2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! *Argument value list* evaluation entity.
5
6use crate::{eval::*, src_ref::*, value::*};
7use derive_more::Deref;
8
9/// Collection of *argument values* (e.g. `( x=1, y=2 )`).
10///
11/// Also provides methods to find a matching call
12/// between it and a given *parameter list*.
13#[derive(Clone, Debug, Default, Deref)]
14pub struct ArgumentValueList {
15    #[deref]
16    map: Vec<(Identifier, ArgumentValue)>,
17    src_ref: SrcRef,
18}
19
20impl ArgumentValueList {
21    /// Create new [`ArgumentValueList`]
22    pub fn new(map: Vec<(Identifier, ArgumentValue)>, src_ref: SrcRef) -> Self {
23        Self { map, src_ref }
24    }
25
26    /// Return a single argument.
27    ///
28    /// Returns error if there is no or more than one argument available.
29    pub fn get_single(&self) -> EvalResult<(&Identifier, &ArgumentValue)> {
30        if self.map.len() == 1 {
31            if let Some(a) = self.map.first() {
32                return Ok((&a.0, &a.1));
33            }
34        }
35
36        Err(EvalError::ArgumentCountMismatch {
37            args: self.clone(),
38            expected: 1,
39            found: self.map.len(),
40        })
41    }
42
43    /// Get value by type
44    pub fn get_by_type(&self, ty: &Type) -> Option<(&Identifier, &ArgumentValue)> {
45        let arg = self.map.iter().find(|(_, arg)| arg.value.ty() == *ty);
46        arg.map(|arg| (&arg.0, &arg.1))
47    }
48}
49
50impl ValueAccess for ArgumentValueList {
51    fn by_id(&self, id: &Identifier) -> Option<&Value> {
52        self.map
53            .iter()
54            .find(|(i, _)| i == id)
55            .map(|arg| &arg.1.value)
56    }
57
58    fn by_ty(&self, ty: &Type) -> Option<&Value> {
59        self.get_by_type(ty).map(|(_, arg)| &arg.value)
60    }
61}
62
63impl SrcReferrer for ArgumentValueList {
64    fn src_ref(&self) -> SrcRef {
65        self.src_ref.clone()
66    }
67}
68
69impl std::fmt::Display for ArgumentValueList {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        write!(f, "{}", {
72            let mut v = self
73                .map
74                .iter()
75                .map(|(id, p)| format!("{id:?}: {p}"))
76                .collect::<Vec<_>>();
77            v.sort();
78            v.join(", ")
79        })
80    }
81}
82
83impl FromIterator<(Identifier, ArgumentValue)> for ArgumentValueList {
84    fn from_iter<T: IntoIterator<Item = (Identifier, ArgumentValue)>>(iter: T) -> Self {
85        let map: Vec<_> = iter.into_iter().collect();
86        Self {
87            src_ref: SrcRef::merge_all(map.iter().map(|(_, v)| v.src_ref())),
88            map,
89        }
90    }
91}