Skip to main content

microcad_lang/syntax/expression/
array_expression.rs

1// Copyright © 2024-2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! List of expression
5
6use crate::syntax::*;
7use derive_more::{Deref, DerefMut};
8use microcad_lang_base::{SrcRef, SrcReferrer, TreeDisplay, TreeState};
9
10/// Inner of an [`ArrayExpression`].
11#[derive(Clone, PartialEq)]
12pub enum ArrayExpressionInner {
13    /// List: `a,b,c`.
14    List(ListExpression),
15    /// Range: `a..b`.
16    Range(RangeExpression),
17}
18
19impl Default for ArrayExpressionInner {
20    fn default() -> Self {
21        Self::List(Default::default())
22    }
23}
24
25impl std::fmt::Display for ArrayExpressionInner {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        write!(
28            f,
29            "{}",
30            match &self {
31                ArrayExpressionInner::List(expressions) => expressions
32                    .iter()
33                    .map(|c| c.to_string())
34                    .collect::<Vec<_>>()
35                    .join(", "),
36                ArrayExpressionInner::Range(range_expression) => range_expression.to_string(),
37            }
38        )
39    }
40}
41
42impl std::fmt::Debug for ArrayExpressionInner {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        write!(
45            f,
46            "{}",
47            match &self {
48                ArrayExpressionInner::List(expressions) => expressions
49                    .iter()
50                    .map(|c| format!("{c:?}"))
51                    .collect::<Vec<_>>()
52                    .join(", "),
53                ArrayExpressionInner::Range(range_expression) => range_expression.to_string(),
54            }
55        )
56    }
57}
58
59impl SrcReferrer for ArrayExpressionInner {
60    fn src_ref(&self) -> SrcRef {
61        match &self {
62            ArrayExpressionInner::List(expressions) => SrcRef::merge(
63                &expressions
64                    .first()
65                    .map(|start| start.src_ref())
66                    .unwrap_or_default(),
67                &expressions
68                    .last()
69                    .map(|end| end.src_ref())
70                    .unwrap_or_default(),
71            ),
72            ArrayExpressionInner::Range(range_expression) => range_expression.src_ref(),
73        }
74    }
75}
76
77impl TreeDisplay for ArrayExpressionInner {
78    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
79        match &self {
80            ArrayExpressionInner::List(expressions) => {
81                writeln!(f, "{:depth$}List:", "")?;
82                depth.indent();
83                expressions
84                    .iter()
85                    .try_for_each(|expression| expression.tree_print(f, depth))
86            }
87            ArrayExpressionInner::Range(range_expression) => range_expression.tree_print(f, depth),
88        }
89    }
90}
91
92/// Array of expressions with common result unit, e.g. `[1+2,4,9]`.
93#[derive(Default, Clone, Deref, DerefMut, PartialEq)]
94pub struct ArrayExpression {
95    /// Expression list.
96    #[deref]
97    #[deref_mut]
98    pub inner: ArrayExpressionInner,
99    /// Unit.
100    pub unit: Unit,
101    /// Source code reference.
102    pub src_ref: SrcRef,
103}
104
105impl SrcReferrer for ArrayExpression {
106    fn src_ref(&self) -> microcad_lang_base::SrcRef {
107        self.src_ref.clone()
108    }
109}
110
111impl std::fmt::Display for ArrayExpression {
112    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
113        write!(f, "[{}]{}", self.inner, self.unit)
114    }
115}
116
117impl std::fmt::Debug for ArrayExpression {
118    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
119        write!(f, "[{:?}]{}", self.inner, self.unit)
120    }
121}
122
123impl TreeDisplay for ArrayExpression {
124    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
125        writeln!(f, "{:depth$}ArrayExpression:", "")?;
126        depth.indent();
127        self.inner.tree_print(f, depth)?;
128        self.unit.tree_print(f, depth)
129    }
130}