microcad_lang/eval/call/
argument_value_list.rs1use crate::eval::*;
7use derive_more::{Deref, DerefMut};
8use microcad_lang_base::{Identifier, SrcRef, SrcReferrer};
9use microcad_lang_proc_macros::SrcReferrer;
10
11#[derive(Clone, Debug, Default, Deref, DerefMut, SrcReferrer)]
16pub struct ArgumentValueList {
17 #[deref]
18 #[deref_mut]
19 map: Vec<(Identifier, ArgumentValue)>,
20 src_ref: SrcRef,
21}
22
23impl ArgumentValueList {
24 pub fn get_single(&self) -> EvalResult<(&Identifier, &ArgumentValue)> {
28 if self.map.len() == 1 {
29 if let Some(a) = self.map.first() {
30 return Ok((&a.0, &a.1));
31 }
32 }
33
34 Err(EvalError::ArgumentCountMismatch {
35 args: self.to_string(),
36 expected: 1,
37 found: self.map.len(),
38 }
39 .into())
40 }
41
42 pub fn get_by_type(&self, ty: &Type) -> Option<(&Identifier, &ArgumentValue)> {
44 let arg = self.map.iter().find(|(_, arg)| arg.value.ty() == *ty);
45 arg.map(|arg| (&arg.0, &arg.1))
46 }
47
48 pub fn get_by_index(&self, index: usize) -> Option<&(Identifier, ArgumentValue)> {
50 self.map.get(index)
51 }
52}
53
54impl ValueAccess for ArgumentValueList {
55 fn by_id(&self, id: &Identifier) -> Option<&Value> {
56 self.map
57 .iter()
58 .find(|(i, _)| i == id)
59 .map(|arg| &arg.1.value)
60 }
61
62 fn by_ty(&self, ty: &Type) -> Option<&Value> {
63 self.get_by_type(ty).map(|(_, arg)| &arg.value)
64 }
65}
66
67impl std::fmt::Display for ArgumentValueList {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 write!(f, "{}", {
70 let mut v = self
71 .map
72 .iter()
73 .map(|(id, val)| {
74 if !id.is_empty() {
75 format!("{id} = {}", val.value)
76 } else if let Some(id) = &val.inline_id {
77 format!("{id} = {}", val.value)
78 } else {
79 format!("{}", val.value)
80 }
81 })
82 .collect::<Vec<_>>();
83 v.sort();
84 v.join(", ")
85 })
86 }
87}
88
89impl FromIterator<(Identifier, ArgumentValue)> for ArgumentValueList {
90 fn from_iter<T: IntoIterator<Item = (Identifier, ArgumentValue)>>(iter: T) -> Self {
91 let map: Vec<_> = iter.into_iter().collect();
92 Self {
93 src_ref: SrcRef::merge_all(map.iter().map(|(_, v)| v.src_ref())),
94 map,
95 }
96 }
97}