Struct naga::front::SymbolTable

source ·
pub struct SymbolTable<Name, Var> {
    scopes: Vec<FastHashMap<Name, Var>>,
    cursor: usize,
}
Expand description

Structure responsible for managing variable lookups and keeping track of lexical scopes

The symbol table is generic over the variable representation and its name to allow larger flexibility on the frontends on how they might represent them.

use naga::front::SymbolTable;

// Create a new symbol table with `u32`s representing the variable
let mut symbol_table: SymbolTable<&str, u32> = SymbolTable::default();

// Add two variables named `var1` and `var2` with 0 and 2 respectively
symbol_table.add("var1", 0);
symbol_table.add("var2", 2);

// Check that `var1` exists and is `0`
assert_eq!(symbol_table.lookup("var1"), Some(&0));

// Push a new scope and add a variable to it named `var1` shadowing the
// variable of our previous scope
symbol_table.push_scope();
symbol_table.add("var1", 1);

// Check that `var1` now points to the new value of `1` and `var2` still
// exists with its value of `2`
assert_eq!(symbol_table.lookup("var1"), Some(&1));
assert_eq!(symbol_table.lookup("var2"), Some(&2));

// Pop the scope
symbol_table.pop_scope();

// Check that `var1` now refers to our initial variable with value `0`
assert_eq!(symbol_table.lookup("var1"), Some(&0));

Scopes are ordered as a LIFO stack so a variable defined in a later scope with the same name as another variable defined in a earlier scope will take precedence in the lookup. Scopes can be added with push_scope and removed with pop_scope.

A root scope is added when the symbol table is created and must always be present. Trying to pop it will result in a panic.

Variables can be added with add and looked up with lookup. Adding a variable will do so in the currently active scope and as mentioned previously a lookup will search from the current scope to the root scope.

Fields§

§scopes: Vec<FastHashMap<Name, Var>>

Stack of lexical scopes. Not all scopes are active; see cursor.

§cursor: usize

Limit of the scopes stack (exclusive). By using a separate value for the stack length instead of Vec’s own internal length, the scopes can be reused to cache memory allocations.

Implementations§

source§

impl<Name, Var> SymbolTable<Name, Var>

source

pub fn push_scope(&mut self)

Adds a new lexical scope.

All variables declared after this point will be added to this scope until another scope is pushed or pop_scope is called, causing this scope to be removed along with all variables added to it.

source

pub fn pop_scope(&mut self)

Removes the current lexical scope and all its variables

§PANICS
  • If the current lexical scope is the root scope
source§

impl<Name, Var> SymbolTable<Name, Var>
where Name: Hash + Eq,

source

pub fn lookup<Q>(&self, name: &Q) -> Option<&Var>
where Name: Borrow<Q>, Q: Hash + Eq + ?Sized,

Perform a lookup for a variable named name.

As stated in the struct level documentation the lookup will proceed from the current scope to the root scope, returning Some when a variable is found or None if there doesn’t exist a variable with name in any scope.

source

pub fn add(&mut self, name: Name, var: Var) -> Option<Var>

Adds a new variable to the current scope.

Returns the previous variable with the same name in this scope if it exists, so that the frontend might handle it in case variable shadowing is disallowed.

source

pub fn add_root(&mut self, name: Name, var: Var) -> Option<Var>

Adds a new variable to the root scope.

This is used in GLSL for builtins which aren’t known in advance and only when used for the first time, so there must be a way to add those declarations to the root unconditionally from the current scope.

Returns the previous variable with the same name in the root scope if it exists, so that the frontend might handle it in case variable shadowing is disallowed.

Trait Implementations§

source§

impl<Name: Debug, Var: Debug> Debug for SymbolTable<Name, Var>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<Name, Var> Default for SymbolTable<Name, Var>

source§

fn default() -> Self

Constructs a new symbol table with a root scope

Auto Trait Implementations§

§

impl<Name, Var> Freeze for SymbolTable<Name, Var>

§

impl<Name, Var> RefUnwindSafe for SymbolTable<Name, Var>
where Name: RefUnwindSafe, Var: RefUnwindSafe,

§

impl<Name, Var> Send for SymbolTable<Name, Var>
where Name: Send, Var: Send,

§

impl<Name, Var> Sync for SymbolTable<Name, Var>
where Name: Sync, Var: Sync,

§

impl<Name, Var> Unpin for SymbolTable<Name, Var>
where Name: Unpin, Var: Unpin,

§

impl<Name, Var> UnwindSafe for SymbolTable<Name, Var>
where Name: UnwindSafe, Var: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.