intent_ir/types.rs
1//! Core IR type definitions for IntentLang.
2//!
3//! The IR is a typed, formally verifiable representation generated from
4//! intent specs. Every IR node carries a `SourceTrace` linking it back
5//! to the originating spec element (for Phase 3 Audit Bridge).
6
7use intent_parser::ast::Span;
8use serde::Serialize;
9
10// ── Source tracing ──────────────────────────────────────────
11
12/// Links an IR node back to its originating spec element.
13#[derive(Debug, Clone, Serialize)]
14pub struct SourceTrace {
15 /// Module name from the intent file.
16 pub module: String,
17 /// Which spec item produced this IR node (e.g., "Transfer", "NoNegativeBalances").
18 pub item: String,
19 /// Which part of the spec item (e.g., "requires", "ensures", "field:balance").
20 pub part: String,
21 /// Byte span in the original source.
22 pub span: Span,
23}
24
25// ── Module ──────────────────────────────────────────────────
26
27/// A compiled IR module — the output of lowering a single `.intent` file.
28#[derive(Debug, Clone, Serialize)]
29pub struct Module {
30 pub name: String,
31 pub structs: Vec<Struct>,
32 pub functions: Vec<Function>,
33 pub invariants: Vec<Invariant>,
34 pub edge_guards: Vec<EdgeGuard>,
35}
36
37// ── Types ───────────────────────────────────────────────────
38
39/// An IR type — resolved from the intent language's type expressions.
40#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
41pub enum IrType {
42 /// Named primitive or domain type (UUID, String, Int, Bool, etc.)
43 Named(String),
44 /// Reference to a struct defined in this module.
45 Struct(String),
46 /// `List<T>`
47 List(Box<IrType>),
48 /// `Set<T>`
49 Set(Box<IrType>),
50 /// `Map<K, V>`
51 Map(Box<IrType>, Box<IrType>),
52 /// Optional wrapper: `T?`
53 Optional(Box<IrType>),
54 /// Union of variants (enum-like): `Active | Frozen | Closed`
55 Union(Vec<String>),
56 /// Decimal with precision: `Decimal(2)`
57 Decimal(u32),
58}
59
60// ── Struct (from entity) ────────────────────────────────────
61
62/// A struct type — lowered from an `entity` declaration.
63#[derive(Debug, Clone, Serialize)]
64pub struct Struct {
65 pub name: String,
66 pub fields: Vec<Field>,
67 pub trace: SourceTrace,
68}
69
70/// A typed field within a struct.
71#[derive(Debug, Clone, Serialize)]
72pub struct Field {
73 pub name: String,
74 pub ty: IrType,
75 pub trace: SourceTrace,
76}
77
78// ── Function (from action) ──────────────────────────────────
79
80/// A function — lowered from an `action` declaration.
81/// Contains typed parameters, pre/postconditions, and effect/property annotations.
82#[derive(Debug, Clone, Serialize)]
83pub struct Function {
84 pub name: String,
85 pub params: Vec<Param>,
86 pub preconditions: Vec<Condition>,
87 pub postconditions: Vec<Postcondition>,
88 pub properties: Vec<Property>,
89 pub trace: SourceTrace,
90}
91
92/// A typed function parameter.
93#[derive(Debug, Clone, Serialize)]
94pub struct Param {
95 pub name: String,
96 pub ty: IrType,
97 pub trace: SourceTrace,
98}
99
100/// A precondition (from `requires`).
101#[derive(Debug, Clone, Serialize)]
102pub struct Condition {
103 pub expr: IrExpr,
104 pub trace: SourceTrace,
105}
106
107/// A postcondition (from `ensures`) — may be unconditional or guarded by `when`.
108#[derive(Debug, Clone, Serialize)]
109pub enum Postcondition {
110 /// Always holds after execution.
111 Always { expr: IrExpr, trace: SourceTrace },
112 /// Holds only when `guard` is true.
113 When {
114 guard: IrExpr,
115 expr: IrExpr,
116 trace: SourceTrace,
117 },
118}
119
120/// A declarative property annotation (idempotent, atomic, etc.)
121#[derive(Debug, Clone, Serialize)]
122pub struct Property {
123 pub key: String,
124 pub value: PropertyValue,
125 pub trace: SourceTrace,
126}
127
128/// Property value — mirrors the AST's PropValue but in IR form.
129#[derive(Debug, Clone, Serialize)]
130pub enum PropertyValue {
131 Bool(bool),
132 Int(i64),
133 String(String),
134 Ident(String),
135}
136
137// ── Invariant ───────────────────────────────────────────────
138
139/// A module-level invariant — a proof obligation that must always hold.
140#[derive(Debug, Clone, Serialize)]
141pub struct Invariant {
142 pub name: String,
143 pub expr: IrExpr,
144 pub trace: SourceTrace,
145}
146
147// ── Edge guards ─────────────────────────────────────────────
148
149/// An edge-case guard — lowered from `edge_cases { when cond => action }`.
150#[derive(Debug, Clone, Serialize)]
151pub struct EdgeGuard {
152 pub condition: IrExpr,
153 pub action: String,
154 pub args: Vec<(String, IrExpr)>,
155 pub trace: SourceTrace,
156}
157
158// ── IR Expressions ──────────────────────────────────────────
159
160/// An IR expression — a simplified, typed expression tree.
161#[derive(Debug, Clone, Serialize)]
162pub enum IrExpr {
163 /// Variable reference (parameter name or quantifier binding).
164 Var(String),
165 /// Literal value.
166 Literal(IrLiteral),
167 /// Field access: `obj.field`
168 FieldAccess { root: Box<IrExpr>, field: String },
169 /// Binary comparison.
170 Compare {
171 left: Box<IrExpr>,
172 op: CmpOp,
173 right: Box<IrExpr>,
174 },
175 /// Arithmetic operation.
176 Arithmetic {
177 left: Box<IrExpr>,
178 op: ArithOp,
179 right: Box<IrExpr>,
180 },
181 /// Logical AND.
182 And(Box<IrExpr>, Box<IrExpr>),
183 /// Logical OR.
184 Or(Box<IrExpr>, Box<IrExpr>),
185 /// Logical NOT.
186 Not(Box<IrExpr>),
187 /// Logical implication: `a => b` ≡ `!a || b`.
188 Implies(Box<IrExpr>, Box<IrExpr>),
189 /// Pre-state reference: `old(expr)`.
190 Old(Box<IrExpr>),
191 /// Universal quantifier: `forall x: T => body`.
192 Forall {
193 binding: String,
194 ty: String,
195 body: Box<IrExpr>,
196 },
197 /// Existential quantifier: `exists x: T => body`.
198 Exists {
199 binding: String,
200 ty: String,
201 body: Box<IrExpr>,
202 },
203 /// Function call.
204 Call { name: String, args: Vec<IrExpr> },
205}
206
207/// Comparison operators (shared with AST but owned by IR).
208#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
209pub enum CmpOp {
210 Eq,
211 Ne,
212 Lt,
213 Gt,
214 Le,
215 Ge,
216}
217
218/// Arithmetic operators.
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
220pub enum ArithOp {
221 Add,
222 Sub,
223}
224
225/// IR literal values.
226#[derive(Debug, Clone, PartialEq, Serialize)]
227pub enum IrLiteral {
228 Null,
229 Bool(bool),
230 Int(i64),
231 Decimal(String),
232 String(String),
233}