1pub struct CoreBenchCase {
2 pub slug: &'static str,
3 pub name: &'static str,
4 pub source: &'static str,
5}
6
7const FIBONACCI: &str = "\
8fn fib(n: Int) -> Int
9 match n < 2
10 true -> n
11 false -> fib(n - 1) + fib(n - 2)
12
13fn main() -> Int
14 fib(25)
15";
16
17const SUM_TCO: &str = "\
18fn sum(n: Int, acc: Int) -> Int
19 match n == 0
20 true -> acc
21 false -> sum(n - 1, acc + n)
22
23fn main() -> Int
24 sum(1000000, 0)
25";
26
27const COUNTDOWN: &str = "\
28fn countdown(n: Int) -> Int
29 match n == 0
30 true -> 0
31 false -> countdown(n - 1)
32
33fn main() -> Int
34 countdown(1000000)
35";
36
37const FACTORIAL_TCO: &str = "\
38fn fact(n: Int, acc: Int) -> Int
39 match n == 0
40 true -> acc
41 false -> fact(n - 1, acc * n)
42
43fn repeat(n: Int, acc: Int) -> Int
44 match n == 0
45 true -> acc
46 false -> repeat(n - 1, acc + Result.withDefault(Int.mod(fact(20, 1), 1000000), 0))
47
48fn main() -> Int
49 repeat(5000, 0)
50";
51
52const NESTED_MATCH: &str = "\
53fn abs(n: Int) -> Int\n match n < 0\n true -> 0 - n\n false -> n\n\nfn classify(n: Int) -> Int\n match n == 0\n true -> 0\n false -> abs(n) * 2\n\nfn run(n: Int, acc: Int) -> Int\n match n == 0\n true -> acc\n false -> run(n - 1, acc + classify(n - 18000))\n\nfn main() -> Int\n run(36000, 0)\n";
54
55const RESULT_CHAIN: &str = "\
56fn safeDivide(a: Int, b: Int) -> Result<Int, Int>\n match b == 0\n true -> Result.Err(0)\n false -> Result.Ok(a / b)\n\nfn unwrapOr(r: Result<Int, Int>, d: Int) -> Int\n match r\n Result.Ok(v) -> v\n Result.Err(_) -> d\n\nfn chain(n: Int, acc: Int) -> Int\n match n == 0\n true -> acc\n false -> chain(n - 1, acc + unwrapOr(safeDivide(n * 10, n), 0))\n\nfn main() -> Int\n chain(40000, 0)\n";
57
58const LIST_WALK: &str = "\
59fn build(n: Int, acc: List<Int>) -> List<Int>\n match n == 0\n true -> acc\n false -> build(n - 1, List.prepend(n, acc))\n\nfn listLen(xs: List<Int>, acc: Int) -> Int\n match xs\n [] -> acc\n [h, ..t] -> listLen(t, acc + 1)\n\nfn walkFive(xs: List<Int>) -> Int\n listLen(xs, 0) + listLen(xs, 0) + listLen(xs, 0) + listLen(xs, 0) + listLen(xs, 0)\n\nfn main() -> Int\n walkFive(build(10000, []))\n";
60
61const SHAPES: &str = "\
62type Shape\n Circle(Float)\n Rect(Float, Float)\n Point\n\nfn area(s: Shape) -> Float\n match s\n Shape.Circle(r) -> r * r * 3.14159\n Shape.Rect(w, h) -> w * h\n Shape.Point -> 0.0\n\nfn sumAreas(n: Int, acc: Float) -> Float\n match n == 0\n true -> acc\n false -> sumAreas(n - 1, acc + area(Shape.Circle(1.0)) + area(Shape.Rect(3.0, 4.0)))\n\nfn main() -> Float\n sumAreas(30000, 0.0)\n";
63
64const RECORD_HEAVY: &str = "\
65record Point\n x: Int\n y: Int\n\nfn moveRight(p: Point) -> Point\n Point.update(p, x = p.x + 1)\n\nfn walk(n: Int, p: Point) -> Int\n match n == 0\n true -> p.x + p.y\n false -> walk(n - 1, moveRight(p))\n\nfn main() -> Int\n walk(40000, Point(x = 0, y = 0))\n";
66
67const STRING_BUILD: &str = "\
68fn repeat(n: Int, s: String, acc: String) -> String\n match n == 0\n true -> acc\n false -> repeat(n - 1, s, acc + s)\n\nfn main() -> Int\n r = repeat(8000, \"ab\", \"\")\n String.len(r)\n";
69
70const ERROR_PIPELINE: &str = "\
71fn validate(n: Int) -> Result<Int, String>\n match n < 0\n true -> Result.Err(\"negative\")\n false -> Result.Ok(n)\n\nfn transform(n: Int) -> Result<Int, String>\n match n > 1000\n true -> Result.Err(\"too large\")\n false -> Result.Ok(n * 2)\n\nfn pipeline(n: Int) -> Result<Int, String>\n v = validate(n)?\n transform(v)\n\nfn run(n: Int, acc: Int) -> Int\n match n == 0\n true -> acc\n false -> run(n - 1, acc + Result.withDefault(pipeline(n), 0))\n\nfn main() -> Int\n run(20000, 0)\n";
72
73const LIST_BUILTINS: &str = "\
74fn buildAndMeasure(n: Int, acc: List<Int>) -> Int\n match n == 0\n true -> List.len(acc)\n false -> buildAndMeasure(n - 1, List.prepend(n, acc))\n\nfn main() -> Int\n buildAndMeasure(40000, [])\n";
75
76const LIST_APPEND_SCAN: &str = "\
77fn build(n: Int, acc: List<Int>) -> List<Int>\n match n == 0\n true -> acc\n false -> build(n - 1, List.append(acc, n))\n\nfn sum(xs: List<Int>, i: Int, acc: Int) -> Int\n match List.get(xs, i)\n Option.None -> acc\n Option.Some(v) -> sum(xs, i + 1, acc + v)\n\nfn main() -> Int\n sum(build(12000, []), 0, 0)\n";
78
79const MIXED_REAL: &str = "\
80record Order\n id: Int\n amount: Int\n valid: Bool\n\nfn processOrder(o: Order) -> Result<Int, String>\n match o.valid\n true -> Result.Ok(o.amount * 2)\n false -> Result.Err(\"invalid\")\n\nfn processAll(n: Int, acc: Int) -> Int\n match n == 0\n true -> acc\n false -> processAll(n - 1, acc + Result.withDefault(processOrder(Order(id = n, amount = n * 10, valid = true)), 0))\n\nfn main() -> Int\n processAll(20000, 0)\n";
81
82pub const CORE_BENCH_CASES: &[CoreBenchCase] = &[
83 CoreBenchCase {
84 slug: "fib_25",
85 name: "fib(25)",
86 source: FIBONACCI,
87 },
88 CoreBenchCase {
89 slug: "sum_tco_1m",
90 name: "sum_tco(1M)",
91 source: SUM_TCO,
92 },
93 CoreBenchCase {
94 slug: "countdown_1m",
95 name: "countdown(1M)",
96 source: COUNTDOWN,
97 },
98 CoreBenchCase {
99 slug: "factorial_20",
100 name: "factorial(20) x 5K",
101 source: FACTORIAL_TCO,
102 },
103 CoreBenchCase {
104 slug: "nested_match_1k",
105 name: "nested_match(36K)",
106 source: NESTED_MATCH,
107 },
108 CoreBenchCase {
109 slug: "result_chain_10k",
110 name: "result_chain(40K)",
111 source: RESULT_CHAIN,
112 },
113 CoreBenchCase {
114 slug: "list_walk_10",
115 name: "list_walk(10K x5)",
116 source: LIST_WALK,
117 },
118 CoreBenchCase {
119 slug: "shapes_10k",
120 name: "shapes(30K)",
121 source: SHAPES,
122 },
123 CoreBenchCase {
124 slug: "record_heavy_10k",
125 name: "record_heavy(40K)",
126 source: RECORD_HEAVY,
127 },
128 CoreBenchCase {
129 slug: "string_build_1k",
130 name: "string_build(8K)",
131 source: STRING_BUILD,
132 },
133 CoreBenchCase {
134 slug: "error_pipeline_10k",
135 name: "error_pipeline(20K)",
136 source: ERROR_PIPELINE,
137 },
138 CoreBenchCase {
139 slug: "list_builtins_1k",
140 name: "list_builtins(40K)",
141 source: LIST_BUILTINS,
142 },
143 CoreBenchCase {
144 slug: "list_append_scan_1k",
145 name: "list_append_scan(12K)",
146 source: LIST_APPEND_SCAN,
147 },
148 CoreBenchCase {
149 slug: "mixed_real_10k",
150 name: "mixed_real(20K)",
151 source: MIXED_REAL,
152 },
153];