1#![allow(type_alias_bounds)]
7
8pub use anyhow::bail;
11pub use contracts::requires;
12pub use tracing::debug;
13pub use tracing::instrument;
14pub use tracing::trace;
15
16pub use formality_macros::{fixed_point, term, test, Visit};
18
19pub type Fallible<T> = anyhow::Result<T>;
20
21pub mod binder;
25mod cast;
26mod collections;
27pub mod fixed_point;
28pub mod fold;
29pub mod judgment;
30pub mod language;
31pub mod parse;
32pub mod substitution;
33pub mod term;
34pub mod variable;
35pub mod visit;
36
37pub use cast::{Downcast, DowncastFrom, DowncastTo, Downcasted, To, Upcast, UpcastFrom, Upcasted};
38pub use collections::Deduplicate;
39pub use collections::Map;
40pub use collections::Set;
41pub use collections::SetExt;
42
43pub fn with_tracing_logs<T>(action: impl FnOnce() -> T) -> T {
46 use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
47 use tracing_tree::HierarchicalLayer;
48 let filter = EnvFilter::from_env("RUST_LOG");
49 let subscriber = Registry::default()
50 .with(filter)
51 .with(HierarchicalLayer::new(2).with_writer(std::io::stdout));
52 tracing::subscriber::with_default(subscriber, action)
53}
54
55#[macro_export]
56macro_rules! trait_alias {
57 (
58 $(#[$m:meta])*
59 $v:vis trait $t:ident = $($u:tt)*
60 ) => {
61 $($m)*
62 $v trait $t: $($u)* { }
63
64 impl<T> $t for T
65 where
66 T: $($u)*
67 { }
68 }
69}
70
71#[macro_export]
83macro_rules! declare_language {
84 (
85 $(#[$the_lang_m:meta])*
86 $the_lang_v:vis mod $the_lang:ident {
87 const NAME = $name:expr;
88 type Kind = $kind:ty;
89 type Parameter = $param:ty;
90 const BINDING_OPEN = $binding_open:expr;
91 const BINDING_CLOSE = $binding_close:expr;
92 }
93 ) => {
94 $(#[$the_lang_m:meta])*
95 $the_lang_v mod $the_lang {
96 use super::*;
97
98 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
99 pub struct FormalityLang;
100
101 impl $crate::language::Language for FormalityLang {
102 const NAME: &'static str = $name;
103 type Kind = $kind;
104 type Parameter = $param;
105 const BINDING_OPEN: char = $binding_open;
106 const BINDING_CLOSE: char = $binding_close;
107 }
108
109 $crate::trait_alias! {
110 pub trait Fold = $crate::fold::CoreFold<FormalityLang>
111 }
112
113 $crate::trait_alias! {
114 pub trait Visit = $crate::visit::CoreVisit<FormalityLang>
115 }
116
117 $crate::trait_alias! {
118 pub trait Parse = $crate::parse::CoreParse<FormalityLang>
119 }
120
121 $crate::trait_alias! {
122 pub trait Term = $crate::term::CoreTerm<FormalityLang>
123 }
124
125 pub type Variable = $crate::variable::CoreVariable<FormalityLang>;
126 pub type ExistentialVar = $crate::variable::CoreExistentialVar<FormalityLang>;
127 pub type UniversalVar = $crate::variable::CoreUniversalVar<FormalityLang>;
128 pub type BoundVar = $crate::variable::CoreBoundVar<FormalityLang>;
129 pub type DebruijnIndex = $crate::variable::DebruijnIndex;
130 pub type VarIndex = $crate::variable::VarIndex;
131 pub type Binder<T> = $crate::binder::CoreBinder<FormalityLang, T>;
132 pub type Substitution = $crate::substitution::CoreSubstitution<FormalityLang>;
133 pub type VarSubstitution = $crate::substitution::CoreVarSubstitution<FormalityLang>;
134
135 #[track_caller]
137 pub fn term<T>(text: &str) -> T
138 where
139 T: Parse,
140 {
141 try_term(text).unwrap()
142 }
143
144 #[track_caller]
146 pub fn try_term<T>(text: &str) -> anyhow::Result<T>
147 where
148 T: Parse,
149 {
150 term_with(None::<(String, $param)>, text)
151 }
152
153 #[track_caller]
158 pub fn term_with<T, B>(bindings: impl IntoIterator<Item = B>, text: &str) -> anyhow::Result<T>
159 where
160 T: Parse,
161 B: $crate::Upcast<(String, $param)>,
162 {
163 let scope = $crate::parse::Scope::new(bindings.into_iter().map(|b| b.upcast()));
164 let (t, remainder) = match T::parse(&scope, text) {
165 Ok(v) => v,
166 Err(errors) => {
167 let mut err = anyhow::anyhow!("failed to parse {text}");
168 for error in errors {
169 err = err.context(error.text.to_owned()).context(error.message);
170 }
171 return Err(err);
172 }
173 };
174 if !$crate::parse::skip_whitespace(remainder).is_empty() {
175 anyhow::bail!("extra tokens after parsing {text:?} to {t:?}: {remainder:?}");
176 }
177 Ok(t)
178 }
179 }
180 }
181}
182
183#[macro_export]
186macro_rules! id {
187 ($n:ident) => {
188 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
189 pub struct $n {
190 data: std::sync::Arc<String>,
191 }
192
193 const _: () = {
194 use $crate::fold::{self, CoreFold};
195 use $crate::parse::{self, CoreParse};
196 use $crate::variable::CoreVariable;
197 use $crate::visit::CoreVisit;
198
199 $crate::cast_impl!($n);
200
201 impl $n {
202 pub fn new(s: &str) -> $n {
203 $n {
204 data: std::sync::Arc::new(s.to_string()),
205 }
206 }
207 }
208
209 impl std::ops::Deref for $n {
210 type Target = String;
211
212 fn deref(&self) -> &String {
213 &self.data
214 }
215 }
216
217 impl CoreVisit<crate::FormalityLang> for $n {
218 fn free_variables(&self) -> Vec<CoreVariable<crate::FormalityLang>> {
219 vec![]
220 }
221
222 fn size(&self) -> usize {
223 1
224 }
225
226 fn assert_valid(&self) {}
227 }
228
229 impl CoreFold<crate::FormalityLang> for $n {
230 fn substitute(
231 &self,
232 _substitution_fn: fold::SubstitutionFn<'_, crate::FormalityLang>,
233 ) -> Self {
234 self.clone()
235 }
236 }
237
238 impl CoreParse<crate::FormalityLang> for $n {
239 fn parse<'t>(
240 _scope: &parse::Scope<crate::FormalityLang>,
241 text: &'t str,
242 ) -> parse::ParseResult<'t, Self> {
243 let (string, text) = parse::identifier(text)?;
244 let n = $n::new(&string);
245 Ok((n, text))
246 }
247 }
248
249 impl std::fmt::Debug for $n {
250 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251 write!(f, "{}", &self.data)
252 }
253 }
254 };
255 };
256}