Skip to main content

microcad_lang/syntax/
init_definition.rs

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