Skip to main content

microcad_lang/lower/
mod.rs

1// Copyright © 2024-2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Lowering compile step
5
6pub mod ir;
7
8#[allow(clippy::module_inception)]
9mod lower;
10
11use microcad_lang_base::{ComputedHash, Hashed, Identifier, LineIndex, Span, SrcRef};
12
13pub use lower::{LowerError, LowerErrorsWithSource, LowerResult};
14
15/// Check if the element only includes one identifier
16pub trait SingleIdentifier {
17    /// If the element only includes one identifier, return it
18    fn single_identifier(&self) -> Option<&Identifier>;
19
20    /// Returns true if the element only includes a single identifier.
21    fn is_single_identifier(&self) -> bool {
22        self.single_identifier().is_some()
23    }
24}
25
26/// Identifier accessor.
27pub trait Identifiable {
28    /// Get clone of the identifier.
29    fn id(&self) -> Identifier {
30        self.id_ref().clone()
31    }
32
33    /// Get reference to the identifier.
34    fn id_ref(&self) -> &Identifier;
35
36    /// Get identifier as string.
37    fn id_as_str(&self) -> &str {
38        self.id_ref().0.as_str()
39    }
40}
41
42/// Interface for elements which have *initializers*.
43pub trait Initialized<'a> {
44    /// return iterator of body statements.
45    fn statements(&'a self) -> std::slice::Iter<'a, ir::Statement>;
46
47    /// Return iterator over all initializers.
48    fn inits(&'a self) -> ir::Inits<'a>
49    where
50        Self: std::marker::Sized,
51    {
52        ir::Inits::new(self)
53    }
54}
55
56pub struct LowerContext<'source> {
57    pub source: Hashed<&'source str>,
58    line_index: LineIndex,
59    line_offset: u32,
60}
61
62impl<'source> LowerContext<'source> {
63    pub fn new(source: &'source str) -> Self {
64        LowerContext {
65            source: Hashed::new(source),
66            line_index: LineIndex::new(source),
67            line_offset: 0,
68        }
69    }
70
71    pub fn with_line_offset(self, line_offset: u32) -> Self {
72        Self {
73            source: self.source,
74            line_index: self.line_index,
75            line_offset,
76        }
77    }
78
79    pub fn src_ref(&self, span: &Span) -> SrcRef {
80        self.line_index
81            .src_ref(self.source.value(), span, self.source.computed_hash())
82            .with_line_offset(self.line_offset)
83    }
84}
85
86pub trait Lower: Sized {
87    type AstNode;
88
89    fn lower(node: &Self::AstNode, context: &LowerContext) -> Result<Self, LowerError>;
90}