Skip to main content

oxilean_std/sigma/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::functions::*;
8use std::collections::BTreeMap;
9
10/// A telescope — a sequence of dependent types, each depending on the previous.
11/// The type at position `i` is a function from the product of all prior types to `Type`.
12/// Represented here as a Vec of named field descriptors.
13#[allow(dead_code)]
14#[derive(Debug, Clone)]
15pub struct DependentTelescope {
16    fields: Vec<(String, String)>,
17}
18#[allow(dead_code)]
19impl DependentTelescope {
20    /// Create an empty telescope.
21    pub fn new() -> Self {
22        Self { fields: Vec::new() }
23    }
24    /// Append a new field to the telescope, extending the dependent context.
25    pub fn extend(&self, name: impl Into<String>, ty_desc: impl Into<String>) -> Self {
26        let mut fields = self.fields.clone();
27        fields.push((name.into(), ty_desc.into()));
28        Self { fields }
29    }
30    /// Return the number of fields (depth of the telescope).
31    pub fn depth(&self) -> usize {
32        self.fields.len()
33    }
34    /// Return the field names in order.
35    pub fn field_names(&self) -> Vec<&str> {
36        self.fields.iter().map(|(n, _)| n.as_str()).collect()
37    }
38    /// Check if the telescope contains a field with the given name.
39    pub fn has_field(&self, name: &str) -> bool {
40        self.fields.iter().any(|(n, _)| n == name)
41    }
42    /// Return the type description for a named field, if present.
43    pub fn field_type(&self, name: &str) -> Option<&str> {
44        self.fields
45            .iter()
46            .find(|(n, _)| n == name)
47            .map(|(_, t)| t.as_str())
48    }
49    /// Project out a sub-telescope by keeping only fields up to (and including) `depth`.
50    pub fn truncate(&self, depth: usize) -> Self {
51        Self {
52            fields: self.fields[..self.fields.len().min(depth)].to_vec(),
53        }
54    }
55}
56/// A refinement-type value: a value together with a dynamically-checked proof tag.
57/// The proof is stored as a `bool` result from a predicate closure so the type
58/// can be constructed and inspected without heavyweight theorem-prover plumbing.
59#[allow(dead_code)]
60#[derive(Debug, Clone)]
61pub struct RefinementValue<T: Clone> {
62    value: T,
63    predicate_name: String,
64    predicate_holds: bool,
65}
66#[allow(dead_code)]
67impl<T: Clone> RefinementValue<T> {
68    /// Construct a refinement value, evaluating the predicate immediately.
69    pub fn new(
70        value: T,
71        predicate_name: impl Into<String>,
72        predicate: impl Fn(&T) -> bool,
73    ) -> Self {
74        let holds = predicate(&value);
75        Self {
76            value,
77            predicate_name: predicate_name.into(),
78            predicate_holds: holds,
79        }
80    }
81    /// Return a reference to the underlying value.
82    pub fn val(&self) -> &T {
83        &self.value
84    }
85    /// Return whether the predicate holds for this value.
86    pub fn is_valid(&self) -> bool {
87        self.predicate_holds
88    }
89    /// Name of the predicate used to refine this type.
90    pub fn predicate_name(&self) -> &str {
91        &self.predicate_name
92    }
93    /// Coerce to a different refinement type given a proof that the new predicate
94    /// follows from the old one (encoded as a Rust closure for demo purposes).
95    pub fn coerce(
96        &self,
97        new_name: impl Into<String>,
98        implication: impl Fn(&T) -> bool,
99    ) -> RefinementValue<T> {
100        RefinementValue::new(self.value.clone(), new_name, implication)
101    }
102}
103/// Existential pack: hides the type index, exposing only the interface type.
104/// This models `∃ α, value : α` where the type is erased at the boundary.
105#[allow(dead_code)]
106pub struct ExistentialPack<Interface> {
107    value: Box<dyn std::any::Any + Send + Sync>,
108    interface: Interface,
109    type_name: &'static str,
110}
111#[allow(dead_code)]
112impl<Interface: Clone> ExistentialPack<Interface> {
113    /// Pack a value of any type together with its interface projection.
114    pub fn pack<T: std::any::Any + Send + Sync>(
115        value: T,
116        interface: Interface,
117        type_name: &'static str,
118    ) -> Self {
119        Self {
120            value: Box::new(value),
121            interface,
122            type_name,
123        }
124    }
125    /// Access the sealed interface.
126    pub fn interface(&self) -> &Interface {
127        &self.interface
128    }
129    /// The Rust type name of the hidden implementation.
130    pub fn hidden_type_name(&self) -> &'static str {
131        self.type_name
132    }
133    /// Attempt to unpack if the hidden type is known statically.
134    pub fn unpack<T: std::any::Any + Clone>(&self) -> Option<T> {
135        self.value.downcast_ref::<T>().cloned()
136    }
137}
138/// W-type node: a well-founded tree where each node has a label of type `A`
139/// and a (possibly empty) family of children indexed by `B(label)`.
140#[allow(dead_code)]
141#[derive(Debug, Clone)]
142pub struct WNode<A: Clone, B: Clone + Ord> {
143    label: A,
144    children: std::collections::BTreeMap<B, WNode<A, B>>,
145}
146#[allow(dead_code)]
147impl<A: Clone, B: Clone + Ord> WNode<A, B> {
148    /// Construct a leaf node (no children).
149    pub fn leaf(label: A) -> Self {
150        Self {
151            label,
152            children: std::collections::BTreeMap::new(),
153        }
154    }
155    /// Construct an interior node with the given children.
156    pub fn node(label: A, children: std::collections::BTreeMap<B, WNode<A, B>>) -> Self {
157        Self { label, children }
158    }
159    /// Access the label of this node.
160    pub fn label(&self) -> &A {
161        &self.label
162    }
163    /// Number of immediate children.
164    pub fn arity(&self) -> usize {
165        self.children.len()
166    }
167    /// Compute the height of the W-tree (maximum depth).
168    pub fn height(&self) -> usize {
169        if self.children.is_empty() {
170            0
171        } else {
172            1 + self
173                .children
174                .values()
175                .map(|c| c.height())
176                .max()
177                .unwrap_or(0)
178        }
179    }
180    /// Count the total number of nodes in the tree.
181    pub fn size(&self) -> usize {
182        1 + self.children.values().map(|c| c.size()).sum::<usize>()
183    }
184    /// Map a function over all node labels.
185    pub fn map_labels<C: Clone>(&self, f: &impl Fn(&A) -> C) -> WNode<C, B> {
186        WNode {
187            label: f(&self.label),
188            children: self
189                .children
190                .iter()
191                .map(|(k, v)| (k.clone(), v.map_labels(f)))
192                .collect(),
193        }
194    }
195    /// Fold over the tree in a bottom-up manner.
196    pub fn fold<R: Clone>(&self, f: &impl Fn(&A, Vec<R>) -> R) -> R {
197        let child_results: Vec<R> = self.children.values().map(|c| c.fold(f)).collect();
198        f(&self.label, child_results)
199    }
200}
201/// Row type: a dictionary of named fields with types, supporting width subtyping.
202/// Implements a lightweight record row that can be checked for subtype relationships.
203#[allow(dead_code)]
204#[derive(Debug, Clone)]
205pub struct RowRecord {
206    fields: std::collections::BTreeMap<String, String>,
207}
208#[allow(dead_code)]
209impl RowRecord {
210    /// Empty row.
211    pub fn empty() -> Self {
212        Self {
213            fields: std::collections::BTreeMap::new(),
214        }
215    }
216    /// Extend the row with a new field.
217    pub fn with(mut self, label: impl Into<String>, ty: impl Into<String>) -> Self {
218        self.fields.insert(label.into(), ty.into());
219        self
220    }
221    /// Check width subtyping: `self` is a subtype of `other` if `other`'s fields ⊆ `self`'s fields.
222    pub fn is_width_subtype_of(&self, other: &RowRecord) -> bool {
223        other
224            .fields
225            .keys()
226            .all(|k| self.fields.contains_key(k.as_str()))
227    }
228    /// Check depth subtyping: every field in `other` appears in `self` with compatible type.
229    /// Here "compatible" is modelled as equality of type descriptions (simplified).
230    pub fn is_depth_subtype_of(&self, other: &RowRecord) -> bool {
231        other.fields.iter().all(|(k, v)| {
232            self.fields
233                .get(k.as_str())
234                .map(|tv| tv == v)
235                .unwrap_or(false)
236        })
237    }
238    /// Number of fields in this row.
239    pub fn width(&self) -> usize {
240        self.fields.len()
241    }
242    /// Restrict the row to a given set of field names.
243    pub fn restrict(&self, labels: &[&str]) -> Self {
244        Self {
245            fields: labels
246                .iter()
247                .filter_map(|l| self.fields.get(*l).map(|v| ((*l).to_string(), v.clone())))
248                .collect(),
249        }
250    }
251    /// Merge two rows (fields from `other` override `self` on collision).
252    pub fn merge(&self, other: &RowRecord) -> Self {
253        let mut fields = self.fields.clone();
254        for (k, v) in &other.fields {
255            fields.insert(k.clone(), v.clone());
256        }
257        Self { fields }
258    }
259}