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, Debug)]
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<String>>()
37                    .join(", "),
38                ArrayExpressionInner::Range(range_expression) => range_expression.to_string(),
39            }
40        )
41    }
42}
43
44impl SrcReferrer for ArrayExpressionInner {
45    fn src_ref(&self) -> SrcRef {
46        match &self {
47            ArrayExpressionInner::List(expressions) => SrcRef::merge(
48                &expressions
49                    .first()
50                    .map(|start| start.src_ref())
51                    .unwrap_or_default(),
52                &expressions
53                    .last()
54                    .map(|end| end.src_ref())
55                    .unwrap_or_default(),
56            ),
57            ArrayExpressionInner::Range(range_expression) => range_expression.src_ref(),
58        }
59    }
60}
61
62impl TreeDisplay for ArrayExpressionInner {
63    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
64        match &self {
65            ArrayExpressionInner::List(expressions) => {
66                writeln!(f, "{:depth$}List:", "")?;
67                depth.indent();
68                expressions
69                    .iter()
70                    .try_for_each(|expression| expression.tree_print(f, depth))
71            }
72            ArrayExpressionInner::Range(range_expression) => range_expression.tree_print(f, depth),
73        }
74    }
75}
76
77/// Array of expressions with common result unit, e.g. `[1+2,4,9]`.
78#[derive(Default, Clone, Debug, Deref, DerefMut)]
79pub struct ArrayExpression {
80    /// Expression list.
81    #[deref]
82    #[deref_mut]
83    pub inner: ArrayExpressionInner,
84    /// Unit.
85    pub unit: Unit,
86    /// Source code reference.
87    pub src_ref: SrcRef,
88}
89
90impl SrcReferrer for ArrayExpression {
91    fn src_ref(&self) -> crate::src_ref::SrcRef {
92        self.src_ref.clone()
93    }
94}
95
96impl std::fmt::Display for ArrayExpression {
97    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
98        write!(f, "[{}]{}", self.inner, self.unit)
99    }
100}
101
102impl TreeDisplay for ArrayExpression {
103    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
104        writeln!(f, "{:depth$}ArrayExpression:", "")?;
105        depth.indent();
106        self.inner.tree_print(f, depth)?;
107        self.unit.tree_print(f, depth)
108    }
109}