bock_air/stubs.rs
1//! Stub layer-slot types populated by later compiler passes.
2//!
3//! These types are defined here as placeholders. The actual implementations
4//! are filled in by the type-checker (T-AIR), context resolver (C-AIR), and
5//! target analyzer (TR-AIR) passes.
6
7use std::collections::{HashMap, HashSet};
8
9// ─── Layer 1: Type / Ownership / Effects / Capabilities ──────────────────────
10
11/// Opaque reference to a resolved type from the type checker's table.
12///
13/// The full `Type` algebra lives in `bock-types`. This lightweight wrapper
14/// is stored on AIR nodes so later passes can identify the resolved type
15/// without pulling in the full type-system crate.
16#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17pub struct TypeRef(pub String);
18
19/// Type information attached to an AIR node by the type checker (T-AIR pass).
20#[derive(Debug, Clone, PartialEq)]
21pub struct TypeInfo {
22 /// Resolved type reference, populated by the T-AIR pass.
23 pub resolved_type: Option<TypeRef>,
24}
25
26/// Ownership state of a value, as tracked on AIR nodes.
27///
28/// Mirrors the ownership states from the type-level ownership analysis;
29/// defined here so AIR nodes can carry this without depending on `bock-types`.
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum OwnershipState {
32 /// The binding owns its value.
33 Owned,
34 /// The value is immutably borrowed.
35 Borrowed,
36 /// The value is mutably borrowed.
37 MutBorrowed,
38 /// The value has been moved; the binding is no longer valid.
39 Moved,
40 /// Managed ownership — GC/refcount semantics (`@managed`).
41 Managed,
42}
43
44/// Ownership/borrow information attached to an AIR node by ownership analysis.
45#[derive(Debug, Clone, PartialEq)]
46pub struct OwnershipInfo {
47 /// Ownership state, populated by ownership analysis.
48 pub state: Option<OwnershipState>,
49}
50
51/// A reference to an algebraic effect, identified by its fully-qualified name.
52///
53/// Used in the `effects` set on each AIR node.
54#[derive(Debug, Clone, PartialEq, Eq, Hash)]
55pub struct EffectRef {
56 /// Fully-qualified name of the effect (e.g. `"Std.Io.Log"`).
57 pub name: String,
58}
59
60impl EffectRef {
61 /// Creates a new effect reference from a fully-qualified name.
62 #[must_use]
63 pub fn new(name: impl Into<String>) -> Self {
64 Self { name: name.into() }
65 }
66}
67
68/// A platform/language capability required or provided by a node.
69///
70/// Used in the `capabilities` set on each AIR node.
71#[derive(Debug, Clone, PartialEq, Eq, Hash)]
72pub struct Capability {
73 /// Fully-qualified capability name (e.g. `"Std.Io.FileSystem"`).
74 pub name: String,
75}
76
77impl Capability {
78 /// Creates a new capability from a fully-qualified name.
79 #[must_use]
80 pub fn new(name: impl Into<String>) -> Self {
81 Self { name: name.into() }
82 }
83}
84
85// ─── Layer 2: Context ─────────────────────────────────────────────────────────
86
87/// A behavioral modifier annotation that affects code generation or analysis.
88///
89/// These are extracted from annotations like `@concurrent`, `@managed`,
90/// `@deterministic`, `@inline`, `@cold`, `@hot`, and `@deprecated`.
91#[derive(Debug, Clone, PartialEq, Eq)]
92pub enum BehavioralModifier {
93 /// `@concurrent` — marks a function as safe for concurrent execution.
94 Concurrent,
95 /// `@managed` — opts into managed ownership (escape hatch for ownership analysis).
96 Managed,
97 /// `@deterministic` — asserts the function is pure/deterministic.
98 Deterministic,
99 /// `@inline` — hints that the function should be inlined.
100 Inline,
101 /// `@cold` — marks a code path as unlikely to be taken.
102 Cold,
103 /// `@hot` — marks a code path as frequently taken.
104 Hot,
105 /// `@deprecated` — marks the item as deprecated, with an optional reason.
106 Deprecated(Option<String>),
107}
108
109/// Context annotations attached/validated by the context resolver (C-AIR pass).
110///
111/// Produced by [`crate::context::interpret_context`] from parsed AST annotations.
112#[derive(Debug, Clone, PartialEq, Default)]
113pub struct ContextBlock {
114 /// Free-form text from `@context("""...""")`.
115 pub context_text: Option<String>,
116 /// Structured markers extracted from `@context` text (e.g. `@intent:`, `@assumption:`).
117 pub markers: Vec<ContextMarker>,
118 /// Capabilities declared via `@requires(Capability.Network, ...)`.
119 pub capabilities: HashSet<Capability>,
120 /// Performance budget from `@performance(max_latency: 100.ms, max_memory: 50.mb)`.
121 pub performance: Option<PerformanceBudget>,
122 /// Invariant expressions from `@invariant(expr)`.
123 pub invariants: Vec<String>,
124 /// Security classification from `@security(level: "confidential", pii: true)`.
125 pub security: Option<SecurityInfo>,
126 /// Domain tags from `@domain("e-commerce", "checkout")`.
127 pub domains: Vec<String>,
128 /// Behavioral modifiers from `@concurrent`, `@managed`, `@inline`, etc.
129 pub modifiers: Vec<BehavioralModifier>,
130}
131
132impl ContextBlock {
133 /// Returns `true` if this context block has no annotations.
134 #[must_use]
135 pub fn is_empty(&self) -> bool {
136 self.context_text.is_none()
137 && self.markers.is_empty()
138 && self.capabilities.is_empty()
139 && self.performance.is_none()
140 && self.invariants.is_empty()
141 && self.security.is_none()
142 && self.domains.is_empty()
143 && self.modifiers.is_empty()
144 }
145}
146
147/// A structured marker extracted from `@context` free-form text.
148///
149/// Markers follow the pattern `@tag: text` within the context string.
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub struct ContextMarker {
152 /// The marker tag (e.g. `"intent"`, `"assumption"`, `"constraint"`).
153 pub tag: String,
154 /// The text following the marker tag.
155 pub text: String,
156}
157
158/// Performance budget constraints from `@performance(...)`.
159#[derive(Debug, Clone, PartialEq)]
160pub struct PerformanceBudget {
161 /// Maximum latency constraint (e.g. `Duration` from `100.ms`).
162 pub max_latency: Option<Duration>,
163 /// Maximum memory constraint (e.g. `ByteSize` from `50.mb`).
164 pub max_memory: Option<ByteSize>,
165}
166
167/// A duration value with unit.
168#[derive(Debug, Clone, Copy, PartialEq)]
169pub struct Duration {
170 /// The numeric value.
171 pub value: f64,
172 /// The time unit.
173 pub unit: TimeUnit,
174}
175
176/// Time unit for duration values.
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
178pub enum TimeUnit {
179 /// Nanoseconds.
180 Ns,
181 /// Microseconds.
182 Us,
183 /// Milliseconds.
184 Ms,
185 /// Seconds.
186 S,
187}
188
189/// A byte size value with unit.
190#[derive(Debug, Clone, Copy, PartialEq)]
191pub struct ByteSize {
192 /// The numeric value.
193 pub value: f64,
194 /// The size unit.
195 pub unit: SizeUnit,
196}
197
198/// Size unit for byte size values.
199#[derive(Debug, Clone, Copy, PartialEq, Eq)]
200pub enum SizeUnit {
201 /// Bytes.
202 B,
203 /// Kilobytes.
204 Kb,
205 /// Megabytes.
206 Mb,
207 /// Gigabytes.
208 Gb,
209}
210
211/// Security classification from `@security(...)`.
212#[derive(Debug, Clone, PartialEq, Eq)]
213pub struct SecurityInfo {
214 /// Classification level (e.g. `"public"`, `"internal"`, `"confidential"`, `"secret"`).
215 pub level: String,
216 /// Whether this data contains personally identifiable information.
217 pub pii: bool,
218}
219
220/// Known security levels in ascending order of sensitivity.
221///
222/// Index position defines the ordering: higher index = more sensitive.
223pub const SECURITY_LEVELS: &[&str] = &["public", "internal", "confidential", "secret"];
224
225/// Returns the sensitivity rank of a security level (0 = least sensitive).
226///
227/// Returns `None` if the level is not recognized.
228#[must_use]
229pub fn security_level_rank(level: &str) -> Option<usize> {
230 SECURITY_LEVELS.iter().position(|&l| l == level)
231}
232
233/// Known capability names in the Bock capability taxonomy.
234///
235/// These are the 16 spec-defined capabilities from s02-types / s09-context.
236pub const KNOWN_CAPABILITIES: &[&str] = &[
237 "Network",
238 "Storage",
239 "Crypto",
240 "GPU",
241 "Camera",
242 "Microphone",
243 "Location",
244 "Notifications",
245 "Bluetooth",
246 "Biometrics",
247 "Clipboard",
248 "SystemProcess",
249 "FFI",
250 "Environment",
251 "Clock",
252 "Random",
253];
254
255// ─── Layer 3: Target ──────────────────────────────────────────────────────────
256
257/// Target-specific information attached by the target analyzer (TR-AIR pass).
258#[derive(Debug, Clone, PartialEq)]
259pub struct TargetInfo {
260 /// Placeholder field — filled in by the TR-AIR pass.
261 pub _placeholder: (),
262}
263
264// ─── Metadata value type ──────────────────────────────────────────────────────
265
266/// A dynamically-typed metadata value stored in `AIRNode::metadata`.
267#[derive(Debug, Clone, PartialEq)]
268pub enum Value {
269 Null,
270 Bool(bool),
271 Int(i64),
272 Float(f64),
273 String(String),
274 List(Vec<Value>),
275 Map(HashMap<String, Value>),
276}