1use joule_common::{Span, Symbol};
7use std::fmt;
8
9pub mod generics;
10pub use generics::*;
11
12pub mod energy;
13pub use energy::*;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
17pub enum Visibility {
18 #[default]
20 Private,
21 Public,
23}
24
25#[derive(Debug, Clone, PartialEq)]
27pub struct File {
28 pub items: Vec<Item>,
29}
30
31#[derive(Debug, Clone, PartialEq)]
33pub enum Item {
34 Function(Function),
35 Struct(Struct),
36 Enum(Enum),
37 Trait(Trait),
38 Impl(Impl),
39 Use(Use),
40 Const(Const),
41 Static(Static),
42 TypeAlias(TypeAlias),
43 Module(ModuleDecl),
44 OpaqueType(OpaqueType),
46 Extend(Extend),
48 Effect(EffectDecl),
50 Supervisor(SupervisorDecl),
52}
53
54#[derive(Debug, Clone, PartialEq)]
56pub struct ModuleDecl {
57 pub visibility: Visibility,
58 pub name: Ident,
59 pub contents: Option<File>,
61 pub span: Span,
62}
63
64#[derive(Debug, Clone, PartialEq)]
69pub struct OpaqueType {
70 pub visibility: Visibility,
71 pub name: Ident,
72 pub generics: GenericParams,
73 pub underlying: Type,
74 pub span: Span,
75}
76
77#[derive(Debug, Clone, PartialEq)]
81pub struct Extend {
82 pub ty: Type,
83 pub methods: Vec<Function>,
84 pub span: Span,
85}
86
87#[derive(Debug, Clone, PartialEq)]
92pub struct EffectDecl {
93 pub visibility: Visibility,
94 pub name: Ident,
95 pub operations: Vec<EffectOperation>,
96 pub span: Span,
97}
98
99#[derive(Debug, Clone, PartialEq)]
101pub struct EffectOperation {
102 pub name: Ident,
103 pub params: Vec<Param>,
104 pub return_type: Option<Type>,
105 pub span: Span,
106}
107
108#[derive(Debug, Clone, PartialEq)]
112pub struct SupervisorDecl {
113 pub visibility: Visibility,
114 pub name: Ident,
115 pub strategy: SupervisorStrategy,
116 pub children: Vec<SupervisorChild>,
117 pub span: Span,
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq)]
122pub enum SupervisorStrategy {
123 OneForOne,
125 OneForAll,
127 RestForOne,
129}
130
131#[derive(Debug, Clone, PartialEq)]
133pub struct SupervisorChild {
134 pub name: Ident,
135 pub func: Expr,
136 pub restart: ChildRestart,
137 pub span: Span,
138}
139
140#[derive(Debug, Clone, Copy, PartialEq, Eq)]
142pub enum ChildRestart {
143 Permanent,
145 Temporary,
147 Transient,
149}
150
151#[derive(Debug, Clone, PartialEq)]
153pub struct TypeAlias {
154 pub visibility: Visibility,
155 pub name: Ident,
156 pub generics: GenericParams,
157 pub ty: Type,
158 pub span: Span,
159}
160
161#[derive(Debug, Clone, Copy, PartialEq, Eq)]
163pub enum ProcMacroKind {
164 FunctionLike,
166 Derive,
168 Attribute,
170}
171
172#[derive(Debug, Clone, PartialEq)]
174pub struct Function {
175 pub visibility: Visibility,
176 pub name: Ident,
177 pub generics: GenericParams,
178 pub params: Vec<Param>,
179 pub return_type: Option<Type>,
180 pub where_clause: WhereClause,
181 pub body: Option<Block>,
183 pub is_extern: bool,
185 pub is_async: bool,
187 pub is_const: bool,
189 pub attributes: Vec<Attribute>,
191 pub energy_budget: Option<EnergyBudget>,
193 pub proc_macro_kind: Option<ProcMacroKind>,
195 pub span: Span,
196}
197
198#[derive(Debug, Clone, PartialEq)]
200pub struct Param {
201 pub pattern: Pattern,
202 pub ty: Type,
203 pub span: Span,
204}
205
206#[derive(Debug, Clone, PartialEq)]
208pub struct ClosureParam {
209 pub pattern: Pattern,
210 pub ty: Option<Type>,
211 pub span: Span,
212}
213
214#[derive(Debug, Clone, PartialEq)]
216pub struct Struct {
217 pub visibility: Visibility,
218 pub name: Ident,
219 pub generics: GenericParams,
220 pub fields: Vec<Field>,
221 pub where_clause: WhereClause,
222 pub attributes: Vec<Attribute>,
223 pub span: Span,
224}
225
226#[derive(Debug, Clone, PartialEq)]
228pub struct Field {
229 pub visibility: Visibility,
230 pub name: Ident,
231 pub ty: Type,
232 pub span: Span,
233}
234
235#[derive(Debug, Clone, PartialEq)]
237pub struct Enum {
238 pub visibility: Visibility,
239 pub name: Ident,
240 pub generics: GenericParams,
241 pub variants: Vec<Variant>,
242 pub where_clause: WhereClause,
243 pub span: Span,
244}
245
246#[derive(Debug, Clone, PartialEq)]
248pub struct Variant {
249 pub name: Ident,
250 pub fields: VariantFields,
251 pub span: Span,
252}
253
254#[derive(Debug, Clone, PartialEq)]
255pub enum VariantFields {
256 Unit, Tuple(Vec<Type>), Struct(Vec<Field>), }
260
261#[derive(Debug, Clone, PartialEq)]
263pub struct Trait {
264 pub visibility: Visibility,
265 pub name: Ident,
266 pub generics: GenericParams,
267 pub items: Vec<TraitItem>,
268 pub where_clause: WhereClause,
269 pub span: Span,
270}
271
272#[derive(Debug, Clone, PartialEq)]
273pub enum TraitItem {
274 Function(TraitFunction),
275 TypeAlias {
276 name: Ident,
277 bounds: Vec<TypeBound>,
278 span: Span,
279 },
280}
281
282#[derive(Debug, Clone, PartialEq)]
283pub struct TraitFunction {
284 pub name: Ident,
285 pub generics: GenericParams,
286 pub params: Vec<Param>,
287 pub return_type: Option<Type>,
288 pub where_clause: WhereClause,
289 pub body: Option<Block>, pub span: Span,
291}
292
293#[derive(Debug, Clone, PartialEq)]
295pub struct Impl {
296 pub generics: GenericParams,
297 pub ty: Type,
298 pub trait_: Option<Type>, pub items: Vec<ImplItem>,
300 pub where_clause: WhereClause,
301 pub span: Span,
302}
303
304#[derive(Debug, Clone, PartialEq)]
305pub enum ImplItem {
306 Function(Function),
307}
308
309#[derive(Debug, Clone, PartialEq)]
311pub struct Use {
312 pub tree: UseTree,
313 pub span: Span,
314}
315
316#[derive(Debug, Clone, PartialEq)]
318pub enum UseTree {
319 Path { path: Path, alias: Option<Ident> },
321 Glob { path: Path },
323 Group { path: Path, items: Vec<Self> },
325}
326
327#[derive(Debug, Clone, PartialEq)]
329pub struct Const {
330 pub visibility: Visibility,
331 pub name: Ident,
332 pub ty: Type,
333 pub value: Expr,
334 pub span: Span,
335}
336
337#[derive(Debug, Clone, PartialEq)]
339pub struct Static {
340 pub visibility: Visibility,
341 pub name: Ident,
342 pub ty: Type,
343 pub value: Expr,
344 pub mutable: bool,
345 pub span: Span,
346}
347
348#[derive(Debug, Clone, PartialEq)]
350pub enum Type {
351 Path {
353 path: Path,
354 generics: Option<GenericArgs>,
355 },
356 Reference { mutable: bool, inner: Box<Self> },
358 Array { element: Box<Self>, size: Box<Expr> },
360 Slice { element: Box<Self> },
362 Tuple(Vec<Self>),
364 Function {
366 params: Vec<Self>,
367 return_type: Box<Self>,
368 },
369 Unit,
371 Never,
373 SelfType,
375 TraitObject { trait_name: Path, span: Span },
377 Union { types: Vec<Self>, span: Span },
379}
380
381#[derive(Debug, Clone, PartialEq, Eq)]
383pub struct Path {
384 pub segments: Vec<Ident>,
385 pub span: Span,
386}
387
388#[derive(Debug, Clone, PartialEq, Eq, Hash)]
390pub struct Ident {
391 pub symbol: Symbol,
392 pub span: Span,
393}
394
395impl Ident {
396 pub const fn new(symbol: Symbol, span: Span) -> Self {
397 Self { symbol, span }
398 }
399
400 pub fn as_str(&self) -> String {
401 self.symbol.as_str()
402 }
403}
404
405impl fmt::Display for Ident {
406 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
407 write!(f, "{}", self.symbol)
408 }
409}
410
411#[derive(Debug, Clone, PartialEq)]
413pub enum Statement {
414 Let {
416 pattern: Pattern,
417 ty: Option<Type>,
418 init: Option<Expr>,
419 span: Span,
420 },
421 Expr(Expr),
423 Item(Box<Item>),
425}
426
427#[derive(Debug, Clone, PartialEq)]
429pub enum Pattern {
430 Ident { name: Ident, mutable: bool },
432 Wildcard { span: Span },
434 Tuple { patterns: Vec<Self>, span: Span },
436 Struct {
438 path: Path,
439 fields: Vec<FieldPattern>,
440 span: Span,
441 },
442 Path { path: Path },
444 TupleVariant {
446 path: Path,
447 patterns: Vec<Self>,
448 span: Span,
449 },
450 Literal(Literal),
452 Or {
454 patterns: Vec<Self>,
455 span: Span,
456 },
457 Range {
459 lo: Literal,
460 hi: Literal,
461 inclusive: bool,
462 span: Span,
463 },
464}
465
466#[derive(Debug, Clone, PartialEq)]
467pub struct FieldPattern {
468 pub name: Ident,
469 pub pattern: Pattern,
470 pub span: Span,
471}
472
473#[derive(Debug, Clone, PartialEq)]
475pub struct Block {
476 pub statements: Vec<Statement>,
477 pub expr: Option<Box<Expr>>, pub span: Span,
479}
480
481#[derive(Debug, Clone, PartialEq)]
483pub enum Expr {
484 Literal(Literal),
486
487 Ident(Ident),
489
490 Path(Path),
492
493 Macro {
495 name: Path,
496 args: Vec<Self>,
497 span: Span,
498 },
499
500 Binary {
502 op: BinOp,
503 left: Box<Self>,
504 right: Box<Self>,
505 span: Span,
506 },
507
508 Unary {
510 op: UnOp,
511 expr: Box<Self>,
512 span: Span,
513 },
514
515 Call {
517 func: Box<Self>,
518 args: Vec<Self>,
519 span: Span,
520 },
521
522 MethodCall {
524 receiver: Box<Self>,
525 method: Ident,
526 args: Vec<Self>,
527 span: Span,
528 },
529
530 Field {
532 expr: Box<Self>,
533 field: Ident,
534 span: Span,
535 },
536
537 Index {
539 expr: Box<Self>,
540 index: Box<Self>,
541 span: Span,
542 },
543
544 MultiDimIndex {
546 expr: Box<Self>,
547 indices: Vec<IndexComponent>,
548 span: Span,
549 },
550
551 Range {
553 start: Option<Box<Self>>,
554 end: Option<Box<Self>>,
555 inclusive: bool,
556 span: Span,
557 },
558
559 Tuple { elements: Vec<Self>, span: Span },
561
562 Array { elements: Vec<Self>, span: Span },
564
565 ArrayRepeat {
567 element: Box<Self>,
568 count: Box<Self>,
569 span: Span,
570 },
571
572 Struct {
574 path: Path,
575 fields: Vec<FieldInit>,
576 span: Span,
577 },
578
579 Block(Block),
581
582 If {
584 condition: Box<Self>,
585 then_block: Block,
586 else_block: Option<Box<Self>>, span: Span,
588 },
589
590 Match {
592 expr: Box<Self>,
593 arms: Vec<MatchArm>,
594 span: Span,
595 },
596
597 Loop { body: Block, span: Span },
599
600 While {
602 condition: Box<Self>,
603 body: Block,
604 span: Span,
605 },
606
607 For {
609 pattern: Pattern,
610 iter: Box<Self>,
611 body: Block,
612 span: Span,
613 },
614
615 Return {
617 value: Option<Box<Self>>,
618 span: Span,
619 },
620
621 Break {
623 value: Option<Box<Self>>,
624 span: Span,
625 },
626
627 Continue { span: Span },
629
630 Assign {
632 target: Box<Self>,
633 value: Box<Self>,
634 span: Span,
635 },
636
637 AssignOp {
639 op: BinOp,
640 target: Box<Self>,
641 value: Box<Self>,
642 span: Span,
643 },
644
645 Reference {
647 mutable: bool,
648 expr: Box<Self>,
649 span: Span,
650 },
651
652 Dereference { expr: Box<Self>, span: Span },
654
655 Cast {
657 expr: Box<Self>,
658 ty: Type,
659 span: Span,
660 },
661
662 Spawn { expr: Box<Self>, span: Span },
665
666 SpawnWithDeadline {
668 deadline: Box<Self>,
669 body: Block,
670 span: Span,
671 },
672
673 TaskGroup { body: Block, span: Span },
675
676 TaskGroupAll { body: Block, span: Span },
678
679 Channel {
681 element_type: Option<Type>,
682 capacity: Box<Self>,
683 span: Span,
684 },
685
686 Select { arms: Vec<SelectArm>, span: Span },
688
689 SelectBiased { arms: Vec<SelectArm>, span: Span },
691
692 Gpu { body: Block, span: Span },
694
695 Distributed { body: Block, span: Span },
697
698 SpawnRemote {
700 node: Box<Self>,
701 expr: Box<Self>,
702 span: Span,
703 },
704
705 Cancelled { span: Span },
707
708 EnergyBudgetBlock {
710 budget: EnergyBudget,
711 body: Block,
712 span: Span,
713 },
714
715 ThermalAdapt { arms: Vec<ThermalArm>, span: Span },
717
718 Await { expr: Box<Self>, span: Span },
720
721 Try { expr: Box<Self>, span: Span },
723
724 Closure {
726 params: Vec<ClosureParam>,
727 return_type: Option<Type>,
728 body: Box<Self>,
729 is_move: bool,
730 span: Span,
731 },
732
733 Comptime { body: Block, span: Span },
735
736 Perform {
738 effect: Path,
739 args: Vec<Self>,
740 span: Span,
741 },
742
743 Handle {
745 body: Block,
746 handlers: Vec<EffectHandler>,
747 span: Span,
748 },
749
750 Parallel {
752 pattern: Pattern,
753 iter: Box<Self>,
754 body: Block,
755 span: Span,
756 },
757
758 Build {
764 builder_ty: Type,
765 body: Block,
766 span: Span,
767 },
768}
769
770#[derive(Debug, Clone, PartialEq)]
772pub struct MatchArm {
773 pub pattern: Pattern,
774 pub guard: Option<Expr>, pub body: Expr,
776 pub span: Span,
777}
778
779#[derive(Debug, Clone, PartialEq)]
781pub struct SelectArm {
782 pub operation: SelectOperation,
784 pub binding: Option<Pattern>,
786 pub body: Expr,
788 pub span: Span,
789}
790
791#[derive(Debug, Clone, PartialEq)]
793pub enum SelectOperation {
794 Recv { channel: Expr, span: Span },
796 Send {
798 channel: Expr,
799 value: Expr,
800 span: Span,
801 },
802 Timeout { duration: Expr, span: Span },
804}
805
806#[derive(Debug, Clone, PartialEq)]
808pub struct ThermalArm {
809 pub state: Ident,
811 pub body: Expr,
813 pub span: Span,
814}
815
816#[derive(Debug, Clone, PartialEq)]
818pub struct EffectHandler {
819 pub effect: Path,
821 pub handler: Expr,
823 pub span: Span,
824}
825
826#[derive(Debug, Clone, PartialEq)]
828pub struct FieldInit {
829 pub name: Ident,
830 pub value: Expr,
831 pub span: Span,
832}
833
834#[derive(Debug, Clone, PartialEq)]
836pub enum Literal {
837 Int(u64, Span),
838 Float(f64, Span),
839 String(String, Span),
840 Char(char, Span),
841 Bool(bool, Span),
842}
843
844impl Literal {
845 pub const fn span(&self) -> Span {
846 match self {
847 Self::Int(_, span) => *span,
848 Self::Float(_, span) => *span,
849 Self::String(_, span) => *span,
850 Self::Char(_, span) => *span,
851 Self::Bool(_, span) => *span,
852 }
853 }
854}
855
856#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
858pub enum BinOp {
859 Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Shl, Shr, And, Or, Eq, Ne, Lt, Le, Gt, Ge, }
885
886#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
888pub enum UnOp {
889 Neg, Not, }
892
893#[derive(Debug, Clone, PartialEq)]
900pub enum IndexComponent {
901 Single(Expr),
903 Range {
905 start: Option<Box<Expr>>,
906 end: Option<Box<Expr>>,
907 step: Option<Box<Expr>>,
908 inclusive: bool,
909 },
910 Full,
912}
913
914impl fmt::Display for BinOp {
915 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
916 let s = match self {
917 Self::Add => "+",
918 Self::Sub => "-",
919 Self::Mul => "*",
920 Self::Div => "/",
921 Self::Rem => "%",
922 Self::BitAnd => "&",
923 Self::BitOr => "|",
924 Self::BitXor => "^",
925 Self::Shl => "<<",
926 Self::Shr => ">>",
927 Self::And => "&&",
928 Self::Or => "||",
929 Self::Eq => "==",
930 Self::Ne => "!=",
931 Self::Lt => "<",
932 Self::Le => "<=",
933 Self::Gt => ">",
934 Self::Ge => ">=",
935 };
936 write!(f, "{s}")
937 }
938}
939
940impl fmt::Display for UnOp {
941 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
942 let s = match self {
943 Self::Neg => "-",
944 Self::Not => "!",
945 };
946 write!(f, "{s}")
947 }
948}
949
950impl Expr {
952 pub const fn span(&self) -> Span {
953 match self {
954 Self::Literal(lit) => lit.span(),
955 Self::Ident(ident) => ident.span,
956 Self::Path(path) => path.span,
957 Self::Macro { span, .. } => *span,
958 Self::Binary { span, .. } => *span,
959 Self::Unary { span, .. } => *span,
960 Self::Call { span, .. } => *span,
961 Self::MethodCall { span, .. } => *span,
962 Self::Field { span, .. } => *span,
963 Self::Index { span, .. } => *span,
964 Self::MultiDimIndex { span, .. } => *span,
965 Self::Range { span, .. } => *span,
966 Self::Tuple { span, .. } => *span,
967 Self::Array { span, .. } => *span,
968 Self::ArrayRepeat { span, .. } => *span,
969 Self::Struct { span, .. } => *span,
970 Self::Block(block) => block.span,
971 Self::If { span, .. } => *span,
972 Self::Match { span, .. } => *span,
973 Self::Loop { span, .. } => *span,
974 Self::While { span, .. } => *span,
975 Self::For { span, .. } => *span,
976 Self::Return { span, .. } => *span,
977 Self::Break { span, .. } => *span,
978 Self::Continue { span } => *span,
979 Self::Assign { span, .. } => *span,
980 Self::AssignOp { span, .. } => *span,
981 Self::Reference { span, .. } => *span,
982 Self::Dereference { span, .. } => *span,
983 Self::Cast { span, .. } => *span,
984 Self::Spawn { span, .. } => *span,
986 Self::SpawnWithDeadline { span, .. } => *span,
987 Self::TaskGroup { span, .. } => *span,
988 Self::TaskGroupAll { span, .. } => *span,
989 Self::Channel { span, .. } => *span,
990 Self::Select { span, .. } => *span,
991 Self::SelectBiased { span, .. } => *span,
992 Self::Gpu { span, .. } => *span,
993 Self::Distributed { span, .. } => *span,
994 Self::SpawnRemote { span, .. } => *span,
995 Self::Cancelled { span } => *span,
996 Self::EnergyBudgetBlock { span, .. } => *span,
997 Self::ThermalAdapt { span, .. } => *span,
998 Self::Await { span, .. } => *span,
999 Self::Try { span, .. } => *span,
1000 Self::Closure { span, .. } => *span,
1001 Self::Comptime { span, .. } => *span,
1002 Self::Perform { span, .. } => *span,
1003 Self::Handle { span, .. } => *span,
1004 Self::Parallel { span, .. } => *span,
1005 Self::Build { span, .. } => *span,
1006 }
1007 }
1008}
1009
1010impl Type {
1011 pub fn span(&self) -> Span {
1012 match self {
1013 Self::Path { path, generics } => {
1014 if let Some(args) = generics {
1015 path.span.to(args.span)
1016 } else {
1017 path.span
1018 }
1019 }
1020 Self::Reference { inner, .. } => inner.span(),
1021 Self::Array { element, size } => element.span().to(size.span()),
1022 Self::Slice { element } => element.span(),
1023 Self::Tuple(types) => {
1024 if let (Some(first), Some(last)) = (types.first(), types.last()) {
1025 first.span().to(last.span())
1026 } else {
1027 Span::new(0, 0, 0)
1028 }
1029 }
1030 Self::Function {
1031 params,
1032 return_type,
1033 } => {
1034 if let Some(first) = params.first() {
1035 first.span().to(return_type.span())
1036 } else {
1037 return_type.span()
1038 }
1039 }
1040 Self::Unit => Span::new(0, 0, 0),
1041 Self::Never => Span::new(0, 0, 0),
1042 Self::SelfType => Span::new(0, 0, 0),
1043 Self::TraitObject { span, .. } => *span,
1044 Self::Union { span, .. } => *span,
1045 }
1046 }
1047}
1048
1049impl Pattern {
1050 pub const fn span(&self) -> Span {
1051 match self {
1052 Self::Ident { name, .. } => name.span,
1053 Self::Wildcard { span } => *span,
1054 Self::Tuple { span, .. } => *span,
1055 Self::Struct { span, .. } => *span,
1056 Self::Path { path } => path.span,
1057 Self::TupleVariant { span, .. } => *span,
1058 Self::Literal(lit) => lit.span(),
1059 Self::Or { span, .. } => *span,
1060 Self::Range { span, .. } => *span,
1061 }
1062 }
1063}
1064
1065#[cfg(test)]
1066mod tests {
1067 use super::*;
1068 use joule_common::Symbol;
1069
1070 #[test]
1071 fn test_ident_creation() {
1072 let symbol = Symbol::from_u32(0);
1073 let span = Span::new(0, 3, 0);
1074 let ident = Ident::new(symbol, span);
1075
1076 assert_eq!(ident.span, span);
1077 }
1078
1079 #[test]
1080 fn test_literal_span() {
1081 let span = Span::new(0, 2, 0);
1082 let lit = Literal::Int(42, span);
1083 assert_eq!(lit.span(), span);
1084 }
1085
1086 #[test]
1087 fn test_binop_display() {
1088 assert_eq!(format!("{}", BinOp::Add), "+");
1089 assert_eq!(format!("{}", BinOp::Eq), "==");
1090 assert_eq!(format!("{}", BinOp::And), "&&");
1091 }
1092}