Skip to content
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
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-05-24 - Avoid vec! for constant collections in initialization loops
**Learning:** Initializing maps/operator managers by iterating over `vec![...]` causes unnecessary heap allocations. Using array literals `[...]` is significantly more efficient since the size is known at compile time and the arrays can be stack-allocated or embedded directly into the binary.
**Action:** Always prefer iterating over array literals instead of `vec![...]` for statically known collections, especially in hot paths or initialization loops.
2 changes: 1 addition & 1 deletion benches/display_expression.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use criterion::{criterion_group, criterion_main, Criterion, black_box};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only change here is reordering the criterion imports, which is unrelated to the operator initialization optimization described in the PR. Consider dropping this from the PR or documenting why it’s included, to avoid mixing perf changes with style-only diffs.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This appears to be a stylistic change that reorders the imports. While not harmful, it's unrelated to the performance optimizations in this PR. To keep pull requests focused on a single concern, it's good practice to exclude unrelated changes. Please consider reverting this change from this PR.

use expression_engine::{parse_expression, ExprAST};

fn bench_display_expression(c: &mut Criterion) {
Expand Down
15 changes: 8 additions & 7 deletions src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ impl InfixOpManager {
use InfixOpType::*;
self.register("=", 20, SETTER, RIGHT, Arc::new(|_, right| Ok(right)));

for op in vec!["+=", "-=", "*=", "/=", "%="] {
// Iterate over an array literal `[...]` instead of `vec![...]` to avoid heap allocations
for op in ["+=", "-=", "*=", "/=", "%="] {
self.register(
op,
20,
Expand Down Expand Up @@ -88,7 +89,7 @@ impl InfixOpManager {
);
}

for op in vec!["<<=", ">>=", "&=", "^=", "|="] {
for op in ["<<=", ">>=", "&=", "^=", "|="] {
self.register(
op,
20,
Expand All @@ -109,7 +110,7 @@ impl InfixOpManager {
);
}

for (op, precedence) in vec![("||", 40), ("&&", 50)] {
for (op, precedence) in [("||", 40), ("&&", 50)] {
self.register(
op,
precedence,
Expand All @@ -127,7 +128,7 @@ impl InfixOpManager {
);
}

for op in vec!["<", "<=", ">", ">="] {
for op in ["<", "<=", ">", ">="] {
self.register(
op,
60,
Expand All @@ -148,7 +149,7 @@ impl InfixOpManager {
);
}

for op in vec!["==", "!="] {
for op in ["==", "!="] {
self.register(
op,
60,
Expand All @@ -166,7 +167,7 @@ impl InfixOpManager {
);
}

for (op, precedence) in vec![("|", 70), ("^", 80), ("&", 90), ("<<", 100), (">>", 100)] {
for (op, precedence) in [("|", 70), ("^", 80), ("&", 90), ("<<", 100), (">>", 100)] {
self.register(
op,
precedence,
Expand All @@ -187,7 +188,7 @@ impl InfixOpManager {
);
}

for (op, precedence) in vec![("+", 110), ("-", 110), ("*", 120), ("/", 120), ("%", 120)] {
for (op, precedence) in [("+", 110), ("-", 110), ("*", 120), ("/", 120), ("%", 120)] {
self.register(
op,
precedence,
Expand Down
14 changes: 4 additions & 10 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,16 @@ impl<'a> fmt::Display for ExprAST<'a> {
Self::Unary(op, rhs) => {
write!(f, "Unary AST: Op: {}, Rhs: {}", op, rhs)
}
Self::Binary(op, lhs, rhs) => write!(
f,
"Binary AST: Op: {}, Lhs: {}, Rhs: {}",
op,
lhs,
rhs
),
Self::Binary(op, lhs, rhs) => {
write!(f, "Binary AST: Op: {}, Lhs: {}, Rhs: {}", op, lhs, rhs)
}
Comment thread
ashyanSpada marked this conversation as resolved.
Comment thread
ashyanSpada marked this conversation as resolved.
Self::Postfix(lhs, op) => {
write!(f, "Postfix AST: Lhs: {}, Op: {}", lhs, op,)
}
Self::Ternary(condition, lhs, rhs) => write!(
f,
"Ternary AST: Condition: {}, Lhs: {}, Rhs: {}",
condition,
lhs,
rhs
condition, lhs, rhs
),
Self::Reference(name) => write!(f, "Reference AST: reference: {}", name),
Self::Function(name, params) => {
Expand Down
Loading