Skip to main content

microcad_lang/syntax/call/
argument.rs

1// Copyright © 2024-2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! A single argument
5
6use microcad_lang_base::{SrcRef, SrcReferrer, TreeDisplay, TreeState};
7
8use crate::{ord_map::*, syntax::*};
9
10/// Argument in a [`Call`].
11#[derive(Clone, PartialEq)]
12pub struct Argument {
13    /// Name of the argument
14    pub id: Option<Identifier>,
15    /// Value of the argument
16    pub expression: Expression,
17    /// Source code reference
18    pub src_ref: SrcRef,
19}
20
21impl Argument {
22    /// Returns the name, if self.name is some. If self.name is None, try to extract the name from the expression
23    pub fn derived_name(&self) -> Option<Identifier> {
24        match &self.id {
25            Some(name) => Some(name.clone()),
26            None => self.expression.single_identifier().cloned(),
27        }
28    }
29}
30
31impl SrcReferrer for Argument {
32    fn src_ref(&self) -> SrcRef {
33        self.src_ref.clone()
34    }
35}
36
37impl OrdMapValue<Identifier> for Argument {
38    fn key(&self) -> Option<Identifier> {
39        self.id.clone()
40    }
41}
42
43impl std::fmt::Display for Argument {
44    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
45        match self.id {
46            Some(ref id) => write!(f, "{id} = {}", self.expression),
47            None => write!(f, "{}", self.expression),
48        }
49    }
50}
51
52impl std::fmt::Debug for Argument {
53    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
54        match self.id {
55            Some(ref id) => write!(f, "{id:?} = {:?}", self.expression),
56            None => write!(f, "{:?}", self.expression),
57        }
58    }
59}
60
61impl TreeDisplay for Argument {
62    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
63        match self.id {
64            Some(ref id) => writeln!(f, "{:depth$}Argument '{id:?}':", "")?,
65            None => writeln!(f, "{:depth$}Argument:", "")?,
66        };
67        depth.indent();
68        self.expression.tree_print(f, depth)
69    }
70}
71
72#[test]
73fn test_argument_debug() {
74    let arg1 = Argument {
75        id: Some("id1".into()),
76        expression: Expression::QualifiedName("my::name1".into()),
77        src_ref: SrcRef(None),
78    };
79
80    let arg2 = Argument {
81        id: None,
82        expression: Expression::QualifiedName("my::name2".into()),
83        src_ref: SrcRef(None),
84    };
85
86    let arg3 = Argument {
87        id: Some(Identifier::none()),
88        expression: Expression::QualifiedName("my::name2".into()),
89        src_ref: SrcRef(None),
90    };
91
92    let mut args = ArgumentList::default();
93
94    args.try_push(arg1).expect("test error");
95    args.try_push(arg2).expect("test error");
96    args.try_push(arg3).expect("test error");
97
98    log::info!("{args}");
99    log::info!("{args:?}");
100}