1use serde::{Deserialize, Serialize};
14
15pub const IR_VERSION: &str = "1.0.0";
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct IrModule {
21 pub version: String,
23 pub source: String,
25 pub functions: Vec<IrFunction>,
27 pub types: Vec<IrTypeDef>,
29 pub traits: Vec<IrTraitDef>,
31 pub impls: Vec<IrImplBlock>,
33 pub constants: Vec<IrConstant>,
35 pub evidentiality_lattice: EvidentialityLattice,
37}
38
39impl IrModule {
40 pub fn new(source: String) -> Self {
42 Self {
43 version: IR_VERSION.to_string(),
44 source,
45 functions: Vec::new(),
46 types: Vec::new(),
47 traits: Vec::new(),
48 impls: Vec::new(),
49 constants: Vec::new(),
50 evidentiality_lattice: EvidentialityLattice::default(),
51 }
52 }
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct EvidentialityLattice {
58 pub levels: Vec<EvidenceLevel>,
60 pub join_rules: Vec<LatticeRule>,
62 pub meet_rules: Vec<LatticeRule>,
64}
65
66impl Default for EvidentialityLattice {
67 fn default() -> Self {
68 Self {
69 levels: vec![
70 EvidenceLevel {
71 name: "known".to_string(),
72 symbol: "!".to_string(),
73 order: 0,
74 description: "Direct computation, verified".to_string(),
75 },
76 EvidenceLevel {
77 name: "uncertain".to_string(),
78 symbol: "?".to_string(),
79 order: 1,
80 description: "Inferred, possibly absent".to_string(),
81 },
82 EvidenceLevel {
83 name: "reported".to_string(),
84 symbol: "~".to_string(),
85 order: 2,
86 description: "External source, untrusted".to_string(),
87 },
88 EvidenceLevel {
89 name: "paradox".to_string(),
90 symbol: "‽".to_string(),
91 order: 3,
92 description: "Contradictory, trust boundary".to_string(),
93 },
94 ],
95 join_rules: vec![
96 LatticeRule::new("known", "uncertain", "uncertain"),
97 LatticeRule::new("known", "reported", "reported"),
98 LatticeRule::new("known", "paradox", "paradox"),
99 LatticeRule::new("uncertain", "reported", "reported"),
100 LatticeRule::new("uncertain", "paradox", "paradox"),
101 LatticeRule::new("reported", "paradox", "paradox"),
102 ],
103 meet_rules: vec![
104 LatticeRule::new("known", "uncertain", "known"),
105 LatticeRule::new("known", "reported", "known"),
106 LatticeRule::new("known", "paradox", "known"),
107 LatticeRule::new("uncertain", "reported", "uncertain"),
108 LatticeRule::new("uncertain", "paradox", "uncertain"),
109 LatticeRule::new("reported", "paradox", "reported"),
110 ],
111 }
112 }
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct EvidenceLevel {
118 pub name: String,
119 pub symbol: String,
120 pub order: u8,
121 pub description: String,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct LatticeRule {
127 pub left: String,
128 pub right: String,
129 pub result: String,
130}
131
132impl LatticeRule {
133 pub fn new(left: &str, right: &str, result: &str) -> Self {
134 Self {
135 left: left.to_string(),
136 right: right.to_string(),
137 result: result.to_string(),
138 }
139 }
140}
141
142#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
144#[serde(rename_all = "lowercase")]
145pub enum IrEvidence {
146 Known,
147 Uncertain,
148 Reported,
149 Paradox,
150}
151
152impl IrEvidence {
153 pub fn join(self, other: IrEvidence) -> IrEvidence {
155 match (self, other) {
156 (IrEvidence::Paradox, _) | (_, IrEvidence::Paradox) => IrEvidence::Paradox,
157 (IrEvidence::Reported, _) | (_, IrEvidence::Reported) => IrEvidence::Reported,
158 (IrEvidence::Uncertain, _) | (_, IrEvidence::Uncertain) => IrEvidence::Uncertain,
159 (IrEvidence::Known, IrEvidence::Known) => IrEvidence::Known,
160 }
161 }
162
163 pub fn meet(self, other: IrEvidence) -> IrEvidence {
165 match (self, other) {
166 (IrEvidence::Known, _) | (_, IrEvidence::Known) => IrEvidence::Known,
167 (IrEvidence::Uncertain, _) | (_, IrEvidence::Uncertain) => IrEvidence::Uncertain,
168 (IrEvidence::Reported, _) | (_, IrEvidence::Reported) => IrEvidence::Reported,
169 (IrEvidence::Paradox, IrEvidence::Paradox) => IrEvidence::Paradox,
170 }
171 }
172
173 pub fn symbol(&self) -> &'static str {
175 match self {
176 IrEvidence::Known => "!",
177 IrEvidence::Uncertain => "?",
178 IrEvidence::Reported => "~",
179 IrEvidence::Paradox => "‽",
180 }
181 }
182}
183
184impl Default for IrEvidence {
185 fn default() -> Self {
186 IrEvidence::Known
187 }
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct IrSpan {
193 pub start: IrPosition,
194 pub end: IrPosition,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct IrPosition {
199 pub line: usize,
200 pub column: usize,
201}
202
203#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
205#[serde(rename_all = "lowercase")]
206pub enum IrVisibility {
207 Public,
208 Private,
209 Crate,
210}
211
212impl Default for IrVisibility {
213 fn default() -> Self {
214 IrVisibility::Private
215 }
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct IrFunction {
221 pub name: String,
223 pub id: String,
225 pub visibility: IrVisibility,
227 pub generics: Vec<IrGenericParam>,
229 pub params: Vec<IrParam>,
231 pub return_type: IrType,
233 pub body: Option<IrOperation>,
235 pub attributes: Vec<String>,
237 pub is_async: bool,
239 #[serde(skip_serializing_if = "Option::is_none")]
241 pub span: Option<IrSpan>,
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct IrGenericParam {
247 pub name: String,
248 pub bounds: Vec<String>,
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct IrParam {
254 pub name: String,
255 #[serde(rename = "type")]
256 pub ty: IrType,
257 pub evidence: IrEvidence,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
262#[serde(tag = "kind")]
263pub enum IrType {
264 #[serde(rename = "primitive")]
266 Primitive { name: String },
267
268 #[serde(rename = "unit")]
270 Unit,
271
272 #[serde(rename = "never")]
274 Never,
275
276 #[serde(rename = "array")]
278 Array {
279 element: Box<IrType>,
280 size: Option<usize>,
281 },
282
283 #[serde(rename = "slice")]
285 Slice { element: Box<IrType> },
286
287 #[serde(rename = "tuple")]
289 Tuple { elements: Vec<IrType> },
290
291 #[serde(rename = "named")]
293 Named { name: String, generics: Vec<IrType> },
294
295 #[serde(rename = "reference")]
297 Reference { lifetime: Option<String>, mutable: bool, inner: Box<IrType> },
298
299 #[serde(rename = "pointer")]
301 Pointer { mutable: bool, inner: Box<IrType> },
302
303 #[serde(rename = "function")]
305 Function {
306 params: Vec<IrType>,
307 return_type: Box<IrType>,
308 is_async: bool,
309 },
310
311 #[serde(rename = "evidential")]
313 Evidential {
314 inner: Box<IrType>,
315 evidence: IrEvidence,
316 },
317
318 #[serde(rename = "cycle")]
320 Cycle { modulus: u64 },
321
322 #[serde(rename = "simd")]
324 Simd { element: Box<IrType>, lanes: usize },
325
326 #[serde(rename = "atomic")]
328 Atomic { inner: Box<IrType> },
329
330 #[serde(rename = "var")]
332 Var { id: String },
333
334 #[serde(rename = "infer")]
336 Infer,
337
338 #[serde(rename = "lifetime")]
340 Lifetime { name: String },
341
342 #[serde(rename = "trait_object")]
344 TraitObject { bounds: Vec<IrType> },
345
346 #[serde(rename = "hrtb")]
348 Hrtb {
349 lifetimes: Vec<String>,
350 bound: Box<IrType>,
351 },
352
353 #[serde(rename = "inline_struct")]
355 InlineStruct {
356 fields: Vec<(String, IrType)>,
357 },
358
359 #[serde(rename = "impl_trait")]
361 ImplTrait { bounds: Vec<IrType> },
362
363 #[serde(rename = "inline_enum")]
365 InlineEnum { variants: Vec<String> },
366
367 #[serde(rename = "assoc_type_binding")]
369 AssocTypeBinding { name: String, ty: Box<IrType> },
370
371 #[serde(rename = "error")]
373 Error,
374}
375
376impl Default for IrType {
377 fn default() -> Self {
378 IrType::Unit
379 }
380}
381
382#[derive(Debug, Clone, Serialize, Deserialize)]
384#[serde(tag = "kind")]
385pub enum IrTypeDef {
386 #[serde(rename = "struct_def")]
387 Struct {
388 name: String,
389 generics: Vec<IrGenericParam>,
390 fields: Vec<IrField>,
391 #[serde(skip_serializing_if = "Option::is_none")]
392 span: Option<IrSpan>,
393 },
394 #[serde(rename = "enum_def")]
395 Enum {
396 name: String,
397 generics: Vec<IrGenericParam>,
398 variants: Vec<IrVariant>,
399 #[serde(skip_serializing_if = "Option::is_none")]
400 span: Option<IrSpan>,
401 },
402 #[serde(rename = "type_alias")]
403 TypeAlias {
404 name: String,
405 generics: Vec<IrGenericParam>,
406 target: IrType,
407 #[serde(skip_serializing_if = "Option::is_none")]
408 span: Option<IrSpan>,
409 },
410}
411
412#[derive(Debug, Clone, Serialize, Deserialize)]
414pub struct IrField {
415 pub name: String,
416 #[serde(rename = "type")]
417 pub ty: IrType,
418 pub visibility: IrVisibility,
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize)]
423pub struct IrVariant {
424 pub name: String,
425 pub fields: Option<Vec<IrField>>,
426 pub discriminant: Option<i64>,
427}
428
429#[derive(Debug, Clone, Serialize, Deserialize)]
431pub struct IrTraitDef {
432 pub name: String,
433 pub generics: Vec<IrGenericParam>,
434 pub super_traits: Vec<String>,
435 pub methods: Vec<IrFunction>,
436 #[serde(skip_serializing_if = "Option::is_none")]
437 pub span: Option<IrSpan>,
438}
439
440#[derive(Debug, Clone, Serialize, Deserialize)]
442pub struct IrImplBlock {
443 #[serde(skip_serializing_if = "Option::is_none")]
444 pub trait_name: Option<String>,
445 pub target_type: IrType,
446 pub generics: Vec<IrGenericParam>,
447 pub methods: Vec<IrFunction>,
448 #[serde(skip_serializing_if = "Option::is_none")]
449 pub span: Option<IrSpan>,
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize)]
454pub struct IrConstant {
455 pub name: String,
456 #[serde(rename = "type")]
457 pub ty: IrType,
458 pub value: IrOperation,
459 pub visibility: IrVisibility,
460 #[serde(skip_serializing_if = "Option::is_none")]
461 pub span: Option<IrSpan>,
462}
463
464#[derive(Debug, Clone, Serialize, Deserialize)]
466#[serde(tag = "kind")]
467pub enum IrOperation {
468 #[serde(rename = "literal")]
470 Literal {
471 variant: LiteralVariant,
472 value: serde_json::Value,
473 #[serde(rename = "type")]
474 ty: IrType,
475 evidence: IrEvidence,
476 },
477
478 #[serde(rename = "var")]
480 Var {
481 name: String,
482 id: String,
483 #[serde(rename = "type")]
484 ty: IrType,
485 evidence: IrEvidence,
486 },
487
488 #[serde(rename = "let")]
490 Let {
491 pattern: IrPattern,
492 #[serde(skip_serializing_if = "Option::is_none")]
493 type_annotation: Option<IrType>,
494 init: Box<IrOperation>,
495 evidence: IrEvidence,
496 },
497
498 #[serde(rename = "binary")]
500 Binary {
501 operator: BinaryOp,
502 left: Box<IrOperation>,
503 right: Box<IrOperation>,
504 #[serde(rename = "type")]
505 ty: IrType,
506 evidence: IrEvidence,
507 },
508
509 #[serde(rename = "unary")]
511 Unary {
512 operator: UnaryOp,
513 operand: Box<IrOperation>,
514 #[serde(rename = "type")]
515 ty: IrType,
516 evidence: IrEvidence,
517 },
518
519 #[serde(rename = "call")]
521 Call {
522 function: String,
523 function_id: String,
524 args: Vec<IrOperation>,
525 #[serde(skip_serializing_if = "Vec::is_empty")]
526 type_args: Vec<IrType>,
527 #[serde(rename = "type")]
528 ty: IrType,
529 evidence: IrEvidence,
530 },
531
532 #[serde(rename = "method_call")]
533 MethodCall {
534 receiver: Box<IrOperation>,
535 method: String,
536 args: Vec<IrOperation>,
537 #[serde(skip_serializing_if = "Vec::is_empty")]
538 type_args: Vec<IrType>,
539 #[serde(rename = "type")]
540 ty: IrType,
541 evidence: IrEvidence,
542 },
543
544 #[serde(rename = "closure")]
546 Closure {
547 params: Vec<IrParam>,
548 body: Box<IrOperation>,
549 captures: Vec<String>,
550 #[serde(rename = "type")]
551 ty: IrType,
552 evidence: IrEvidence,
553 },
554
555 #[serde(rename = "if")]
557 If {
558 condition: Box<IrOperation>,
559 then_branch: Box<IrOperation>,
560 #[serde(skip_serializing_if = "Option::is_none")]
561 else_branch: Option<Box<IrOperation>>,
562 #[serde(rename = "type")]
563 ty: IrType,
564 evidence: IrEvidence,
565 },
566
567 #[serde(rename = "match")]
568 Match {
569 scrutinee: Box<IrOperation>,
570 arms: Vec<IrMatchArm>,
571 #[serde(rename = "type")]
572 ty: IrType,
573 evidence: IrEvidence,
574 },
575
576 #[serde(rename = "let_match")]
580 LetMatch {
581 pattern: IrPattern,
582 value: Box<IrOperation>,
583 #[serde(rename = "type")]
584 ty: IrType,
585 evidence: IrEvidence,
586 },
587
588 #[serde(rename = "loop")]
589 Loop {
590 variant: LoopVariant,
591 #[serde(skip_serializing_if = "Option::is_none")]
592 condition: Option<Box<IrOperation>>,
593 #[serde(skip_serializing_if = "Option::is_none")]
594 iterator: Option<IrForIterator>,
595 body: Box<IrOperation>,
596 #[serde(rename = "type")]
597 ty: IrType,
598 evidence: IrEvidence,
599 },
600
601 #[serde(rename = "break")]
602 Break {
603 #[serde(skip_serializing_if = "Option::is_none")]
604 value: Option<Box<IrOperation>>,
605 evidence: IrEvidence,
606 },
607
608 #[serde(rename = "continue")]
609 Continue { evidence: IrEvidence },
610
611 #[serde(rename = "return")]
612 Return {
613 #[serde(skip_serializing_if = "Option::is_none")]
614 value: Option<Box<IrOperation>>,
615 evidence: IrEvidence,
616 },
617
618 #[serde(rename = "block")]
620 Block {
621 statements: Vec<IrOperation>,
622 #[serde(rename = "type")]
623 ty: IrType,
624 evidence: IrEvidence,
625 },
626
627 #[serde(rename = "pipeline")]
629 Pipeline {
630 input: Box<IrOperation>,
631 steps: Vec<IrPipelineStep>,
632 #[serde(rename = "type")]
633 ty: IrType,
634 evidence: IrEvidence,
635 },
636
637 #[serde(rename = "morpheme")]
639 Morpheme {
640 morpheme: MorphemeKind,
641 symbol: String,
642 input: Box<IrOperation>,
643 #[serde(skip_serializing_if = "Option::is_none")]
644 body: Option<Box<IrOperation>>,
645 #[serde(rename = "type")]
646 ty: IrType,
647 evidence: IrEvidence,
648 },
649
650 #[serde(rename = "fork")]
652 Fork {
653 branches: Vec<IrOperation>,
654 join_strategy: JoinStrategy,
655 #[serde(rename = "type")]
656 ty: IrType,
657 evidence: IrEvidence,
658 },
659
660 #[serde(rename = "identity")]
661 Identity {
662 #[serde(rename = "type")]
663 ty: IrType,
664 evidence: IrEvidence,
665 },
666
667 #[serde(rename = "array")]
669 Array {
670 elements: Vec<IrOperation>,
671 #[serde(rename = "type")]
672 ty: IrType,
673 evidence: IrEvidence,
674 },
675
676 #[serde(rename = "tuple")]
677 Tuple {
678 elements: Vec<IrOperation>,
679 #[serde(rename = "type")]
680 ty: IrType,
681 evidence: IrEvidence,
682 },
683
684 #[serde(rename = "struct_init")]
685 StructInit {
686 name: String,
687 fields: Vec<(String, IrOperation)>,
688 #[serde(skip_serializing_if = "Option::is_none")]
689 rest: Option<Box<IrOperation>>,
690 #[serde(rename = "type")]
691 ty: IrType,
692 evidence: IrEvidence,
693 },
694
695 #[serde(rename = "field")]
697 Field {
698 expr: Box<IrOperation>,
699 field: String,
700 #[serde(rename = "type")]
701 ty: IrType,
702 evidence: IrEvidence,
703 },
704
705 #[serde(rename = "index")]
706 Index {
707 expr: Box<IrOperation>,
708 index: Box<IrOperation>,
709 #[serde(rename = "type")]
710 ty: IrType,
711 evidence: IrEvidence,
712 },
713
714 #[serde(rename = "assign")]
716 Assign {
717 target: Box<IrOperation>,
718 value: Box<IrOperation>,
719 evidence: IrEvidence,
720 },
721
722 #[serde(rename = "evidence_coerce")]
724 EvidenceCoerce {
725 operation: EvidenceOp,
726 expr: Box<IrOperation>,
727 from_evidence: IrEvidence,
728 to_evidence: IrEvidence,
729 #[serde(rename = "type")]
730 ty: IrType,
731 },
732
733 #[serde(rename = "incorporation")]
735 Incorporation {
736 segments: Vec<IncorporationSegment>,
737 args: Vec<IrOperation>,
738 #[serde(rename = "type")]
739 ty: IrType,
740 evidence: IrEvidence,
741 },
742
743 #[serde(rename = "affect")]
745 Affect {
746 expr: Box<IrOperation>,
747 affect: IrAffect,
748 #[serde(rename = "type")]
749 ty: IrType,
750 evidence: IrEvidence,
751 },
752
753 #[serde(rename = "http_request")]
755 HttpRequest {
756 method: HttpMethod,
757 url: Box<IrOperation>,
758 #[serde(skip_serializing_if = "Option::is_none")]
759 headers: Option<Box<IrOperation>>,
760 #[serde(skip_serializing_if = "Option::is_none")]
761 body: Option<Box<IrOperation>>,
762 #[serde(skip_serializing_if = "Option::is_none")]
763 timeout: Option<Box<IrOperation>>,
764 #[serde(rename = "type")]
765 ty: IrType,
766 evidence: IrEvidence,
767 },
768
769 #[serde(rename = "grpc_call")]
770 GrpcCall {
771 service: String,
772 method: String,
773 message: Box<IrOperation>,
774 #[serde(skip_serializing_if = "Option::is_none")]
775 metadata: Option<Box<IrOperation>>,
776 #[serde(skip_serializing_if = "Option::is_none")]
777 timeout: Option<Box<IrOperation>>,
778 #[serde(rename = "type")]
779 ty: IrType,
780 evidence: IrEvidence,
781 },
782
783 #[serde(rename = "websocket")]
784 WebSocket {
785 operation: WebSocketOp,
786 url: Box<IrOperation>,
787 #[serde(skip_serializing_if = "Option::is_none")]
788 message: Option<Box<IrOperation>>,
789 #[serde(rename = "type")]
790 ty: IrType,
791 evidence: IrEvidence,
792 },
793
794 #[serde(rename = "kafka_op")]
795 KafkaOp {
796 operation: KafkaOpKind,
797 topic: String,
798 #[serde(skip_serializing_if = "Option::is_none")]
799 payload: Option<Box<IrOperation>>,
800 #[serde(skip_serializing_if = "Option::is_none")]
801 key: Option<Box<IrOperation>>,
802 #[serde(rename = "type")]
803 ty: IrType,
804 evidence: IrEvidence,
805 },
806
807 #[serde(rename = "await")]
809 Await {
810 expr: Box<IrOperation>,
811 #[serde(rename = "type")]
812 ty: IrType,
813 evidence: IrEvidence,
814 },
815
816 #[serde(rename = "unsafe")]
818 Unsafe {
819 body: Box<IrOperation>,
820 #[serde(rename = "type")]
821 ty: IrType,
822 evidence: IrEvidence,
823 },
824
825 #[serde(rename = "async")]
827 Async {
828 body: Box<IrOperation>,
829 is_move: bool,
830 #[serde(rename = "type")]
831 ty: IrType,
832 evidence: IrEvidence,
833 },
834
835 #[serde(rename = "cast")]
837 Cast {
838 expr: Box<IrOperation>,
839 target_type: IrType,
840 #[serde(rename = "type")]
841 ty: IrType,
842 evidence: IrEvidence,
843 },
844
845 #[serde(rename = "try")]
847 Try {
848 expr: Box<IrOperation>,
849 #[serde(rename = "type")]
850 ty: IrType,
851 evidence: IrEvidence,
852 },
853}
854
855#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
857#[serde(rename_all = "lowercase")]
858pub enum LiteralVariant {
859 Int,
860 Float,
861 Bool,
862 Char,
863 String,
864 Null,
865}
866
867#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
869#[serde(rename_all = "snake_case")]
870pub enum BinaryOp {
871 Add,
872 Sub,
873 Mul,
874 Div,
875 Rem,
876 Pow,
877 And,
878 Or,
879 BitAnd,
880 BitOr,
881 BitXor,
882 Shl,
883 Shr,
884 Eq,
885 Ne,
886 Lt,
887 Le,
888 Gt,
889 Ge,
890 Concat,
891 MatMul,
892 Hadamard,
893 TensorProd,
894}
895
896#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
898#[serde(rename_all = "snake_case")]
899pub enum UnaryOp {
900 Neg,
901 Not,
902 Deref,
903 Ref,
904 RefMut,
905}
906
907#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
909#[serde(rename_all = "lowercase")]
910pub enum LoopVariant {
911 Infinite,
912 While,
913 For,
914}
915
916#[derive(Debug, Clone, Serialize, Deserialize)]
918pub struct IrForIterator {
919 pub pattern: IrPattern,
920 pub iterable: Box<IrOperation>,
921}
922
923#[derive(Debug, Clone, Serialize, Deserialize)]
925pub struct IrMatchArm {
926 pub pattern: IrPattern,
927 #[serde(skip_serializing_if = "Option::is_none")]
928 pub guard: Option<IrOperation>,
929 pub body: IrOperation,
930}
931
932#[derive(Debug, Clone, Serialize, Deserialize)]
934#[serde(tag = "kind")]
935pub enum IrPattern {
936 #[serde(rename = "ident")]
937 Ident {
938 name: String,
939 mutable: bool,
940 #[serde(skip_serializing_if = "Option::is_none")]
941 evidence: Option<IrEvidence>,
942 },
943
944 #[serde(rename = "tuple")]
945 Tuple { elements: Vec<IrPattern> },
946
947 #[serde(rename = "struct")]
948 Struct {
949 path: String,
950 fields: Vec<(String, IrPattern)>,
951 rest: bool,
952 },
953
954 #[serde(rename = "tuple_struct")]
955 TupleStruct {
956 path: String,
957 fields: Vec<IrPattern>,
958 },
959
960 #[serde(rename = "slice")]
961 Slice { elements: Vec<IrPattern> },
962
963 #[serde(rename = "or")]
964 Or { patterns: Vec<IrPattern> },
965
966 #[serde(rename = "literal")]
967 Literal { value: serde_json::Value },
968
969 #[serde(rename = "range")]
970 Range {
971 #[serde(skip_serializing_if = "Option::is_none")]
972 start: Option<Box<IrPattern>>,
973 #[serde(skip_serializing_if = "Option::is_none")]
974 end: Option<Box<IrPattern>>,
975 inclusive: bool,
976 },
977
978 #[serde(rename = "wildcard")]
979 Wildcard,
980}
981
982#[derive(Debug, Clone, Serialize, Deserialize)]
984#[serde(tag = "op")]
985pub enum IrPipelineStep {
986 #[serde(rename = "call")]
987 Call {
988 #[serde(rename = "fn")]
989 function: String,
990 args: Vec<IrOperation>,
991 },
992
993 #[serde(rename = "morpheme")]
994 Morpheme {
995 morpheme: MorphemeKind,
996 symbol: String,
997 #[serde(skip_serializing_if = "Option::is_none")]
998 body: Option<Box<IrOperation>>,
999 },
1000
1001 #[serde(rename = "fork")]
1002 Fork { branches: Vec<IrPipelineStep> },
1003
1004 #[serde(rename = "identity")]
1005 Identity,
1006
1007 #[serde(rename = "method")]
1008 Method {
1009 name: String,
1010 args: Vec<IrOperation>,
1011 },
1012
1013 #[serde(rename = "await")]
1014 Await,
1015
1016 #[serde(rename = "protocol")]
1017 Protocol {
1018 operation: ProtocolOp,
1019 #[serde(skip_serializing_if = "Option::is_none")]
1020 config: Option<Box<IrOperation>>,
1021 },
1022}
1023
1024#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1026#[serde(rename_all = "lowercase")]
1027pub enum MorphemeKind {
1028 Transform,
1029 Filter,
1030 Sort,
1031 Reduce,
1032 Lambda,
1033 Sum,
1034 Product,
1035 Min,
1036 Max,
1037 Concat,
1038 All,
1039 Any,
1040 First,
1041 Last,
1042 Middle,
1043 Choice,
1044 Nth,
1045 Next,
1046}
1047
1048impl MorphemeKind {
1049 pub fn symbol(&self) -> &'static str {
1050 match self {
1051 MorphemeKind::Transform => "τ",
1052 MorphemeKind::Filter => "φ",
1053 MorphemeKind::Sort => "σ",
1054 MorphemeKind::Reduce => "ρ",
1055 MorphemeKind::Lambda => "Λ",
1056 MorphemeKind::Sum => "Σ",
1057 MorphemeKind::Product => "Π",
1058 MorphemeKind::Min => "ρ_min",
1059 MorphemeKind::Max => "ρ_max",
1060 MorphemeKind::Concat => "ρ++",
1061 MorphemeKind::All => "ρ&",
1062 MorphemeKind::Any => "ρ|",
1063 MorphemeKind::First => "α",
1064 MorphemeKind::Last => "ω",
1065 MorphemeKind::Middle => "μ",
1066 MorphemeKind::Choice => "χ",
1067 MorphemeKind::Nth => "ν",
1068 MorphemeKind::Next => "ξ",
1069 }
1070 }
1071}
1072
1073#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1075#[serde(rename_all = "lowercase")]
1076pub enum JoinStrategy {
1077 Tuple,
1078 First,
1079 All,
1080 Race,
1081}
1082
1083#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1085#[serde(rename_all = "lowercase")]
1086pub enum EvidenceOp {
1087 Trust,
1088 Verify,
1089 Mark,
1090}
1091
1092#[derive(Debug, Clone, Serialize, Deserialize)]
1094#[serde(tag = "kind")]
1095pub enum IncorporationSegment {
1096 #[serde(rename = "noun")]
1097 Noun { name: String },
1098 #[serde(rename = "verb")]
1099 Verb { name: String },
1100}
1101
1102#[derive(Debug, Clone, Serialize, Deserialize)]
1104pub struct IrAffect {
1105 #[serde(skip_serializing_if = "Option::is_none")]
1106 pub sentiment: Option<Sentiment>,
1107 #[serde(skip_serializing_if = "Option::is_none")]
1108 pub intensity: Option<Intensity>,
1109 #[serde(skip_serializing_if = "Option::is_none")]
1110 pub formality: Option<Formality>,
1111 #[serde(skip_serializing_if = "Option::is_none")]
1112 pub emotion: Option<Emotion>,
1113 #[serde(skip_serializing_if = "Option::is_none")]
1114 pub confidence: Option<Confidence>,
1115 #[serde(default)]
1116 pub sarcasm: bool,
1117}
1118
1119#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1120#[serde(rename_all = "lowercase")]
1121pub enum Sentiment {
1122 Positive,
1123 Negative,
1124 Neutral,
1125}
1126
1127#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1128#[serde(rename_all = "lowercase")]
1129pub enum Intensity {
1130 Up,
1131 Down,
1132 Max,
1133}
1134
1135#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1136#[serde(rename_all = "lowercase")]
1137pub enum Formality {
1138 Formal,
1139 Informal,
1140}
1141
1142#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1143#[serde(rename_all = "lowercase")]
1144pub enum Emotion {
1145 Joy,
1146 Sadness,
1147 Anger,
1148 Fear,
1149 Surprise,
1150 Love,
1151}
1152
1153#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1154#[serde(rename_all = "lowercase")]
1155pub enum Confidence {
1156 High,
1157 Medium,
1158 Low,
1159}
1160
1161#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1163#[serde(rename_all = "UPPERCASE")]
1164pub enum HttpMethod {
1165 Get,
1166 Post,
1167 Put,
1168 Delete,
1169 Patch,
1170 Head,
1171 Options,
1172 Connect,
1173 Trace,
1174}
1175
1176#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1178#[serde(rename_all = "lowercase")]
1179pub enum WebSocketOp {
1180 Connect,
1181 Send,
1182 Receive,
1183 Close,
1184}
1185
1186#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1188#[serde(rename_all = "lowercase")]
1189pub enum KafkaOpKind {
1190 Produce,
1191 Consume,
1192 Subscribe,
1193 Unsubscribe,
1194 Commit,
1195 Seek,
1196}
1197
1198#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1200#[serde(rename_all = "lowercase")]
1201pub enum ProtocolOp {
1202 Send,
1203 Recv,
1204 Stream,
1205 Connect,
1206 Close,
1207 Timeout,
1208 Retry,
1209}
1210
1211#[derive(Debug, Clone, Default)]
1213pub struct IrDumpOptions {
1214 pub pretty: bool,
1216 pub full_types: bool,
1218 pub include_spans: bool,
1220 pub opt_level: Option<u8>,
1222}
1223
1224impl IrModule {
1225 pub fn to_json(&self, pretty: bool) -> Result<String, serde_json::Error> {
1227 if pretty {
1228 serde_json::to_string_pretty(self)
1229 } else {
1230 serde_json::to_string(self)
1231 }
1232 }
1233
1234 pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
1236 serde_json::from_str(json)
1237 }
1238}
1239
1240#[cfg(test)]
1241mod tests {
1242 use super::*;
1243
1244 #[test]
1245 fn test_evidence_join() {
1246 assert_eq!(IrEvidence::Known.join(IrEvidence::Known), IrEvidence::Known);
1247 assert_eq!(
1248 IrEvidence::Known.join(IrEvidence::Uncertain),
1249 IrEvidence::Uncertain
1250 );
1251 assert_eq!(
1252 IrEvidence::Known.join(IrEvidence::Reported),
1253 IrEvidence::Reported
1254 );
1255 assert_eq!(
1256 IrEvidence::Known.join(IrEvidence::Paradox),
1257 IrEvidence::Paradox
1258 );
1259 assert_eq!(
1260 IrEvidence::Reported.join(IrEvidence::Paradox),
1261 IrEvidence::Paradox
1262 );
1263 }
1264
1265 #[test]
1266 fn test_evidence_meet() {
1267 assert_eq!(
1268 IrEvidence::Paradox.meet(IrEvidence::Paradox),
1269 IrEvidence::Paradox
1270 );
1271 assert_eq!(
1272 IrEvidence::Paradox.meet(IrEvidence::Reported),
1273 IrEvidence::Reported
1274 );
1275 assert_eq!(
1276 IrEvidence::Paradox.meet(IrEvidence::Uncertain),
1277 IrEvidence::Uncertain
1278 );
1279 assert_eq!(
1280 IrEvidence::Paradox.meet(IrEvidence::Known),
1281 IrEvidence::Known
1282 );
1283 }
1284
1285 #[test]
1286 fn test_ir_serialization() {
1287 let module = IrModule::new("test.sigil".to_string());
1288 let json = module.to_json(false).unwrap();
1289 let parsed: IrModule = IrModule::from_json(&json).unwrap();
1290 assert_eq!(parsed.version, IR_VERSION);
1291 assert_eq!(parsed.source, "test.sigil");
1292 }
1293
1294 #[test]
1295 fn test_morpheme_symbols() {
1296 assert_eq!(MorphemeKind::Transform.symbol(), "τ");
1297 assert_eq!(MorphemeKind::Filter.symbol(), "φ");
1298 assert_eq!(MorphemeKind::Reduce.symbol(), "ρ");
1299 }
1300}