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