Skip to content

Commit ccc56f8

Browse files
authored
Merge pull request #9 from Tcode-Motion/bolt-parser-optimization-9269391063391972267
⚡ Bolt: Remove unnecessary Token cloning in parser
2 parents 6f75f8a + 34fc972 commit ccc56f8

5 files changed

Lines changed: 27 additions & 7 deletions

File tree

.jules/bolt.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 2024-01-20 - Lifetime Refactoring in Parser to Eliminate Token Cloning
2+
**Learning:** In the Rust parser (`compiler/parser/src/parser.rs`), methods like `advance()` and `previous()` originally returned a reference tied to `&mut self`. Because `Token` was still borrowing `self` mutably, the parser couldn't call methods like `self.parse_prefix` (which requires another `&mut self` borrow) without first calling `.clone()` on the token to drop the initial borrow.
3+
**Action:** By explicitly defining the return lifetime as `&'a Token` (tied to the lifetime of the underlying token slice `&'a [Token]`, rather than the `Parser` instance), the mutable borrow of `self` ends immediately. This elegantly satisfies the borrow checker while removing the overhead of cloning tokens throughout `expressions.rs` and `statements.rs`. Look for similar lifetime constraints elsewhere in the compiler that force unnecessary copies.

compiler/parser/src/expressions.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ impl<'a> Parser<'a> {
1414
precedence: Precedence,
1515
reporter: &mut DiagnosticReporter,
1616
) -> ParseResult<Expression> {
17-
let token = self.advance().clone();
18-
let mut left = self.parse_prefix(&token, reporter)?;
17+
let token = self.advance();
18+
let mut left = self.parse_prefix(token, reporter)?;
1919

2020
while !self.is_at_end() {
2121
let next_prec = self.peek().kind.precedence();
@@ -41,8 +41,8 @@ impl<'a> Parser<'a> {
4141
break;
4242
}
4343

44-
let next_token = self.advance().clone();
45-
left = self.parse_infix(left, &next_token, reporter)?;
44+
let next_token = self.advance();
45+
left = self.parse_infix(left, next_token, reporter)?;
4646
}
4747

4848
Ok(left)

compiler/parser/src/parser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,15 @@ impl<'a> Parser<'a> {
162162
}
163163

164164
/// Advances the cursor and returns the previous token.
165-
pub(crate) fn advance(&mut self) -> &Token {
165+
pub(crate) fn advance(&mut self) -> &'a Token {
166166
if !self.is_at_end() {
167167
self.pos += 1;
168168
}
169169
&self.tokens[self.pos - 1]
170170
}
171171

172172
/// Returns the previous token.
173-
pub(crate) fn previous(&self) -> &Token {
173+
pub(crate) fn previous(&self) -> &'a Token {
174174
&self.tokens[self.pos - 1]
175175
}
176176

compiler/parser/src/statements.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<'a> Parser<'a> {
6767
|| self.check(TokenKind::Send)
6868
{
6969
let start_pos = self.peek().span.start;
70-
let kw_token = self.peek().clone();
70+
let kw_token = self.peek();
7171
if kw_token.kind == TokenKind::Return {
7272
reporter.report(techscript_errors::Diagnostic::new(
7373
techscript_errors::DiagnosticLevel::Warning,

patch_expressions.diff

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--- compiler/parser/src/expressions.rs
2+
+++ compiler/parser/src/expressions.rs
3+
@@ -17,7 +17,7 @@
4+
let token = self.advance();
5+
- let mut left = self.parse_prefix(&token, reporter)?;
6+
+ let mut left = self.parse_prefix(token, reporter)?;
7+
8+
while !self.is_at_end() {
9+
let next_prec = self.peek().kind.precedence();
10+
@@ -44,7 +44,7 @@
11+
12+
let next_token = self.advance();
13+
- left = self.parse_infix(left, &next_token, reporter)?;
14+
+ left = self.parse_infix(left, next_token, reporter)?;
15+
}
16+
17+
Ok(left)

0 commit comments

Comments
 (0)