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