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);
|
pub struct Index(pub u32);
|
||||||
|
|
||||||
impl Index {
|
impl Index {
|
||||||
|
|
@ -1091,6 +1091,7 @@ fn attrs<'a>() -> impl Parser<'a, TokenInput<'a>, Index, ParserExtra> + Clone {
|
||||||
|
|
||||||
mod constants;
|
mod constants;
|
||||||
mod pretty;
|
mod pretty;
|
||||||
|
mod symbols;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
@ -1181,6 +1182,7 @@ mod tests {
|
||||||
print_ast(
|
print_ast(
|
||||||
new_token_input(
|
new_token_input(
|
||||||
r#"
|
r#"
|
||||||
|
/// docs!
|
||||||
fn my_function(a: i32, b: *const u8) -> i32 {
|
fn my_function(a: i32, b: *const u8) -> i32 {
|
||||||
x = a + 1;
|
x = a + 1;
|
||||||
x
|
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