microcad_lang/syntax/
workbench.rs

1// Copyright © 2025 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    /// Workbench code reference
50    pub src_ref: SrcRef,
51}
52
53impl WorkbenchDefinition {
54    /// Return the source code reference of the head of the definition.
55    ///
56    /// This excludes any attribute, visibility and body.
57    pub fn src_ref_head(&self) -> SrcRef {
58        SrcRef::merge(&self.kind, &self.plan)
59    }
60}
61
62impl<'a> Initialized<'a> for WorkbenchDefinition {
63    fn statements(&'a self) -> std::slice::Iter<'a, Statement> {
64        self.body.statements.iter()
65    }
66}
67
68impl SrcReferrer for WorkbenchDefinition {
69    fn src_ref(&self) -> SrcRef {
70        self.src_ref.clone()
71    }
72}
73
74impl std::fmt::Display for WorkbenchDefinition {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(
77            f,
78            "{visibility}{kind} {id}({plan}) {body}",
79            visibility = self.visibility,
80            kind = self.kind,
81            id = self.id,
82            plan = self.plan,
83            body = self.body
84        )
85    }
86}
87
88impl std::fmt::Debug for WorkbenchDefinition {
89    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90        write!(
91            f,
92            "{visibility}{kind} {id:?}({plan:?}) {body:?}",
93            visibility = self.visibility,
94            kind = self.kind,
95            id = self.id,
96            plan = self.plan,
97            body = self.body
98        )
99    }
100}
101
102impl TreeDisplay for WorkbenchDefinition {
103    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
104        writeln!(
105            f,
106            "{:depth$}{visibility}Workbench ({kind}) '{id}':",
107            "",
108            visibility = self.visibility,
109            kind = self.kind,
110            id = self.id
111        )?;
112        depth.indent();
113        if let Some(doc) = &self.doc {
114            doc.tree_print(f, depth)?;
115        }
116        self.plan.tree_print(f, depth)?;
117        self.body.tree_print(f, depth)
118    }
119}
120
121impl Doc for WorkbenchDefinition {
122    fn doc(&self) -> Option<DocBlock> {
123        self.doc.clone()
124    }
125}