#![cfg(feature = "oxc")]
#[cfg(feature = "swc")]
fn main() {
println!("declarative_composition bench: skipped (swc feature enabled)");
}
#[cfg(not(feature = "swc"))]
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
#[cfg(not(feature = "swc"))]
use std::hint::black_box;
#[cfg(not(feature = "swc"))]
use macroforge_ts::host::declarative::{BuildMode, DeclarativeMacroRegistry, discover, rewrite};
#[cfg(not(feature = "swc"))]
use oxc::allocator::Allocator;
#[cfg(not(feature = "swc"))]
use oxc::parser::Parser;
#[cfg(not(feature = "swc"))]
use oxc::span::SourceType;
#[cfg(not(feature = "swc"))]
fn composition_source(depth: usize) -> String {
let mut body = String::from("$x");
for _ in 0..depth {
body = format!("$double({})", body);
}
format!(
"import {{ macroRules }} from \"macroforge/rules\";\n\
const $double = macroRules`($x:Expr) => ($x * 2)`;\n\
const $q = macroRules`($x:Expr) => {}`;\n\
const out = $q(1);\n",
body
)
}
#[cfg(not(feature = "swc"))]
fn run_rewrite(source: &str) {
let allocator = Allocator::default();
let parsed = Parser::new(&allocator, source, SourceType::ts()).parse();
assert!(
parsed.errors.is_empty(),
"parse errors in bench fixture: {:?}",
parsed.errors
);
let discovered = discover(&parsed.program, source).expect("discover");
let mut registry = DeclarativeMacroRegistry::new();
for dm in &discovered {
registry
.register_scoped(dm.def.clone(), dm.scope_span)
.unwrap();
}
let out = rewrite(
&parsed.program,
source,
®istry,
&discovered,
BuildMode::dev(),
None,
None,
);
black_box(out);
}
#[cfg(not(feature = "swc"))]
fn bench_composition(c: &mut Criterion) {
let mut group = c.benchmark_group("composition");
for depth in [4usize, 16, 64, 192] {
let source = composition_source(depth);
group.bench_with_input(BenchmarkId::from_parameter(depth), &source, |b, src| {
b.iter(|| run_rewrite(src));
});
}
group.finish();
}
#[cfg(not(feature = "swc"))]
fn hygiene_source() -> String {
let mut body = String::from("{\n");
for i in 0..50 {
body.push_str(&format!(" const __v{} = {};\n", i, i));
}
for i in 0..50 {
body.push_str(&format!(
" const __r{} = __v{} + __v{} + __v{};\n",
i,
i,
(i + 1) % 50,
(i + 2) % 50
));
}
body.push_str(" __v0\n}");
format!(
"import {{ macroRules }} from \"macroforge/rules\";\n\
const $big = macroRules`() => {}`;\n\
const out = $big();\n",
body
)
}
#[cfg(not(feature = "swc"))]
fn bench_hygiene(c: &mut Criterion) {
let source = hygiene_source();
c.bench_function("hygiene/rewrite_large_body", |b| {
b.iter(|| run_rewrite(&source));
});
}
#[cfg(not(feature = "swc"))]
fn cluster_source() -> String {
let mut calls = String::new();
for prefix in ['A', 'B', 'C', 'D', 'E'] {
for i in 0..10 {
calls.push_str(&format!(
"const v_{}_{} = $serialize({}{});\n",
prefix, i, prefix, i
));
}
}
format!(
"import {{ macroRules }} from \"macroforge/rules\";\n\
const $serialize = macroRules({{\n\
mode: \"auto\",\n\
expand: macroRules`($x:Expr) => __inline($x)`,\n\
runtime: \"function __serialize(v) {{ return v; }}\",\n\
runtimeName: \"__serialize_$__cluster__\",\n\
call: macroRules`($x:Expr) => __serialize_$__cluster__($x)`,\n\
megamorphismThreshold: 10,\n\
}});\n\
{}",
calls
)
}
#[cfg(not(feature = "swc"))]
fn bench_cluster(c: &mut Criterion) {
let source = cluster_source();
c.bench_function("cluster/analyze_50_shapes", |b| {
b.iter(|| {
let allocator = Allocator::default();
let parsed = Parser::new(&allocator, &source, SourceType::ts()).parse();
assert!(
parsed.errors.is_empty(),
"parse errors: {:?}",
parsed.errors
);
let discovered = discover(&parsed.program, &source).expect("discover");
let mut registry = DeclarativeMacroRegistry::new();
for dm in &discovered {
registry
.register_scoped(dm.def.clone(), dm.scope_span)
.unwrap();
}
let out = rewrite(
&parsed.program,
&source,
®istry,
&discovered,
BuildMode::prod(),
None,
None,
);
black_box(out);
});
});
}
#[cfg(not(feature = "swc"))]
criterion_group!(benches, bench_composition, bench_hygiene, bench_cluster);
#[cfg(not(feature = "swc"))]
criterion_main!(benches);