From 13a0d28ddc138609b1ed686aaa69d922f87adfed Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Thu, 1 Sep 2022 17:37:44 -0700 Subject: [PATCH] wgsl-in: Rename `Scope` to `Rule`, since we now have lexical scope. Rename related functions and variables appropriately. Also, make `Rule` private to the WGSL front end, and remove the unused `ImportDecl` variant. --- src/front/wgsl/construction.rs | 12 ++-- src/front/wgsl/mod.rs | 126 +++++++++++++++++---------------- 2 files changed, 71 insertions(+), 67 deletions(-) diff --git a/src/front/wgsl/construction.rs b/src/front/wgsl/construction.rs index 7039bb5dd8..43e719d0f3 100644 --- a/src/front/wgsl/construction.rs +++ b/src/front/wgsl/construction.rs @@ -3,7 +3,7 @@ use crate::{ ScalarKind, ScalarValue, Span as NagaSpan, Type, TypeInner, UniqueArena, VectorSize, }; -use super::{Error, ExpressionContext, Lexer, Parser, Scope, Span, Token}; +use super::{Error, ExpressionContext, Lexer, Parser, Rule, Span, Token}; /// Represents the type of the constructor /// @@ -216,7 +216,7 @@ fn parse_constructor_type<'a>( } } -/// Expects [`Scope::PrimaryExpr`] scope on top; if returning Some(_), pops it. +/// Expects [`Rule::PrimaryExpr`] on top of rule stack; if returning Some(_), pops it. pub(super) fn parse_construction<'a>( parser: &mut Parser, lexer: &mut Lexer<'a>, @@ -225,8 +225,8 @@ pub(super) fn parse_construction<'a>( mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result>, Error<'a>> { assert_eq!( - parser.scopes.last().map(|&(ref scope, _)| scope.clone()), - Some(Scope::PrimaryExpr) + parser.rules.last().map(|&(ref rule, _)| rule.clone()), + Some(Rule::PrimaryExpr) ); let dst_ty = match parser.lookup_type.get(type_name) { Some(&handle) => ConstructorType::Struct(handle), @@ -322,7 +322,7 @@ pub(super) fn parse_construction<'a>( return match ctx.create_zero_value_constant(ty) { Some(constant) => { - let span = parser.pop_scope(lexer); + let span = parser.pop_rule_span(lexer); Ok(Some(ctx.interrupt_emitter( Expression::Constant(constant), span.into(), @@ -674,6 +674,6 @@ pub(super) fn parse_construction<'a>( } }; - let span = NagaSpan::from(parser.pop_scope(lexer)); + let span = NagaSpan::from(parser.pop_rule_span(lexer)); Ok(Some(ctx.expressions.append(expr, span))) } diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index 489c16f339..657de486f3 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -1154,10 +1154,14 @@ struct TypeAttributes { // Therefore, we are leaving the plumbing in for now. } +/// Which grammar rule we are in the midst of parsing. +/// +/// This is used for error checking. `Parser` maintains a stack of +/// these and (occasionally) checks that it is being pushed and popped +/// as expected. #[derive(Clone, Debug, PartialEq)] -pub enum Scope { +enum Rule { Attribute, - ImportDecl, VariableDecl, TypeDecl, FunctionDecl, @@ -1348,7 +1352,7 @@ impl std::error::Error for ParseError { } pub struct Parser { - scopes: Vec<(Scope, usize)>, + rules: Vec<(Rule, usize)>, module_scope_identifiers: FastHashMap, lookup_type: FastHashMap>, layouter: Layouter, @@ -1357,7 +1361,7 @@ pub struct Parser { impl Parser { pub fn new() -> Self { Parser { - scopes: Vec::new(), + rules: Vec::new(), module_scope_identifiers: FastHashMap::default(), lookup_type: FastHashMap::default(), layouter: Default::default(), @@ -1365,23 +1369,23 @@ impl Parser { } fn reset(&mut self) { - self.scopes.clear(); + self.rules.clear(); self.module_scope_identifiers.clear(); self.lookup_type.clear(); self.layouter.clear(); } - fn push_scope(&mut self, scope: Scope, lexer: &Lexer<'_>) { - self.scopes.push((scope, lexer.current_byte_offset())); + fn push_rule_span(&mut self, rule: Rule, lexer: &Lexer<'_>) { + self.rules.push((rule, lexer.current_byte_offset())); } - fn pop_scope(&mut self, lexer: &Lexer<'_>) -> Span { - let (_, initial) = self.scopes.pop().unwrap(); + fn pop_rule_span(&mut self, lexer: &Lexer<'_>) -> Span { + let (_, initial) = self.rules.pop().unwrap(); lexer.span_from(initial) } - fn peek_scope(&mut self, lexer: &Lexer<'_>) -> Span { - let &(_, initial) = self.scopes.last().unwrap(); + fn peek_rule_span(&mut self, lexer: &Lexer<'_>) -> Span { + let &(_, initial) = self.rules.last().unwrap(); lexer.span_from(initial) } @@ -1519,7 +1523,7 @@ impl Parser { Ok(result) } - /// Expects [`Scope::PrimaryExpr`] or [`Scope::SingularExpr`] on top; does not pop it. + /// Expects [`Rule::PrimaryExpr`] or [`Rule::SingularExpr`] on top; does not pop it. /// Expects `word` to be peeked (still in lexer), doesn't consume if returning None. fn parse_function_call_inner<'a>( &mut self, @@ -1527,7 +1531,7 @@ impl Parser { name: &'a str, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result, Error<'a>> { - assert!(self.scopes.last().is_some()); + assert!(self.rules.last().is_some()); let expr = if let Some(fun) = conv::map_relational_fun(name) { let _ = lexer.next(); lexer.open_arguments()?; @@ -1738,7 +1742,7 @@ impl Parser { _ => return Err(Error::InvalidAtomicOperandType(value_span)), }; - let span = NagaSpan::from(self.peek_scope(lexer)); + let span = NagaSpan::from(self.peek_rule_span(lexer)); let result = ctx.interrupt_emitter(expression, span); ctx.block.push( crate::Statement::Atomic { @@ -2130,7 +2134,7 @@ impl Parser { let result = match self.parse_local_function_call(lexer, name, ctx.reborrow())? { Some((function, arguments)) => { - let span = NagaSpan::from(self.peek_scope(lexer)); + let span = NagaSpan::from(self.peek_rule_span(lexer)); ctx.block.extend(ctx.emitter.finish(ctx.expressions)); let result = ctx.functions[function].result.as_ref().map(|_| { ctx.expressions @@ -2153,7 +2157,7 @@ impl Parser { } } }; - let span = NagaSpan::from(self.peek_scope(lexer)); + let span = NagaSpan::from(self.peek_rule_span(lexer)); let handle = ctx.expressions.append(expr, span); Ok(Some(CalledFunction { result: Some(handle), @@ -2168,7 +2172,7 @@ impl Parser { type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result, Error<'a>> { - self.push_scope(Scope::ConstantExpr, lexer); + self.push_rule_span(Rule::ConstantExpr, lexer); let inner = match first_token_span { (Token::Word("true"), _) => crate::ConstantInner::boolean(true), (Token::Word("false"), _) => crate::ConstantInner::boolean(false), @@ -2193,7 +2197,7 @@ impl Parser { for (handle, var) in const_arena.iter() { match var.name { Some(ref string) if string == name => { - self.pop_scope(lexer); + self.pop_rule_span(lexer); return Ok(handle); } _ => {} @@ -2226,7 +2230,7 @@ impl Parser { // Only set span if it's a named constant. Otherwise, the enclosing Expression should have // the span. - let span = self.pop_scope(lexer); + let span = self.pop_rule_span(lexer); let handle = if let Some(name) = register_name { if crate::keywords::wgsl::RESERVED.contains(&name) { return Err(Error::ReservedKeyword(span)); @@ -2268,19 +2272,19 @@ impl Parser { mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result> { // Will be popped inside match, possibly inside parse_function_call_inner or parse_construction - self.push_scope(Scope::PrimaryExpr, lexer); + self.push_rule_span(Rule::PrimaryExpr, lexer); let expr = match lexer.peek() { (Token::Paren('('), _) => { let _ = lexer.next(); let (expr, _span) = self.parse_general_expression_for_reference(lexer, ctx.reborrow())?; lexer.expect(Token::Paren(')'))?; - self.pop_scope(lexer); + self.pop_rule_span(lexer); expr } (Token::Word("true" | "false") | Token::Number(..), _) => { let const_handle = self.parse_const_expression(lexer, ctx.types, ctx.constants)?; - let span = NagaSpan::from(self.pop_scope(lexer)); + let span = NagaSpan::from(self.pop_rule_span(lexer)); TypedExpression::non_reference( ctx.interrupt_emitter(crate::Expression::Constant(const_handle), span), ) @@ -2288,14 +2292,14 @@ impl Parser { (Token::Word(word), span) => { if let Some(definition) = ctx.symbol_table.lookup(word) { let _ = lexer.next(); - self.pop_scope(lexer); + self.pop_rule_span(lexer); *definition } else if let Some(CalledFunction { result: Some(expr) }) = self.parse_function_call_inner(lexer, word, ctx.reborrow())? { //TODO: resolve the duplicate call in `parse_singular_expression` - self.pop_scope(lexer); + self.pop_rule_span(lexer); TypedExpression::non_reference(expr) } else { let _ = lexer.next(); @@ -2487,7 +2491,7 @@ impl Parser { lexer: &mut Lexer<'a>, mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result> { - self.push_scope(Scope::UnaryExpr, lexer); + self.push_rule_span(Rule::UnaryExpr, lexer); //TODO: refactor this to avoid backing up let expr = match lexer.peek().0 { Token::Operation('-') => { @@ -2498,7 +2502,7 @@ impl Parser { op: crate::UnaryOperator::Negate, expr, }; - let span = NagaSpan::from(self.peek_scope(lexer)); + let span = NagaSpan::from(self.peek_rule_span(lexer)); TypedExpression::non_reference(ctx.expressions.append(expr, span)) } Token::Operation('!' | '~') => { @@ -2509,7 +2513,7 @@ impl Parser { op: crate::UnaryOperator::Not, expr, }; - let span = NagaSpan::from(self.peek_scope(lexer)); + let span = NagaSpan::from(self.peek_rule_span(lexer)); TypedExpression::non_reference(ctx.expressions.append(expr, span)) } Token::Operation('*') => { @@ -2529,7 +2533,7 @@ impl Parser { .expressions .get_span(pointer) .to_range() - .unwrap_or_else(|| self.peek_scope(lexer)); + .unwrap_or_else(|| self.peek_rule_span(lexer)); return Err(Error::NotPointer(span)); } @@ -2548,7 +2552,7 @@ impl Parser { .expressions .get_span(operand.handle) .to_range() - .unwrap_or_else(|| self.peek_scope(lexer)); + .unwrap_or_else(|| self.peek_rule_span(lexer)); return Err(Error::NotReference("the operand of the `&` operator", span)); } @@ -2561,7 +2565,7 @@ impl Parser { _ => self.parse_singular_expression(lexer, ctx.reborrow())?, }; - self.pop_scope(lexer); + self.pop_rule_span(lexer); Ok(expr) } @@ -2572,10 +2576,10 @@ impl Parser { mut ctx: ExpressionContext<'a, '_, '_>, ) -> Result> { let start = lexer.current_byte_offset(); - self.push_scope(Scope::SingularExpr, lexer); + self.push_rule_span(Rule::SingularExpr, lexer); let primary_expr = self.parse_primary_expression(lexer, ctx.reborrow())?; let singular_expr = self.parse_postfix(start, lexer, ctx.reborrow(), primary_expr)?; - self.pop_scope(lexer); + self.pop_rule_span(lexer); Ok(singular_expr) } @@ -2681,7 +2685,7 @@ impl Parser { lexer: &mut Lexer<'a>, mut context: ExpressionContext<'a, '_, '_>, ) -> Result<(TypedExpression, Span), Error<'a>> { - self.push_scope(Scope::GeneralExpr, lexer); + self.push_rule_span(Rule::GeneralExpr, lexer); // logical_or_expression let handle = context.parse_binary_op( lexer, @@ -2737,7 +2741,7 @@ impl Parser { ) }, )?; - Ok((handle, self.pop_scope(lexer))) + Ok((handle, self.pop_rule_span(lexer))) } fn parse_variable_ident_decl<'a>( @@ -2758,7 +2762,7 @@ impl Parser { type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result, Error<'a>> { - self.push_scope(Scope::VariableDecl, lexer); + self.push_rule_span(Rule::VariableDecl, lexer); let mut space = None; if lexer.skip(Token::Paren('<')) { @@ -2788,7 +2792,7 @@ impl Parser { None }; lexer.expect(Token::Separator(';'))?; - let name_span = self.pop_scope(lexer); + let name_span = self.pop_rule_span(lexer); Ok(ParsedVariable { name, name_span, @@ -2818,7 +2822,7 @@ impl Parser { )); } let (mut size_attr, mut align_attr) = (None, None); - self.push_scope(Scope::Attribute, lexer); + self.push_rule_span(Rule::Attribute, lexer); let mut bind_parser = BindingParser::default(); while lexer.skip(Token::Attribute) { match lexer.next_ident_with_span()? { @@ -2840,7 +2844,7 @@ impl Parser { } } - let bind_span = self.pop_scope(lexer); + let bind_span = self.pop_rule_span(lexer); let mut binding = bind_parser.finish(bind_span)?; let (name, span) = match lexer.next() { @@ -3253,7 +3257,7 @@ impl Parser { type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result, Error<'a>> { - self.push_scope(Scope::TypeDecl, lexer); + self.push_rule_span(Rule::TypeDecl, lexer); let attribute = TypeAttributes::default(); if lexer.skip(Token::Attribute) { @@ -3271,7 +3275,7 @@ impl Parser { type_arena, const_arena, )?; - self.pop_scope(lexer); + self.pop_rule_span(lexer); // Only set span if it's the first occurrence of the type. // Type spans therefore should only be used for errors in type declarations; // use variable spans/expression spans/etc. otherwise @@ -3409,7 +3413,7 @@ impl Parser { ident: &'a str, mut context: ExpressionContext<'a, '_, 'out>, ) -> Result<(), Error<'a>> { - self.push_scope(Scope::SingularExpr, lexer); + self.push_rule_span(Rule::SingularExpr, lexer); context.emitter.start(context.expressions); if self .parse_function_call_inner(lexer, ident, context.reborrow())? @@ -3421,7 +3425,7 @@ impl Parser { context .block .extend(context.emitter.finish(context.expressions)); - self.pop_scope(lexer); + self.pop_rule_span(lexer); Ok(()) } @@ -3461,15 +3465,15 @@ impl Parser { block: &'out mut crate::Block, is_uniform_control_flow: bool, ) -> Result<(), Error<'a>> { - self.push_scope(Scope::Statement, lexer); + self.push_rule_span(Rule::Statement, lexer); match lexer.peek() { (Token::Separator(';'), _) => { let _ = lexer.next(); - self.pop_scope(lexer); + self.pop_rule_span(lexer); return Ok(()); } (Token::Paren('{'), _) => { - self.push_scope(Scope::Block, lexer); + self.push_rule_span(Rule::Block, lexer); // Push a new lexical scope for the block statement context.symbol_table.push_scope(); @@ -3486,8 +3490,8 @@ impl Parser { // Pop the block statement lexical scope context.symbol_table.pop_scope(); - self.pop_scope(lexer); - let span = NagaSpan::from(self.pop_scope(lexer)); + self.pop_rule_span(lexer); + let span = NagaSpan::from(self.pop_rule_span(lexer)); block.push(crate::Statement::Block(statements), span); return Ok(()); } @@ -4050,7 +4054,7 @@ impl Parser { None } }; - let span = NagaSpan::from(self.pop_scope(lexer)); + let span = NagaSpan::from(self.pop_rule_span(lexer)); if let Some(statement) = statement { block.push(statement, span); } @@ -4058,7 +4062,7 @@ impl Parser { _ => { let mut emitter = super::Emitter::default(); self.parse_assignment_statement(lexer, context.as_expression(block, &mut emitter))?; - self.pop_scope(lexer); + self.pop_rule_span(lexer); } } Ok(()) @@ -4155,7 +4159,7 @@ impl Parser { mut context: StatementContext<'a, '_, '_>, is_uniform_control_flow: bool, ) -> Result> { - self.push_scope(Scope::Block, lexer); + self.push_rule_span(Rule::Block, lexer); // Push a lexical scope for the block context.symbol_table.push_scope(); @@ -4172,7 +4176,7 @@ impl Parser { //Pop the block lexical scope context.symbol_table.pop_scope(); - self.pop_scope(lexer); + self.pop_rule_span(lexer); Ok(block) } @@ -4181,14 +4185,14 @@ impl Parser { lexer: &mut Lexer<'a>, ) -> Result, Error<'a>> { let mut bind_parser = BindingParser::default(); - self.push_scope(Scope::Attribute, lexer); + self.push_rule_span(Rule::Attribute, lexer); while lexer.skip(Token::Attribute) { let (word, span) = lexer.next_ident_with_span()?; bind_parser.parse(lexer, word, span)?; } - let span = self.pop_scope(lexer); + let span = self.pop_rule_span(lexer); bind_parser.finish(span) } @@ -4198,7 +4202,7 @@ impl Parser { module: &mut crate::Module, lookup_global_expression: &FastHashMap<&'a str, crate::Expression>, ) -> Result<(crate::Function, &'a str), Error<'a>> { - self.push_scope(Scope::FunctionDecl, lexer); + self.push_rule_span(Rule::FunctionDecl, lexer); // read function name let mut symbol_table = super::SymbolTable::default(); let (fun_name, span) = lexer.next_ident_with_span()?; @@ -4317,7 +4321,7 @@ impl Parser { // fixup the IR ensure_block_returns(&mut fun.body); // done - self.pop_scope(lexer); + self.pop_rule_span(lexer); // Set named expressions after block parsing ends fun.named_expressions = named_expressions; @@ -4338,7 +4342,7 @@ impl Parser { let mut early_depth_test = None; let (mut bind_index, mut bind_group) = (None, None); - self.push_scope(Scope::Attribute, lexer); + self.push_rule_span(Rule::Attribute, lexer); while lexer.skip(Token::Attribute) { match lexer.next_ident_with_span()? { ("binding", _) => { @@ -4392,7 +4396,7 @@ impl Parser { } } - let attrib_scope = self.pop_scope(lexer); + let attrib_span = self.pop_rule_span(lexer); match (bind_group, bind_index) { (Some(group), Some(index)) => { binding = Some(crate::ResourceBinding { @@ -4400,8 +4404,8 @@ impl Parser { binding: index, }); } - (Some(_), None) => return Err(Error::MissingAttribute("binding", attrib_scope)), - (None, Some(_)) => return Err(Error::MissingAttribute("group", attrib_scope)), + (Some(_), None) => return Err(Error::MissingAttribute("binding", attrib_span)), + (None, Some(_)) => return Err(Error::MissingAttribute("group", attrib_span)), (None, None) => {} } @@ -4577,8 +4581,8 @@ impl Parser { Err(error) => return Err(error.as_parse_error(lexer.source)), Ok(true) => {} Ok(false) => { - if !self.scopes.is_empty() { - log::error!("Reached the end of file, but scopes are not closed"); + if !self.rules.is_empty() { + log::error!("Reached the end of file, but rule stack is not empty"); return Err(Error::Other.as_parse_error(lexer.source)); }; return Ok(module);