Skip to content

Commit

Permalink
cleanup bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
vincenthz committed Feb 20, 2024
1 parent 17060cb commit fcb5256
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 225 deletions.
155 changes: 0 additions & 155 deletions werbolg-compile/src/bindings.rs

This file was deleted.

64 changes: 64 additions & 0 deletions werbolg-compile/src/bindings/bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use hashbrown::{hash_map, HashMap};
use werbolg_core::Ident;

#[derive(Clone)]
pub struct Bindings<T>(HashMap<Ident, T>);

impl<T> Default for Bindings<T> {
fn default() -> Self {
Bindings::new()
}
}

pub struct BindingsIterator<'a, T>(hash_map::Iter<'a, Ident, T>);

impl<'a, T> Iterator for BindingsIterator<'a, T> {
type Item = (&'a Ident, &'a T);

fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}

pub struct BindingInsertError {
pub name: Ident,
}

impl<T> Bindings<T> {
pub fn new() -> Self {
Self(HashMap::new())
}

pub fn add(&mut self, name: Ident, value: T) -> Result<(), BindingInsertError> {
if self.0.get(&name).is_some() {
Err(BindingInsertError { name })
} else {
self.0.insert(name, value);
Ok(())
}
}

pub fn add_replace(&mut self, name: Ident, value: T) {
self.0.insert(name, value);
}

#[allow(unused)]
pub fn remove(&mut self, name: Ident) {
self.0.remove(&name);
}

pub fn get(&self, name: &Ident) -> Option<&T> {
self.0.get(name)
}

pub fn dump<W: core::fmt::Write>(&self, writer: &mut W) -> Result<(), core::fmt::Error> {
for (ident, _) in self.iter() {
writeln!(writer, "{:?}", ident)?
}
Ok(())
}

pub fn iter<'a>(&'a self) -> BindingsIterator<'a, T> {
BindingsIterator(self.0.iter())
}
}
52 changes: 52 additions & 0 deletions werbolg-compile/src/bindings/bindings_stack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use super::bindings::Bindings;
use alloc::{vec, vec::Vec};
use werbolg_core::Ident;

pub struct BindingsStack<T> {
stack: Vec<Bindings<T>>,
}

impl<T> BindingsStack<T> {
pub fn new() -> Self {
Self { stack: vec![] }
}

pub fn scope_enter(&mut self) {
self.stack.push(Bindings::new())
}

pub fn scope_pop(&mut self) -> Bindings<T> {
self.stack.pop().unwrap()
}

pub fn add(&mut self, name: Ident, value: T) {
match self.stack.last_mut() {
None => {
panic!("add failed {:?}", name);
// fall through to the global
}
Some(bindings) => {
bindings.add_replace(name.clone(), value);
}
}
}

pub fn get(&self, name: &Ident) -> Option<&T> {
for bindings in self.stack.iter().rev() {
if let Some(t) = bindings.get(name) {
return Some(t);
}
}
None
}

#[allow(unused)]
pub fn dump<W: core::fmt::Write>(&self, writer: &mut W) -> Result<(), core::fmt::Error> {
writeln!(writer, "bindings-stack: {}", self.stack.len())?;
for (i, bindings) in self.stack.iter().rev().enumerate() {
writeln!(writer, "== Level {}", i)?;
bindings.dump(writer)?
}
Ok(())
}
}
41 changes: 41 additions & 0 deletions werbolg-compile/src/bindings/global_bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use super::bindings::Bindings;
use super::types::BindingType;
use crate::hier::Hier;
use werbolg_core::{AbsPath, Namespace};

pub struct GlobalBindings(pub(crate) Hier<Bindings<BindingType>>);

impl GlobalBindings {
pub fn new() -> Self {
Self(Hier::default())
}

pub fn add(&mut self, name: AbsPath, value: BindingType) -> Result<(), ()> {
let (namespace, ident) = name.split();

if !self.0.namespace_exist(namespace.clone()) {
self.0.add_ns_hier(namespace.clone()).unwrap()
}

self.0
.on_mut(&namespace, |bindings| {
bindings.add(ident.clone(), value.clone())
})
.map_err(|_| ())
}

#[allow(unused)]
pub fn get(&self, name: &AbsPath) -> Option<&BindingType> {
let (namespace, ident) = name.split();
let bindings = self.0.get(&namespace).unwrap();
bindings.get(&ident)
}

#[allow(unused)]
pub fn iter<'a>(&'a self) -> impl Iterator<Item = (AbsPath, &'a BindingType)> {
self.0.iterator(
Namespace::root(),
alloc::rc::Rc::new(|x: &'a Bindings<BindingType>| alloc::boxed::Box::new(x.iter())),
)
}
}
63 changes: 63 additions & 0 deletions werbolg-compile/src/bindings/local_bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use super::bindings_stack::BindingsStack;
use super::types::BindingType;
use crate::defs::LocalStackSize;
use crate::instructions::{LocalBindIndex, ParamBindIndex};
use alloc::{vec, vec::Vec};
use werbolg_core::Ident;

pub struct LocalBindings {
bindings: BindingsStack<BindingType>,
local: Vec<u16>,
max_local: u16,
}

impl LocalBindings {
pub fn new() -> Self {
Self {
bindings: BindingsStack::new(),
local: vec![0],
max_local: 0,
}
}

pub fn add_param(&mut self, ident: Ident, n: u8) {
self.bindings
.add(ident, BindingType::Param(ParamBindIndex(n)))
}

pub fn add_local(&mut self, ident: Ident) -> LocalBindIndex {
match self.local.last_mut() {
None => panic!("internal error: cannot add local without an empty binding stack"),
Some(x) => {
let local = *x;
*x += 1;

let local = LocalBindIndex(local);
self.bindings.add(ident, BindingType::Local(local));
local
}
}
}

pub fn scope_enter(&mut self) {
let top = self.local.last().unwrap();
self.local.push(*top);
self.bindings.scope_enter();
}

pub fn scope_leave(&mut self) {
let _x = self.bindings.scope_pop();
let local = self.local.pop().unwrap();
self.max_local = core::cmp::max(self.max_local, local);
}

pub fn scope_terminate(mut self) -> LocalStackSize {
self.scope_leave();
assert_eq!(self.local.len(), 1, "internal compilation error");
LocalStackSize(self.max_local as u16)
}

pub fn get(&self, ident: &Ident) -> Option<&BindingType> {
self.bindings.get(ident)
}
}
11 changes: 11 additions & 0 deletions werbolg-compile/src/bindings/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Local and Global Bindings
mod bindings;
mod bindings_stack;
mod global_bindings;
mod local_bindings;
mod types;

pub use global_bindings::GlobalBindings;
pub use local_bindings::LocalBindings;
pub use types::BindingType;
Loading

0 comments on commit fcb5256

Please sign in to comment.