This commit is contained in:
2026-03-12 17:47:46 +08:00
parent 7a7229d70e
commit 0c9a391618
511 changed files with 234 additions and 12772 deletions

113
fix/benches/basic_ops.rs Normal file
View File

@@ -0,0 +1,113 @@
mod utils;
use std::hint::black_box;
use criterion::{Criterion, criterion_group, criterion_main};
use utils::eval;
fn bench_arithmetic(c: &mut Criterion) {
let mut group = c.benchmark_group("arithmetic");
group.bench_function("addition", |b| b.iter(|| eval(black_box("1 + 1"))));
group.bench_function("subtraction", |b| b.iter(|| eval(black_box("10 - 5"))));
group.bench_function("multiplication", |b| b.iter(|| eval(black_box("6 * 7"))));
group.bench_function("division", |b| b.iter(|| eval(black_box("100 / 5"))));
group.bench_function("complex_expression", |b| {
b.iter(|| eval(black_box("(5 + 3) * (10 - 2) / 4")))
});
group.finish();
}
fn bench_comparison(c: &mut Criterion) {
let mut group = c.benchmark_group("comparison");
group.bench_function("equality", |b| b.iter(|| eval(black_box("42 == 42"))));
group.bench_function("less_than", |b| b.iter(|| eval(black_box("5 < 10"))));
group.bench_function("logical_and", |b| {
b.iter(|| eval(black_box("true && false")))
});
group.bench_function("logical_or", |b| {
b.iter(|| eval(black_box("true || false")))
});
group.finish();
}
fn bench_function_application(c: &mut Criterion) {
let mut group = c.benchmark_group("function_application");
group.bench_function("simple_identity", |b| {
b.iter(|| eval(black_box("(x: x) 42")))
});
group.bench_function("curried_function", |b| {
b.iter(|| eval(black_box("(x: y: x + y) 10 20")))
});
group.bench_function("nested_application", |b| {
b.iter(|| eval(black_box("((x: y: z: x + y + z) 1) 2 3")))
});
group.finish();
}
fn bench_let_bindings(c: &mut Criterion) {
let mut group = c.benchmark_group("let_bindings");
group.bench_function("simple_let", |b| {
b.iter(|| eval(black_box("let x = 5; in x + 10")))
});
group.bench_function("multiple_bindings", |b| {
b.iter(|| eval(black_box("let a = 1; b = 2; c = 3; in a + b + c")))
});
group.bench_function("dependent_bindings", |b| {
b.iter(|| eval(black_box("let x = 5; y = x * 2; z = y + 3; in z")))
});
group.finish();
}
fn bench_attrsets(c: &mut Criterion) {
let mut group = c.benchmark_group("attrsets");
group.bench_function("simple_attrset", |b| {
b.iter(|| eval(black_box("{ a = 1; b = 2; }.a")))
});
group.bench_function("nested_attrset", |b| {
b.iter(|| eval(black_box("{ a.b.c = 42; }.a.b.c")))
});
group.bench_function("rec_attrset", |b| {
b.iter(|| eval(black_box("rec { a = 1; b = a + 1; }.b")))
});
group.bench_function("attrset_update", |b| {
b.iter(|| eval(black_box("{ a = 1; } // { b = 2; }")))
});
group.finish();
}
fn bench_lists(c: &mut Criterion) {
let mut group = c.benchmark_group("lists");
group.bench_function("simple_list", |b| {
b.iter(|| eval(black_box("[ 1 2 3 4 5 ]")))
});
group.bench_function("list_concatenation", |b| {
b.iter(|| eval(black_box("[ 1 2 3 ] ++ [ 4 5 6 ]")))
});
group.bench_function("nested_list", |b| {
b.iter(|| eval(black_box("[ [ 1 2 ] [ 3 4 ] [ 5 6 ] ]")))
});
group.finish();
}
criterion_group!(
benches,
bench_arithmetic,
bench_comparison,
bench_function_application,
bench_let_bindings,
bench_attrsets,
bench_lists
);
criterion_main!(benches);

145
fix/benches/builtins.rs Normal file
View File

@@ -0,0 +1,145 @@
mod utils;
use std::hint::black_box;
use criterion::{Criterion, criterion_group, criterion_main};
use utils::eval;
fn bench_builtin_math(c: &mut Criterion) {
let mut group = c.benchmark_group("builtin_math");
group.bench_function("add", |b| b.iter(|| eval(black_box("builtins.add 10 20"))));
group.bench_function("sub", |b| b.iter(|| eval(black_box("builtins.sub 20 10"))));
group.bench_function("mul", |b| b.iter(|| eval(black_box("builtins.mul 6 7"))));
group.bench_function("div", |b| b.iter(|| eval(black_box("builtins.div 100 5"))));
group.finish();
}
fn bench_builtin_list(c: &mut Criterion) {
let mut group = c.benchmark_group("builtin_list");
group.bench_function("length_small", |b| {
b.iter(|| eval(black_box("builtins.length [1 2 3 4 5]")))
});
group.bench_function("length_large", |b| {
b.iter(|| {
eval(black_box(
"builtins.length [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]",
))
})
});
group.bench_function("head", |b| {
b.iter(|| eval(black_box("builtins.head [1 2 3 4 5]")))
});
group.bench_function("tail", |b| {
b.iter(|| eval(black_box("builtins.tail [1 2 3 4 5]")))
});
group.bench_function("elem_found", |b| {
b.iter(|| eval(black_box("builtins.elem 3 [1 2 3 4 5]")))
});
group.bench_function("elem_not_found", |b| {
b.iter(|| eval(black_box("builtins.elem 10 [1 2 3 4 5]")))
});
group.bench_function("concat_lists", |b| {
b.iter(|| eval(black_box("builtins.concatLists [[1 2] [3 4] [5 6]]")))
});
group.finish();
}
fn bench_builtin_map_filter(c: &mut Criterion) {
let mut group = c.benchmark_group("builtin_map_filter");
group.bench_function("map_small", |b| {
b.iter(|| eval(black_box("builtins.map (x: x * 2) [1 2 3 4 5]")))
});
group.bench_function("map_large", |b| {
b.iter(|| {
eval(black_box(
"builtins.map (x: x * 2) [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]",
))
})
});
group.bench_function("filter_small", |b| {
b.iter(|| eval(black_box("builtins.filter (x: x > 2) [1 2 3 4 5]")))
});
group.bench_function("filter_large", |b| {
b.iter(|| {
eval(black_box(
"builtins.filter (x: x > 10) [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]",
))
})
});
group.bench_function("foldl", |b| {
b.iter(|| {
eval(black_box(
"builtins.foldl' (acc: x: acc + x) 0 [1 2 3 4 5 6 7 8 9 10]",
))
})
});
group.finish();
}
fn bench_builtin_attrset(c: &mut Criterion) {
let mut group = c.benchmark_group("builtin_attrset");
group.bench_function("attrNames", |b| {
b.iter(|| eval(black_box("builtins.attrNames { a = 1; b = 2; c = 3; }")))
});
group.bench_function("attrValues", |b| {
b.iter(|| eval(black_box("builtins.attrValues { a = 1; b = 2; c = 3; }")))
});
group.bench_function("hasAttr", |b| {
b.iter(|| eval(black_box("builtins.hasAttr \"a\" { a = 1; b = 2; c = 3; }")))
});
group.bench_function("getAttr", |b| {
b.iter(|| eval(black_box("builtins.getAttr \"b\" { a = 1; b = 2; c = 3; }")))
});
group.finish();
}
fn bench_builtin_type_checks(c: &mut Criterion) {
let mut group = c.benchmark_group("builtin_type_checks");
group.bench_function("isInt", |b| b.iter(|| eval(black_box("builtins.isInt 42"))));
group.bench_function("isList", |b| {
b.iter(|| eval(black_box("builtins.isList [1 2 3]")))
});
group.bench_function("isAttrs", |b| {
b.iter(|| eval(black_box("builtins.isAttrs { a = 1; }")))
});
group.bench_function("isFunction", |b| {
b.iter(|| eval(black_box("builtins.isFunction (x: x)")))
});
group.bench_function("typeOf", |b| {
b.iter(|| eval(black_box("builtins.typeOf 42")))
});
group.finish();
}
fn bench_free_globals(c: &mut Criterion) {
let mut group = c.benchmark_group("free_globals");
group.bench_function("map", |b| {
b.iter(|| eval(black_box("map (x: x * 2) [1 2 3 4 5]")))
});
group.bench_function("isNull", |b| b.iter(|| eval(black_box("isNull null"))));
group.bench_function("toString", |b| b.iter(|| eval(black_box("toString 42"))));
group.finish();
}
criterion_group!(
benches,
bench_builtin_math,
bench_builtin_list,
bench_builtin_map_filter,
bench_builtin_attrset,
bench_builtin_type_checks,
bench_free_globals
);
criterion_main!(benches);

174
fix/benches/thunk_scope.rs Normal file
View File

@@ -0,0 +1,174 @@
mod utils;
use std::hint::black_box;
use criterion::{Criterion, criterion_group, criterion_main};
use utils::eval;
fn bench_non_recursive(c: &mut Criterion) {
let mut group = c.benchmark_group("non_recursive");
group.bench_function("simple_bindings", |b| {
b.iter(|| eval(black_box("let x = 1; y = 2; z = x + y; in z")))
});
group.bench_function("many_bindings", |b| {
b.iter(|| {
eval(black_box(
"let a = 1; b = 2; c = 3; d = 4; e = 5; f = 6; g = 7; h = 8; i = 9; j = 10; in a + b + c + d + e + f + g + h + i + j",
))
})
});
group.bench_function("dependent_chain", |b| {
b.iter(|| {
eval(black_box(
"let a = 1; b = a + 1; c = b + 1; d = c + 1; e = d + 1; in e",
))
})
});
group.bench_function("rec_attrset_non_recursive", |b| {
b.iter(|| eval(black_box("rec { a = 1; b = 2; c = 3; d = a + b + c; }.d")))
});
group.finish();
}
fn bench_recursive(c: &mut Criterion) {
let mut group = c.benchmark_group("recursive");
group.bench_function("simple_recursion", |b| {
b.iter(|| {
eval(black_box(
"let f = n: if n == 0 then 0 else f (n - 1); in f 10",
))
})
});
group.bench_function("fibonacci", |b| {
b.iter(|| {
eval(black_box(
"let fib = n: if n <= 1 then 1 else fib (n - 1) + fib (n - 2); in fib 10",
))
})
});
group.bench_function("factorial", |b| {
b.iter(|| {
eval(black_box(
"let factorial = n: if n == 0 then 1 else n * factorial (n - 1); in factorial 10",
))
})
});
group.bench_function("rec_attrset_recursive", |b| {
b.iter(|| {
eval(black_box(
"rec { f = n: if n == 0 then 1 else f (n - 1); }.f 10",
))
})
});
group.finish();
}
fn bench_mutual_recursion(c: &mut Criterion) {
let mut group = c.benchmark_group("mutual_recursion");
group.bench_function("two_way", |b| {
b.iter(|| {
eval(black_box(
"let f = n: if n == 0 then 0 else g (n - 1); g = n: if n == 0 then 1 else f (n - 1); in f 10",
))
})
});
group.bench_function("even_odd", |b| {
b.iter(|| {
eval(black_box(
"let even = n: if n == 0 then true else odd (n - 1); odd = n: if n == 0 then false else even (n - 1); in even 20",
))
})
});
group.bench_function("three_way", |b| {
b.iter(|| {
eval(black_box(
"let a = n: if n == 0 then 1 else b (n - 1); b = n: if n == 0 then 2 else c (n - 1); c = n: if n == 0 then 3 else a (n - 1); in a 15",
))
})
});
group.finish();
}
fn bench_mixed(c: &mut Criterion) {
let mut group = c.benchmark_group("mixed");
group.bench_function("recursive_with_constants", |b| {
b.iter(|| {
eval(black_box(
"let x = 10; fib = n: if n <= 1 then 1 else fib (n - 1) + fib (n - 2); in fib x",
))
})
});
group.bench_function("multiple_recursive_functions", |b| {
b.iter(|| {
eval(black_box(
"let fib = n: if n <= 1 then 1 else fib (n - 1) + fib (n - 2); fact = n: if n == 0 then 1 else n * fact (n - 1); in (fib 8) + (fact 5)",
))
})
});
group.bench_function("complex_dependency_graph", |b| {
b.iter(|| {
eval(black_box(
"let a = 1; b = 2; c = a + b; fib = n: if n <= 1 then 1 else fib (n - 1) + fib (n - 2); result = c + fib 8; in result",
))
})
});
group.finish();
}
fn bench_nested_scopes(c: &mut Criterion) {
let mut group = c.benchmark_group("nested_scopes");
group.bench_function("nested_let_non_recursive", |b| {
b.iter(|| {
eval(black_box(
"let x = 1; in let y = x + 1; in let z = y + 1; in z",
))
})
});
group.bench_function("nested_let_with_recursive", |b| {
b.iter(|| {
eval(black_box(
"let f = n: if n == 0 then 0 else f (n - 1); in let g = m: f m; in g 10",
))
})
});
group.bench_function("deeply_nested", |b| {
b.iter(|| {
eval(black_box(
"let a = 1; in let b = a + 1; in let c = b + 1; in let d = c + 1; in let e = d + 1; in e",
))
})
});
group.finish();
}
criterion_group!(
benches,
bench_non_recursive,
bench_recursive,
bench_mutual_recursion,
bench_mixed,
bench_nested_scopes
);
criterion_main!(benches);

18
fix/benches/utils.rs Normal file
View File

@@ -0,0 +1,18 @@
#![allow(dead_code)]
use fix::context::Context;
use fix::error::{Result, Source};
use fix::value::Value;
pub fn eval(expr: &str) -> Value {
Context::new()
.unwrap()
.eval(Source::new_eval(expr.into()).unwrap())
.unwrap()
}
pub fn eval_result(expr: &str) -> Result<Value> {
Context::new()
.unwrap()
.eval(Source::new_eval(expr.into()).unwrap())
}