use std::{rc::Rc, fmt, any, fmt::{Debug,Formatter}, hash::{Hash,Hasher}};
use crate::{
shared::Shared,
normal,
dynamics
};
pub type Var = String;
pub type Ident = String;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize,PartialOrd,Ord)]
pub enum Name {
Bin(NameRec, NameRec),
Leaf,
Sym(String),
Num(usize),
NoParse(String),
}
pub type NameRec = Rc<Name>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize,PartialOrd,Ord)]
pub enum NameTm {
Var(Var),
Ident(Ident),
ValVar(Var),
Name(Name),
Bin(NameTmRec, NameTmRec),
Lam(Var, Sort, NameTmRec),
App(NameTmRec, NameTmRec),
WriteScope,
NoParse(String),
}
pub type NameTmRec = Rc<NameTm>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize,PartialOrd,Ord)]
pub enum IdxTm {
Var(Var),
Ident(Ident),
Sing(NameTm),
Empty,
Apart(IdxTmRec, IdxTmRec),
Union(IdxTmRec, IdxTmRec),
Unit,
Bin(IdxTmRec, IdxTmRec),
Pair(IdxTmRec, IdxTmRec),
Proj1(IdxTmRec),
Proj2(IdxTmRec),
WriteScope,
NmSet(normal::NmSet),
Lam(Var, Sort, IdxTmRec),
App(IdxTmRec, IdxTmRec),
Map(NameTmRec, IdxTmRec),
MapStar(NameTmRec, IdxTmRec),
FlatMap(IdxTmRec, IdxTmRec),
FlatMapStar(IdxTmRec, IdxTmRec),
NmTm(NameTm),
NoParse(String),
Unknown,
}
pub type IdxTmRec = Rc<IdxTm>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize,PartialOrd,Ord)]
pub enum Sort {
Nm,
NmSet,
NmArrow(SortRec,SortRec),
IdxArrow(SortRec,SortRec),
Unit,
Prod(SortRec,SortRec),
NoParse(String),
}
pub type SortRec = Rc<Sort>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum Kind {
Type,
TypeParam(KindRec),
IdxParam(Sort, KindRec),
NoParse(String),
}
pub type KindRec = Rc<Kind>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum Prop {
Tt,
Equiv(IdxTm, IdxTm, Sort),
Apart(IdxTm, IdxTm, Sort),
Conj(PropRec, PropRec),
NoParse(String),
}
pub type PropRec = Rc<Prop>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum Effect {
WR(IdxTm, IdxTm),
NoParse(String),
}
pub type EffectRec = Rc<Effect>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum PrimType {
Nat,
Bool,
String,
}
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum Type {
Var(Var),
Ident(Ident),
Abstract(Ident),
Prim(PrimType),
IdentDef(Ident, TypeRec),
IdentUndef(Ident),
Sum(TypeRec, TypeRec),
Prod(TypeRec, TypeRec),
Unit,
Ref(IdxTm, TypeRec),
Thk(IdxTm, CEffectRec),
IdxApp(TypeRec, IdxTm),
TypeApp(TypeRec, TypeRec),
Nm(IdxTm),
NmFn(NameTm),
TypeFn(Var, Kind, TypeRec),
IdxFn(Var, Sort, TypeRec),
Rec(Var, TypeRec),
Exists(Var, SortRec, Prop, TypeRec),
NoParse(String),
}
pub type TypeRec = Rc<Type>;
pub fn ident_nat() -> Ident { "Nat".to_string() }
pub fn ident_bool() -> Ident { "Bool".to_string() }
pub fn ident_string() -> Ident { "String".to_string() }
pub fn type_string() -> Type { Type::Prim(PrimType::String) }
pub fn type_nat() -> Type { Type::Prim(PrimType::Nat) }
pub fn type_bool() -> Type { Type::Prim(PrimType::Bool) }
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum CType {
Lift(Type),
Arrow(Type,CEffectRec),
NoParse(String),
}
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum CEffect {
Cons(CType,Effect),
ForallType(Var,Kind,CEffectRec),
ForallIdx(Var,Sort,Prop,CEffectRec),
NoParse(String),
}
pub type CEffectRec = Rc<CEffect>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum Val {
Var(Var),
Unit,
Pair(ValRec, ValRec),
Inj1(ValRec),
Inj2(ValRec),
Roll(ValRec),
Name(Name),
NameFn(NameTm),
Anno(ValRec,Type),
Pack(IdxTm, ValRec),
ThunkAnon(ExpRec),
Bool(bool),
Nat(usize),
Str(String),
HostObj(HostObj),
NoParse(String),
}
pub type ValRec = Rc<Val>;
#[derive(Clone,Serialize)]
pub struct HostObj {
#[serde(skip_serializing)]
pub ops:Rc<HostObjOps>,
#[serde(skip_serializing)]
pub any:Rc<any::Any>
}
pub trait HostObjOps {
fn eq(&self, x:&Rc<any::Any>, y:&Rc<any::Any>) -> bool;
fn hash(&self, x:&Rc<any::Any>) -> u64;
fn fmt(&self, f:&mut Formatter, x:&Rc<any::Any> ) -> fmt::Result;
}
impl Hash for HostObj {
fn hash<H:Hasher>(&self, hasher: &mut H) {
self.ops.hash( &self.any ).hash( hasher )
}
}
impl Debug for HostObj {
fn fmt(&self, f:&mut Formatter) -> fmt::Result {
self.ops.fmt( f, &self.any )
}
}
impl PartialEq for HostObj {
fn eq(&self, other:&Self) -> bool {
self.ops.eq( &self.any, &other.any )
}
}
impl Eq for HostObj { }
#[derive(Clone,Serialize)]
pub struct HostEvalFn {
pub path:String,
pub arity:usize,
#[serde(skip_serializing)]
pub eval:Rc<Fn(Vec<dynamics::RtVal>) -> dynamics::ExpTerm>
}
impl Hash for HostEvalFn {
fn hash<H:Hasher>(&self, hasher: &mut H) {
self.path.hash(hasher)
}
}
impl Debug for HostEvalFn {
fn fmt(&self, f:&mut Formatter) -> fmt::Result {
write!(f, "HostEvalFn({:?})", self.path)
}
}
impl PartialEq for HostEvalFn {
fn eq(&self, other:&Self) -> bool {
self.path == other.path
}
}
impl Eq for HostEvalFn { }
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum PrimApp {
NameBin(Val,Val),
RefThunk(Val),
NatEq(Val,Val),
NatLt(Val,Val),
NatLte(Val,Val),
NatPlus(Val,Val),
}
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum Exp {
Doc(String, ExpRec),
UseAll(UseAllModule, ExpRec),
Decls(DeclsRec, ExpRec),
AnnoE(ExpRec,CEffect),
AnnoC(ExpRec,CType),
Force(Val),
Thunk(Val,ExpRec),
Unroll(Val,Var,ExpRec),
Unpack(Var,Var,Val,ExpRec),
Fix(Var,ExpRec),
Ret(Val),
DefType(Var,Type,ExpRec),
Let(Var,ExpRec,ExpRec),
Lam(Var, ExpRec),
HostFn(HostEvalFn),
App(ExpRec, Val),
IdxApp(ExpRec, IdxTm),
Split(Val, Var, Var, ExpRec),
Case(Val, Var, ExpRec, Var, ExpRec),
IfThenElse(Val, ExpRec, ExpRec),
RefAnon(Val),
Ref(Val,Val),
Get(Val),
WriteScope(Val,ExpRec),
NameFnApp(Val,Val),
PrimApp(PrimApp),
Unimp,
DebugLabel(Option<Name>,Option<String>,ExpRec),
NoParse(String),
}
pub type ExpRec = Rc<Exp>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub struct Module {
pub path: String,
pub body: String,
pub decls: Decls,
}
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub enum Decls {
UseAll(UseAllModule, DeclsRec),
Doc( String, DeclsRec),
NmTm( String,NameTm, DeclsRec),
IdxTm(String,IdxTm, DeclsRec),
Type( String,Type, DeclsRec),
Val( String,Option<Type>, Val, DeclsRec),
Fn( String,Type,Exp, DeclsRec),
End,
NoParse(String),
}
pub type DeclsRec = Rc<Decls>;
#[derive(Clone,Debug,Eq,PartialEq,Hash,Serialize)]
pub struct UseAllModule {
pub path: String,
pub module: Shared<Module>
}