use truncate() instead of pop() for unused and shadowed variables#23
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR optimizes the parser code generation by replacing individual pop() calls with more efficient truncate() operations for unused and shadowed variables on parser stacks. This reduces unnecessary work when variables are not referenced in the reduce action code.
Key changes:
- Implements analysis to detect unused location variables in reduce actions
- Replaces multiple consecutive
pop()operations with singletruncate()calls - Handles variable shadowing by nullifying earlier declarations of the same variable name
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| rusty_lr_parser/src/parser/parser_expanded.rs | Generated parser code updated to use truncate() instead of pop() for unused variables |
| rusty_lr_parser/src/emit.rs | Code generation logic enhanced to analyze variable usage and emit optimized stack operations |
| SYNTAX.md | Documentation updated to clarify variable access patterns in reduce actions |
| for (token_index_from_end, token) in rule.tokens.iter().rev().enumerate() { | ||
| let stack_name = token_to_stack_name(token.token); | ||
| let tag_name = stack_name.unwrap_or(&empty_tag_name); | ||
|
|
||
| #[derive(PartialEq, Eq, PartialOrd, Ord)] | ||
| enum StackName { | ||
| DataStack(Ident), | ||
| LocationStack, | ||
| } | ||
| impl StackName { | ||
| pub fn to_token_stream(&self) -> TokenStream { | ||
| match self { | ||
| StackName::DataStack(name) => quote! {__data_stack.#name}, | ||
| StackName::LocationStack => quote! {__location_stack}, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if let Some(stack_name) = stack_name { |
There was a problem hiding this comment.
The StackName enum definition is placed inside the loop, which means it gets redefined for every iteration. This should be moved outside the loop to avoid redundant type definitions.
| for (token_index_from_end, token) in rule.tokens.iter().rev().enumerate() { | |
| let stack_name = token_to_stack_name(token.token); | |
| let tag_name = stack_name.unwrap_or(&empty_tag_name); | |
| #[derive(PartialEq, Eq, PartialOrd, Ord)] | |
| enum StackName { | |
| DataStack(Ident), | |
| LocationStack, | |
| } | |
| impl StackName { | |
| pub fn to_token_stream(&self) -> TokenStream { | |
| match self { | |
| StackName::DataStack(name) => quote! {__data_stack.#name}, | |
| StackName::LocationStack => quote! {__location_stack}, | |
| } | |
| } | |
| } | |
| if let Some(stack_name) = stack_name { | |
| #[derive(PartialEq, Eq, PartialOrd, Ord)] | |
| enum StackName { | |
| DataStack(Ident), | |
| LocationStack, | |
| } | |
| impl StackName { | |
| pub fn to_token_stream(&self) -> TokenStream { | |
| match self { | |
| StackName::DataStack(name) => quote! {__data_stack.#name}, | |
| StackName::LocationStack => quote! {__location_stack}, | |
| } | |
| } | |
| } | |
| for (token_index_from_end, token) in rule.tokens.iter().rev().enumerate() { | |
| let stack_name = token_to_stack_name(token.token); | |
| let tag_name = stack_name.unwrap_or(&empty_tag_name); |
| fn tokenstream_contains_ident( | ||
| stream: TokenStream, | ||
| ident: &Ident, | ||
| ) -> bool { | ||
| for t in stream { | ||
| match t { | ||
| proc_macro2::TokenTree::Ident(i) if &i == ident => { | ||
| return true | ||
| } | ||
| proc_macro2::TokenTree::Group(g) => { | ||
| if tokenstream_contains_ident(g.stream(), ident) { | ||
| return true; | ||
| } | ||
| } | ||
| _ => {} | ||
| } | ||
| } | ||
| false | ||
| } | ||
|
|
There was a problem hiding this comment.
The tokenstream_contains_ident function is defined inside the loop, causing it to be redefined on every iteration. This helper function should be moved outside the loop or to module level for better performance and code organization.
| fn tokenstream_contains_ident( | |
| stream: TokenStream, | |
| ident: &Ident, | |
| ) -> bool { | |
| for t in stream { | |
| match t { | |
| proc_macro2::TokenTree::Ident(i) if &i == ident => { | |
| return true | |
| } | |
| proc_macro2::TokenTree::Group(g) => { | |
| if tokenstream_contains_ident(g.stream(), ident) { | |
| return true; | |
| } | |
| } | |
| _ => {} | |
| } | |
| } | |
| false | |
| } |
No description provided.