<commit_before>use fixpoint::{Fix, fix, fix_result};

use super::term::Term;

#[derive (Debug, PartialEq, Eq)]
pub enum Ctx<T> {
    Top,
    Abs(Box<Ctx<T>>),
    AppL(Box<Ctx<T>>, Term<T>),
    AppR(Term<T>, Box<Ctx<T>>),
    Let(Box<Ctx<T>>),
}

#[derive (Debug, PartialEq, Eq)]
enum Bind<T> {
    Var(String, T),
    Let(String, Option<(T, Box<Term<T>>)>)
}

impl<T> Bind<T> {

    fn is_identified_by(&self, id: &str) -> bool {
        match self {
            &Bind::Var(ref s, _) => id == s,
            &Bind::Let(ref s, _) => id == s
        }
    }

    fn take(&mut self) -> Option<(T, Box<Term<T>>)> where T: Clone {
        match self {
            &mut Bind::Var(ref s, ref y) => Some((y.clone(), Box::new(Term::Var(s.clone())))),
            &mut Bind::Let(_, ref mut o) => o.take()
        }
    }

}

#[derive (Debug, PartialEq, Eq)]
pub struct Env<T>(Vec<Bind<T>>);

impl<T> Env<T> {

    pub fn new() -> Env<T> {
        Env(Vec::new())
    }

    pub fn push_var(&mut self, s: String, y: T) {
        self.0.push(Bind::Var(s, y))
    }

    pub fn push_let(&mut self, s: String, o: Option<(T, Box<Term<T>>)>) {
        self.0.push(Bind::Let(s, o))
    }

    pub fn pop_var(&mut self) -> (String, T) {
        self.0.pop().map(|bind| {
            match bind {
                Bind::Let(_, _) => panic!("tried to pop a let"),
                Bind::Var(s, y) => (s, y)
            }
        }).unwrap()
    }

    pub fn pop_let(&mut self) -> (String, Option<(T, Box<Term<T>>)>) {
        self.0.pop().map(|bind| {
            match bind {
                Bind::Let(s, o) => (s, o),
                Bind::Var(_, _) => panic!("tried to pop a var")
            }
        }).unwrap()
    }<commit_msg>make fragile zipper functions private<commit_after>use fixpoint::{Fix, fix, fix_result};

use super::term::Term;

#[derive (Debug, PartialEq, Eq)]
pub enum Ctx<T> {
    Top,
    Abs(Box<Ctx<T>>),
    AppL(Box<Ctx<T>>, Term<T>),
    AppR(Term<T>, Box<Ctx<T>>),
    Let(Box<Ctx<T>>),
}

#[derive (Debug, PartialEq, Eq)]
enum Bind<T> {
    Var(String, T),
    Let(String, Option<(T, Box<Term<T>>)>)
}

impl<T> Bind<T> {

    fn is_identified_by(&self, id: &str) -> bool {
        match self {
            &Bind::Var(ref s, _) => id == s,
            &Bind::Let(ref s, _) => id == s
        }
    }

    fn take(&mut self) -> Option<(T, Box<Term<T>>)> where T: Clone {
        match self {
            &mut Bind::Var(ref s, ref y) => Some((y.clone(), Box::new(Term::Var(s.clone())))),
            &mut Bind::Let(_, ref mut o) => o.take()
        }
    }

}

#[derive (Debug, PartialEq, Eq)]
pub struct Env<T>(Vec<Bind<T>>);

impl<T> Env<T> {

    fn new() -> Env<T> {
        Env(Vec::new())
    }

    fn push_var(&mut self, s: String, y: T) {
        self.0.push(Bind::Var(s, y))
    }

    fn push_let(&mut self, s: String, o: Option<(T, Box<Term<T>>)>) {
        self.0.push(Bind::Let(s, o))
    }

    fn pop_var(&mut self) -> (String, T) {
        self.0.pop().map(|bind| {
            match bind {
                Bind::Let(_, _) => panic!("tried to pop a let"),
                Bind::Var(s, y) => (s, y)
            }
        }).unwrap()
    }

    fn pop_let(&mut self) -> (String, Option<(T, Box<Term<T>>)>) {
        self.0.pop().map(|bind| {
            match bind {
                Bind::Let(s, o) => (s, o),
                Bind::Var(_, _) => panic!("tried to pop a var")
            }
        }).unwrap()
    }
{'fraction_non_alphanumeric': 0.2164048865619546, 'fraction_numerical': 0.002326934264107039, 'mean_word_length': 2.0596085409252667, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3251819', 'n_tokens_mistral': 1344, 'n_tokens_neox': 1337, 'n_words': 293}