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}
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}