#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_imports)]
use crate::syntax::ast::{self, NodeId};
use moore_common::name::*;
use moore_common::source::*;
use std;
use std::collections::{HashMap, HashSet};
#[derive(Debug)]
pub struct SymTbl {
next_id: usize,
pub root_scope: Scope,
libs: HashMap<Name, NodeId>,
pub scopes: HashMap<NodeId, Scope>,
}
impl SymTbl {
pub fn new() -> SymTbl {
SymTbl {
next_id: 1,
root_scope: Scope::new(Default::default()),
libs: HashMap::new(),
scopes: HashMap::new(),
}
}
pub fn alloc_id(&mut self) -> NodeId {
let id = NodeId::new(self.next_id);
self.next_id += 1;
id
}
pub fn get_library_id(&mut self, name: Name) -> NodeId {
let id = *self.libs.entry(name).or_insert(NodeId::new(self.next_id));
if id.as_usize() == self.next_id {
self.next_id += 1;
self.root_scope.declare(
Spanned::new(DefName::Ident(name), INVALID_SPAN),
Def::Lib(id),
);
}
id
}
pub fn add_scope(&mut self, scope: Scope) {
use std::collections::hash_map::Entry;
match self.scopes.entry(scope.node_id) {
Entry::Occupied(e) => {
e.into_mut().merge(scope);
}
Entry::Vacant(e) => {
e.insert(scope);
}
}
}
}
#[derive(Debug)]
pub struct Scope {
pub node_id: NodeId,
pub subscopes: HashSet<NodeId>,
pub defs: HashMap<DefName, Vec<(Span, Def)>>,
pub parent_id: Option<NodeId>,
}
impl Scope {
pub fn new(node_id: NodeId) -> Scope {
Scope {
node_id: node_id,
subscopes: HashSet::new(),
defs: HashMap::new(),
parent_id: None,
}
}
pub fn merge(&mut self, other: Scope) {
self.subscopes.extend(other.subscopes);
for (k, v) in other.defs {
self.defs.entry(k).or_insert_with(|| Vec::new()).extend(v);
}
}
pub fn declare_subscope(&mut self, scope_id: NodeId) {
assert!(scope_id != Default::default());
self.subscopes.insert(scope_id);
}
pub fn declare(&mut self, name: Spanned<DefName>, def: Def) {
assert!(def.node_id() != Default::default());
self.defs
.entry(name.value)
.or_insert_with(|| Vec::new())
.push((name.span, def));
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum DefName {
Ident(Name),
Char(char),
String(Name),
}
impl std::fmt::Display for DefName {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
DefName::Ident(n) => write!(f, "{}", n),
DefName::Char(n) => write!(f, "'{}'", n),
DefName::String(n) => write!(f, "\"{}\"", n),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Def {
Lib(NodeId),
Entity(NodeId),
Cfg(NodeId),
Pkg(NodeId),
PkgInst(NodeId),
Ctx(NodeId),
Arch(NodeId),
Const(NodeId),
Signal(NodeId),
File(NodeId),
Var(NodeId),
Ty(NodeId),
Subty(NodeId),
Alias(NodeId),
Subprog(NodeId),
Comp(NodeId),
Attr(NodeId),
Intf(NodeId),
Group(NodeId),
Stmt(NodeId),
}
impl Def {
pub fn node_id(&self) -> NodeId {
use self::Def::*;
match *self {
Lib(id) | Entity(id) | Cfg(id) | Pkg(id) | PkgInst(id) | Ctx(id) | Arch(id)
| Const(id) | Signal(id) | File(id) | Var(id) | Ty(id) | Subty(id) | Alias(id)
| Subprog(id) | Comp(id) | Attr(id) | Intf(id) | Group(id) | Stmt(id) => id,
}
}
}
pub fn def_name_from_primary_name(name: &ast::PrimaryName) -> Spanned<DefName> {
Spanned::new(
match name.kind {
ast::PrimaryNameKind::Ident(n) => DefName::Ident(n),
ast::PrimaryNameKind::Char(n) => DefName::Char(n),
ast::PrimaryNameKind::String(n) => DefName::String(n),
},
name.span,
)
}