Skip to main content

microcad_lang/syntax/
init_definition.rs

1// Copyright © 2024-2026 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    /// SrcRef of the `init` keyword
20    pub keyword_ref: SrcRef,
21    /// Documentation.
22    pub doc: Option<DocBlock>,
23    /// Parameter list for this init definition
24    pub parameters: ParameterList,
25    /// Body if the init definition
26    pub body: Body,
27    /// Source reference
28    pub src_ref: SrcRef,
29}
30
31impl Doc for InitDefinition {
32    fn doc(&self) -> Option<DocBlock> {
33        self.doc.clone()
34    }
35}
36
37impl SrcReferrer for InitDefinition {
38    fn src_ref(&self) -> SrcRef {
39        self.src_ref.clone()
40    }
41}
42
43impl std::fmt::Display for InitDefinition {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        write!(f, "init({parameters}) ", parameters = self.parameters)?;
46        write!(f, "{body}", body = self.body)
47    }
48}
49
50impl std::fmt::Debug for InitDefinition {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        write!(f, "init({parameters:?}) ", parameters = self.parameters)?;
53        write!(f, "{body:?}", body = self.body)
54    }
55}
56
57impl TreeDisplay for InitDefinition {
58    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
59        writeln!(f, "{:depth$}InitDefinition:", "")?;
60        depth.indent();
61        if let Some(doc) = &self.doc {
62            doc.tree_print(f, depth)?;
63        }
64        self.parameters.tree_print(f, depth)?;
65        self.body.tree_print(f, depth)
66    }
67}
68
69/// Iterator over part's *initializers*.
70pub struct Inits<'a>(std::slice::Iter<'a, Statement>);
71
72/// Interface for elements which have *initializers*.
73pub trait Initialized<'a> {
74    /// return iterator of body statements.
75    fn statements(&'a self) -> std::slice::Iter<'a, Statement>;
76
77    /// Return iterator over all initializers.
78    fn inits(&'a self) -> Inits<'a>
79    where
80        Self: std::marker::Sized,
81    {
82        Inits::new(self)
83    }
84}
85
86impl<'a> Inits<'a> {
87    /// Create new init for a part.
88    pub fn new(def: &'a impl Initialized<'a>) -> Self {
89        Self(def.statements())
90    }
91}
92
93impl<'a> Iterator for Inits<'a> {
94    type Item = &'a InitDefinition;
95
96    fn next(&mut self) -> Option<Self::Item> {
97        for statement in self.0.by_ref() {
98            match statement {
99                Statement::Init(init_definition) => {
100                    return Some(init_definition);
101                }
102                _ => continue,
103            }
104        }
105
106        None
107    }
108}