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