Skip to content

Commit 1448e59

Browse files
committed
create formality-core with the core binding logic
1 parent 913563e commit 1448e59

File tree

18 files changed

+838
-299
lines changed

18 files changed

+838
-299
lines changed

Cargo.lock

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/formality-core/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ edition = "2021"
88
[dependencies]
99
lazy_static = "1.4.0"
1010
env_logger = "*"
11+
stacker = "0.1.15"
1112
tracing = "0.1"
1213
tracing-subscriber = {version = "0.3", default-features = false, features = ["env-filter", "fmt"]}
1314
tracing-tree = { version = "0.2" }
14-
formality-macros = { path = "../formality-macros" }
15+
formality-macros = { path = "../formality-macros" }
16+
anyhow = "1.0.75"
17+
contracts = "0.6.3"

crates/formality-core/src/binder.rs

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,28 @@ use crate::{
99
cast::{Downcast, DowncastFrom, DowncastTo, To, Upcast, UpcastFrom},
1010
fold::Fold,
1111
fold::SubstitutionFn,
12-
grammar::VarIndex,
12+
language::{HasKind, Kind, Language, Parameter},
13+
substitution::Substitution,
14+
variable::{BoundVar, DebruijnIndex, VarIndex, Variable},
1315
visit::Visit,
16+
Fallible,
1417
};
1518

16-
use super::{BoundVar, DebruijnIndex, Fallible, Parameter, ParameterKind, Substitution, Variable};
17-
1819
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
19-
pub struct Binder<T> {
20-
kinds: Vec<ParameterKind>,
20+
pub struct Binder<L: Language, T> {
21+
kinds: Vec<Kind<L>>,
2122
term: T,
2223
}
2324

24-
impl<T: Fold> Binder<T> {
25+
impl<L: Language, T: Fold<L>> Binder<L, T> {
2526
/// Accesses the contents of the binder.
2627
///
2728
/// The variables inside will be renamed to fresh var indices
2829
/// that do not alias any other indices seen during this computation.
2930
///
3031
/// The expectation is that you will create a term and use `Binder::new`.
31-
pub fn open(&self) -> (Vec<BoundVar>, T) {
32-
let (bound_vars, substitution): (Vec<BoundVar>, Substitution) = self
32+
pub fn open(&self) -> (Vec<BoundVar<L>>, T) {
33+
let (bound_vars, substitution): (Vec<BoundVar<L>>, Substitution<L>) = self
3334
.kinds
3435
.iter()
3536
.zip(0..)
@@ -48,21 +49,21 @@ impl<T: Fold> Binder<T> {
4849
}
4950

5051
pub fn dummy(term: T) -> Self {
51-
let v: Vec<Variable> = vec![];
52+
let v: Vec<Variable<L>> = vec![];
5253
Self::new(v, term)
5354
}
5455

5556
/// Given a set of variables (X, Y, Z) and a term referecing some subset of them,
5657
/// create a binder where exactly those variables are bound (even the ones not used).
57-
pub fn new(variables: impl Upcast<Vec<Variable>>, term: T) -> Self {
58-
let variables: Vec<Variable> = variables.upcast();
59-
let (kinds, substitution): (Vec<ParameterKind>, Substitution) = variables
58+
pub fn new(variables: impl Upcast<Vec<Variable<L>>>, term: T) -> Self {
59+
let variables: Vec<Variable<L>> = variables.upcast();
60+
let (kinds, substitution): (Vec<Kind<L>>, Substitution<L>) = variables
6061
.iter()
6162
.zip(0..)
6263
.map(|(old_bound_var, index)| {
63-
let old_bound_var: Variable = old_bound_var.upcast();
64+
let old_bound_var: Variable<L> = old_bound_var.upcast();
6465
assert!(old_bound_var.is_free());
65-
let new_bound_var: Parameter = BoundVar {
66+
let new_bound_var: Parameter<L> = BoundVar {
6667
debruijn: Some(DebruijnIndex::INNERMOST),
6768
var_index: VarIndex { index },
6869
kind: old_bound_var.kind(),
@@ -78,15 +79,15 @@ impl<T: Fold> Binder<T> {
7879

7980
/// Given a set of variables (X, Y, Z) and a term referecing some subset of them,
8081
/// create a binder for just those variables that are mentioned.
81-
pub fn mentioned(variables: impl Upcast<Vec<Variable>>, term: T) -> Self {
82-
let mut variables: Vec<Variable> = variables.upcast();
82+
pub fn mentioned(variables: impl Upcast<Vec<Variable<L>>>, term: T) -> Self {
83+
let mut variables: Vec<Variable<L>> = variables.upcast();
8384
let fv = term.free_variables();
8485
variables.retain(|v| fv.contains(v));
85-
let variables: Vec<Variable> = variables.into_iter().collect();
86+
let variables: Vec<Variable<L>> = variables.into_iter().collect();
8687
Binder::new(variables, term)
8788
}
8889

89-
pub fn into<U>(self) -> Binder<U>
90+
pub fn into<U>(self) -> Binder<L, U>
9091
where
9192
T: Into<U>,
9293
{
@@ -107,13 +108,13 @@ impl<T: Fold> Binder<T> {
107108

108109
/// Instantiate the binder with the given parameters, returning an err if the parameters
109110
/// are the wrong number or ill-kinded.
110-
pub fn instantiate_with(&self, parameters: &[impl Upcast<Parameter>]) -> Fallible<T> {
111+
pub fn instantiate_with(&self, parameters: &[impl Upcast<Parameter<L>>]) -> Fallible<T> {
111112
if parameters.len() != self.kinds.len() {
112113
bail!("wrong number of parameters");
113114
}
114115

115116
for ((p, k), i) in parameters.iter().zip(&self.kinds).zip(0..) {
116-
let p: Parameter = p.upcast();
117+
let p: Parameter<L> = p.upcast();
117118
if p.kind() != *k {
118119
bail!(
119120
"parameter {i} has kind {:?} but should have kind {:?}",
@@ -127,8 +128,8 @@ impl<T: Fold> Binder<T> {
127128
}
128129

129130
/// Instantiate the term, replacing each bound variable with `op(i)`.
130-
pub fn instantiate(&self, mut op: impl FnMut(ParameterKind, VarIndex) -> Parameter) -> T {
131-
let substitution: Vec<Parameter> = self
131+
pub fn instantiate(&self, mut op: impl FnMut(Kind<L>, VarIndex) -> Parameter<L>) -> T {
132+
let substitution: Vec<Parameter<L>> = self
132133
.kinds
133134
.iter()
134135
.zip(0..)
@@ -153,11 +154,11 @@ impl<T: Fold> Binder<T> {
153154
}
154155

155156
/// Returns the kinds of each variable bound by this binder
156-
pub fn kinds(&self) -> &[ParameterKind] {
157+
pub fn kinds(&self) -> &[Kind<L>] {
157158
&self.kinds
158159
}
159160

160-
pub fn map<U: Fold>(&self, op: impl FnOnce(T) -> U) -> Binder<U> {
161+
pub fn map<U: Fold<L>>(&self, op: impl FnOnce(T) -> U) -> Binder<L, U> {
161162
let (vars, t) = self.open();
162163
let u = op(t);
163164
Binder::new(vars, u)
@@ -166,7 +167,7 @@ impl<T: Fold> Binder<T> {
166167

167168
/// Creates a fresh bound var of the given kind that is not yet part of a binder.
168169
/// You can put this into a term and then use `Binder::new`.
169-
pub fn fresh_bound_var(kind: ParameterKind) -> BoundVar {
170+
pub fn fresh_bound_var<L: Language>(kind: Kind<L>) -> BoundVar<L> {
170171
lazy_static! {
171172
static ref COUNTER: AtomicUsize = AtomicUsize::new(0);
172173
}
@@ -180,8 +181,8 @@ pub fn fresh_bound_var(kind: ParameterKind) -> BoundVar {
180181
}
181182
}
182183

183-
impl<T: Visit> Visit for Binder<T> {
184-
fn free_variables(&self) -> Vec<Variable> {
184+
impl<L: Language, T: Visit<L>> Visit<L> for Binder<L, T> {
185+
fn free_variables(&self) -> Vec<Variable<L>> {
185186
self.term.free_variables()
186187
}
187188

@@ -194,8 +195,8 @@ impl<T: Visit> Visit for Binder<T> {
194195
}
195196
}
196197

197-
impl<T: Fold> Fold for Binder<T> {
198-
fn substitute(&self, substitution_fn: SubstitutionFn<'_>) -> Self {
198+
impl<L: Language, T: Fold<L>> Fold<L> for Binder<L, T> {
199+
fn substitute(&self, substitution_fn: SubstitutionFn<'_, L>) -> Self {
199200
let term = self.term.substitute(&mut |v| {
200201
// Shift this variable out through the binder. If that fails,
201202
// it's a variable bound by this binder, so the substitution can't
@@ -224,13 +225,13 @@ impl<T: Fold> Fold for Binder<T> {
224225
}
225226
}
226227

227-
impl<T, U> UpcastFrom<Binder<T>> for Binder<U>
228+
impl<L: Language, T, U> UpcastFrom<Binder<L, T>> for Binder<L, U>
228229
where
229230
T: Clone,
230231
U: Clone,
231232
T: Upcast<U>,
232233
{
233-
fn upcast_from(term: Binder<T>) -> Self {
234+
fn upcast_from(term: Binder<L, T>) -> Self {
234235
let Binder { kinds, term } = term;
235236
Binder {
236237
kinds,
@@ -239,11 +240,11 @@ where
239240
}
240241
}
241242

242-
impl<T, U> DowncastTo<Binder<T>> for Binder<U>
243+
impl<L: Language, T, U> DowncastTo<Binder<L, T>> for Binder<L, U>
243244
where
244245
T: DowncastFrom<U>,
245246
{
246-
fn downcast_to(&self) -> Option<Binder<T>> {
247+
fn downcast_to(&self) -> Option<Binder<L, T>> {
247248
let Binder { kinds, term } = self;
248249
let term = term.downcast()?;
249250
Some(Binder {
@@ -253,7 +254,7 @@ where
253254
}
254255
}
255256

256-
impl<T> std::fmt::Debug for Binder<T>
257+
impl<L: Language, T> std::fmt::Debug for Binder<L, T>
257258
where
258259
T: std::fmt::Debug,
259260
{

crates/formality-core/src/cast.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::sync::Arc;
22

3-
use crate::{collections::Set, derive_links::Term};
3+
use crate::collections::Set;
44

55
pub trait To {
66
fn to<T>(&self) -> T
@@ -311,6 +311,23 @@ macro_rules! cast_impl {
311311
}
312312
};
313313

314+
(impl($($p:tt)*) $e:ident ($($ep:tt)*) :: $v:ident ($u:ty)) => {
315+
impl<$($p)*> $crate::cast::UpcastFrom<$u> for $e<$($ep)*> {
316+
fn upcast_from(v: $u) -> $e<$($ep)*> {
317+
$e::$v(v)
318+
}
319+
}
320+
321+
impl<$($p)*> $crate::cast::DowncastTo<$u> for $e<$($ep)*> {
322+
fn downcast_to(&self) -> Option<$u> {
323+
match self {
324+
$e::$v(u) => Some(Clone::clone(u)),
325+
_ => None,
326+
}
327+
}
328+
}
329+
};
330+
314331
(impl($($p:tt)*) $t:ty) => {
315332
impl<$($p)*> $crate::cast::UpcastFrom<$t> for $t {
316333
fn upcast_from(v: $t) -> $t {
@@ -339,8 +356,8 @@ macro_rules! cast_impl {
339356
}
340357
};
341358

342-
(($bot:ty) <: ($($mid:ty),*) <: ($top:ty)) => {
343-
impl $crate::cast::UpcastFrom<$bot> for $top {
359+
($(impl($($p:tt)*))? ($bot:ty) <: ($($mid:ty),*) <: ($top:ty)) => {
360+
impl$(<$($p)*>)? $crate::cast::UpcastFrom<$bot> for $top {
344361
fn upcast_from(v: $bot) -> $top {
345362
$(
346363
let v: $mid = $crate::cast::Upcast::upcast(v);
@@ -349,7 +366,7 @@ macro_rules! cast_impl {
349366
}
350367
}
351368

352-
impl $crate::cast::DowncastTo<$bot> for $top {
369+
impl$(<$($p)*>)? $crate::cast::DowncastTo<$bot> for $top {
353370
fn downcast_to(&self) -> Option<$bot> {
354371
let v: &$top = self;
355372
$(
@@ -371,15 +388,6 @@ impl UpcastFrom<&str> for String {
371388
}
372389
}
373390

374-
impl<T> UpcastFrom<&str> for T
375-
where
376-
T: Term,
377-
{
378-
fn upcast_from(text: &str) -> Self {
379-
crate::parse::term(text)
380-
}
381-
}
382-
383391
pub trait Upcasted<'a, T> {
384392
fn upcasted(self) -> Box<dyn Iterator<Item = T> + 'a>;
385393
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//! This module is a total hack. The Fold procedural macro references it.
2+
//! It's the only way I can find to have the procedural macro generate
3+
//! references to the Fold trait that work both in this crate and others.
4+
//! Other crates that wish to use the Fold macro must re-export this module.
5+
6+
pub use crate::cast::DowncastTo;
7+
pub use crate::cast::UpcastFrom;
8+
pub use crate::fixed_point;
9+
pub use crate::fold::Fold;
10+
pub use crate::fold::SubstitutionFn;
11+
pub use crate::parse;
12+
pub use crate::term::Term;
13+
pub use crate::variable::Variable;
14+
pub use crate::visit::Visit;

0 commit comments

Comments
 (0)