Skip to main content

microcad_lang/syntax/
workbench.rs

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