-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
14f2af2
commit 0e55691
Showing
10 changed files
with
1,034 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub mod scope; | ||
pub mod tree; | ||
pub mod types; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
use crate::check::types; | ||
use std::collections::HashMap; | ||
|
||
pub type Id = usize; | ||
pub type InnerId = usize; | ||
pub type VariableId = (Id, InnerId); | ||
|
||
#[derive(Debug)] | ||
pub struct Scope { | ||
parent: Option<Id>, | ||
is_loop: bool, | ||
name_map: HashMap<String, InnerId>, | ||
type_map: Vec<types::Id>, | ||
} | ||
|
||
impl Scope { | ||
pub fn lookup(&self, name: &str) -> Option<(InnerId, types::Id)> { | ||
self.name_map | ||
.get(name) | ||
.map(|inner_id| (*inner_id, self.type_map[*inner_id])) | ||
} | ||
|
||
pub fn insert(&mut self, name: String, ty: types::Id) -> InnerId { | ||
let inner_id = self.type_map.len(); | ||
self.type_map.push(ty); | ||
self.name_map.insert(name, inner_id); | ||
inner_id | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct Table { | ||
scopes: Vec<Scope>, | ||
} | ||
|
||
impl Table { | ||
pub fn new() -> Self { | ||
Self { scopes: vec![] } | ||
} | ||
|
||
pub fn lookup(&self, scope: Id, name: &str) -> Option<(VariableId, types::Id)> { | ||
let scope_obj = &self.scopes[scope]; | ||
match scope_obj.lookup(name) { | ||
Some((inner_id, ty)) => Some(((scope, inner_id), ty)), | ||
None => match scope_obj.parent { | ||
Some(parent) => self.lookup(parent, name), | ||
None => None, | ||
}, | ||
} | ||
} | ||
|
||
pub fn nearest_loop(&self, scope: Id) -> Option<Id> { | ||
let scope_obj = &self.scopes[scope]; | ||
if scope_obj.is_loop { | ||
Some(scope) | ||
} else { | ||
match scope_obj.parent { | ||
Some(parent) => self.nearest_loop(parent), | ||
None => None, | ||
} | ||
} | ||
} | ||
|
||
pub fn insert(&mut self, scope: Id, name: String, ty: types::Id) -> VariableId { | ||
let scope_obj = &mut self.scopes[scope]; | ||
let inner_id = scope_obj.insert(name, ty); | ||
(scope, inner_id) | ||
} | ||
|
||
pub fn push_root(&mut self) -> Id { | ||
let id = self.scopes.len(); | ||
self.scopes.push(Scope { | ||
parent: None, | ||
is_loop: false, | ||
name_map: HashMap::new(), | ||
type_map: Vec::new(), | ||
}); | ||
id | ||
} | ||
|
||
pub fn push_loop(&mut self, parent: Id) -> Id { | ||
let id = self.scopes.len(); | ||
self.scopes.push(Scope { | ||
parent: Some(parent), | ||
is_loop: true, | ||
name_map: HashMap::new(), | ||
type_map: Vec::new(), | ||
}); | ||
id | ||
} | ||
|
||
pub fn push(&mut self, parent: Id) -> Id { | ||
let id = self.scopes.len(); | ||
self.scopes.push(Scope { | ||
parent: Some(parent), | ||
is_loop: false, | ||
name_map: HashMap::new(), | ||
type_map: Vec::new(), | ||
}); | ||
id | ||
} | ||
} |
Oops, something went wrong.