microcad_lang/syntax/
init_definition.rs

1// Copyright © 2024-2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Initialization definition syntax element
5
6use crate::{src_ref::*, syntax::*};
7
8/// Workbench *initializer* definition
9///
10/// Example:
11///
12/// ```uCAD
13/// part A(a: Length) {
14///     init(b: Length) { a = 2.0*b; } // The init definition
15/// }
16/// ```
17#[derive(Clone)]
18pub struct InitDefinition {
19    /// Documentation.
20    pub doc: Option<DocBlock>,
21    /// Parameter list for this init definition
22    pub parameters: ParameterList,
23    /// Body if the init definition
24    pub body: Body,
25    /// Source reference
26    pub src_ref: SrcRef,
27}
28
29impl Doc for InitDefinition {
30    fn doc(&self) -> Option<DocBlock> {
31        self.doc.clone()
32    }
33}
34
35impl SrcReferrer for InitDefinition {
36    fn src_ref(&self) -> SrcRef {
37        self.src_ref.clone()
38    }
39}
40
41impl std::fmt::Display for InitDefinition {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        write!(f, "init({parameters}) ", parameters = self.parameters)?;
44        write!(f, "{body}", body = self.body)
45    }
46}
47
48impl std::fmt::Debug for InitDefinition {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "init({parameters:?}) ", parameters = self.parameters)?;
51        write!(f, "{body:?}", body = self.body)
52    }
53}
54
55impl TreeDisplay for InitDefinition {
56    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
57        writeln!(f, "{:depth$}InitDefinition:", "")?;
58        depth.indent();
59        if let Some(doc) = &self.doc {
60            doc.tree_print(f, depth)?;
61        }
62        self.parameters.tree_print(f, depth)?;
63        self.body.tree_print(f, depth)
64    }
65}
66
67/// Iterator over part's *initializers*.
68pub struct Inits<'a>(std::slice::Iter<'a, Statement>);
69
70/// Interface for elements which have *initializers*.
71pub trait Initialized<'a> {
72    /// return iterator of body statements.
73    fn statements(&'a self) -> std::slice::Iter<'a, Statement>;
74
75    /// Return iterator over all initializers.
76    fn inits(&'a self) -> Inits<'a>
77    where
78        Self: std::marker::Sized,
79    {
80        Inits::new(self)
81    }
82}
83
84impl<'a> Inits<'a> {
85    /// Create new init for a part.
86    pub fn new(def: &'a impl Initialized<'a>) -> Self {
87        Self(def.statements())
88    }
89}
90
91impl<'a> Iterator for Inits<'a> {
92    type Item = &'a InitDefinition;
93
94    fn next(&mut self) -> Option<Self::Item> {
95        for statement in self.0.by_ref() {
96            match statement {
97                Statement::Init(init_definition) => {
98                    return Some(init_definition);
99                }
100                _ => continue,
101            }
102        }
103
104        None
105    }
106}