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 Convolve,
897}
898
899#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
901#[serde(rename_all = "snake_case")]
902pub enum UnaryOp {
903 Neg,
904 Not,
905 Deref,
906 Ref,
907 RefMut,
908}
909
910#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
912#[serde(rename_all = "lowercase")]
913pub enum LoopVariant {
914 Infinite,
915 While,
916 For,
917}
918
919#[derive(Debug, Clone, Serialize, Deserialize)]
921pub struct IrForIterator {
922 pub pattern: IrPattern,
923 pub iterable: Box<IrOperation>,
924}
925
926#[derive(Debug, Clone, Serialize, Deserialize)]
928pub struct IrMatchArm {
929 pub pattern: IrPattern,
930 #[serde(skip_serializing_if = "Option::is_none")]
931 pub guard: Option<IrOperation>,
932 pub body: IrOperation,
933}
934
935#[derive(Debug, Clone, Serialize, Deserialize)]
937#[serde(tag = "kind")]
938pub enum IrPattern {
939 #[serde(rename = "ident")]
940 Ident {
941 name: String,
942 mutable: bool,
943 #[serde(skip_serializing_if = "Option::is_none")]
944 evidence: Option<IrEvidence>,
945 },
946
947 #[serde(rename = "tuple")]
948 Tuple { elements: Vec<IrPattern> },
949
950 #[serde(rename = "struct")]
951 Struct {
952 path: String,
953 fields: Vec<(String, IrPattern)>,
954 rest: bool,
955 },
956
957 #[serde(rename = "tuple_struct")]
958 TupleStruct {
959 path: String,
960 fields: Vec<IrPattern>,
961 },
962
963 #[serde(rename = "slice")]
964 Slice { elements: Vec<IrPattern> },
965
966 #[serde(rename = "or")]
967 Or { patterns: Vec<IrPattern> },
968
969 #[serde(rename = "literal")]
970 Literal { value: serde_json::Value },
971
972 #[serde(rename = "range")]
973 Range {
974 #[serde(skip_serializing_if = "Option::is_none")]
975 start: Option<Box<IrPattern>>,
976 #[serde(skip_serializing_if = "Option::is_none")]
977 end: Option<Box<IrPattern>>,
978 inclusive: bool,
979 },
980
981 #[serde(rename = "wildcard")]
982 Wildcard,
983}
984
985#[derive(Debug, Clone, Serialize, Deserialize)]
987#[serde(tag = "op")]
988pub enum IrPipelineStep {
989 #[serde(rename = "call")]
990 Call {
991 #[serde(rename = "fn")]
992 function: String,
993 args: Vec<IrOperation>,
994 },
995
996 #[serde(rename = "morpheme")]
997 Morpheme {
998 morpheme: MorphemeKind,
999 symbol: String,
1000 #[serde(skip_serializing_if = "Option::is_none")]
1001 body: Option<Box<IrOperation>>,
1002 },
1003
1004 #[serde(rename = "fork")]
1005 Fork { branches: Vec<IrPipelineStep> },
1006
1007 #[serde(rename = "identity")]
1008 Identity,
1009
1010 #[serde(rename = "method")]
1011 Method {
1012 name: String,
1013 args: Vec<IrOperation>,
1014 },
1015
1016 #[serde(rename = "await")]
1017 Await,
1018
1019 #[serde(rename = "protocol")]
1020 Protocol {
1021 operation: ProtocolOp,
1022 #[serde(skip_serializing_if = "Option::is_none")]
1023 config: Option<Box<IrOperation>>,
1024 },
1025}
1026
1027#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1029#[serde(rename_all = "lowercase")]
1030pub enum MorphemeKind {
1031 Transform,
1032 Filter,
1033 Sort,
1034 Reduce,
1035 Lambda,
1036 Sum,
1037 Product,
1038 Min,
1039 Max,
1040 Concat,
1041 All,
1042 Any,
1043 First,
1044 Last,
1045 Middle,
1046 Choice,
1047 Nth,
1048 Next,
1049}
1050
1051impl MorphemeKind {
1052 pub fn symbol(&self) -> &'static str {
1053 match self {
1054 MorphemeKind::Transform => "τ",
1055 MorphemeKind::Filter => "φ",
1056 MorphemeKind::Sort => "σ",
1057 MorphemeKind::Reduce => "ρ",
1058 MorphemeKind::Lambda => "λ",
1059 MorphemeKind::Sum => "Σ",
1060 MorphemeKind::Product => "Π",
1061 MorphemeKind::Min => "ρ_min",
1062 MorphemeKind::Max => "ρ_max",
1063 MorphemeKind::Concat => "ρ++",
1064 MorphemeKind::All => "ρ&",
1065 MorphemeKind::Any => "ρ|",
1066 MorphemeKind::First => "α",
1067 MorphemeKind::Last => "ω",
1068 MorphemeKind::Middle => "μ",
1069 MorphemeKind::Choice => "χ",
1070 MorphemeKind::Nth => "ν",
1071 MorphemeKind::Next => "ξ",
1072 }
1073 }
1074}
1075
1076#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1078#[serde(rename_all = "lowercase")]
1079pub enum JoinStrategy {
1080 Tuple,
1081 First,
1082 All,
1083 Race,
1084}
1085
1086#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1088#[serde(rename_all = "lowercase")]
1089pub enum EvidenceOp {
1090 Trust,
1091 Verify,
1092 Mark,
1093}
1094
1095#[derive(Debug, Clone, Serialize, Deserialize)]
1097#[serde(tag = "kind")]
1098pub enum IncorporationSegment {
1099 #[serde(rename = "noun")]
1100 Noun { name: String },
1101 #[serde(rename = "verb")]
1102 Verb { name: String },
1103}
1104
1105#[derive(Debug, Clone, Serialize, Deserialize)]
1107pub struct IrAffect {
1108 #[serde(skip_serializing_if = "Option::is_none")]
1109 pub sentiment: Option<Sentiment>,
1110 #[serde(skip_serializing_if = "Option::is_none")]
1111 pub intensity: Option<Intensity>,
1112 #[serde(skip_serializing_if = "Option::is_none")]
1113 pub formality: Option<Formality>,
1114 #[serde(skip_serializing_if = "Option::is_none")]
1115 pub emotion: Option<Emotion>,
1116 #[serde(skip_serializing_if = "Option::is_none")]
1117 pub confidence: Option<Confidence>,
1118 #[serde(default)]
1119 pub sarcasm: bool,
1120}
1121
1122#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1123#[serde(rename_all = "lowercase")]
1124pub enum Sentiment {
1125 Positive,
1126 Negative,
1127 Neutral,
1128}
1129
1130#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1131#[serde(rename_all = "lowercase")]
1132pub enum Intensity {
1133 Up,
1134 Down,
1135 Max,
1136}
1137
1138#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1139#[serde(rename_all = "lowercase")]
1140pub enum Formality {
1141 Formal,
1142 Informal,
1143}
1144
1145#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1146#[serde(rename_all = "lowercase")]
1147pub enum Emotion {
1148 Joy,
1149 Sadness,
1150 Anger,
1151 Fear,
1152 Surprise,
1153 Love,
1154}
1155
1156#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1157#[serde(rename_all = "lowercase")]
1158pub enum Confidence {
1159 High,
1160 Medium,
1161 Low,
1162}
1163
1164#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1166#[serde(rename_all = "UPPERCASE")]
1167pub enum HttpMethod {
1168 Get,
1169 Post,
1170 Put,
1171 Delete,
1172 Patch,
1173 Head,
1174 Options,
1175 Connect,
1176 Trace,
1177}
1178
1179#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1181#[serde(rename_all = "lowercase")]
1182pub enum WebSocketOp {
1183 Connect,
1184 Send,
1185 Receive,
1186 Close,
1187}
1188
1189#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1191#[serde(rename_all = "lowercase")]
1192pub enum KafkaOpKind {
1193 Produce,
1194 Consume,
1195 Subscribe,
1196 Unsubscribe,
1197 Commit,
1198 Seek,
1199}
1200
1201#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1203#[serde(rename_all = "lowercase")]
1204pub enum ProtocolOp {
1205 Send,
1206 Recv,
1207 Stream,
1208 Connect,
1209 Close,
1210 Timeout,
1211 Retry,
1212}
1213
1214#[derive(Debug, Clone, Default)]
1216pub struct IrDumpOptions {
1217 pub pretty: bool,
1219 pub full_types: bool,
1221 pub include_spans: bool,
1223 pub opt_level: Option<u8>,
1225}
1226
1227impl IrModule {
1228 pub fn to_json(&self, pretty: bool) -> Result<String, serde_json::Error> {
1230 if pretty {
1231 serde_json::to_string_pretty(self)
1232 } else {
1233 serde_json::to_string(self)
1234 }
1235 }
1236
1237 pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
1239 serde_json::from_str(json)
1240 }
1241}
1242
1243#[cfg(test)]
1244mod tests {
1245 use super::*;
1246
1247 #[test]
1248 fn test_evidence_join() {
1249 assert_eq!(IrEvidence::Known.join(IrEvidence::Known), IrEvidence::Known);
1250 assert_eq!(
1251 IrEvidence::Known.join(IrEvidence::Uncertain),
1252 IrEvidence::Uncertain
1253 );
1254 assert_eq!(
1255 IrEvidence::Known.join(IrEvidence::Reported),
1256 IrEvidence::Reported
1257 );
1258 assert_eq!(
1259 IrEvidence::Known.join(IrEvidence::Paradox),
1260 IrEvidence::Paradox
1261 );
1262 assert_eq!(
1263 IrEvidence::Reported.join(IrEvidence::Paradox),
1264 IrEvidence::Paradox
1265 );
1266 }
1267
1268 #[test]
1269 fn test_evidence_meet() {
1270 assert_eq!(
1271 IrEvidence::Paradox.meet(IrEvidence::Paradox),
1272 IrEvidence::Paradox
1273 );
1274 assert_eq!(
1275 IrEvidence::Paradox.meet(IrEvidence::Reported),
1276 IrEvidence::Reported
1277 );
1278 assert_eq!(
1279 IrEvidence::Paradox.meet(IrEvidence::Uncertain),
1280 IrEvidence::Uncertain
1281 );
1282 assert_eq!(
1283 IrEvidence::Paradox.meet(IrEvidence::Known),
1284 IrEvidence::Known
1285 );
1286 }
1287
1288 #[test]
1289 fn test_ir_serialization() {
1290 let module = IrModule::new("test.sigil".to_string());
1291 let json = module.to_json(false).unwrap();
1292 let parsed: IrModule = IrModule::from_json(&json).unwrap();
1293 assert_eq!(parsed.version, IR_VERSION);
1294 assert_eq!(parsed.source, "test.sigil");
1295 }
1296
1297 #[test]
1298 fn test_morpheme_symbols() {
1299 assert_eq!(MorphemeKind::Transform.symbol(), "τ");
1300 assert_eq!(MorphemeKind::Filter.symbol(), "φ");
1301 assert_eq!(MorphemeKind::Reduce.symbol(), "ρ");
1302 }
1303}