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