feat: use a stack for scope

This commit is contained in:
rvcas 2022-06-04 00:29:30 -04:00
parent 946937f945
commit 2ad630de90
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
3 changed files with 33 additions and 17 deletions

View File

@ -1,3 +1,3 @@
(program 11.22.33
(lam x x)
(lam x (lam x y))
)

View File

@ -86,15 +86,15 @@ pub struct NamedDeBruijn {
}
#[derive(Debug, Clone, PartialEq, Copy)]
pub struct DeBruijn(u64);
pub struct DeBruijn(usize);
impl From<u64> for DeBruijn {
fn from(i: u64) -> Self {
impl From<usize> for DeBruijn {
fn from(i: usize) -> Self {
DeBruijn(i)
}
}
impl From<DeBruijn> for u64 {
impl From<DeBruijn> for usize {
fn from(d: DeBruijn) -> Self {
d.0
}

View File

@ -3,18 +3,18 @@ use std::collections::HashMap;
use crate::ast::{DeBruijn, Name, NamedDeBruijn, Term, Unique};
#[derive(Debug, Copy, Clone)]
struct Level(u64);
struct Level(usize);
pub(crate) struct Converter {
current_level: Level,
levels: HashMap<Unique, Level>,
levels: Vec<HashMap<Unique, Level>>,
}
impl Converter {
pub(crate) fn new() -> Self {
Converter {
current_level: Level(0),
levels: HashMap::new(),
levels: vec![HashMap::new()],
}
}
@ -41,11 +41,15 @@ impl Converter {
index,
};
self.with_scope();
self.start_scope();
let body = self.name_to_named_debruijn(*body)?;
self.end_scope();
Term::Lambda {
parameter_name: name,
body: Box::new(self.name_to_named_debruijn(*body)?),
body: Box::new(body),
}
}
Term::Apply { function, argument } => Term::Apply {
@ -69,20 +73,32 @@ impl Converter {
}
fn get_index(&mut self, unique: Unique) -> anyhow::Result<DeBruijn> {
if let Some(found_level) = self.levels.get(&unique) {
let index = self.current_level.0 - found_level.0;
for scope in self.levels.iter().rev() {
if let Some(found_level) = scope.get(&unique) {
let index = self.current_level.0 - found_level.0;
Ok(index.into())
} else {
anyhow::bail!("Free unique: {}", isize::from(unique));
return Ok(index.into());
}
}
anyhow::bail!("Free unique: {}", isize::from(unique))
}
fn declare_unique(&mut self, unique: Unique) {
self.levels.insert(unique, self.current_level);
let scope = &mut self.levels[self.current_level.0];
scope.insert(unique, self.current_level);
}
fn with_scope(&mut self) {
fn start_scope(&mut self) {
self.current_level = Level(self.current_level.0 + 1);
self.levels.push(HashMap::new());
}
fn end_scope(&mut self) {
self.current_level = Level(self.current_level.0 - 1);
self.levels.pop();
}
}