port symbol table from old crate
This commit is contained in:
parent
0468f1fab3
commit
0ee6bbad61
|
|
@ -198,7 +198,7 @@ impl ControlFlowKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Index(pub u32);
|
||||
|
||||
impl Index {
|
||||
|
|
@ -1091,6 +1091,7 @@ fn attrs<'a>() -> impl Parser<'a, TokenInput<'a>, Index, ParserExtra> + Clone {
|
|||
|
||||
mod constants;
|
||||
mod pretty;
|
||||
mod symbols;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
@ -1181,6 +1182,7 @@ mod tests {
|
|||
print_ast(
|
||||
new_token_input(
|
||||
r#"
|
||||
/// docs!
|
||||
fn my_function(a: i32, b: *const u8) -> i32 {
|
||||
x = a + 1;
|
||||
x
|
||||
|
|
|
|||
178
crates/parser/src/symbols.rs
Normal file
178
crates/parser/src/symbols.rs
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
//! Coming from the ast, we have a `DeclRef` with an interned identifier `ident`
|
||||
//! and want to find the symbol it refers to.
|
||||
//!
|
||||
//! To help, we have a struct keeping track of all accessible scopes. Now, we
|
||||
//! want to look through any accessible scope `s` for a symbol with the name
|
||||
//! `ident`. Thus: `Symbol {scope: `s`, name: `ident`, ..}`.
|
||||
//!
|
||||
//! We might also know the type of the symbol we are looking for, if we want
|
||||
//! to permit fields/variables and methods/functions sharing names.
|
||||
//!
|
||||
//! Since I want to allow variable shadowing for local variables, some strategy
|
||||
//! to differentiate between shadowed variables must be employed:
|
||||
//! - keys of type SymbolKind::Local might point to a list of values with source locations
|
||||
//! - keys might contain source locations.
|
||||
//!
|
||||
//! Any symbol pointed at from within the ast must again point at an ast
|
||||
//! object.
|
||||
//! Thus: `Key` -> `AstIndex`
|
||||
//! Exception: `Key::ScopeByIndex` -> `InternIndex`
|
||||
|
||||
use core::fmt::Debug;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use internment::Intern;
|
||||
|
||||
use crate::Index;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Span(u32);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Spanned<T>(pub T, Span);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum SymbolKind {
|
||||
__First,
|
||||
Const,
|
||||
Function,
|
||||
Type,
|
||||
__TypeScope,
|
||||
Scope,
|
||||
ParentScope,
|
||||
Parameter(Span),
|
||||
Local(Span),
|
||||
__Last,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Key {
|
||||
ScopeByName {
|
||||
name: Intern<str>,
|
||||
},
|
||||
/// not all scopes have a name, as some are anonymous blocks or otherwise nameless
|
||||
ScopeByIndex {
|
||||
ast: Index,
|
||||
},
|
||||
Symbol {
|
||||
scope: Index,
|
||||
name: Intern<str>,
|
||||
kind: SymbolKind,
|
||||
},
|
||||
}
|
||||
|
||||
impl Key {
|
||||
pub fn parent(scope: Index) -> Key {
|
||||
Key::Symbol {
|
||||
scope,
|
||||
name: Intern::from(""),
|
||||
kind: SymbolKind::ParentScope,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Payload {
|
||||
Ast(Index),
|
||||
Name(Intern<str>),
|
||||
}
|
||||
|
||||
pub struct Symbols {
|
||||
inner: BTreeMap<Key, Payload>,
|
||||
}
|
||||
|
||||
impl Debug for Symbols {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Symbols [")?;
|
||||
if f.alternate() {
|
||||
writeln!(f, "")?;
|
||||
}
|
||||
let entries = self.inner.iter();
|
||||
f.debug_list().entries(entries).finish()?;
|
||||
write!(f, "]")?;
|
||||
if f.alternate() {
|
||||
writeln!(f, "")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// checks for each scope in scopes_in_tree Symbol { scope, kind: SymbolKind::Local, 0}..Symbol { scope, kind: SymbolKind::Scope, u32::MAX}
|
||||
struct SymbolTreePos {
|
||||
scopes_in_scope: Vec<Index>,
|
||||
}
|
||||
|
||||
impl Symbols {
|
||||
pub fn new() -> Symbols {
|
||||
Self {
|
||||
inner: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
pub fn insert_scope(&mut self, name: Intern<str>, ast: Index) {
|
||||
self.inner
|
||||
.insert(Key::ScopeByIndex { ast }, Payload::Name(name));
|
||||
self.inner
|
||||
.insert(Key::ScopeByName { name }, Payload::Ast(ast));
|
||||
}
|
||||
|
||||
pub fn find_symbol(&self, scope: Index, name: Intern<str>, loc: Span) -> Option<(Key, Index)> {
|
||||
use SymbolKind::*;
|
||||
let range = self.inner.range(
|
||||
Key::Symbol {
|
||||
scope,
|
||||
name,
|
||||
kind: __First,
|
||||
}..=Key::Symbol {
|
||||
scope,
|
||||
name,
|
||||
kind: Local(loc),
|
||||
},
|
||||
);
|
||||
|
||||
if let Some((&key, &Payload::Ast(index))) = range.rev().next() {
|
||||
Some((key, index))
|
||||
} else {
|
||||
if let Some(&Payload::Ast(parent)) = self.inner.get(&Key::parent(scope)) {
|
||||
self.find_symbol(parent, name, loc)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_type_symbol(
|
||||
&self,
|
||||
scope: Index,
|
||||
name: Intern<str>,
|
||||
loc: Span,
|
||||
) -> Option<(Key, Index)> {
|
||||
use SymbolKind::*;
|
||||
let range = self.inner.range(
|
||||
Key::Symbol {
|
||||
scope,
|
||||
name,
|
||||
kind: __First,
|
||||
}..=Key::Symbol {
|
||||
scope,
|
||||
name,
|
||||
kind: __TypeScope,
|
||||
},
|
||||
);
|
||||
|
||||
if let Some((&key, &Payload::Ast(index))) = range.rev().next() {
|
||||
Some((key, index))
|
||||
} else {
|
||||
if let Some(&Payload::Ast(parent)) = self.inner.get(&Key::parent(scope)) {
|
||||
self.find_type_symbol(parent, name, loc)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_symbol(&mut self, scope: Index, name: Intern<str>, kind: SymbolKind, ast: Index) {
|
||||
self.inner
|
||||
.insert(Key::Symbol { scope, name, kind }, Payload::Ast(ast));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue