use std::collections::HashMap;
use std::fmt::{self, Display};
use std::iter::FromIterator;
use term::{Term, VarName};
pub fn bind(name: impl Into<String>, term: impl Into<Term>) -> Binding {
Binding::new(VarName(name.into()), term.into())
}
#[derive(Debug, Clone, PartialEq)]
pub struct Environment {
bindings: HashMap<VarName, Term>,
}
impl Environment {
pub fn new() -> Self {
Environment {
bindings: HashMap::new(),
}
}
pub fn insert_binding(&mut self, binding: Binding) {
let (name, term) = binding.unwrap();
self.bindings.insert(name, term);
}
pub fn bind(&mut self, name: VarName, term: Term) -> Option<Term> {
self.bindings.insert(name, term)
}
pub fn unbind(&mut self, name: &VarName) -> Option<Term> {
self.bindings.remove(name)
}
pub fn clear_bindings(&mut self) {
self.bindings.clear();
}
pub fn bindings(&self) -> impl Iterator<Item = (&VarName, &Term)> {
self.bindings.iter()
}
pub fn into_bindings(self) -> impl Iterator<Item = Binding> {
self.bindings.into_iter().map(Binding::from)
}
pub fn lookup_term(&self, name: &VarName) -> Option<&Term> {
self.bindings.get(name)
}
}
impl FromIterator<(VarName, Term)> for Environment {
fn from_iter<I>(set: I) -> Self
where
I: IntoIterator<Item = (VarName, Term)>,
{
Environment {
bindings: HashMap::from_iter(set.into_iter()),
}
}
}
impl FromIterator<Binding> for Environment {
fn from_iter<I>(set: I) -> Self
where
I: IntoIterator<Item = Binding>,
{
Environment {
bindings: HashMap::from_iter(set.into_iter().map(|b| (b.name, b.term))),
}
}
}
impl Extend<(VarName, Term)> for Environment {
fn extend<I: IntoIterator<Item = (VarName, Term)>>(&mut self, iter: I) {
self.bindings.extend(iter)
}
}
impl Extend<Binding> for Environment {
fn extend<I: IntoIterator<Item = Binding>>(&mut self, iter: I) {
self.bindings
.extend(iter.into_iter().map(|b| (b.name, b.term)))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Binding {
name: VarName,
term: Term,
}
impl Display for Binding {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "let {} = {}", self.name, self.term)
}
}
impl Binding {
pub fn new(name: VarName, term: Term) -> Self {
Binding { name, term }
}
pub fn unwrap(self) -> (VarName, Term) {
(self.name, self.term)
}
pub fn name(&self) -> &VarName {
&self.name
}
pub fn term(&self) -> &Term {
&self.term
}
}
impl From<(VarName, Term)> for Binding {
fn from(bound: (VarName, Term)) -> Self {
Binding {
name: bound.0,
term: bound.1,
}
}
}
#[macro_export]
macro_rules! bind {
($name:ident => $term:expr) => {
$crate::environment::Binding::new($crate::VarName(String::from(stringify!($name))), $term)
};
($name:expr => $term:expr) => {
$crate::environment::Binding::new($crate::VarName(String::from($name)), $term)
};
}
#[macro_export]
macro_rules! binds {
($($name:ident => $term:expr),* $(,)*) => {
{
let mut binds = HashSet::new();
$(
binds.insert($crate::environment::Binding::new($crate::VarName(String::from(stringify!($name))), $term));
)*
binds
}
};
($($name:expr => $term:expr),* $(,)*) => {
{
let mut binds = HashSet::new();
$(
binds.insert($crate::environment::Binding::new($crate::VarName(String::from($name)), $term));
)*
binds
}
};
}