joule_hir/
lib.rs

1//! High-level Intermediate Representation (HIR) for Joule
2//!
3//! HIR is a typed, desugared representation of the AST. It includes:
4//! - Resolved types for all expressions
5//! - Resolved names (symbols point to definitions)
6//! - Desugared syntax (no syntactic sugar)
7//! - Type annotations on all nodes
8//! - Energy budget metadata from `#[energy_budget(...)]` attributes
9
10use joule_common::{Span, Symbol};
11use std::collections::HashMap;
12
13pub mod energy;
14pub use energy::{EnergyMetadata, EnergyViolation, EnergyViolationKind, HirEnergyBudget};
15
16/// Unique identifier for HIR nodes
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub struct HirId(pub u32);
19
20impl HirId {
21    pub const fn new(id: u32) -> Self {
22        Self(id)
23    }
24}
25
26/// A complete HIR module (file)
27#[derive(Debug, Clone)]
28pub struct Hir {
29    pub items: Vec<Item>,
30    pub type_map: HashMap<HirId, Ty>,
31    /// Type aliases (name → resolved type)
32    pub type_aliases: HashMap<Symbol, Ty>,
33}
34
35/// Top-level items
36#[derive(Debug, Clone)]
37pub enum Item {
38    Function(Function),
39    Struct(Struct),
40    Enum(Enum),
41    Trait(Trait),
42    Impl(Impl),
43    Const(Const),
44    Static(Static),
45    /// Algebraic effect declaration
46    Effect(EffectDef),
47    /// Supervisor tree declaration
48    Supervisor(SupervisorDef),
49}
50
51/// Parsed function attributes for code generation decisions
52#[derive(Debug, Clone, Default)]
53pub struct FunctionAttributes {
54    /// Function is a GPU kernel (marked with `#[gpu_kernel]` or `#[gpu]`)
55    pub is_gpu_kernel: bool,
56    /// Function should have thermal-aware code generation (`#[thermal_aware]`)
57    pub is_thermal_aware: bool,
58    /// Function targets a specific processor (`#[target(cpu|gpu|tpu|npu)]`)
59    pub target: Option<ProcessorTarget>,
60    /// Function should be inlined (`#[inline]` or `#[inline(always)]`)
61    pub inline: InlineHint,
62    /// Function is marked as cold/unlikely to be called (`#[cold]`)
63    pub is_cold: bool,
64    /// Function is a test (`#[test]`) — included only in `--test` mode
65    pub is_test: bool,
66    /// Function is a benchmark (`#[bench]`) — included only in `--bench` mode
67    pub is_bench: bool,
68    /// Function should be ignored in test/bench mode (`#[ignore]`)
69    pub is_ignored: bool,
70    /// Raw attributes for extensions
71    pub raw: Vec<(String, Vec<(String, String)>)>,
72}
73
74/// Target processor for heterogeneous compilation
75#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub enum ProcessorTarget {
77    Cpu,
78    Gpu,
79    Tpu,
80    Npu,
81    Auto,
82}
83
84/// Inline hints for the compiler
85#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
86pub enum InlineHint {
87    #[default]
88    None,
89    Hint,
90    Always,
91    Never,
92}
93
94/// Function definition (with resolved types)
95#[derive(Debug, Clone)]
96pub struct Function {
97    pub id: HirId,
98    pub name: Symbol,
99    pub params: Vec<Param>,
100    pub return_ty: Ty,
101    pub body: Block,
102    /// Whether this is an extern function declaration (no body)
103    pub is_extern: bool,
104    /// Whether this is an async function (`async fn`)
105    pub is_async: bool,
106    /// Whether this is a const function (`const fn`)
107    pub is_const: bool,
108    /// Energy metadata including budget constraints and compile-time estimates
109    pub energy: EnergyMetadata,
110    /// Parsed function attributes for code generation
111    pub attributes: FunctionAttributes,
112    pub span: Span,
113}
114
115/// Function parameter
116#[derive(Debug, Clone)]
117pub struct Param {
118    pub id: HirId,
119    pub pattern: Pattern,
120    pub ty: Ty,
121    pub span: Span,
122}
123
124/// Struct definition
125#[derive(Debug, Clone)]
126pub struct Struct {
127    pub id: HirId,
128    pub name: Symbol,
129    pub fields: Vec<Field>,
130    pub span: Span,
131}
132
133/// Struct field
134#[derive(Debug, Clone)]
135pub struct Field {
136    pub id: HirId,
137    pub name: Symbol,
138    pub ty: Ty,
139    pub span: Span,
140}
141
142/// Enum definition
143#[derive(Debug, Clone)]
144pub struct Enum {
145    pub id: HirId,
146    pub name: Symbol,
147    pub variants: Vec<Variant>,
148    pub span: Span,
149}
150
151/// Enum variant
152#[derive(Debug, Clone)]
153pub struct Variant {
154    pub id: HirId,
155    pub name: Symbol,
156    pub fields: VariantFields,
157    pub span: Span,
158}
159
160#[derive(Debug, Clone)]
161pub enum VariantFields {
162    Unit,
163    Tuple(Vec<Ty>),
164    Struct(Vec<Field>),
165}
166
167/// Trait definition
168#[derive(Debug, Clone)]
169pub struct Trait {
170    pub id: HirId,
171    pub name: Symbol,
172    pub items: Vec<TraitItem>,
173    pub span: Span,
174}
175
176#[derive(Debug, Clone)]
177pub enum TraitItem {
178    Function(TraitFunction),
179}
180
181#[derive(Debug, Clone)]
182pub struct TraitFunction {
183    pub id: HirId,
184    pub name: Symbol,
185    pub params: Vec<Param>,
186    pub return_ty: Ty,
187    pub body: Option<Block>,
188    pub span: Span,
189}
190
191/// Impl block
192#[derive(Debug, Clone)]
193pub struct Impl {
194    pub id: HirId,
195    pub ty: Ty,
196    pub trait_ref: Option<Ty>,
197    pub items: Vec<ImplItem>,
198    pub span: Span,
199}
200
201#[derive(Debug, Clone)]
202pub enum ImplItem {
203    Function(Function),
204}
205
206/// Const declaration
207#[derive(Debug, Clone)]
208pub struct Const {
209    pub id: HirId,
210    pub name: Symbol,
211    pub ty: Ty,
212    pub value: Expr,
213    pub span: Span,
214}
215
216/// Static declaration
217#[derive(Debug, Clone)]
218pub struct Static {
219    pub id: HirId,
220    pub name: Symbol,
221    pub ty: Ty,
222    pub value: Expr,
223    pub mutable: bool,
224    pub span: Span,
225}
226
227/// Type representation in HIR
228#[derive(Debug, Clone, PartialEq, Eq, Hash)]
229pub enum Ty {
230    /// Integer types
231    Int(IntTy),
232    /// Unsigned integer types
233    Uint(UintTy),
234    /// Float types
235    Float(FloatTy),
236    /// Boolean
237    Bool,
238    /// Character
239    Char,
240    /// String
241    String,
242    /// Reference type (&T or &mut T)
243    Ref { mutable: bool, inner: Box<Self> },
244    /// Array type [T; N]
245    Array { element: Box<Self>, size: u64 },
246    /// Slice type [T]
247    Slice { element: Box<Self> },
248    /// Tuple type (T, U, V)
249    Tuple(Vec<Self>),
250    /// Function type
251    Function {
252        params: Vec<Self>,
253        return_ty: Box<Self>,
254    },
255    /// Named type (structs, enums, etc.)
256    Named { def_id: HirId, name: Symbol },
257    /// Generic type instantiation (e.g., Vec<i32>, Option<String>)
258    Generic {
259        def_id: HirId,
260        name: Symbol,
261        args: Vec<Self>,
262    },
263    /// Type parameter reference (e.g., T in fn foo<T>)
264    TypeParam { index: u32, name: Symbol },
265    /// Unit type ()
266    Unit,
267    /// Never type !
268    Never,
269    /// Type variable (for inference)
270    Infer(InferTy),
271    /// Error type (for error recovery)
272    Error,
273
274    /// Trait object type (dyn Trait)
275    TraitObject { trait_name: Symbol },
276
277    // === Concurrency Types ===
278    /// Task handle - represents a spawned task that will produce a value
279    Task { result_ty: Box<Self> },
280    /// Task group handle - for structured concurrency
281    TaskGroup,
282    /// Channel - bidirectional communication channel
283    Channel { element_ty: Box<Self> },
284    /// Channel sender half
285    Sender { element_ty: Box<Self> },
286    /// Channel receiver half
287    Receiver { element_ty: Box<Self> },
288
289    /// Future type (result of calling an async function)
290    Future { result_ty: Box<Self> },
291
292    /// Closure type (captures + params → return)
293    Closure {
294        id: HirId,
295        params: Vec<Self>,
296        return_ty: Box<Self>,
297        capture_tys: Vec<Self>,
298    },
299
300    /// Union type: `i64 | f64 | String` — tagged discriminated union
301    Union { variants: Vec<Self> },
302
303    /// Opaque type: zero-cost newtype with hidden underlying representation
304    Opaque { name: Symbol, def_id: HirId },
305
306    // === N-Dimensional Array Types ===
307    /// Owned N-dimensional array: NDArray[T; N] — heap-allocated contiguous data
308    NDArray { element: Box<Self>, rank: u32 },
309    /// Borrowed N-dimensional view: NDView[T; N] — zero-copy slice into an NDArray
310    NDView { element: Box<Self>, rank: u32 },
311    /// Copy-on-write array: CowArray[T; N] — shared data, cloned on mutation
312    CowArray { element: Box<Self>, rank: u32 },
313    /// Dynamic-rank array: DynArray[T] — rank determined at runtime
314    DynArray { element: Box<Self> },
315
316    // === Const-Generic Types ===
317    /// Small vector with inline storage: SmallVec[T; N]
318    SmallVec { element: Box<Self>, capacity: u32 },
319    /// SIMD vector type: Simd[T; N]
320    Simd { element: Box<Self>, lanes: u32 },
321}
322
323#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
324pub enum IntTy {
325    I8,
326    I16,
327    I32,
328    I64,
329    Isize,
330}
331
332#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
333pub enum UintTy {
334    U8,
335    U16,
336    U32,
337    U64,
338    Usize,
339}
340
341#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
342pub enum FloatTy {
343    F16,
344    BF16,
345    F32,
346    F64,
347}
348
349/// Type variable for type inference
350#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
351pub struct InferTy(pub u32);
352
353/// Statement
354#[derive(Debug, Clone)]
355pub enum Statement {
356    /// Let binding with explicit type
357    Let {
358        id: HirId,
359        pattern: Pattern,
360        ty: Ty,
361        init: Option<Expr>,
362        span: Span,
363    },
364    /// Expression statement
365    Expr(Expr),
366}
367
368/// Literal value for pattern matching
369#[derive(Debug, Clone)]
370pub enum LitValue {
371    Int(i128),
372    Char(char),
373    Bool(bool),
374    String(String),
375}
376
377/// Pattern (simplified from AST)
378#[derive(Debug, Clone)]
379pub enum Pattern {
380    /// Identifier pattern
381    Ident {
382        id: HirId,
383        name: Symbol,
384        mutable: bool,
385        ty: Ty,
386    },
387    /// Wildcard pattern
388    Wildcard { id: HirId, ty: Ty },
389    /// Tuple pattern
390    Tuple {
391        id: HirId,
392        patterns: Vec<Self>,
393        ty: Ty,
394    },
395    /// Struct pattern
396    Struct {
397        id: HirId,
398        def_id: HirId,
399        fields: Vec<FieldPattern>,
400        ty: Ty,
401    },
402    /// Enum variant pattern (e.g., `Result::Ok(value)`, `Option::Some(x)`)
403    Variant {
404        id: HirId,
405        enum_name: Symbol,
406        variant_name: Symbol,
407        fields: Vec<Self>,
408        ty: Ty,
409    },
410    /// Literal pattern (e.g., 'a', 42, true)
411    Literal { id: HirId, value: LitValue, ty: Ty },
412    /// Or-pattern (e.g., `1 | 2 | 3`)
413    Or {
414        id: HirId,
415        patterns: Vec<Self>,
416        ty: Ty,
417    },
418    /// Range pattern (e.g., `1..=10`, `'a'..='z'`)
419    Range {
420        id: HirId,
421        lo: LitValue,
422        hi: LitValue,
423        inclusive: bool,
424        ty: Ty,
425    },
426}
427
428#[derive(Debug, Clone)]
429pub struct FieldPattern {
430    pub id: HirId,
431    pub name: Symbol,
432    pub pattern: Pattern,
433}
434
435/// Block expression
436#[derive(Debug, Clone)]
437pub struct Block {
438    pub id: HirId,
439    pub statements: Vec<Statement>,
440    pub expr: Option<Box<Expr>>,
441    pub ty: Ty,
442    pub span: Span,
443}
444
445/// Expression (with explicit types)
446#[derive(Debug, Clone)]
447pub struct Expr {
448    pub id: HirId,
449    pub kind: ExprKind,
450    pub ty: Ty,
451    pub span: Span,
452}
453
454#[derive(Debug, Clone)]
455pub enum ExprKind {
456    /// Literal value
457    Literal(Literal),
458
459    /// Variable reference (resolved to definition)
460    Var { def_id: HirId, name: Symbol },
461
462    /// Binary operation
463    Binary {
464        op: BinOp,
465        left: Box<Expr>,
466        right: Box<Expr>,
467    },
468
469    /// Unary operation
470    Unary { op: UnOp, expr: Box<Expr> },
471
472    /// Function call
473    Call { func: Box<Expr>, args: Vec<Expr> },
474
475    /// Method call
476    MethodCall {
477        receiver: Box<Expr>,
478        method: Symbol,
479        args: Vec<Expr>,
480    },
481
482    /// Field access
483    Field {
484        expr: Box<Expr>,
485        field: Symbol,
486        field_idx: usize,
487    },
488
489    /// Index
490    Index { expr: Box<Expr>, index: Box<Expr> },
491
492    /// Multi-dimensional index: arr[i, j], arr[1..5, ::2]
493    MultiDimIndex {
494        expr: Box<Expr>,
495        indices: Vec<HirIndexComponent>,
496    },
497
498    /// Tuple
499    Tuple { elements: Vec<Expr> },
500
501    /// Array
502    Array { elements: Vec<Expr> },
503
504    /// Array repeat [value; count]
505    ArrayRepeat { element: Box<Expr>, count: u64 },
506
507    /// Struct literal (variant_name is set for enum variant struct literals like `Enum::Variant { .. }`)
508    Struct {
509        def_id: HirId,
510        fields: Vec<FieldInit>,
511        variant_name: Option<Symbol>,
512    },
513
514    /// Block
515    Block(Block),
516
517    /// If expression
518    If {
519        condition: Box<Expr>,
520        then_block: Block,
521        else_block: Option<Box<Expr>>,
522    },
523
524    /// Match expression
525    Match {
526        expr: Box<Expr>,
527        arms: Vec<MatchArm>,
528    },
529
530    /// Loop
531    Loop { body: Block },
532
533    /// While loop
534    While { condition: Box<Expr>, body: Block },
535
536    /// For loop
537    For {
538        pattern: Pattern,
539        iter: Box<Expr>,
540        body: Block,
541    },
542
543    /// Return
544    Return { value: Option<Box<Expr>> },
545
546    /// Break
547    Break { value: Option<Box<Expr>> },
548
549    /// Continue
550    Continue,
551
552    /// Assignment
553    Assign { target: Box<Expr>, value: Box<Expr> },
554
555    /// Reference &x or &mut x
556    Ref { mutable: bool, expr: Box<Expr> },
557
558    /// Dereference *x
559    Deref { expr: Box<Expr> },
560
561    /// Type cast x as T
562    Cast { expr: Box<Expr>, target_ty: Ty },
563
564    // ===== Concurrency Expressions =====
565    /// Spawn a task
566    Spawn { expr: Box<Expr> },
567
568    /// Spawn with deadline
569    SpawnWithDeadline { deadline: Box<Expr>, body: Block },
570
571    /// Task group (structured concurrency)
572    TaskGroup { body: Block },
573
574    /// Task group collecting all results
575    TaskGroupAll { body: Block },
576
577    /// Channel creation
578    Channel { element_ty: Ty, capacity: Box<Expr> },
579
580    /// Select (random among ready)
581    Select { arms: Vec<HirSelectArm> },
582
583    /// Biased select (first-listed priority)
584    SelectBiased { arms: Vec<HirSelectArm> },
585
586    /// GPU execution block
587    Gpu { body: Block },
588
589    /// Distributed execution block
590    Distributed { body: Block },
591
592    /// Energy budget block: energy_budget(max_joules = 0.001) { ... }
593    EnergyBudgetBlock {
594        budget: EnergyBudgetConstraint,
595        body: Block,
596    },
597
598    /// Thermal adaptation: thermal_adapt { Cool => { ... }, Hot => { ... } }
599    ThermalAdapt { arms: Vec<HirThermalArm> },
600
601    /// Await expression: expr.await (extracts value from Future/Task)
602    Await { expr: Box<Expr> },
603
604    /// Try operator: expr?
605    Try { expr: Box<Expr> },
606
607    /// Remote spawn
608    SpawnRemote { node: Box<Expr>, expr: Box<Expr> },
609
610    /// Check if current task is cancelled
611    Cancelled,
612
613    /// Qualified path (like `EnumName::VariantName`)
614    Path { segments: Vec<Symbol> },
615
616    /// Closure expression
617    Closure {
618        params: Vec<Param>,
619        return_ty: Ty,
620        body: Box<Expr>,
621        captures: Vec<Capture>,
622        is_move: bool,
623    },
624
625    /// Perform an algebraic effect operation: `perform IO::read()`
626    Perform {
627        effect_name: Symbol,
628        operation: Symbol,
629        args: Vec<Expr>,
630    },
631
632    /// Handle algebraic effects: `handle { body } with { IO => handler }`
633    Handle {
634        body: Block,
635        handlers: Vec<HirEffectHandler>,
636    },
637
638    /// Parallel for loop: `parallel for x in iter { body }`
639    Parallel {
640        pattern: Pattern,
641        iter: Box<Expr>,
642        body: Block,
643    },
644
645    /// Result builder expression: `build TypeName { stmt1; stmt2; ... }`
646    Build {
647        builder_ty: Ty,
648        body: Block,
649    },
650}
651
652/// Match arm
653#[derive(Debug, Clone)]
654pub struct MatchArm {
655    pub id: HirId,
656    pub pattern: Pattern,
657    pub guard: Option<Expr>,
658    pub body: Expr,
659}
660
661/// Energy budget constraint for block-level energy checking
662#[derive(Debug, Clone)]
663pub struct EnergyBudgetConstraint {
664    pub max_joules: Option<f64>,
665    pub max_watts: Option<f64>,
666    pub max_temp_delta: Option<f64>,
667}
668
669/// Thermal adaptation arm
670#[derive(Debug, Clone)]
671pub struct HirThermalArm {
672    pub id: HirId,
673    /// Thermal state name: Cool, Nominal, Elevated, Hot, Critical
674    pub state: Symbol,
675    pub body: Expr,
676}
677
678/// An effect handler clause in the HIR
679#[derive(Debug, Clone)]
680pub struct HirEffectHandler {
681    pub id: HirId,
682    /// The effect being handled
683    pub effect_name: Symbol,
684    /// Handler expression (closure or block)
685    pub handler: Expr,
686}
687
688/// Algebraic effect definition in HIR
689#[derive(Debug, Clone)]
690pub struct EffectDef {
691    pub id: HirId,
692    pub name: Symbol,
693    pub operations: Vec<EffectOpDef>,
694}
695
696/// A single operation within an effect definition
697#[derive(Debug, Clone)]
698pub struct EffectOpDef {
699    pub id: HirId,
700    pub name: Symbol,
701    pub params: Vec<Param>,
702    pub return_ty: Ty,
703}
704
705/// Supervisor tree definition in HIR
706#[derive(Debug, Clone)]
707pub struct SupervisorDef {
708    pub id: HirId,
709    pub name: Symbol,
710    pub strategy: HirSupervisorStrategy,
711    pub children: Vec<HirSupervisorChild>,
712}
713
714/// Supervisor strategy in HIR
715#[derive(Debug, Clone, Copy, PartialEq, Eq)]
716pub enum HirSupervisorStrategy {
717    OneForOne,
718    OneForAll,
719    RestForOne,
720}
721
722/// Supervisor child specification in HIR
723#[derive(Debug, Clone)]
724pub struct HirSupervisorChild {
725    pub id: HirId,
726    pub name: Symbol,
727    pub func: Expr,
728    pub restart: HirChildRestart,
729}
730
731/// Child restart policy in HIR
732#[derive(Debug, Clone, Copy, PartialEq, Eq)]
733pub enum HirChildRestart {
734    Permanent,
735    Temporary,
736    Transient,
737}
738
739/// Select arm for channel selection
740#[derive(Debug, Clone)]
741pub struct HirSelectArm {
742    pub id: HirId,
743    pub operation: HirSelectOperation,
744    pub binding: Option<Pattern>,
745    pub body: Expr,
746    pub span: Span,
747}
748
749/// Channel operation in a select arm
750#[derive(Debug, Clone)]
751pub enum HirSelectOperation {
752    /// Receive from channel
753    Recv { channel: Expr },
754    /// Send to channel
755    Send { channel: Expr, value: Expr },
756    /// Timeout
757    Timeout { duration: Expr },
758}
759
760/// Captured variable from enclosing scope
761#[derive(Debug, Clone)]
762pub struct Capture {
763    pub def_id: HirId,
764    pub name: Symbol,
765    pub ty: Ty,
766    pub by_ref: bool,
767}
768
769/// Field initialization
770#[derive(Debug, Clone)]
771pub struct FieldInit {
772    pub id: HirId,
773    pub name: Symbol,
774    pub value: Expr,
775    pub field_idx: usize,
776}
777
778/// Literal values
779#[derive(Debug, Clone, PartialEq)]
780pub enum Literal {
781    Int(i64, IntTy),
782    Uint(u64, UintTy),
783    Float(f64, FloatTy),
784    String(String),
785    Char(char),
786    Bool(bool),
787}
788
789/// Binary operators
790#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
791pub enum BinOp {
792    // Arithmetic
793    Add,
794    Sub,
795    Mul,
796    Div,
797    Rem,
798    // Bitwise
799    BitAnd,
800    BitOr,
801    BitXor,
802    Shl,
803    Shr,
804    // Logical
805    And,
806    Or,
807    // Comparison
808    Eq,
809    Ne,
810    Lt,
811    Le,
812    Gt,
813    Ge,
814}
815
816/// Unary operators
817#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
818pub enum UnOp {
819    Neg,
820    Not,
821}
822
823/// A single component of a multi-dimensional index in HIR.
824#[derive(Debug, Clone)]
825pub enum HirIndexComponent {
826    /// Single index expression
827    Single(Expr),
828    /// Range with optional start, end, step
829    Range {
830        start: Option<Box<Expr>>,
831        end: Option<Box<Expr>>,
832        step: Option<Box<Expr>>,
833        inclusive: bool,
834    },
835    /// Full dimension (select all elements along this axis)
836    Full,
837}
838
839impl Ty {
840    /// Check if this type is an integer type
841    pub const fn is_int(&self) -> bool {
842        matches!(self, Self::Int(_) | Self::Uint(_))
843    }
844
845    /// Check if this type is a float type
846    pub const fn is_float(&self) -> bool {
847        matches!(self, Self::Float(_))
848    }
849
850    /// Check if this type is numeric
851    pub fn is_numeric(&self) -> bool {
852        self.is_int() || self.is_float()
853    }
854
855    /// Check if this type is copyable
856    pub fn is_copy(&self) -> bool {
857        match self {
858            Self::Int(_)
859            | Self::Uint(_)
860            | Self::Float(_)
861            | Self::Bool
862            | Self::Char
863            | Self::Unit => true,
864            Self::Ref { .. } => true,
865            Self::Tuple(tys) => tys.iter().all(Ty::is_copy),
866            _ => false,
867        }
868    }
869
870    /// Get the default value for this type (for uninitialized variables)
871    pub const fn default_value(&self) -> Option<Literal> {
872        match self {
873            Self::Int(int_ty) => Some(Literal::Int(0, *int_ty)),
874            Self::Uint(uint_ty) => Some(Literal::Uint(0, *uint_ty)),
875            Self::Float(float_ty) => Some(Literal::Float(0.0, *float_ty)),
876            Self::Bool => Some(Literal::Bool(false)),
877            Self::Char => Some(Literal::Char('\0')),
878            _ => None,
879        }
880    }
881}
882
883impl Pattern {
884    /// Get the type of this pattern
885    pub const fn ty(&self) -> &Ty {
886        match self {
887            Self::Ident { ty, .. } => ty,
888            Self::Wildcard { ty, .. } => ty,
889            Self::Tuple { ty, .. } => ty,
890            Self::Struct { ty, .. } => ty,
891            Self::Variant { ty, .. } => ty,
892            Self::Literal { ty, .. } => ty,
893            Self::Or { ty, .. } => ty,
894            Self::Range { ty, .. } => ty,
895        }
896    }
897}
898
899#[cfg(test)]
900mod tests {
901    use super::*;
902
903    #[test]
904    fn test_ty_is_numeric() {
905        assert!(Ty::Int(IntTy::I32).is_numeric());
906        assert!(Ty::Float(FloatTy::F64).is_numeric());
907        assert!(!Ty::Bool.is_numeric());
908    }
909
910    #[test]
911    fn test_ty_is_copy() {
912        assert!(Ty::Int(IntTy::I32).is_copy());
913        assert!(Ty::Bool.is_copy());
914        assert!(!Ty::String.is_copy());
915        assert!(
916            Ty::Ref {
917                mutable: false,
918                inner: Box::new(Ty::Int(IntTy::I32))
919            }
920            .is_copy()
921        );
922    }
923
924    #[test]
925    fn test_ty_default_value() {
926        assert_eq!(
927            Ty::Int(IntTy::I32).default_value(),
928            Some(Literal::Int(0, IntTy::I32))
929        );
930        assert_eq!(Ty::Bool.default_value(), Some(Literal::Bool(false)));
931        assert_eq!(Ty::String.default_value(), None);
932    }
933}