#![allow(type_alias_bounds)]
pub use anyhow::bail;
pub use contracts::requires;
pub use tracing::debug;
pub use tracing::instrument;
pub use tracing::trace;
pub use formality_macros::{fixed_point, term, test, Visit};
pub type Fallible<T> = anyhow::Result<T>;
pub mod binder;
mod cast;
mod collections;
pub mod fixed_point;
pub mod fold;
pub mod judgment;
pub mod language;
pub mod parse;
pub mod substitution;
pub mod term;
pub mod variable;
pub mod visit;
pub use cast::{Downcast, DowncastFrom, DowncastTo, Downcasted, To, Upcast, UpcastFrom, Upcasted};
pub use collections::Deduplicate;
pub use collections::Map;
pub use collections::Set;
pub use collections::SetExt;
pub fn with_tracing_logs<T>(action: impl FnOnce() -> T) -> T {
use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
use tracing_tree::HierarchicalLayer;
let filter = EnvFilter::from_env("RUST_LOG");
let subscriber = Registry::default()
.with(filter)
.with(HierarchicalLayer::new(2).with_writer(std::io::stdout));
tracing::subscriber::with_default(subscriber, action)
}
#[macro_export]
macro_rules! trait_alias {
(
$(#[$m:meta])*
$v:vis trait $t:ident = $($u:tt)*
) => {
$($m)*
$v trait $t: $($u)* { }
impl<T> $t for T
where
T: $($u)*
{ }
}
}
#[macro_export]
macro_rules! declare_language {
(
$(#[$the_lang_m:meta])*
$the_lang_v:vis mod $the_lang:ident {
const NAME = $name:expr;
type Kind = $kind:ty;
type Parameter = $param:ty;
const BINDING_OPEN = $binding_open:expr;
const BINDING_CLOSE = $binding_close:expr;
}
) => {
$(#[$the_lang_m:meta])*
$the_lang_v mod $the_lang {
use super::*;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
pub struct FormalityLang;
impl $crate::language::Language for FormalityLang {
const NAME: &'static str = $name;
type Kind = $kind;
type Parameter = $param;
const BINDING_OPEN: char = $binding_open;
const BINDING_CLOSE: char = $binding_close;
}
$crate::trait_alias! {
pub trait Fold = $crate::fold::CoreFold<FormalityLang>
}
$crate::trait_alias! {
pub trait Visit = $crate::visit::CoreVisit<FormalityLang>
}
$crate::trait_alias! {
pub trait Parse = $crate::parse::CoreParse<FormalityLang>
}
$crate::trait_alias! {
pub trait Term = $crate::term::CoreTerm<FormalityLang>
}
pub type Variable = $crate::variable::CoreVariable<FormalityLang>;
pub type ExistentialVar = $crate::variable::CoreExistentialVar<FormalityLang>;
pub type UniversalVar = $crate::variable::CoreUniversalVar<FormalityLang>;
pub type BoundVar = $crate::variable::CoreBoundVar<FormalityLang>;
pub type DebruijnIndex = $crate::variable::DebruijnIndex;
pub type VarIndex = $crate::variable::VarIndex;
pub type Binder<T> = $crate::binder::CoreBinder<FormalityLang, T>;
pub type Substitution = $crate::substitution::CoreSubstitution<FormalityLang>;
pub type VarSubstitution = $crate::substitution::CoreVarSubstitution<FormalityLang>;
#[track_caller]
pub fn term<T>(text: &str) -> T
where
T: Parse,
{
try_term(text).unwrap()
}
#[track_caller]
pub fn try_term<T>(text: &str) -> anyhow::Result<T>
where
T: Parse,
{
term_with(None::<(String, $param)>, text)
}
#[track_caller]
pub fn term_with<T, B>(bindings: impl IntoIterator<Item = B>, text: &str) -> anyhow::Result<T>
where
T: Parse,
B: $crate::Upcast<(String, $param)>,
{
let scope = $crate::parse::Scope::new(bindings.into_iter().map(|b| b.upcast()));
let (t, remainder) = match T::parse(&scope, text) {
Ok(v) => v,
Err(errors) => {
let mut err = anyhow::anyhow!("failed to parse {text}");
for error in errors {
err = err.context(error.text.to_owned()).context(error.message);
}
return Err(err);
}
};
if !$crate::parse::skip_whitespace(remainder).is_empty() {
anyhow::bail!("extra tokens after parsing {text:?} to {t:?}: {remainder:?}");
}
Ok(t)
}
}
}
}
#[macro_export]
macro_rules! id {
($n:ident) => {
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $n {
data: std::sync::Arc<String>,
}
const _: () = {
use $crate::fold::{self, CoreFold};
use $crate::parse::{self, CoreParse};
use $crate::variable::CoreVariable;
use $crate::visit::CoreVisit;
$crate::cast_impl!($n);
impl $n {
pub fn new(s: &str) -> $n {
$n {
data: std::sync::Arc::new(s.to_string()),
}
}
}
impl std::ops::Deref for $n {
type Target = String;
fn deref(&self) -> &String {
&self.data
}
}
impl CoreVisit<crate::FormalityLang> for $n {
fn free_variables(&self) -> Vec<CoreVariable<crate::FormalityLang>> {
vec![]
}
fn size(&self) -> usize {
1
}
fn assert_valid(&self) {}
}
impl CoreFold<crate::FormalityLang> for $n {
fn substitute(
&self,
_substitution_fn: fold::SubstitutionFn<'_, crate::FormalityLang>,
) -> Self {
self.clone()
}
}
impl CoreParse<crate::FormalityLang> for $n {
fn parse<'t>(
_scope: &parse::Scope<crate::FormalityLang>,
text: &'t str,
) -> parse::ParseResult<'t, Self> {
let (string, text) = parse::identifier(text)?;
let n = $n::new(&string);
Ok((n, text))
}
}
impl std::fmt::Debug for $n {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", &self.data)
}
}
};
};
}