1use joule_common::{Span, Symbol};
11use std::collections::HashMap;
12
13pub mod energy;
14pub use energy::{EnergyMetadata, EnergyViolation, EnergyViolationKind, HirEnergyBudget};
15
16#[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#[derive(Debug, Clone)]
28pub struct Hir {
29 pub items: Vec<Item>,
30 pub type_map: HashMap<HirId, Ty>,
31 pub type_aliases: HashMap<Symbol, Ty>,
33}
34
35#[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 Effect(EffectDef),
47 Supervisor(SupervisorDef),
49}
50
51#[derive(Debug, Clone, Default)]
53pub struct FunctionAttributes {
54 pub is_gpu_kernel: bool,
56 pub is_thermal_aware: bool,
58 pub target: Option<ProcessorTarget>,
60 pub inline: InlineHint,
62 pub is_cold: bool,
64 pub is_test: bool,
66 pub is_bench: bool,
68 pub is_ignored: bool,
70 pub raw: Vec<(String, Vec<(String, String)>)>,
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub enum ProcessorTarget {
77 Cpu,
78 Gpu,
79 Tpu,
80 Npu,
81 Auto,
82}
83
84#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
86pub enum InlineHint {
87 #[default]
88 None,
89 Hint,
90 Always,
91 Never,
92}
93
94#[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 pub is_extern: bool,
104 pub is_async: bool,
106 pub is_const: bool,
108 pub energy: EnergyMetadata,
110 pub attributes: FunctionAttributes,
112 pub span: Span,
113}
114
115#[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#[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#[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#[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#[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#[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#[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#[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#[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#[derive(Debug, Clone, PartialEq, Eq, Hash)]
229pub enum Ty {
230 Int(IntTy),
232 Uint(UintTy),
234 Float(FloatTy),
236 Bool,
238 Char,
240 String,
242 Ref { mutable: bool, inner: Box<Self> },
244 Array { element: Box<Self>, size: u64 },
246 Slice { element: Box<Self> },
248 Tuple(Vec<Self>),
250 Function {
252 params: Vec<Self>,
253 return_ty: Box<Self>,
254 },
255 Named { def_id: HirId, name: Symbol },
257 Generic {
259 def_id: HirId,
260 name: Symbol,
261 args: Vec<Self>,
262 },
263 TypeParam { index: u32, name: Symbol },
265 Unit,
267 Never,
269 Infer(InferTy),
271 Error,
273
274 TraitObject { trait_name: Symbol },
276
277 Task { result_ty: Box<Self> },
280 TaskGroup,
282 Channel { element_ty: Box<Self> },
284 Sender { element_ty: Box<Self> },
286 Receiver { element_ty: Box<Self> },
288
289 Future { result_ty: Box<Self> },
291
292 Closure {
294 id: HirId,
295 params: Vec<Self>,
296 return_ty: Box<Self>,
297 capture_tys: Vec<Self>,
298 },
299
300 Union { variants: Vec<Self> },
302
303 Opaque { name: Symbol, def_id: HirId },
305
306 NDArray { element: Box<Self>, rank: u32 },
309 NDView { element: Box<Self>, rank: u32 },
311 CowArray { element: Box<Self>, rank: u32 },
313 DynArray { element: Box<Self> },
315
316 SmallVec { element: Box<Self>, capacity: u32 },
319 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#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
351pub struct InferTy(pub u32);
352
353#[derive(Debug, Clone)]
355pub enum Statement {
356 Let {
358 id: HirId,
359 pattern: Pattern,
360 ty: Ty,
361 init: Option<Expr>,
362 span: Span,
363 },
364 Expr(Expr),
366}
367
368#[derive(Debug, Clone)]
370pub enum LitValue {
371 Int(i128),
372 Char(char),
373 Bool(bool),
374 String(String),
375}
376
377#[derive(Debug, Clone)]
379pub enum Pattern {
380 Ident {
382 id: HirId,
383 name: Symbol,
384 mutable: bool,
385 ty: Ty,
386 },
387 Wildcard { id: HirId, ty: Ty },
389 Tuple {
391 id: HirId,
392 patterns: Vec<Self>,
393 ty: Ty,
394 },
395 Struct {
397 id: HirId,
398 def_id: HirId,
399 fields: Vec<FieldPattern>,
400 ty: Ty,
401 },
402 Variant {
404 id: HirId,
405 enum_name: Symbol,
406 variant_name: Symbol,
407 fields: Vec<Self>,
408 ty: Ty,
409 },
410 Literal { id: HirId, value: LitValue, ty: Ty },
412 Or {
414 id: HirId,
415 patterns: Vec<Self>,
416 ty: Ty,
417 },
418 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#[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#[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(Literal),
458
459 Var { def_id: HirId, name: Symbol },
461
462 Binary {
464 op: BinOp,
465 left: Box<Expr>,
466 right: Box<Expr>,
467 },
468
469 Unary { op: UnOp, expr: Box<Expr> },
471
472 Call { func: Box<Expr>, args: Vec<Expr> },
474
475 MethodCall {
477 receiver: Box<Expr>,
478 method: Symbol,
479 args: Vec<Expr>,
480 },
481
482 Field {
484 expr: Box<Expr>,
485 field: Symbol,
486 field_idx: usize,
487 },
488
489 Index { expr: Box<Expr>, index: Box<Expr> },
491
492 MultiDimIndex {
494 expr: Box<Expr>,
495 indices: Vec<HirIndexComponent>,
496 },
497
498 Tuple { elements: Vec<Expr> },
500
501 Array { elements: Vec<Expr> },
503
504 ArrayRepeat { element: Box<Expr>, count: u64 },
506
507 Struct {
509 def_id: HirId,
510 fields: Vec<FieldInit>,
511 variant_name: Option<Symbol>,
512 },
513
514 Block(Block),
516
517 If {
519 condition: Box<Expr>,
520 then_block: Block,
521 else_block: Option<Box<Expr>>,
522 },
523
524 Match {
526 expr: Box<Expr>,
527 arms: Vec<MatchArm>,
528 },
529
530 Loop { body: Block },
532
533 While { condition: Box<Expr>, body: Block },
535
536 For {
538 pattern: Pattern,
539 iter: Box<Expr>,
540 body: Block,
541 },
542
543 Return { value: Option<Box<Expr>> },
545
546 Break { value: Option<Box<Expr>> },
548
549 Continue,
551
552 Assign { target: Box<Expr>, value: Box<Expr> },
554
555 Ref { mutable: bool, expr: Box<Expr> },
557
558 Deref { expr: Box<Expr> },
560
561 Cast { expr: Box<Expr>, target_ty: Ty },
563
564 Spawn { expr: Box<Expr> },
567
568 SpawnWithDeadline { deadline: Box<Expr>, body: Block },
570
571 TaskGroup { body: Block },
573
574 TaskGroupAll { body: Block },
576
577 Channel { element_ty: Ty, capacity: Box<Expr> },
579
580 Select { arms: Vec<HirSelectArm> },
582
583 SelectBiased { arms: Vec<HirSelectArm> },
585
586 Gpu { body: Block },
588
589 Distributed { body: Block },
591
592 EnergyBudgetBlock {
594 budget: EnergyBudgetConstraint,
595 body: Block,
596 },
597
598 ThermalAdapt { arms: Vec<HirThermalArm> },
600
601 Await { expr: Box<Expr> },
603
604 Try { expr: Box<Expr> },
606
607 SpawnRemote { node: Box<Expr>, expr: Box<Expr> },
609
610 Cancelled,
612
613 Path { segments: Vec<Symbol> },
615
616 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 {
627 effect_name: Symbol,
628 operation: Symbol,
629 args: Vec<Expr>,
630 },
631
632 Handle {
634 body: Block,
635 handlers: Vec<HirEffectHandler>,
636 },
637
638 Parallel {
640 pattern: Pattern,
641 iter: Box<Expr>,
642 body: Block,
643 },
644
645 Build {
647 builder_ty: Ty,
648 body: Block,
649 },
650}
651
652#[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#[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#[derive(Debug, Clone)]
671pub struct HirThermalArm {
672 pub id: HirId,
673 pub state: Symbol,
675 pub body: Expr,
676}
677
678#[derive(Debug, Clone)]
680pub struct HirEffectHandler {
681 pub id: HirId,
682 pub effect_name: Symbol,
684 pub handler: Expr,
686}
687
688#[derive(Debug, Clone)]
690pub struct EffectDef {
691 pub id: HirId,
692 pub name: Symbol,
693 pub operations: Vec<EffectOpDef>,
694}
695
696#[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#[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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
716pub enum HirSupervisorStrategy {
717 OneForOne,
718 OneForAll,
719 RestForOne,
720}
721
722#[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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
733pub enum HirChildRestart {
734 Permanent,
735 Temporary,
736 Transient,
737}
738
739#[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#[derive(Debug, Clone)]
751pub enum HirSelectOperation {
752 Recv { channel: Expr },
754 Send { channel: Expr, value: Expr },
756 Timeout { duration: Expr },
758}
759
760#[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#[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#[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#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
791pub enum BinOp {
792 Add,
794 Sub,
795 Mul,
796 Div,
797 Rem,
798 BitAnd,
800 BitOr,
801 BitXor,
802 Shl,
803 Shr,
804 And,
806 Or,
807 Eq,
809 Ne,
810 Lt,
811 Le,
812 Gt,
813 Ge,
814}
815
816#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
818pub enum UnOp {
819 Neg,
820 Not,
821}
822
823#[derive(Debug, Clone)]
825pub enum HirIndexComponent {
826 Single(Expr),
828 Range {
830 start: Option<Box<Expr>>,
831 end: Option<Box<Expr>>,
832 step: Option<Box<Expr>>,
833 inclusive: bool,
834 },
835 Full,
837}
838
839impl Ty {
840 pub const fn is_int(&self) -> bool {
842 matches!(self, Self::Int(_) | Self::Uint(_))
843 }
844
845 pub const fn is_float(&self) -> bool {
847 matches!(self, Self::Float(_))
848 }
849
850 pub fn is_numeric(&self) -> bool {
852 self.is_int() || self.is_float()
853 }
854
855 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 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 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}