Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

glsl-in: Migrate to SymbolTable #2044

Merged
merged 2 commits into from
Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 39 additions & 77 deletions src/front/glsl/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ pub struct Context {
pub parameters: Vec<Handle<Type>>,
pub parameters_info: Vec<ParameterInfo>,

//TODO: Find less allocation heavy representation
pub scopes: Vec<FastHashMap<String, VariableReference>>,
pub lookup_global_var_exps: FastHashMap<String, VariableReference>,
pub symbol_table: crate::front::SymbolTable<String, VariableReference>,
pub samplers: FastHashMap<Handle<Expression>, Handle<Expression>>,

pub typifier: Typifier,
Expand All @@ -69,11 +67,7 @@ impl Context {
parameters: Vec::new(),
parameters_info: Vec::new(),

scopes: vec![FastHashMap::default()],
lookup_global_var_exps: FastHashMap::with_capacity_and_hasher(
parser.global_variables.len(),
Default::default(),
),
symbol_table: crate::front::SymbolTable::default(),
samplers: FastHashMap::default(),

typifier: Typifier::new(),
Expand Down Expand Up @@ -167,7 +161,7 @@ impl Context {
entry_arg,
};

self.lookup_global_var_exps.insert(name.into(), var);
self.symbol_table.add(name.into(), var);
}

/// Starts the expression emitter
Expand Down Expand Up @@ -220,42 +214,25 @@ impl Context {
handle
}

pub fn lookup_local_var(&self, name: &str) -> Option<VariableReference> {
for scope in self.scopes.iter().rev() {
if let Some(var) = scope.get(name) {
return Some(var.clone());
}
}
None
}

pub fn lookup_global_var(&mut self, name: &str) -> Option<VariableReference> {
self.lookup_global_var_exps.get(name).cloned()
}

#[cfg(feature = "glsl-validate")]
pub fn lookup_local_var_current_scope(&self, name: &str) -> Option<VariableReference> {
if let Some(current) = self.scopes.last() {
current.get(name).cloned()
} else {
None
}
}

/// Add variable to current scope
pub fn add_local_var(&mut self, name: String, expr: Handle<Expression>, mutable: bool) {
if let Some(current) = self.scopes.last_mut() {
(*current).insert(
name,
VariableReference {
expr,
load: true,
mutable,
constant: None,
entry_arg: None,
},
);
}
///
/// Returns a variable if a variable with the same name was already defined,
/// otherwise returns `None`
pub fn add_local_var(
&mut self,
name: String,
expr: Handle<Expression>,
mutable: bool,
) -> Option<VariableReference> {
let var = VariableReference {
expr,
load: true,
mutable,
constant: None,
entry_arg: None,
};

self.symbol_table.add(name, var)
}

/// Add function argument to current scope
Expand Down Expand Up @@ -306,7 +283,7 @@ impl Context {
let mutable = qualifier != ParameterQualifier::Const && !opaque;
let load = qualifier.is_lhs();

if mutable && !load {
let var = if mutable && !load {
let handle = self.locals.append(
LocalVariable {
name: Some(name.clone()),
Expand All @@ -327,40 +304,25 @@ impl Context {
meta,
);

if let Some(current) = self.scopes.last_mut() {
(*current).insert(
name,
VariableReference {
expr: local_expr,
load: true,
mutable,
constant: None,
entry_arg: None,
},
);
VariableReference {
expr: local_expr,
load: true,
mutable,
constant: None,
entry_arg: None,
}
} else if let Some(current) = self.scopes.last_mut() {
(*current).insert(
name,
VariableReference {
expr,
load,
mutable,
constant: None,
entry_arg: None,
},
);
}
}
}

/// Add new empty scope
pub fn push_scope(&mut self) {
self.scopes.push(FastHashMap::default());
}
} else {
VariableReference {
expr,
load,
mutable,
constant: None,
entry_arg: None,
}
};

pub fn remove_current_scope(&mut self) {
self.scopes.pop();
self.symbol_table.add(name, var);
}
}

/// Returns a [`StmtContext`](StmtContext) to be used in parsing and lowering
Expand Down
11 changes: 6 additions & 5 deletions src/front/glsl/parser/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ impl<'source> ParsingContext<'source> {
TokenValue::For => {
let mut meta = self.bump(parser)?.meta;

ctx.push_scope();
ctx.symbol_table.push_scope();
self.expect(parser, TokenValue::LeftParen)?;

if self.bump_if(parser, TokenValue::Semicolon).is_none() {
Expand Down Expand Up @@ -520,15 +520,14 @@ impl<'source> ParsingContext<'source> {
meta,
);

ctx.remove_current_scope();
ctx.symbol_table.pop_scope();

meta
}
TokenValue::LeftBrace => {
let meta = self.bump(parser)?.meta;

let mut block = Block::new();
ctx.push_scope();

let mut block_terminator = None;
let meta = self.parse_compound_statement(
Expand All @@ -539,8 +538,6 @@ impl<'source> ParsingContext<'source> {
&mut block_terminator,
)?;

ctx.remove_current_scope();

body.push(Statement::Block(block), meta);
if block_terminator.is_some() {
terminator.get_or_insert(body.len());
Expand Down Expand Up @@ -572,6 +569,8 @@ impl<'source> ParsingContext<'source> {
body: &mut Block,
terminator: &mut Option<usize>,
) -> Result<Span> {
ctx.symbol_table.push_scope();

loop {
if let Some(Token {
meta: brace_meta, ..
Expand All @@ -592,6 +591,8 @@ impl<'source> ParsingContext<'source> {
body.cull(idx..)
}

ctx.symbol_table.pop_scope();

Ok(meta)
}

Expand Down
50 changes: 23 additions & 27 deletions src/front/glsl/variables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,18 @@ impl Parser {
));

let expr = ctx.add_expression(Expression::GlobalVariable(handle), meta, body);
ctx.lookup_global_var_exps.insert(
name.into(),
VariableReference {
expr,
load: true,
mutable: data.mutable,
constant: None,
entry_arg: Some(idx),
},
);

ctx.lookup_global_var(name)
let var = VariableReference {
expr,
load: true,
mutable: data.mutable,
constant: None,
entry_arg: Some(idx),
};

ctx.symbol_table.add_root(name.into(), var.clone());

Some(var)
}

pub(crate) fn lookup_variable(
Expand All @@ -103,11 +103,8 @@ impl Parser {
name: &str,
meta: Span,
) -> Option<VariableReference> {
if let Some(local_var) = ctx.lookup_local_var(name) {
return Some(local_var);
}
if let Some(global_var) = ctx.lookup_global_var(name) {
return Some(global_var);
if let Some(var) = ctx.symbol_table.lookup(name).cloned() {
return Some(var);
}

let data = match name {
Expand Down Expand Up @@ -616,16 +613,6 @@ impl Parser {
body: &mut Block,
decl: VarDeclaration,
) -> Result<Handle<Expression>> {
#[cfg(feature = "glsl-validate")]
if let Some(ref name) = decl.name {
if ctx.lookup_local_var_current_scope(name).is_some() {
self.errors.push(Error {
kind: ErrorKind::VariableAlreadyDeclared(name.clone()),
meta: decl.meta,
})
}
}

let storage = decl.qualifiers.storage;
let mutable = match storage.0 {
StorageQualifier::AddressSpace(AddressSpace::Function) => true,
Expand All @@ -650,7 +637,16 @@ impl Parser {
let expr = ctx.add_expression(Expression::LocalVariable(handle), decl.meta, body);

if let Some(name) = decl.name {
ctx.add_local_var(name, expr, mutable);
#[allow(unused_variables)]
let maybe_var = ctx.add_local_var(name.clone(), expr, mutable);

#[cfg(feature = "glsl-validate")]
if maybe_var.is_some() {
self.errors.push(Error {
kind: ErrorKind::VariableAlreadyDeclared(name),
meta: decl.meta,
})
}
}

decl.qualifiers.unused_errors(&mut self.errors);
Expand Down
26 changes: 25 additions & 1 deletion src/front/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ where
/// 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.
pub fn lookup<Q: ?Sized>(&mut self, name: &Q) -> Option<&Var>
pub fn lookup<Q: ?Sized>(&self, name: &Q) -> Option<&Var>
where
Name: std::borrow::Borrow<Q>,
Q: std::hash::Hash + Eq,
Expand All @@ -277,6 +277,19 @@ where
pub fn add(&mut self, name: Name, var: Var) -> Option<Var> {
self.scopes[self.cursor - 1].insert(name, 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.
jimblandy marked this conversation as resolved.
Show resolved Hide resolved
pub fn add_root(&mut self, name: Name, var: Var) -> Option<Var> {
self.scopes[0].insert(name, var)
}
}

impl<Name, Var> Default for SymbolTable<Name, Var> {
Expand All @@ -288,3 +301,14 @@ impl<Name, Var> Default for SymbolTable<Name, Var> {
}
}
}

use std::fmt;

impl<Name: fmt::Debug, Var: fmt::Debug> fmt::Debug for SymbolTable<Name, Var> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("SymbolTable ")?;
f.debug_list()
.entries(self.scopes[..self.cursor].iter())
.finish()
}
}