Skip to main content

microcad_lang/syntax/statement/
if_statement.rs

1// Copyright © 2025-2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! If statement syntax elements.
5
6use microcad_lang_base::{SrcRef, SrcReferrer, TreeDisplay, TreeState};
7
8use crate::syntax::*;
9
10/// If statement.
11#[derive(Clone)]
12pub struct IfStatement {
13    /// SrcRef of the `if` keyword.
14    pub if_ref: SrcRef,
15    /// If condition.
16    pub cond: Expression,
17    /// Body if `true`.
18    pub body: Body,
19    /// SrcRef of the `else` keyword, if present.
20    pub else_ref: Option<SrcRef>,
21    /// Body if `false`.
22    pub body_else: Option<Body>,
23    /// SrcRef of the `else[ if]` keyword, if present.
24    pub next_if_ref: Option<SrcRef>,
25    /// Next if statement: `else if x == 1`.
26    pub next_if: Option<Box<IfStatement>>,
27    /// Source code reference.
28    pub src_ref: SrcRef,
29}
30
31impl IfStatement {
32    /// Checks if all branches of the if statement are set
33    pub fn is_complete(&self) -> bool {
34        if let Some(next_if) = &self.next_if {
35            next_if.is_complete()
36        } else {
37            self.body_else.is_some()
38        }
39    }
40}
41
42impl SrcReferrer for IfStatement {
43    fn src_ref(&self) -> SrcRef {
44        self.src_ref.clone()
45    }
46}
47
48impl std::fmt::Display for IfStatement {
49    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
50        writeln!(f, "if {cond} {body}", cond = self.cond, body = self.body)?;
51        if let Some(next) = &self.next_if {
52            writeln!(f, "else {next}")?;
53        }
54        if let Some(body) = &self.body_else {
55            writeln!(f, "else {body}")?;
56        }
57        Ok(())
58    }
59}
60
61impl std::fmt::Debug for IfStatement {
62    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
63        writeln!(
64            f,
65            "if {cond:?} {body:?}",
66            cond = self.cond,
67            body = self.body
68        )?;
69        if let Some(next) = &self.next_if {
70            writeln!(f, "else {next:?}")?;
71        }
72        if let Some(body) = &self.body_else {
73            writeln!(f, "else {body:?}")?;
74        }
75        Ok(())
76    }
77}
78
79impl TreeDisplay for IfStatement {
80    fn tree_print(&self, f: &mut std::fmt::Formatter, mut depth: TreeState) -> std::fmt::Result {
81        writeln!(f, "{:depth$}IfStatement:", "")?;
82        depth.indent();
83        writeln!(f, "{:depth$}Condition:", "")?;
84        self.cond.tree_print(f, depth.indented())?;
85        writeln!(f, "{:depth$}If:", "")?;
86        self.body.tree_print(f, depth.indented())?;
87        if let Some(body_else) = &self.body_else {
88            writeln!(f, "{:depth$}Else:", "")?;
89            body_else.tree_print(f, depth.indented())?;
90        }
91        Ok(())
92    }
93}