Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

refactor pattern matching to favour first appearing variable

author
Giacomo Cavalieri
committer
Louis Pilfold
date (Oct 3, 2025, 12:25 PM +0100) commit 499dc4a8 parent 8bdec6d2 change-id wnymptzp
+95 -91
+14 -12
compiler-core/src/exhaustiveness.rs
··· 2748 2748 } 2749 2749 } 2750 2750 2751 - // Maximize ( -branching_factor, references ). 2751 + // We want to picke the variable that has the smallest branching factor 2752 + // possible, this tends to yield smaller, shallower decision trees. 2753 + // So, for example, we will pick a list (branching factor of 2 `[]` and 2754 + // `[_, ..]`) over an integer (infinitely many choices). 2752 2755 // 2753 - // - branching_factor: prefer the split that creates the FEWEST switch arms. 2754 - // Fewer children tends to yield smaller, shallower decision trees. 2755 - // 2756 - // - references: break ties by choosing the subject that appears in the most 2757 - // clauses (i.e. a test that will pay off for more rows). 2756 + // In case two variables are tied we break the tie by choosing the subject 2757 + // that appears in the most clauses (i.e. a test that will pay off for more 2758 + // rows). 2758 2759 // 2759 2760 // Both parts mirror standard guidance for good match trees (small branching 2760 - // factor; prioritize columns that are widely useful). 2761 - // 2761 + // factor; prioritize columns that are widely useful): 2762 2762 // https://www.cs.tufts.edu/~nr/cs257/archive/luc-maranget/jun08.pdf 2763 2763 first_branch 2764 2764 .checks 2765 2765 .iter() 2766 - .max_by_key(|check| { 2767 - let mode = check.var.branch_mode(env); 2768 - let branching_factor = mode.branching_factor(); 2766 + .min_by_key(|check| { 2767 + let branching_factor = check.var.branch_mode(env).branching_factor(); 2769 2768 let references = var_references.get(&check.var.id).cloned().unwrap_or(0); 2770 2769 2771 - (usize::MAX - branching_factor, references) 2770 + // Notice how we're using `-references`: we want to favour the one 2771 + // that has the most references, so the one were `-references` is 2772 + // the smallest. 2773 + (branching_factor, -references) 2772 2774 }) 2773 2775 .cloned() 2774 2776 }
+4 -4
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__assignments__assert1.snap
··· 11 11 const FILEPATH = "src/module.gleam"; 12 12 13 13 export function go(x) { 14 - let $ = x[1]; 15 - if ($ === 2) { 16 - let $1 = x[0]; 17 - if (!($1 === 1)) { 14 + let $ = x[0]; 15 + if ($ === 1) { 16 + let $1 = x[1]; 17 + if (!($1 === 2)) { 18 18 throw makeError( 19 19 "let_assert", 20 20 FILEPATH,
+4 -4
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__assignments__nested_binding.snap
··· 19 19 let t; 20 20 let b; 21 21 let c; 22 - let $ = x[1][2]; 23 - if ($ === 2) { 24 - let $1 = x[3]; 25 - if ($1 === 1) { 22 + let $ = x[3]; 23 + if ($ === 1) { 24 + let $1 = x[1][2]; 25 + if ($1 === 2) { 26 26 a = x[0]; 27 27 t = x[1]; 28 28 b = x[1][0];
+4 -4
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__assignments__tuple_matching.snap
··· 15 15 const FILEPATH = "src/module.gleam"; 16 16 17 17 export function go(x) { 18 - let $ = x[1]; 19 - if ($ === 2) { 20 - let $1 = x[0]; 21 - if (!($1 === 1)) { 18 + let $ = x[0]; 19 + if ($ === 1) { 20 + let $1 = x[1]; 21 + if (!($1 === 2)) { 22 22 throw makeError( 23 23 "let_assert", 24 24 FILEPATH,
+11 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bit_arrays__tuple_multiple_bit_arrays.snap
··· 15 15 const FILEPATH = "src/module.gleam"; 16 16 17 17 export function go(x) { 18 - let $ = x[2]; 19 - if ( 20 - $.bitSize >= 8 && 21 - $.byteAt(0) === 2 && 22 - $.bitSize === 16 && 23 - $.byteAt(1) === 3 24 - ) { 18 + let $ = x[0]; 19 + if ($.bitSize === 0) { 25 20 let $1 = x[1]; 26 - if ($1.bitSize === 8 && $1.byteAt(0) === 1) { 27 - let $2 = x[0]; 28 - if (!($2.bitSize === 0)) { 21 + if ($1.bitSize === 8) { 22 + let $2 = x[2]; 23 + if (!( 24 + $2.bitSize >= 8 && 25 + $1.byteAt(0) === 1 && 26 + $2.byteAt(0) === 2 && 27 + $2.bitSize === 16 && 28 + $2.byteAt(1) === 3 29 + )) { 29 30 throw makeError( 30 31 "let_assert", 31 32 FILEPATH,
+11 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__bit_arrays__tuple_multiple_bit_arrays_case.snap
··· 14 14 15 15 ----- COMPILED JAVASCRIPT 16 16 export function go(x) { 17 - let $ = x[2]; 18 - if ( 19 - $.bitSize >= 8 && 20 - $.byteAt(0) === 2 && 21 - $.bitSize === 16 && 22 - $.byteAt(1) === 3 23 - ) { 17 + let $ = x[0]; 18 + if ($.bitSize === 0) { 24 19 let $1 = x[1]; 25 - if ($1.bitSize === 8 && $1.byteAt(0) === 1) { 26 - let $2 = x[0]; 27 - if ($2.bitSize === 0) { 20 + if ($1.bitSize === 8) { 21 + let $2 = x[2]; 22 + if ( 23 + $2.bitSize >= 8 && 24 + $1.byteAt(0) === 1 && 25 + $2.byteAt(0) === 2 && 26 + $2.bitSize === 16 && 27 + $2.byteAt(1) === 3 28 + ) { 28 29 return true; 29 30 } else { 30 31 return false;
+11 -5
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case__case_with_multiple_subjects_building_list_matched_by_pattern.snap
··· 25 25 } else { 26 26 let $ = x.tail; 27 27 if ($ instanceof $Empty) { 28 - let $1 = x.head; 29 - if ($1 === 1 && n === 3) { 30 - return x; 28 + if (n === 3) { 29 + let $1 = x.head; 30 + if ($1 === 1) { 31 + return x; 32 + } else { 33 + return x; 34 + } 31 35 } else { 32 36 return x; 33 37 } ··· 35 39 let $1 = $.tail; 36 40 if ($1 instanceof $Empty) { 37 41 return x; 38 - } else { 42 + } else if (n === 3) { 39 43 let $2 = x.head; 40 - if ($2 === 1 && n === 3) { 44 + if ($2 === 1) { 41 45 return x; 42 46 } else { 43 47 return x; 44 48 } 49 + } else { 50 + return x; 45 51 } 46 52 } 47 53 }
+10 -10
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case__case_with_multiple_subjects_building_record_matched_by_pattern.snap
··· 15 15 import { Ok, Error } from "../gleam.mjs"; 16 16 17 17 export function go(x, y) { 18 - if (y instanceof Ok) { 19 - if (x instanceof Error) { 20 - return y; 21 - } else { 22 - return new Error(undefined); 23 - } 24 - } else if (x instanceof Ok) { 25 - let $ = x[0]; 26 - if ($ === 1) { 27 - return x; 18 + if (x instanceof Ok) { 19 + if (y instanceof Error) { 20 + let $ = x[0]; 21 + if ($ === 1) { 22 + return x; 23 + } else { 24 + return new Error(undefined); 25 + } 28 26 } else { 29 27 return new Error(undefined); 30 28 } 29 + } else if (y instanceof Ok) { 30 + return y; 31 31 } else { 32 32 return new Error(undefined); 33 33 }
+2 -2
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case__case_with_multiple_subjects_building_same_value_as_two_subjects_one_is_picked.snap
··· 21 21 export function go(x, y) { 22 22 if (y instanceof Ok) { 23 23 if (x instanceof $gleam.Ok) { 24 - let $ = x[0]; 24 + let $ = y[0]; 25 25 if ($ === 1) { 26 - let $1 = y[0]; 26 + let $1 = x[0]; 27 27 if ($1 === 1) { 28 28 return x; 29 29 } else {
+1 -3
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case__multi_subject_catch_all.snap
··· 1 1 --- 2 2 source: compiler-core/src/javascript/tests/case.rs 3 - assertion_line: 95 4 3 expression: "\npub fn go(x, y) {\n case x, y {\n True, True -> 1\n _, _ -> 0\n }\n}\n" 5 - snapshot_kind: text 6 4 --- 7 5 ----- SOURCE CODE 8 6 ··· 16 14 17 15 ----- COMPILED JAVASCRIPT 18 16 export function go(x, y) { 19 - if (y && x) { 17 + if (x && y) { 20 18 return 1; 21 19 } else { 22 20 return 0;
+4 -6
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case__nested_string_prefix_match.snap
··· 1 1 --- 2 2 source: compiler-core/src/javascript/tests/case.rs 3 - assertion_line: 258 4 3 expression: "\npub fn main() {\n case Ok([\"a\", \"b c\", \"d\"]) {\n Ok([\"a\", \"b \" <> _, \"d\"]) -> 1\n _ -> 1\n }\n}\n" 5 - snapshot_kind: text 6 4 --- 7 5 ----- SOURCE CODE 8 6 ··· 33 31 } else { 34 32 let $4 = $3.tail; 35 33 if ($4 instanceof $Empty) { 36 - let $5 = $3.head; 37 - if ($5 === "d") { 34 + let $5 = $1.head; 35 + if ($5 === "a") { 38 36 let $6 = $2.head; 39 37 if ($6.startsWith("b ")) { 40 - let $7 = $1.head; 41 - if ($7 === "a") { 38 + let $7 = $3.head; 39 + if ($7 === "d") { 42 40 return 1; 43 41 } else { 44 42 return 1;
+4 -6
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case__nested_string_prefix_match_that_would_crash_on_js.snap
··· 1 1 --- 2 2 source: compiler-core/src/javascript/tests/case.rs 3 - assertion_line: 273 4 3 expression: "\npub fn main() {\n case Ok([\"b c\", \"d\"]) {\n Ok([\"b \" <> _, \"d\"]) -> 1\n _ -> 1\n }\n}\n" 5 - snapshot_kind: text 6 4 --- 7 5 ----- SOURCE CODE 8 6 ··· 29 27 } else { 30 28 let $3 = $2.tail; 31 29 if ($3 instanceof $Empty) { 32 - let $4 = $2.head; 33 - if ($4 === "d") { 34 - let $5 = $1.head; 35 - if ($5.startsWith("b ")) { 30 + let $4 = $1.head; 31 + if ($4.startsWith("b ")) { 32 + let $5 = $2.head; 33 + if ($5 === "d") { 36 34 return 1; 37 35 } else { 38 36 return 1;
+4 -4
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__case_clause_guards__alternative_patterns_list.snap
··· 29 29 } else { 30 30 let $1 = $.tail; 31 31 if ($1 instanceof $Empty) { 32 - let $2 = $.head; 33 - if ($2 === 2) { 34 - let $3 = xs.head; 35 - if ($3 === 1) { 32 + let $2 = xs.head; 33 + if ($2 === 1) { 34 + let $3 = $.head; 35 + if ($3 === 2) { 36 36 return 0; 37 37 } else { 38 38 return 1;
+4 -4
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__lists__list_destructuring.snap
··· 82 82 } else { 83 83 let $2 = $1.tail; 84 84 if ($2 instanceof $Empty) { 85 - let $3 = $1.head; 86 - if ($3 === 2) { 87 - let $4 = x.head; 88 - if (!($4 === 1)) { 85 + let $3 = x.head; 86 + if ($3 === 1) { 87 + let $4 = $1.head; 88 + if (!($4 === 2)) { 89 89 throw makeError( 90 90 "let_assert", 91 91 FILEPATH,
+2 -2
compiler-core/src/language_server/tests/snapshots/gleam_core__language_server__tests__action__add_missing_patterns_tuple.snap
··· 17 17 pub fn main(two_at_once: #(Bool, Result(Int, Nil))) { 18 18 case two_at_once { 19 19 #(False, Error(_)) -> Nil 20 - #(True, Error(_)) -> todo 21 - #(_, Ok(_)) -> todo 20 + #(False, Ok(_)) -> todo 21 + #(True, _) -> todo 22 22 } 23 23 }
+1 -1
compiler-core/src/type_/snapshots/gleam_core__type___tests__variant_inference_on_literal_record.snap
··· 30 30 31 31 The missing patterns are: 32 32 33 - _, Wobble 33 + Wibble, Wobble
+2 -2
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__exhaustiveness__case_error_prints_module_names.snap
··· 31 31 32 32 The missing patterns are: 33 33 34 - #(_, Thing2(_)) 35 - #(wibble.Wobble, Thing1) 34 + #(wibble.Wibble, Thing2(_)) 35 + #(wibble.Wobble, _)
+2 -2
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__exhaustiveness__inexhaustive_multi_pattern2.snap
··· 25 25 26 26 The missing patterns are: 27 27 28 - Error(_), True 28 + Error(_), _ 29 + Ok(_), False 29 30 Ok(_), True 30 - _, False