knave 0.14.4

A Lisp programming language for humans and agents that infers types and ownership and compiles to readable Rust
Documentation
use rustc_hash::FxHashSet;

use crate::core::BindingId;
use crate::types::{TypedExpr, TypedExprKind, TypedLeaf};

pub struct Subtree;

impl Subtree {
    pub fn of(root: &TypedExpr) -> Vec<&TypedExpr> {
        let mut expressions = vec![root];
        let mut next = 0;
        while let Some(expr) = expressions.get(next).copied() {
            expressions.extend(expr.children());
            next += 1;
        }
        expressions
    }

    pub fn first_capture(closure: &TypedExpr) -> Option<BindingId> {
        let expressions = Self::of(closure);
        let bound: FxHashSet<BindingId> = expressions
            .iter()
            .flat_map(|expr| expr.binders())
            .map(|binder| binder.binding)
            .collect();
        expressions.iter().find_map(|expr| match expr.kind {
            TypedExprKind::Leaf(TypedLeaf::Local(binding)) if !bound.contains(&binding) => {
                Some(binding)
            }
            _ => None,
        })
    }
}