Skip to main content

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    /// Minutes.
188    Min,
189    /// Hours.
190    H,
191}
192
193/// A byte size value with unit.
194#[derive(Debug, Clone, Copy, PartialEq)]
195pub struct ByteSize {
196    /// The numeric value.
197    pub value: f64,
198    /// The size unit.
199    pub unit: SizeUnit,
200}
201
202/// Size unit for byte size values.
203#[derive(Debug, Clone, Copy, PartialEq, Eq)]
204pub enum SizeUnit {
205    /// Bytes.
206    B,
207    /// Kilobytes.
208    Kb,
209    /// Megabytes.
210    Mb,
211    /// Gigabytes.
212    Gb,
213    /// Terabytes.
214    Tb,
215}
216
217/// Security classification from `@security(...)`.
218#[derive(Debug, Clone, PartialEq, Eq)]
219pub struct SecurityInfo {
220    /// Classification level (e.g. `"public"`, `"internal"`, `"confidential"`, `"secret"`).
221    pub level: String,
222    /// Whether this data contains personally identifiable information.
223    pub pii: bool,
224}
225
226/// Known security levels in ascending order of sensitivity.
227///
228/// Index position defines the ordering: higher index = more sensitive.
229pub const SECURITY_LEVELS: &[&str] = &["public", "internal", "confidential", "secret"];
230
231/// Returns the sensitivity rank of a security level (0 = least sensitive).
232///
233/// Returns `None` if the level is not recognized.
234#[must_use]
235pub fn security_level_rank(level: &str) -> Option<usize> {
236    SECURITY_LEVELS.iter().position(|&l| l == level)
237}
238
239/// Known capability names in the Bock capability taxonomy.
240///
241/// These are the 16 spec-defined capabilities from s02-types / s09-context.
242pub const KNOWN_CAPABILITIES: &[&str] = &[
243    "Network",
244    "Storage",
245    "Crypto",
246    "GPU",
247    "Camera",
248    "Microphone",
249    "Location",
250    "Notifications",
251    "Bluetooth",
252    "Biometrics",
253    "Clipboard",
254    "SystemProcess",
255    "FFI",
256    "Environment",
257    "Clock",
258    "Random",
259];
260
261// ─── Layer 3: Target ──────────────────────────────────────────────────────────
262
263/// Target-specific information attached by the target analyzer (TR-AIR pass).
264#[derive(Debug, Clone, PartialEq)]
265pub struct TargetInfo {
266    /// Placeholder field — filled in by the TR-AIR pass.
267    pub _placeholder: (),
268}
269
270// ─── Metadata value type ──────────────────────────────────────────────────────
271
272/// A dynamically-typed metadata value stored in `AIRNode::metadata`.
273#[derive(Debug, Clone, PartialEq)]
274pub enum Value {
275    Null,
276    Bool(bool),
277    Int(i64),
278    Float(f64),
279    String(String),
280    List(Vec<Value>),
281    Map(HashMap<String, Value>),
282}