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 {
298 lifetime: Option<String>,
299 mutable: bool,
300 inner: Box<IrType>,
301 },
302
303 #[serde(rename = "pointer")]
305 Pointer { mutable: bool, inner: Box<IrType> },
306
307 #[serde(rename = "function")]
309 Function {
310 params: Vec<IrType>,
311 return_type: Box<IrType>,
312 is_async: bool,
313 },
314
315 #[serde(rename = "evidential")]
317 Evidential {
318 inner: Box<IrType>,
319 evidence: IrEvidence,
320 },
321
322 #[serde(rename = "cycle")]
324 Cycle { modulus: u64 },
325
326 #[serde(rename = "simd")]
328 Simd { element: Box<IrType>, lanes: usize },
329
330 #[serde(rename = "atomic")]
332 Atomic { inner: Box<IrType> },
333
334 #[serde(rename = "var")]
336 Var { id: String },
337
338 #[serde(rename = "infer")]
340 Infer,
341
342 #[serde(rename = "lifetime")]
344 Lifetime { name: String },
345
346 #[serde(rename = "trait_object")]
348 TraitObject { bounds: Vec<IrType> },
349
350 #[serde(rename = "hrtb")]
352 Hrtb {
353 lifetimes: Vec<String>,
354 bound: Box<IrType>,
355 },
356
357 #[serde(rename = "inline_struct")]
359 InlineStruct { fields: Vec<(String, IrType)> },
360
361 #[serde(rename = "impl_trait")]
363 ImplTrait { bounds: Vec<IrType> },
364
365 #[serde(rename = "inline_enum")]
367 InlineEnum { variants: Vec<String> },
368
369 #[serde(rename = "assoc_type_binding")]
371 AssocTypeBinding { name: String, ty: Box<IrType> },
372
373 #[serde(rename = "error")]
375 Error,
376}
377
378impl Default for IrType {
379 fn default() -> Self {
380 IrType::Unit
381 }
382}
383
384#[derive(Debug, Clone, Serialize, Deserialize)]
386#[serde(tag = "kind")]
387pub enum IrTypeDef {
388 #[serde(rename = "struct_def")]
389 Struct {
390 name: String,
391 generics: Vec<IrGenericParam>,
392 fields: Vec<IrField>,
393 #[serde(skip_serializing_if = "Option::is_none")]
394 span: Option<IrSpan>,
395 },
396 #[serde(rename = "enum_def")]
397 Enum {
398 name: String,
399 generics: Vec<IrGenericParam>,
400 variants: Vec<IrVariant>,
401 #[serde(skip_serializing_if = "Option::is_none")]
402 span: Option<IrSpan>,
403 },
404 #[serde(rename = "type_alias")]
405 TypeAlias {
406 name: String,
407 generics: Vec<IrGenericParam>,
408 target: IrType,
409 #[serde(skip_serializing_if = "Option::is_none")]
410 span: Option<IrSpan>,
411 },
412}
413
414#[derive(Debug, Clone, Serialize, Deserialize)]
416pub struct IrField {
417 pub name: String,
418 #[serde(rename = "type")]
419 pub ty: IrType,
420 pub visibility: IrVisibility,
421}
422
423#[derive(Debug, Clone, Serialize, Deserialize)]
425pub struct IrVariant {
426 pub name: String,
427 pub fields: Option<Vec<IrField>>,
428 pub discriminant: Option<i64>,
429}
430
431#[derive(Debug, Clone, Serialize, Deserialize)]
433pub struct IrTraitDef {
434 pub name: String,
435 pub generics: Vec<IrGenericParam>,
436 pub super_traits: Vec<String>,
437 pub methods: Vec<IrFunction>,
438 #[serde(skip_serializing_if = "Option::is_none")]
439 pub span: Option<IrSpan>,
440}
441
442#[derive(Debug, Clone, Serialize, Deserialize)]
444pub struct IrImplBlock {
445 #[serde(skip_serializing_if = "Option::is_none")]
446 pub trait_name: Option<String>,
447 pub target_type: IrType,
448 pub generics: Vec<IrGenericParam>,
449 pub methods: Vec<IrFunction>,
450 #[serde(skip_serializing_if = "Option::is_none")]
451 pub span: Option<IrSpan>,
452}
453
454#[derive(Debug, Clone, Serialize, Deserialize)]
456pub struct IrConstant {
457 pub name: String,
458 #[serde(rename = "type")]
459 pub ty: IrType,
460 pub value: IrOperation,
461 pub visibility: IrVisibility,
462 #[serde(skip_serializing_if = "Option::is_none")]
463 pub span: Option<IrSpan>,
464}
465
466#[derive(Debug, Clone, Serialize, Deserialize)]
468#[serde(tag = "kind")]
469pub enum IrOperation {
470 #[serde(rename = "literal")]
472 Literal {
473 variant: LiteralVariant,
474 value: serde_json::Value,
475 #[serde(rename = "type")]
476 ty: IrType,
477 evidence: IrEvidence,
478 },
479
480 #[serde(rename = "var")]
482 Var {
483 name: String,
484 id: String,
485 #[serde(rename = "type")]
486 ty: IrType,
487 evidence: IrEvidence,
488 },
489
490 #[serde(rename = "let")]
492 Let {
493 pattern: IrPattern,
494 #[serde(skip_serializing_if = "Option::is_none")]
495 type_annotation: Option<IrType>,
496 init: Box<IrOperation>,
497 evidence: IrEvidence,
498 },
499
500 #[serde(rename = "binary")]
502 Binary {
503 operator: BinaryOp,
504 left: Box<IrOperation>,
505 right: Box<IrOperation>,
506 #[serde(rename = "type")]
507 ty: IrType,
508 evidence: IrEvidence,
509 },
510
511 #[serde(rename = "unary")]
513 Unary {
514 operator: UnaryOp,
515 operand: Box<IrOperation>,
516 #[serde(rename = "type")]
517 ty: IrType,
518 evidence: IrEvidence,
519 },
520
521 #[serde(rename = "call")]
523 Call {
524 function: String,
525 function_id: String,
526 args: Vec<IrOperation>,
527 #[serde(skip_serializing_if = "Vec::is_empty")]
528 type_args: Vec<IrType>,
529 #[serde(rename = "type")]
530 ty: IrType,
531 evidence: IrEvidence,
532 },
533
534 #[serde(rename = "method_call")]
535 MethodCall {
536 receiver: Box<IrOperation>,
537 method: String,
538 args: Vec<IrOperation>,
539 #[serde(skip_serializing_if = "Vec::is_empty")]
540 type_args: Vec<IrType>,
541 #[serde(rename = "type")]
542 ty: IrType,
543 evidence: IrEvidence,
544 },
545
546 #[serde(rename = "closure")]
548 Closure {
549 params: Vec<IrParam>,
550 body: Box<IrOperation>,
551 captures: Vec<String>,
552 #[serde(rename = "type")]
553 ty: IrType,
554 evidence: IrEvidence,
555 },
556
557 #[serde(rename = "if")]
559 If {
560 condition: Box<IrOperation>,
561 then_branch: Box<IrOperation>,
562 #[serde(skip_serializing_if = "Option::is_none")]
563 else_branch: Option<Box<IrOperation>>,
564 #[serde(rename = "type")]
565 ty: IrType,
566 evidence: IrEvidence,
567 },
568
569 #[serde(rename = "match")]
570 Match {
571 scrutinee: Box<IrOperation>,
572 arms: Vec<IrMatchArm>,
573 #[serde(rename = "type")]
574 ty: IrType,
575 evidence: IrEvidence,
576 },
577
578 #[serde(rename = "let_match")]
582 LetMatch {
583 pattern: IrPattern,
584 value: Box<IrOperation>,
585 #[serde(rename = "type")]
586 ty: IrType,
587 evidence: IrEvidence,
588 },
589
590 #[serde(rename = "loop")]
591 Loop {
592 variant: LoopVariant,
593 #[serde(skip_serializing_if = "Option::is_none")]
594 condition: Option<Box<IrOperation>>,
595 #[serde(skip_serializing_if = "Option::is_none")]
596 iterator: Option<IrForIterator>,
597 body: Box<IrOperation>,
598 #[serde(rename = "type")]
599 ty: IrType,
600 evidence: IrEvidence,
601 },
602
603 #[serde(rename = "break")]
604 Break {
605 #[serde(skip_serializing_if = "Option::is_none")]
606 value: Option<Box<IrOperation>>,
607 evidence: IrEvidence,
608 },
609
610 #[serde(rename = "continue")]
611 Continue { evidence: IrEvidence },
612
613 #[serde(rename = "return")]
614 Return {
615 #[serde(skip_serializing_if = "Option::is_none")]
616 value: Option<Box<IrOperation>>,
617 evidence: IrEvidence,
618 },
619
620 #[serde(rename = "block")]
622 Block {
623 statements: Vec<IrOperation>,
624 #[serde(rename = "type")]
625 ty: IrType,
626 evidence: IrEvidence,
627 },
628
629 #[serde(rename = "pipeline")]
631 Pipeline {
632 input: Box<IrOperation>,
633 steps: Vec<IrPipelineStep>,
634 #[serde(rename = "type")]
635 ty: IrType,
636 evidence: IrEvidence,
637 },
638
639 #[serde(rename = "morpheme")]
641 Morpheme {
642 morpheme: MorphemeKind,
643 symbol: String,
644 input: Box<IrOperation>,
645 #[serde(skip_serializing_if = "Option::is_none")]
646 body: Option<Box<IrOperation>>,
647 #[serde(rename = "type")]
648 ty: IrType,
649 evidence: IrEvidence,
650 },
651
652 #[serde(rename = "fork")]
654 Fork {
655 branches: Vec<IrOperation>,
656 join_strategy: JoinStrategy,
657 #[serde(rename = "type")]
658 ty: IrType,
659 evidence: IrEvidence,
660 },
661
662 #[serde(rename = "identity")]
663 Identity {
664 #[serde(rename = "type")]
665 ty: IrType,
666 evidence: IrEvidence,
667 },
668
669 #[serde(rename = "array")]
671 Array {
672 elements: Vec<IrOperation>,
673 #[serde(rename = "type")]
674 ty: IrType,
675 evidence: IrEvidence,
676 },
677
678 #[serde(rename = "tuple")]
679 Tuple {
680 elements: Vec<IrOperation>,
681 #[serde(rename = "type")]
682 ty: IrType,
683 evidence: IrEvidence,
684 },
685
686 #[serde(rename = "struct_init")]
687 StructInit {
688 name: String,
689 fields: Vec<(String, IrOperation)>,
690 #[serde(skip_serializing_if = "Option::is_none")]
691 rest: Option<Box<IrOperation>>,
692 #[serde(rename = "type")]
693 ty: IrType,
694 evidence: IrEvidence,
695 },
696
697 #[serde(rename = "field")]
699 Field {
700 expr: Box<IrOperation>,
701 field: String,
702 #[serde(rename = "type")]
703 ty: IrType,
704 evidence: IrEvidence,
705 },
706
707 #[serde(rename = "index")]
708 Index {
709 expr: Box<IrOperation>,
710 index: Box<IrOperation>,
711 #[serde(rename = "type")]
712 ty: IrType,
713 evidence: IrEvidence,
714 },
715
716 #[serde(rename = "assign")]
718 Assign {
719 target: Box<IrOperation>,
720 value: Box<IrOperation>,
721 evidence: IrEvidence,
722 },
723
724 #[serde(rename = "evidence_coerce")]
726 EvidenceCoerce {
727 operation: EvidenceOp,
728 expr: Box<IrOperation>,
729 from_evidence: IrEvidence,
730 to_evidence: IrEvidence,
731 #[serde(rename = "type")]
732 ty: IrType,
733 },
734
735 #[serde(rename = "incorporation")]
737 Incorporation {
738 segments: Vec<IncorporationSegment>,
739 args: Vec<IrOperation>,
740 #[serde(rename = "type")]
741 ty: IrType,
742 evidence: IrEvidence,
743 },
744
745 #[serde(rename = "affect")]
747 Affect {
748 expr: Box<IrOperation>,
749 affect: IrAffect,
750 #[serde(rename = "type")]
751 ty: IrType,
752 evidence: IrEvidence,
753 },
754
755 #[serde(rename = "http_request")]
757 HttpRequest {
758 method: HttpMethod,
759 url: Box<IrOperation>,
760 #[serde(skip_serializing_if = "Option::is_none")]
761 headers: Option<Box<IrOperation>>,
762 #[serde(skip_serializing_if = "Option::is_none")]
763 body: Option<Box<IrOperation>>,
764 #[serde(skip_serializing_if = "Option::is_none")]
765 timeout: Option<Box<IrOperation>>,
766 #[serde(rename = "type")]
767 ty: IrType,
768 evidence: IrEvidence,
769 },
770
771 #[serde(rename = "grpc_call")]
772 GrpcCall {
773 service: String,
774 method: String,
775 message: Box<IrOperation>,
776 #[serde(skip_serializing_if = "Option::is_none")]
777 metadata: Option<Box<IrOperation>>,
778 #[serde(skip_serializing_if = "Option::is_none")]
779 timeout: Option<Box<IrOperation>>,
780 #[serde(rename = "type")]
781 ty: IrType,
782 evidence: IrEvidence,
783 },
784
785 #[serde(rename = "websocket")]
786 WebSocket {
787 operation: WebSocketOp,
788 url: Box<IrOperation>,
789 #[serde(skip_serializing_if = "Option::is_none")]
790 message: Option<Box<IrOperation>>,
791 #[serde(rename = "type")]
792 ty: IrType,
793 evidence: IrEvidence,
794 },
795
796 #[serde(rename = "kafka_op")]
797 KafkaOp {
798 operation: KafkaOpKind,
799 topic: String,
800 #[serde(skip_serializing_if = "Option::is_none")]
801 payload: Option<Box<IrOperation>>,
802 #[serde(skip_serializing_if = "Option::is_none")]
803 key: Option<Box<IrOperation>>,
804 #[serde(rename = "type")]
805 ty: IrType,
806 evidence: IrEvidence,
807 },
808
809 #[serde(rename = "await")]
811 Await {
812 expr: Box<IrOperation>,
813 #[serde(rename = "type")]
814 ty: IrType,
815 evidence: IrEvidence,
816 },
817
818 #[serde(rename = "unsafe")]
820 Unsafe {
821 body: Box<IrOperation>,
822 #[serde(rename = "type")]
823 ty: IrType,
824 evidence: IrEvidence,
825 },
826
827 #[serde(rename = "async")]
829 Async {
830 body: Box<IrOperation>,
831 is_move: bool,
832 #[serde(rename = "type")]
833 ty: IrType,
834 evidence: IrEvidence,
835 },
836
837 #[serde(rename = "cast")]
839 Cast {
840 expr: Box<IrOperation>,
841 target_type: IrType,
842 #[serde(rename = "type")]
843 ty: IrType,
844 evidence: IrEvidence,
845 },
846
847 #[serde(rename = "try")]
849 Try {
850 expr: Box<IrOperation>,
851 #[serde(rename = "type")]
852 ty: IrType,
853 evidence: IrEvidence,
854 },
855}
856
857#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
859#[serde(rename_all = "lowercase")]
860pub enum LiteralVariant {
861 Int,
862 Float,
863 Bool,
864 Char,
865 String,
866 Null,
867}
868
869#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
871#[serde(rename_all = "snake_case")]
872pub enum BinaryOp {
873 Add,
874 Sub,
875 Mul,
876 Div,
877 Rem,
878 Pow,
879 And,
880 Or,
881 BitAnd,
882 BitOr,
883 BitXor,
884 Shl,
885 Shr,
886 Eq,
887 Ne,
888 Lt,
889 Le,
890 Gt,
891 Ge,
892 Concat,
893 MatMul,
894 Hadamard,
895 TensorProd,
896}
897
898#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
900#[serde(rename_all = "snake_case")]
901pub enum UnaryOp {
902 Neg,
903 Not,
904 Deref,
905 Ref,
906 RefMut,
907}
908
909#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
911#[serde(rename_all = "lowercase")]
912pub enum LoopVariant {
913 Infinite,
914 While,
915 For,
916}
917
918#[derive(Debug, Clone, Serialize, Deserialize)]
920pub struct IrForIterator {
921 pub pattern: IrPattern,
922 pub iterable: Box<IrOperation>,
923}
924
925#[derive(Debug, Clone, Serialize, Deserialize)]
927pub struct IrMatchArm {
928 pub pattern: IrPattern,
929 #[serde(skip_serializing_if = "Option::is_none")]
930 pub guard: Option<IrOperation>,
931 pub body: IrOperation,
932}
933
934#[derive(Debug, Clone, Serialize, Deserialize)]
936#[serde(tag = "kind")]
937pub enum IrPattern {
938 #[serde(rename = "ident")]
939 Ident {
940 name: String,
941 mutable: bool,
942 #[serde(skip_serializing_if = "Option::is_none")]
943 evidence: Option<IrEvidence>,
944 },
945
946 #[serde(rename = "tuple")]
947 Tuple { elements: Vec<IrPattern> },
948
949 #[serde(rename = "struct")]
950 Struct {
951 path: String,
952 fields: Vec<(String, IrPattern)>,
953 rest: bool,
954 },
955
956 #[serde(rename = "tuple_struct")]
957 TupleStruct {
958 path: String,
959 fields: Vec<IrPattern>,
960 },
961
962 #[serde(rename = "slice")]
963 Slice { elements: Vec<IrPattern> },
964
965 #[serde(rename = "or")]
966 Or { patterns: Vec<IrPattern> },
967
968 #[serde(rename = "literal")]
969 Literal { value: serde_json::Value },
970
971 #[serde(rename = "range")]
972 Range {
973 #[serde(skip_serializing_if = "Option::is_none")]
974 start: Option<Box<IrPattern>>,
975 #[serde(skip_serializing_if = "Option::is_none")]
976 end: Option<Box<IrPattern>>,
977 inclusive: bool,
978 },
979
980 #[serde(rename = "wildcard")]
981 Wildcard,
982}
983
984#[derive(Debug, Clone, Serialize, Deserialize)]
986#[serde(tag = "op")]
987pub enum IrPipelineStep {
988 #[serde(rename = "call")]
989 Call {
990 #[serde(rename = "fn")]
991 function: String,
992 args: Vec<IrOperation>,
993 },
994
995 #[serde(rename = "morpheme")]
996 Morpheme {
997 morpheme: MorphemeKind,
998 symbol: String,
999 #[serde(skip_serializing_if = "Option::is_none")]
1000 body: Option<Box<IrOperation>>,
1001 },
1002
1003 #[serde(rename = "fork")]
1004 Fork { branches: Vec<IrPipelineStep> },
1005
1006 #[serde(rename = "identity")]
1007 Identity,
1008
1009 #[serde(rename = "method")]
1010 Method {
1011 name: String,
1012 args: Vec<IrOperation>,
1013 },
1014
1015 #[serde(rename = "await")]
1016 Await,
1017
1018 #[serde(rename = "protocol")]
1019 Protocol {
1020 operation: ProtocolOp,
1021 #[serde(skip_serializing_if = "Option::is_none")]
1022 config: Option<Box<IrOperation>>,
1023 },
1024}
1025
1026#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1028#[serde(rename_all = "lowercase")]
1029pub enum MorphemeKind {
1030 Transform,
1031 Filter,
1032 Sort,
1033 Reduce,
1034 Lambda,
1035 Sum,
1036 Product,
1037 Min,
1038 Max,
1039 Concat,
1040 All,
1041 Any,
1042 First,
1043 Last,
1044 Middle,
1045 Choice,
1046 Nth,
1047 Next,
1048}
1049
1050impl MorphemeKind {
1051 pub fn symbol(&self) -> &'static str {
1052 match self {
1053 MorphemeKind::Transform => "τ",
1054 MorphemeKind::Filter => "φ",
1055 MorphemeKind::Sort => "σ",
1056 MorphemeKind::Reduce => "ρ",
1057 MorphemeKind::Lambda => "λ",
1058 MorphemeKind::Sum => "Σ",
1059 MorphemeKind::Product => "Π",
1060 MorphemeKind::Min => "ρ_min",
1061 MorphemeKind::Max => "ρ_max",
1062 MorphemeKind::Concat => "ρ++",
1063 MorphemeKind::All => "ρ&",
1064 MorphemeKind::Any => "ρ|",
1065 MorphemeKind::First => "α",
1066 MorphemeKind::Last => "ω",
1067 MorphemeKind::Middle => "μ",
1068 MorphemeKind::Choice => "χ",
1069 MorphemeKind::Nth => "ν",
1070 MorphemeKind::Next => "ξ",
1071 }
1072 }
1073}
1074
1075#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1077#[serde(rename_all = "lowercase")]
1078pub enum JoinStrategy {
1079 Tuple,
1080 First,
1081 All,
1082 Race,
1083}
1084
1085#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1087#[serde(rename_all = "lowercase")]
1088pub enum EvidenceOp {
1089 Trust,
1090 Verify,
1091 Mark,
1092}
1093
1094#[derive(Debug, Clone, Serialize, Deserialize)]
1096#[serde(tag = "kind")]
1097pub enum IncorporationSegment {
1098 #[serde(rename = "noun")]
1099 Noun { name: String },
1100 #[serde(rename = "verb")]
1101 Verb { name: String },
1102}
1103
1104#[derive(Debug, Clone, Serialize, Deserialize)]
1106pub struct IrAffect {
1107 #[serde(skip_serializing_if = "Option::is_none")]
1108 pub sentiment: Option<Sentiment>,
1109 #[serde(skip_serializing_if = "Option::is_none")]
1110 pub intensity: Option<Intensity>,
1111 #[serde(skip_serializing_if = "Option::is_none")]
1112 pub formality: Option<Formality>,
1113 #[serde(skip_serializing_if = "Option::is_none")]
1114 pub emotion: Option<Emotion>,
1115 #[serde(skip_serializing_if = "Option::is_none")]
1116 pub confidence: Option<Confidence>,
1117 #[serde(default)]
1118 pub sarcasm: bool,
1119}
1120
1121#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1122#[serde(rename_all = "lowercase")]
1123pub enum Sentiment {
1124 Positive,
1125 Negative,
1126 Neutral,
1127}
1128
1129#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1130#[serde(rename_all = "lowercase")]
1131pub enum Intensity {
1132 Up,
1133 Down,
1134 Max,
1135}
1136
1137#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1138#[serde(rename_all = "lowercase")]
1139pub enum Formality {
1140 Formal,
1141 Informal,
1142}
1143
1144#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1145#[serde(rename_all = "lowercase")]
1146pub enum Emotion {
1147 Joy,
1148 Sadness,
1149 Anger,
1150 Fear,
1151 Surprise,
1152 Love,
1153}
1154
1155#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1156#[serde(rename_all = "lowercase")]
1157pub enum Confidence {
1158 High,
1159 Medium,
1160 Low,
1161}
1162
1163#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1165#[serde(rename_all = "UPPERCASE")]
1166pub enum HttpMethod {
1167 Get,
1168 Post,
1169 Put,
1170 Delete,
1171 Patch,
1172 Head,
1173 Options,
1174 Connect,
1175 Trace,
1176}
1177
1178#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1180#[serde(rename_all = "lowercase")]
1181pub enum WebSocketOp {
1182 Connect,
1183 Send,
1184 Receive,
1185 Close,
1186}
1187
1188#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1190#[serde(rename_all = "lowercase")]
1191pub enum KafkaOpKind {
1192 Produce,
1193 Consume,
1194 Subscribe,
1195 Unsubscribe,
1196 Commit,
1197 Seek,
1198}
1199
1200#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1202#[serde(rename_all = "lowercase")]
1203pub enum ProtocolOp {
1204 Send,
1205 Recv,
1206 Stream,
1207 Connect,
1208 Close,
1209 Timeout,
1210 Retry,
1211}
1212
1213#[derive(Debug, Clone, Default)]
1215pub struct IrDumpOptions {
1216 pub pretty: bool,
1218 pub full_types: bool,
1220 pub include_spans: bool,
1222 pub opt_level: Option<u8>,
1224}
1225
1226impl IrModule {
1227 pub fn to_json(&self, pretty: bool) -> Result<String, serde_json::Error> {
1229 if pretty {
1230 serde_json::to_string_pretty(self)
1231 } else {
1232 serde_json::to_string(self)
1233 }
1234 }
1235
1236 pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
1238 serde_json::from_str(json)
1239 }
1240}
1241
1242#[cfg(test)]
1243mod tests {
1244 use super::*;
1245
1246 #[test]
1247 fn test_evidence_join() {
1248 assert_eq!(IrEvidence::Known.join(IrEvidence::Known), IrEvidence::Known);
1249 assert_eq!(
1250 IrEvidence::Known.join(IrEvidence::Uncertain),
1251 IrEvidence::Uncertain
1252 );
1253 assert_eq!(
1254 IrEvidence::Known.join(IrEvidence::Reported),
1255 IrEvidence::Reported
1256 );
1257 assert_eq!(
1258 IrEvidence::Known.join(IrEvidence::Paradox),
1259 IrEvidence::Paradox
1260 );
1261 assert_eq!(
1262 IrEvidence::Reported.join(IrEvidence::Paradox),
1263 IrEvidence::Paradox
1264 );
1265 }
1266
1267 #[test]
1268 fn test_evidence_meet() {
1269 assert_eq!(
1270 IrEvidence::Paradox.meet(IrEvidence::Paradox),
1271 IrEvidence::Paradox
1272 );
1273 assert_eq!(
1274 IrEvidence::Paradox.meet(IrEvidence::Reported),
1275 IrEvidence::Reported
1276 );
1277 assert_eq!(
1278 IrEvidence::Paradox.meet(IrEvidence::Uncertain),
1279 IrEvidence::Uncertain
1280 );
1281 assert_eq!(
1282 IrEvidence::Paradox.meet(IrEvidence::Known),
1283 IrEvidence::Known
1284 );
1285 }
1286
1287 #[test]
1288 fn test_ir_serialization() {
1289 let module = IrModule::new("test.sigil".to_string());
1290 let json = module.to_json(false).unwrap();
1291 let parsed: IrModule = IrModule::from_json(&json).unwrap();
1292 assert_eq!(parsed.version, IR_VERSION);
1293 assert_eq!(parsed.source, "test.sigil");
1294 }
1295
1296 #[test]
1297 fn test_morpheme_symbols() {
1298 assert_eq!(MorphemeKind::Transform.symbol(), "τ");
1299 assert_eq!(MorphemeKind::Filter.symbol(), "φ");
1300 assert_eq!(MorphemeKind::Reduce.symbol(), "ρ");
1301 }
1302}