use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::functions::*;
use std::collections::BTreeMap;
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct DependentTelescope {
fields: Vec<(String, String)>,
}
#[allow(dead_code)]
impl DependentTelescope {
pub fn new() -> Self {
Self { fields: Vec::new() }
}
pub fn extend(&self, name: impl Into<String>, ty_desc: impl Into<String>) -> Self {
let mut fields = self.fields.clone();
fields.push((name.into(), ty_desc.into()));
Self { fields }
}
pub fn depth(&self) -> usize {
self.fields.len()
}
pub fn field_names(&self) -> Vec<&str> {
self.fields.iter().map(|(n, _)| n.as_str()).collect()
}
pub fn has_field(&self, name: &str) -> bool {
self.fields.iter().any(|(n, _)| n == name)
}
pub fn field_type(&self, name: &str) -> Option<&str> {
self.fields
.iter()
.find(|(n, _)| n == name)
.map(|(_, t)| t.as_str())
}
pub fn truncate(&self, depth: usize) -> Self {
Self {
fields: self.fields[..self.fields.len().min(depth)].to_vec(),
}
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct RefinementValue<T: Clone> {
value: T,
predicate_name: String,
predicate_holds: bool,
}
#[allow(dead_code)]
impl<T: Clone> RefinementValue<T> {
pub fn new(
value: T,
predicate_name: impl Into<String>,
predicate: impl Fn(&T) -> bool,
) -> Self {
let holds = predicate(&value);
Self {
value,
predicate_name: predicate_name.into(),
predicate_holds: holds,
}
}
pub fn val(&self) -> &T {
&self.value
}
pub fn is_valid(&self) -> bool {
self.predicate_holds
}
pub fn predicate_name(&self) -> &str {
&self.predicate_name
}
pub fn coerce(
&self,
new_name: impl Into<String>,
implication: impl Fn(&T) -> bool,
) -> RefinementValue<T> {
RefinementValue::new(self.value.clone(), new_name, implication)
}
}
#[allow(dead_code)]
pub struct ExistentialPack<Interface> {
value: Box<dyn std::any::Any + Send + Sync>,
interface: Interface,
type_name: &'static str,
}
#[allow(dead_code)]
impl<Interface: Clone> ExistentialPack<Interface> {
pub fn pack<T: std::any::Any + Send + Sync>(
value: T,
interface: Interface,
type_name: &'static str,
) -> Self {
Self {
value: Box::new(value),
interface,
type_name,
}
}
pub fn interface(&self) -> &Interface {
&self.interface
}
pub fn hidden_type_name(&self) -> &'static str {
self.type_name
}
pub fn unpack<T: std::any::Any + Clone>(&self) -> Option<T> {
self.value.downcast_ref::<T>().cloned()
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct WNode<A: Clone, B: Clone + Ord> {
label: A,
children: std::collections::BTreeMap<B, WNode<A, B>>,
}
#[allow(dead_code)]
impl<A: Clone, B: Clone + Ord> WNode<A, B> {
pub fn leaf(label: A) -> Self {
Self {
label,
children: std::collections::BTreeMap::new(),
}
}
pub fn node(label: A, children: std::collections::BTreeMap<B, WNode<A, B>>) -> Self {
Self { label, children }
}
pub fn label(&self) -> &A {
&self.label
}
pub fn arity(&self) -> usize {
self.children.len()
}
pub fn height(&self) -> usize {
if self.children.is_empty() {
0
} else {
1 + self
.children
.values()
.map(|c| c.height())
.max()
.unwrap_or(0)
}
}
pub fn size(&self) -> usize {
1 + self.children.values().map(|c| c.size()).sum::<usize>()
}
pub fn map_labels<C: Clone>(&self, f: &impl Fn(&A) -> C) -> WNode<C, B> {
WNode {
label: f(&self.label),
children: self
.children
.iter()
.map(|(k, v)| (k.clone(), v.map_labels(f)))
.collect(),
}
}
pub fn fold<R: Clone>(&self, f: &impl Fn(&A, Vec<R>) -> R) -> R {
let child_results: Vec<R> = self.children.values().map(|c| c.fold(f)).collect();
f(&self.label, child_results)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct RowRecord {
fields: std::collections::BTreeMap<String, String>,
}
#[allow(dead_code)]
impl RowRecord {
pub fn empty() -> Self {
Self {
fields: std::collections::BTreeMap::new(),
}
}
pub fn with(mut self, label: impl Into<String>, ty: impl Into<String>) -> Self {
self.fields.insert(label.into(), ty.into());
self
}
pub fn is_width_subtype_of(&self, other: &RowRecord) -> bool {
other
.fields
.keys()
.all(|k| self.fields.contains_key(k.as_str()))
}
pub fn is_depth_subtype_of(&self, other: &RowRecord) -> bool {
other.fields.iter().all(|(k, v)| {
self.fields
.get(k.as_str())
.map(|tv| tv == v)
.unwrap_or(false)
})
}
pub fn width(&self) -> usize {
self.fields.len()
}
pub fn restrict(&self, labels: &[&str]) -> Self {
Self {
fields: labels
.iter()
.filter_map(|l| self.fields.get(*l).map(|v| ((*l).to_string(), v.clone())))
.collect(),
}
}
pub fn merge(&self, other: &RowRecord) -> Self {
let mut fields = self.fields.clone();
for (k, v) in &other.fields {
fields.insert(k.clone(), v.clone());
}
Self { fields }
}
}