use criterion::{criterion_group, criterion_main, Criterion};
use ruchy::frontend::parser::Parser;
use std::hint::black_box;
fn benchmark_literals(c: &mut Criterion) {
c.bench_function("parse_integer", |b| {
b.iter(|| {
let mut parser = Parser::new(black_box("42"));
parser.parse().unwrap()
});
});
c.bench_function("parse_float", |b| {
b.iter(|| {
let mut parser = Parser::new(black_box("3.14159"));
parser.parse().unwrap()
});
});
c.bench_function("parse_string", |b| {
b.iter(|| {
let mut parser = Parser::new(black_box(r#""hello world""#));
parser.parse().unwrap()
});
});
c.bench_function("parse_interpolated_string", |b| {
let code = r#"f"The answer is {x + y} and pi is {pi:.2}""#;
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
}
fn benchmark_expressions(c: &mut Criterion) {
c.bench_function("parse_arithmetic", |b| {
let code = "2 + 3 * 4 - 5 / 2";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_nested_arithmetic", |b| {
let code = "((2 + 3) * (4 - 1)) / (5 + (6 * 7))";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_method_chain", |b| {
let code = "list.filter(x => x > 0).map(x => x * 2).reduce(0, (a, b) => a + b)";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_pipeline", |b| {
let code = "data |> filter(x => x.active) |> map(x => x.value) |> sum()";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
}
fn benchmark_control_flow(c: &mut Criterion) {
c.bench_function("parse_if_else", |b| {
let code = "if x > 0 { x * 2 } else if x < 0 { x * -1 } else { 0 }";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_match", |b| {
let code = r"
match value {
Some(x) if x > 0 => x * 2,
Some(x) => x,
None => 0,
_ => -1
}
";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_for_loop", |b| {
let code = "for i in 0..100 { sum += i * i }";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_while_loop", |b| {
let code = "while x < 100 { x = x * 2 + 1 }";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
}
fn benchmark_functions(c: &mut Criterion) {
c.bench_function("parse_function_def", |b| {
let code = "fn factorial(n: int) -> int { if n <= 1 { 1 } else { n * factorial(n - 1) } }";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_lambda", |b| {
let code = "x => x * 2";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_nested_lambda", |b| {
let code = "x => y => z => x + y + z";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_generic_function", |b| {
let code = "fn map<T, U>(list: List<T>, f: T -> U) -> List<U> { list.map(f) }";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
}
fn benchmark_data_structures(c: &mut Criterion) {
c.bench_function("parse_list", |b| {
let code = "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_nested_list", |b| {
let code = "[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_object", |b| {
let code = "{ name: \"John\", age: 30, active: true, scores: [85, 90, 95] }";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_tuple", |b| {
let code = "(1, \"hello\", true, 3.14, [1, 2, 3])";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
}
fn benchmark_patterns(c: &mut Criterion) {
c.bench_function("parse_simple_pattern", |b| {
let code = "let x = 42";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_destructuring", |b| {
let code = "let [first, second, ...rest] = list";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_object_destructuring", |b| {
let code = "let { name, age, ...other } = person";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_nested_destructuring", |b| {
let code = "let { user: { name, email }, timestamp } = event";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
}
fn benchmark_real_world(c: &mut Criterion) {
c.bench_function("parse_fibonacci", |b| {
let code = r"
fn fibonacci(n: int) -> int {
if n <= 1 {
n
} else {
fibonacci(n - 1) + fibonacci(n - 2)
}
}
";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_quicksort", |b| {
let code = r"
fn quicksort(arr: List<int>) -> List<int> {
if arr.len() <= 1 {
arr
} else {
let pivot = arr[0]
let less = arr[1..].filter(x => x < pivot)
let greater = arr[1..].filter(x => x >= pivot)
quicksort(less) + [pivot] + quicksort(greater)
}
}
";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_class_definition", |b| {
let code = r#"
struct Person {
name: string,
age: int,
email: Option<string>
}
impl Person {
fn new(name: string, age: int) -> Person {
Person { name: name, age: age, email: None }
}
fn greet(self) -> string {
f"Hello, my name is {self.name}"
}
fn is_adult(self) -> bool {
self.age >= 18
}
}
"#;
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
c.bench_function("parse_async_function", |b| {
let code = r"
async fn fetch_data(url: string) -> Result<Data, Error> {
let response = await http::get(url)
if response.status == 200 {
let data = await response.json()
Ok(data)
} else {
Err(Error::HttpError(response.status))
}
}
";
b.iter(|| {
let mut parser = Parser::new(black_box(code));
parser.parse().unwrap()
});
});
}
fn benchmark_stress_test(c: &mut Criterion) {
c.bench_function("parse_deeply_nested", |b| {
let mut code = String::new();
for _ in 0..20 {
code.push_str("if true { ");
}
code.push_str("42");
for _ in 0..20 {
code.push_str(" }");
}
b.iter(|| {
let mut parser = Parser::new(black_box(&code));
parser.parse().unwrap()
});
});
c.bench_function("parse_long_chain", |b| {
let mut code = String::from("x");
for i in 0..50 {
code.push_str(&format!(".method{i}()"));
}
b.iter(|| {
let mut parser = Parser::new(black_box(&code));
parser.parse().unwrap()
});
});
c.bench_function("parse_large_list", |b| {
let mut code = String::from("[");
for i in 0..100 {
if i > 0 {
code.push_str(", ");
}
code.push_str(&i.to_string());
}
code.push(']');
b.iter(|| {
let mut parser = Parser::new(black_box(&code));
parser.parse().unwrap()
});
});
}
criterion_group!(
benches,
benchmark_literals,
benchmark_expressions,
benchmark_control_flow,
benchmark_functions,
benchmark_data_structures,
benchmark_patterns,
benchmark_real_world,
benchmark_stress_test
);
criterion_main!(benches);