microcad_lang/syntax/expression/
array_expression.rs

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