Skip to main content

microcad_syntax/ast/
statement.rs

1// Copyright © 2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::Span;
5use crate::ast::{Call, Expression, Identifier, ItemExtras, StatementList, Type};
6
7/// A µcad statements
8#[derive(Debug, PartialEq)]
9#[allow(missing_docs)]
10pub enum Statement {
11    /// Workbench statement producing a symbol.
12    Workbench(WorkbenchDefinition),
13    /// Module statement producing a symbol.
14    Module(ModuleDefinition),
15    /// Function statement producing a symbol.
16    Function(FunctionDefinition),
17    /// Use statement producing a symbol.
18    Use(UseStatement),
19    /// Const statement producing a symbol.
20    Const(ConstAssignment),
21
22    Init(InitDefinition),
23    Return(Return),
24    InnerAttribute(Attribute),
25    LocalAssignment(LocalAssignment),
26    Property(PropertyAssignment),
27    Expression(ExpressionStatement),
28    InnerDocComment(Comment),
29    Comment(Comment),
30    Error(Span),
31}
32
33impl Statement {
34    /// Get the span for the statement
35    pub fn span(&self) -> Span {
36        use Statement::*;
37
38        match self {
39            Workbench(st) => st.span.clone(),
40            Module(st) => st.span.clone(),
41            Function(st) => st.span.clone(),
42            Use(st) => st.span.clone(),
43            Const(st) => st.span.clone(),
44            Init(st) => st.span.clone(),
45            Return(st) => st.span.clone(),
46            InnerAttribute(st) => st.span.clone(),
47            LocalAssignment(st) => st.span.clone(),
48            Property(st) => st.span.clone(),
49            Expression(st) => st.span.clone(),
50            InnerDocComment(st) => st.span.clone(),
51            Comment(st) => st.span.clone(),
52            Error(span) => span.clone(),
53        }
54    }
55}
56
57/// The possible type of workbenches
58#[derive(Debug, PartialEq, Copy, Clone)]
59#[allow(missing_docs)]
60pub enum WorkbenchKind {
61    Sketch,
62    Part,
63    Op,
64}
65
66/// A definition of a workbench
67#[derive(Debug, PartialEq)]
68#[allow(missing_docs)]
69pub struct WorkbenchDefinition {
70    pub span: Span,
71    pub keyword_span: Span,
72    pub extras: ItemExtras,
73    pub doc: Option<Comment>,
74    pub kind: WorkbenchKind,
75    pub attributes: Vec<Attribute>,
76    pub visibility: Option<Visibility>,
77    pub name: Identifier,
78    pub plan: ParameterList,
79    pub body: StatementList,
80}
81
82/// A definition of a module
83#[derive(Debug, PartialEq)]
84#[allow(missing_docs)]
85pub struct ModuleDefinition {
86    pub span: Span,
87    pub keyword_span: Span,
88    pub extras: ItemExtras,
89    pub doc: Option<Comment>,
90    pub attributes: Vec<Attribute>,
91    pub visibility: Option<Visibility>,
92    pub name: Identifier,
93    pub body: Option<StatementList>,
94}
95
96/// A definition of a function
97#[derive(Debug, PartialEq)]
98#[allow(missing_docs)]
99pub struct FunctionDefinition {
100    pub span: Span,
101    pub keyword_span: Span,
102    pub extras: ItemExtras,
103    pub doc: Option<Comment>,
104    pub visibility: Option<Visibility>,
105    pub name: Identifier,
106    pub arguments: ParameterList,
107    pub return_type: Option<Type>,
108    pub body: StatementList,
109}
110
111/// An init definition for a workbench
112#[derive(Debug, PartialEq)]
113#[allow(missing_docs)]
114pub struct InitDefinition {
115    pub span: Span,
116    pub keyword_span: Span,
117    pub extras: ItemExtras,
118    pub doc: Option<Comment>,
119    pub attributes: Vec<Attribute>,
120    pub parameters: ParameterList,
121    pub body: StatementList,
122}
123
124/// A use statement that imports an item from an external library
125#[derive(Debug, PartialEq)]
126#[allow(missing_docs)]
127pub struct UseStatement {
128    pub span: Span,
129    pub attributes: Vec<Attribute>,
130    pub keyword_span: Span,
131    pub extras: ItemExtras,
132    pub visibility: Option<Visibility>,
133    pub name: UseName,
134    pub use_as: Option<Identifier>,
135}
136
137/// The name of the item being imported
138#[derive(Debug, PartialEq)]
139#[allow(missing_docs)]
140pub struct UseName {
141    pub span: Span,
142    pub extras: ItemExtras,
143    pub parts: Vec<UseStatementPart>,
144}
145
146/// The parts a [`UseName`] consists of, separated by `::`
147#[derive(Debug, PartialEq)]
148#[allow(missing_docs)]
149pub enum UseStatementPart {
150    Identifier(Identifier),
151    Glob(Span),
152    Error(Span),
153}
154
155/// A return statement
156#[derive(Debug, PartialEq)]
157#[allow(missing_docs)]
158pub struct Return {
159    pub span: Span,
160    pub keyword_span: Span,
161    pub extras: ItemExtras,
162    pub value: Option<Expression>,
163}
164
165/// A parameter list of a workbench definition or function definition
166#[derive(Debug, PartialEq)]
167#[allow(missing_docs)]
168pub struct ParameterList {
169    pub span: Span,
170    pub extras: ItemExtras,
171    pub parameters: Vec<Parameter>,
172}
173
174impl ParameterList {
175    pub(crate) fn dummy(span: Span) -> Self {
176        ParameterList {
177            span,
178            extras: ItemExtras::default(),
179            parameters: Vec::default(),
180        }
181    }
182}
183
184/// A parameter for a workbench definition or function definition
185#[derive(Debug, PartialEq)]
186#[allow(missing_docs)]
187pub struct Parameter {
188    pub span: Span,
189    pub extras: ItemExtras,
190    pub name: Identifier,
191    pub ty: Option<Type>,
192    pub default: Option<Expression>,
193}
194
195/// An attribute that can be attached to a statement
196#[derive(Debug, PartialEq)]
197#[allow(missing_docs)]
198pub struct Attribute {
199    pub span: Span,
200    pub is_inner: bool,
201    pub extras: ItemExtras,
202    pub commands: Vec<AttributeCommand>,
203}
204
205/// The contents an an [`Attribute`]
206#[derive(Debug, PartialEq)]
207#[allow(missing_docs)]
208pub enum AttributeCommand {
209    Ident(Identifier),
210    Assignment(LocalAssignment),
211    Call(Call),
212}
213
214/// An optional qualifier that can be part of an [`Assignment`]
215#[derive(Debug, PartialEq)]
216#[allow(missing_docs)]
217pub enum AssignmentQualifier {
218    Const,
219    Prop,
220}
221
222/// A local assignment statement: `a = 42;`
223#[derive(Debug, PartialEq)]
224#[allow(missing_docs)]
225pub struct LocalAssignment {
226    pub span: Span,
227    pub extras: ItemExtras,
228    pub attributes: Vec<Attribute>,
229    pub name: Identifier,
230    pub ty: Option<Type>,
231    pub value: Box<Expression>,
232}
233
234/// A const assignment: `const A = 42` / `pub A = 32`
235#[derive(Debug, PartialEq)]
236#[allow(missing_docs)]
237pub struct ConstAssignment {
238    pub span: Span,
239    pub keyword_span: Span,
240    pub extras: ItemExtras,
241    pub doc: Option<Comment>,
242    pub attributes: Vec<Attribute>,
243    pub visibility: Option<Visibility>,
244    pub name: Identifier,
245    pub ty: Option<Type>,
246    pub value: Box<Expression>,
247}
248
249/// A property assignment: `prop A = 42`
250#[derive(Debug, PartialEq)]
251#[allow(missing_docs)]
252pub struct PropertyAssignment {
253    pub span: Span,
254    pub keyword_span: Span,
255    pub extras: ItemExtras,
256    pub doc: Option<Comment>,
257    pub attributes: Vec<Attribute>,
258    pub name: Identifier,
259    pub ty: Option<Type>,
260    pub value: Box<Expression>,
261}
262
263/// A single- or multi-line comment
264#[derive(Debug, PartialEq)]
265#[allow(missing_docs)]
266pub struct Comment {
267    pub span: Span,
268    pub lines: Vec<String>,
269}
270
271/// An optional visibility modifier that can be art of assignment and module, function and workbench definitions
272#[derive(Debug, PartialEq)]
273#[allow(missing_docs)]
274pub enum Visibility {
275    Public,
276}
277
278/// A statement containing of a bare expression
279#[derive(Debug, PartialEq)]
280#[allow(missing_docs)]
281pub struct ExpressionStatement {
282    pub span: Span,
283    pub extras: ItemExtras,
284    pub attributes: Vec<Attribute>,
285    pub expression: Expression,
286}