Skip to main content

microcad_lang/syntax/
workbench.rs

1// Copyright © 2025-2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Workbench definition syntax element
5
6use crate::syntax::*;
7use custom_debug::Debug;
8use microcad_lang_base::{Refer, SrcRef, SrcReferrer, TreeDisplay, TreeState};
9use strum::Display;
10
11/// Kind of a [`WorkbenchDefinition`].
12#[derive(Clone, Display, Debug, Copy, PartialEq)]
13pub enum WorkbenchKind {
14    /// 3D part
15    Part,
16    /// 2D sketch
17    Sketch,
18    /// Operation
19    Operation,
20}
21
22impl WorkbenchKind {
23    /// return kind name
24    pub fn as_str(&self) -> &'static str {
25        match self {
26            WorkbenchKind::Part => "part",
27            WorkbenchKind::Sketch => "sketch",
28            WorkbenchKind::Operation => "op",
29        }
30    }
31}
32
33/// Workbench definition, e.g `sketch`, `part` or `op`.
34#[derive(Clone)]
35pub struct WorkbenchDefinition {
36    /// SrcRef of the `sketch`/`part`/`op` keyword
37    pub keyword_ref: SrcRef,
38    /// Documentation.
39    pub doc: Option<DocBlock>,
40    /// Workbench attributes.
41    pub attribute_list: AttributeList,
42    /// Visibility from outside modules.
43    pub visibility: Visibility,
44    /// Workbench kind.
45    pub kind: Refer<WorkbenchKind>,
46    /// Workbench name.
47    pub(crate) id: Identifier,
48    /// Workbench's building plan.
49    pub plan: ParameterList,
50    /// Workbench body
51    pub body: Body,
52}
53
54impl WorkbenchDefinition {
55    pub(crate) fn possible_params(&self) -> Vec<String> {
56        std::iter::once(&self.plan)
57            .chain(self.inits().map(|init| &init.parameters))
58            .map(|params| format!("{}( {})", self.id, params))
59            .collect()
60    }
61}
62
63impl Identifiable for WorkbenchDefinition {
64    fn id_ref(&self) -> &Identifier {
65        &self.id
66    }
67}
68
69impl<'a> Initialized<'a> for WorkbenchDefinition {
70    fn statements(&'a self) -> std::slice::Iter<'a, Statement> {
71        self.body.statements.iter()
72    }
73}
74
75impl SrcReferrer for WorkbenchDefinition {
76    fn src_ref(&self) -> SrcRef {
77        self.id.src_ref()
78    }
79}
80
81impl std::fmt::Display for WorkbenchDefinition {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        write!(
84            f,
85            "{visibility}{kind} {id}({plan}) {body}",
86            visibility = self.visibility,
87            kind = self.kind,
88            id = self.id,
89            plan = self.plan,
90            body = self.body
91        )
92    }
93}
94
95impl std::fmt::Debug for WorkbenchDefinition {
96    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        write!(
98            f,
99            "{visibility}{kind} {id:?}({plan:?}) {body:?}",
100            visibility = self.visibility,
101            kind = self.kind,
102            id = self.id,
103            plan = self.plan,
104            body = self.body
105        )
106    }
107}
108
109impl TreeDisplay for WorkbenchDefinition {
110    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
111        writeln!(
112            f,
113            "{:depth$}{visibility}Workbench ({kind}) '{id}':",
114            "",
115            visibility = self.visibility,
116            kind = self.kind,
117            id = self.id
118        )?;
119        depth.indent();
120        if let Some(doc) = &self.doc {
121            doc.tree_print(f, depth)?;
122        }
123        self.plan.tree_print(f, depth)?;
124        self.body.tree_print(f, depth)
125    }
126}