diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 710bb280b..8be877747 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -10,6 +10,7 @@ use oxc_ast::{ast::*, visit::Visit, AstKind, SourceType, Trivias}; use crate::{ node::{AstNodeId, AstNodes, NodeFlags, SemanticNode}, scope::ScopeBuilder, + symbol::SymbolTable, Semantic, }; @@ -23,6 +24,8 @@ pub struct SemanticBuilder<'a> { // builders nodes: AstNodes<'a>, scope: ScopeBuilder, + #[allow(unused)] + symbols: SymbolTable, } impl<'a> SemanticBuilder<'a> { @@ -33,7 +36,14 @@ impl<'a> SemanticBuilder<'a> { let semantic_node = SemanticNode::new(AstKind::Root, scope.current_scope_id, NodeFlags::empty()); let current_node_id = nodes.new_node(semantic_node).into(); - Self { source_type, current_node_id, nodes, scope, current_node_flags: NodeFlags::empty() } + Self { + source_type, + current_node_id, + current_node_flags: NodeFlags::empty(), + nodes, + scope, + symbols: SymbolTable::default(), + } } #[must_use] diff --git a/crates/oxc_semantic/src/lib.rs b/crates/oxc_semantic/src/lib.rs index 740c8c69c..9bfa38a45 100644 --- a/crates/oxc_semantic/src/lib.rs +++ b/crates/oxc_semantic/src/lib.rs @@ -1,6 +1,7 @@ mod builder; mod node; mod scope; +mod symbol; use std::rc::Rc; diff --git a/crates/oxc_semantic/src/symbol/id.rs b/crates/oxc_semantic/src/symbol/id.rs new file mode 100644 index 000000000..3398aca11 --- /dev/null +++ b/crates/oxc_semantic/src/symbol/id.rs @@ -0,0 +1,40 @@ +use std::{ + hash::Hash, + num::NonZeroUsize, + ops::{Index, IndexMut}, +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct SymbolId(NonZeroUsize); + +impl Default for SymbolId { + fn default() -> Self { + Self::new(1) + } +} + +impl Index for Vec { + type Output = T; + + fn index(&self, id: SymbolId) -> &Self::Output { + &self[id.index0()] + } +} + +impl IndexMut for Vec { + fn index_mut(&mut self, id: SymbolId) -> &mut T { + &mut self[id.index0()] + } +} + +impl SymbolId { + #[must_use] + pub fn new(n: usize) -> Self { + unsafe { Self(NonZeroUsize::new_unchecked(n)) } + } + + #[must_use] + pub(crate) fn index0(self) -> usize { + self.0.get() - 1 + } +} diff --git a/crates/oxc_semantic/src/symbol/mod.rs b/crates/oxc_semantic/src/symbol/mod.rs new file mode 100644 index 000000000..f59fe5e8d --- /dev/null +++ b/crates/oxc_semantic/src/symbol/mod.rs @@ -0,0 +1,47 @@ +//! Symbol and Symbol Table for tracking of semantics of variables + +pub mod id; +pub mod table; + +use oxc_ast::{Atom, Span}; + +pub use self::{id::SymbolId, table::SymbolTable}; + +#[derive(Debug)] +pub struct Symbol { + id: SymbolId, + name: Atom, + span: Span, +} + +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +#[test] +fn symbol_size() { + use std::mem::size_of; + assert_eq!(size_of::(), 40); +} + +impl Symbol { + #[must_use] + pub fn new(id: SymbolId, name: Atom, span: Span) -> Self { + Self { id, name, span } + } + + #[must_use] + #[allow(unused)] + pub fn id(&self) -> SymbolId { + self.id + } + + #[must_use] + #[allow(unused)] + pub fn name(&self) -> &Atom { + &self.name + } + + #[must_use] + #[allow(unused)] + pub fn span(&self) -> &Span { + &self.span + } +} diff --git a/crates/oxc_semantic/src/symbol/table.rs b/crates/oxc_semantic/src/symbol/table.rs new file mode 100644 index 000000000..1cbf504df --- /dev/null +++ b/crates/oxc_semantic/src/symbol/table.rs @@ -0,0 +1,55 @@ +use std::ops::{Deref, Index, IndexMut}; + +use oxc_ast::{Atom, Span}; + +use super::{Symbol, SymbolId}; + +#[derive(Debug, Default)] +pub struct SymbolTable { + symbols: Vec, +} + +impl Index for SymbolTable { + type Output = Symbol; + + fn index(&self, index: SymbolId) -> &Self::Output { + &self.symbols[index.index0()] + } +} + +impl IndexMut for SymbolTable { + fn index_mut(&mut self, index: SymbolId) -> &mut Self::Output { + &mut self.symbols[index.index0()] + } +} + +impl Deref for SymbolTable { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.symbols + } +} + +impl SymbolTable { + #[must_use] + #[allow(unused)] + pub fn symbols(&self) -> &Vec { + &self.symbols + } + + #[must_use] + #[allow(unused)] + pub fn get(&self, id: SymbolId) -> Option<&Symbol> { + self.symbols.get(id.index0()) + } + + #[must_use] + #[allow(unused)] + pub fn create(&mut self, name: Atom, span: Span) -> SymbolId { + let symbol_id = SymbolId::new(self.symbols.len() + 1); + let symbol = Symbol::new(symbol_id, name, span); + self.symbols.push(symbol); + symbol_id + } +}