#[allow(unused_imports)]
use crate::ast::{SimpleNodeKindExt, TreeNodeExt};
use crate::tokens::{Span, StringPart};
use super::functions::*;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum BinderKind {
Default,
Implicit,
Instance,
StrictImplicit,
}
#[allow(dead_code)]
#[allow(missing_docs)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TreePathExt(pub Vec<usize>);
impl TreePathExt {
#[allow(dead_code)]
pub fn root() -> Self {
TreePathExt(Vec::new())
}
#[allow(dead_code)]
pub fn child(&self, idx: usize) -> Self {
let mut v = self.0.clone();
v.push(idx);
TreePathExt(v)
}
#[allow(dead_code)]
pub fn depth(&self) -> usize {
self.0.len()
}
}
#[allow(dead_code)]
#[allow(missing_docs)]
#[derive(Debug, Clone, Default)]
pub struct TreeStatsExt2 {
pub max_depth: usize,
pub node_count: usize,
pub leaf_count: usize,
pub max_branching: usize,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Binder {
pub name: String,
pub ty: Option<Box<Located<SurfaceExpr>>>,
pub info: BinderKind,
}
#[derive(Clone, Debug, PartialEq)]
pub struct WhereClause {
pub name: String,
pub params: Vec<Binder>,
pub ty: Option<Located<SurfaceExpr>>,
pub val: Located<SurfaceExpr>,
}
impl WhereClause {
#[allow(dead_code)]
pub fn new(
name: String,
params: Vec<Binder>,
ty: Option<Located<SurfaceExpr>>,
val: Located<SurfaceExpr>,
) -> Self {
Self {
name,
params,
ty,
val,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct CalcStep {
pub lhs: Located<SurfaceExpr>,
pub rel: String,
pub rhs: Located<SurfaceExpr>,
pub proof: Located<SurfaceExpr>,
}
impl CalcStep {
#[allow(dead_code)]
pub fn new(
lhs: Located<SurfaceExpr>,
rel: String,
rhs: Located<SurfaceExpr>,
proof: Located<SurfaceExpr>,
) -> Self {
Self {
lhs,
rel,
rhs,
proof,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum SurfaceExpr {
Sort(SortKind),
Var(String),
App(Box<Located<SurfaceExpr>>, Box<Located<SurfaceExpr>>),
Lam(Vec<Binder>, Box<Located<SurfaceExpr>>),
Pi(Vec<Binder>, Box<Located<SurfaceExpr>>),
Let(
String,
Option<Box<Located<SurfaceExpr>>>,
Box<Located<SurfaceExpr>>,
Box<Located<SurfaceExpr>>,
),
Lit(Literal),
Ann(Box<Located<SurfaceExpr>>, Box<Located<SurfaceExpr>>),
Hole,
Proj(Box<Located<SurfaceExpr>>, String),
If(
Box<Located<SurfaceExpr>>,
Box<Located<SurfaceExpr>>,
Box<Located<SurfaceExpr>>,
),
Match(Box<Located<SurfaceExpr>>, Vec<MatchArm>),
Do(Vec<DoAction>),
Have(
String,
Box<Located<SurfaceExpr>>,
Box<Located<SurfaceExpr>>,
Box<Located<SurfaceExpr>>,
),
Suffices(String, Box<Located<SurfaceExpr>>, Box<Located<SurfaceExpr>>),
Show(Box<Located<SurfaceExpr>>, Box<Located<SurfaceExpr>>),
NamedArg(Box<Located<SurfaceExpr>>, String, Box<Located<SurfaceExpr>>),
AnonymousCtor(Vec<Located<SurfaceExpr>>),
ListLit(Vec<Located<SurfaceExpr>>),
Tuple(Vec<Located<SurfaceExpr>>),
Return(Box<Located<SurfaceExpr>>),
StringInterp(Vec<StringPart>),
Range(
Option<Box<Located<SurfaceExpr>>>,
Option<Box<Located<SurfaceExpr>>>,
),
ByTactic(Vec<Located<TacticRef>>),
Calc(Vec<CalcStep>),
}
impl SurfaceExpr {
#[allow(dead_code)]
pub fn var(name: &str) -> Self {
SurfaceExpr::Var(name.to_string())
}
#[allow(dead_code)]
pub fn nat(n: u64) -> Self {
SurfaceExpr::Lit(Literal::Nat(n))
}
#[allow(dead_code)]
pub fn string(s: &str) -> Self {
SurfaceExpr::Lit(Literal::String(s.to_string()))
}
#[allow(dead_code)]
pub fn float(v: f64) -> Self {
SurfaceExpr::Lit(Literal::Float(v))
}
#[allow(dead_code)]
pub fn is_hole(&self) -> bool {
matches!(self, SurfaceExpr::Hole)
}
#[allow(dead_code)]
pub fn is_var(&self) -> bool {
matches!(self, SurfaceExpr::Var(_))
}
#[allow(dead_code)]
pub fn as_var(&self) -> Option<&str> {
match self {
SurfaceExpr::Var(s) => Some(s),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct MatchArm {
pub pattern: Located<Pattern>,
pub guard: Option<Located<SurfaceExpr>>,
pub rhs: Located<SurfaceExpr>,
}
#[allow(dead_code)]
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub struct TreeZipper {
pub focus: TreeNodeExt,
pub context: Vec<(String, Vec<TreeNodeExt>, Vec<TreeNodeExt>)>,
}
impl TreeZipper {
#[allow(dead_code)]
pub fn new(tree: TreeNodeExt) -> Self {
TreeZipper {
focus: tree,
context: Vec::new(),
}
}
#[allow(dead_code)]
pub fn down(mut self, i: usize) -> Option<Self> {
if i >= self.focus.children.len() {
return None;
}
let mut children = self.focus.children.clone();
let child = children.remove(i);
let left = children[..i].to_vec();
let right = children[i..].to_vec();
self.context.push((self.focus.label.clone(), left, right));
Some(TreeZipper {
focus: child,
context: self.context,
})
}
#[allow(dead_code)]
pub fn depth(&self) -> usize {
self.context.len()
}
#[allow(dead_code)]
pub fn label(&self) -> &str {
&self.focus.label
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Pattern {
Wild,
Var(String),
Ctor(String, Vec<Located<Pattern>>),
Lit(Literal),
Or(Box<Located<Pattern>>, Box<Located<Pattern>>),
}
#[derive(Clone, Debug, PartialEq)]
#[allow(clippy::large_enum_variant)]
pub enum Decl {
Axiom {
name: String,
univ_params: Vec<String>,
ty: Located<SurfaceExpr>,
attrs: Vec<AttributeKind>,
},
Definition {
name: String,
univ_params: Vec<String>,
ty: Option<Located<SurfaceExpr>>,
val: Located<SurfaceExpr>,
where_clauses: Vec<WhereClause>,
attrs: Vec<AttributeKind>,
},
Theorem {
name: String,
univ_params: Vec<String>,
ty: Located<SurfaceExpr>,
proof: Located<SurfaceExpr>,
where_clauses: Vec<WhereClause>,
attrs: Vec<AttributeKind>,
},
Inductive {
name: String,
univ_params: Vec<String>,
params: Vec<Binder>,
indices: Vec<Binder>,
ty: Located<SurfaceExpr>,
ctors: Vec<Constructor>,
},
Import {
path: Vec<String>,
},
Namespace {
name: String,
decls: Vec<Located<Decl>>,
},
Structure {
name: String,
univ_params: Vec<String>,
extends: Vec<String>,
fields: Vec<FieldDecl>,
},
ClassDecl {
name: String,
univ_params: Vec<String>,
extends: Vec<String>,
fields: Vec<FieldDecl>,
},
InstanceDecl {
name: Option<String>,
class_name: String,
ty: Located<SurfaceExpr>,
defs: Vec<(String, Located<SurfaceExpr>)>,
},
SectionDecl {
name: String,
decls: Vec<Located<Decl>>,
},
Variable {
binders: Vec<Binder>,
},
Open {
path: Vec<String>,
names: Vec<String>,
},
Attribute {
attrs: Vec<String>,
decl: Box<Located<Decl>>,
},
HashCmd {
cmd: String,
arg: Located<SurfaceExpr>,
},
Mutual {
decls: Vec<Located<Decl>>,
},
Derive {
instances: Vec<String>,
type_name: String,
},
NotationDecl {
kind: AstNotationKind,
prec: Option<u32>,
name: String,
notation: String,
},
Universe {
names: Vec<String>,
},
}
impl Decl {
#[allow(dead_code)]
pub fn name(&self) -> Option<&str> {
match self {
Decl::Axiom { name, .. }
| Decl::Definition { name, .. }
| Decl::Theorem { name, .. }
| Decl::Inductive { name, .. }
| Decl::Namespace { name, .. }
| Decl::Structure { name, .. }
| Decl::ClassDecl { name, .. }
| Decl::SectionDecl { name, .. } => Some(name),
Decl::InstanceDecl { name, .. } => name.as_deref(),
Decl::Derive { type_name, .. } => Some(type_name),
Decl::NotationDecl { name, .. } => Some(name),
_ => None,
}
}
#[allow(dead_code)]
pub fn typed_attrs(&self) -> &[AttributeKind] {
match self {
Decl::Axiom { attrs, .. }
| Decl::Definition { attrs, .. }
| Decl::Theorem { attrs, .. } => attrs,
_ => &[],
}
}
#[allow(dead_code)]
pub fn is_mutual(&self) -> bool {
matches!(self, Decl::Mutual { .. })
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum AstNotationKind {
Prefix,
Postfix,
Infixl,
Infixr,
Notation,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Located<T> {
pub value: T,
pub span: Span,
}
impl<T> Located<T> {
pub fn new(value: T, span: Span) -> Self {
Self { value, span }
}
#[allow(dead_code)]
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Located<U> {
Located {
value: f(self.value),
span: self.span,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum AttributeKind {
Simp,
Ext,
Instance,
Reducible,
Irreducible,
Inline,
NoInline,
SpecializeAttr,
Custom(String),
}
impl AttributeKind {
#[allow(dead_code)]
pub fn is_custom(&self) -> bool {
matches!(self, AttributeKind::Custom(_))
}
#[allow(dead_code)]
pub fn name(&self) -> &str {
match self {
AttributeKind::Simp => "simp",
AttributeKind::Ext => "ext",
AttributeKind::Instance => "instance",
AttributeKind::Reducible => "reducible",
AttributeKind::Irreducible => "irreducible",
AttributeKind::Inline => "inline",
AttributeKind::NoInline => "noinline",
AttributeKind::SpecializeAttr => "specialize",
AttributeKind::Custom(s) => s,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Literal {
Nat(u64),
Float(f64),
String(String),
Char(char),
}
#[derive(Clone, Debug, PartialEq)]
pub enum DoAction {
Let(String, Located<SurfaceExpr>),
LetTyped(String, Located<SurfaceExpr>, Located<SurfaceExpr>),
Bind(String, Located<SurfaceExpr>),
Expr(Located<SurfaceExpr>),
Return(Located<SurfaceExpr>),
}
#[derive(Clone, Debug, PartialEq)]
pub struct FieldDecl {
pub name: String,
pub ty: Located<SurfaceExpr>,
pub default: Option<Located<SurfaceExpr>>,
}
#[allow(dead_code)]
#[allow(missing_docs)]
pub struct IdentityTransformExt;
#[derive(Clone, Debug, PartialEq)]
pub struct Constructor {
pub name: String,
pub ty: Located<SurfaceExpr>,
}
#[allow(dead_code)]
#[allow(missing_docs)]
pub struct TransformMemo {
pub cache: std::collections::HashMap<u64, TreeNodeExt>,
}
impl TransformMemo {
#[allow(dead_code)]
pub fn new() -> Self {
TransformMemo {
cache: std::collections::HashMap::new(),
}
}
#[allow(dead_code)]
pub fn get(&self, key: u64) -> Option<&TreeNodeExt> {
self.cache.get(&key)
}
#[allow(dead_code)]
pub fn store(&mut self, key: u64, result: TreeNodeExt) {
self.cache.insert(key, result);
}
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.cache.len()
}
#[allow(dead_code)]
pub fn is_empty(&self) -> bool {
self.cache.is_empty()
}
}
#[allow(dead_code)]
#[allow(missing_docs)]
#[derive(Debug, Default)]
pub struct TreeStats {
pub nodes: usize,
pub leaves: usize,
pub max_depth: usize,
pub total_size: usize,
}
impl TreeStats {
#[allow(dead_code)]
pub fn new() -> Self {
TreeStats::default()
}
#[allow(dead_code)]
pub fn from_tree(root: &TreeNodeExt) -> Self {
let mut stats = TreeStats::new();
collect_stats(root, 0, &mut stats);
stats
}
}
#[allow(dead_code)]
#[allow(missing_docs)]
pub struct TreeCursor {
pub current: TreeNodeExt,
pub ancestors: Vec<TreeNodeExt>,
}
impl TreeCursor {
#[allow(dead_code)]
pub fn new(root: TreeNodeExt) -> Self {
TreeCursor {
current: root,
ancestors: Vec::new(),
}
}
#[allow(dead_code)]
pub fn kind(&self) -> &SimpleNodeKindExt {
&self.current.kind
}
#[allow(dead_code)]
pub fn label(&self) -> &str {
&self.current.label
}
#[allow(dead_code)]
pub fn child_count(&self) -> usize {
self.current.children.len()
}
#[allow(dead_code)]
pub fn depth(&self) -> usize {
self.ancestors.len()
}
}
#[allow(dead_code)]
#[allow(missing_docs)]
pub struct TreeZipperExt {
pub focus: TreeNodeExt,
pub path: TreePathExt,
pub ancestors: Vec<(
SimpleNodeKindExt,
String,
Vec<TreeNodeExt>,
Vec<TreeNodeExt>,
)>,
}
impl TreeZipperExt {
#[allow(dead_code)]
pub fn new(root: TreeNodeExt) -> Self {
TreeZipperExt {
focus: root,
path: TreePathExt::root(),
ancestors: Vec::new(),
}
}
#[allow(dead_code)]
pub fn down(mut self, i: usize) -> Option<Self> {
if i >= self.focus.children.len() {
return None;
}
let mut children = self.focus.children;
let child = children.remove(i);
let left: Vec<TreeNodeExt> = children.drain(..i.min(children.len())).collect();
let right: Vec<TreeNodeExt> = children;
self.ancestors
.push((self.focus.kind, self.focus.label, left, right));
self.path = self.path.child(i);
Some(TreeZipperExt {
focus: child,
path: self.path,
ancestors: self.ancestors,
})
}
#[allow(dead_code)]
pub fn up(mut self) -> Option<(Self, TreeNodeExt)> {
let (kind, label, left, right) = self.ancestors.pop()?;
let child = self.focus;
let mut children = left;
children.push(child.clone());
children.extend(right);
let mut new_path = self.path;
new_path.0.pop();
Some((
TreeZipperExt {
focus: TreeNodeExt {
kind,
label,
children,
},
path: new_path,
ancestors: self.ancestors,
},
child,
))
}
}
#[allow(dead_code)]
#[allow(missing_docs)]
pub struct RenameTransformExt {
pub from: String,
pub to: String,
pub count: usize,
}
impl RenameTransformExt {
#[allow(dead_code)]
pub fn new(from: &str, to: &str) -> Self {
RenameTransformExt {
from: from.to_string(),
to: to.to_string(),
count: 0,
}
}
}
#[allow(dead_code)]
#[allow(missing_docs)]
pub struct NodeCache {
pub values: std::collections::HashMap<String, u64>,
}
impl NodeCache {
#[allow(dead_code)]
pub fn new() -> Self {
NodeCache {
values: std::collections::HashMap::new(),
}
}
#[allow(dead_code)]
pub fn store(&mut self, key: &str, val: u64) {
self.values.insert(key.to_string(), val);
}
#[allow(dead_code)]
pub fn get(&self, key: &str) -> Option<u64> {
self.values.get(key).copied()
}
}
#[allow(dead_code)]
#[allow(missing_docs)]
pub struct TransformMemoExt2 {
pub cache: std::collections::HashMap<String, String>,
}
impl TransformMemoExt2 {
#[allow(dead_code)]
pub fn new() -> Self {
TransformMemoExt2 {
cache: std::collections::HashMap::new(),
}
}
#[allow(dead_code)]
pub fn has(&self, label: &str) -> bool {
self.cache.contains_key(label)
}
#[allow(dead_code)]
pub fn get(&self, label: &str) -> Option<&str> {
self.cache.get(label).map(|s| s.as_str())
}
#[allow(dead_code)]
pub fn insert(&mut self, label: &str, result: &str) {
self.cache.insert(label.to_string(), result.to_string());
}
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.cache.len()
}
#[allow(dead_code)]
pub fn is_empty(&self) -> bool {
self.cache.is_empty()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SortKind {
Type,
Prop,
TypeU(String),
SortU(String),
}