From 73cf47dbd20425fc2c8d237018859258831e8e45 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Wed, 30 Oct 2024 06:21:48 +0100 Subject: [PATCH 1/4] Experiment for untagged pattern matching. First step: remove the distinction between cases with and without payload in the toplevel algorithm. On this test: ```res @unboxed type rec t = | Boolean(bool) | @as(null) Null | String(string) | Number(float) | Object(Dict.t) | Array(array) type group = { id: string, name: string, } let decodeGroup = group => { switch group { | (dict{"id": String(id), "name": String(name)}) => (id, name) | _ => ("e", "f") } } ``` Before: ```js function decodeGroup(group) { let match = group.id; if (match === undefined) { return [ "e", "f" ]; } if (match === null) { return [ "e", "f" ]; } if (typeof match !== "string") { return [ "e", "f" ]; } let match$1 = group.name; if (match$1 !== undefined && !(match$1 === null || typeof match$1 !== "string")) { return [ match, match$1 ]; } else { return [ "e", "f" ]; } } ``` After: ``` function decodeGroup(group) { let match = group.id; if (match === undefined) { return [ "e", "f" ]; } if (typeof match !== "string") { return [ "e", "f" ]; } let match$1 = group.name; if (match$1 !== undefined && typeof match$1 === "string") { return [ match, match$1 ]; } else { return [ "e", "f" ]; } } ``` The 3 cases have become 2: check for optional fields and check for which case it is. --- compiler/core/lam_compile.ml | 72 ++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/compiler/core/lam_compile.ml b/compiler/core/lam_compile.ml index b773eff0ed..db3f92d2a2 100644 --- a/compiler/core/lam_compile.ml +++ b/compiler/core/lam_compile.ml @@ -673,6 +673,8 @@ let compile output_prefix = also if last statement is throw -- should we drop remaining statement? *) + Printf.eprintf "XXX switch_arg: %s\n\n" + (Lam_print.lambda_to_string switch_arg); let ({ sw_consts_full; sw_consts; @@ -713,40 +715,66 @@ let compile output_prefix = block @ if sw_consts_full && sw_consts = [] then + let _ = Printf.eprintf "QQQ sw_consts_full\n\n" in compile_cases ~block_cases ~untagged ~cxt ~switch_exp:(if untagged then e else E.tag ~name:tag_name e) ~default:sw_blocks_default ~get_tag:get_block_tag sw_blocks else if sw_blocks_full && sw_blocks = [] then + let _ = Printf.eprintf "QQQ sw_blocks_full\n\n" in compile_cases ~cxt ~switch_exp:e ~block_cases ~default:sw_num_default ~get_tag:get_const_tag sw_consts else + let _ = Printf.eprintf "QQQ else\n\n" in (* [e] will be used twice *) let dispatch e = let is_a_literal_case = - if block_cases <> [] then - E.is_a_literal_case - ~literal_cases:(get_literal_cases sw_names) - ~block_cases e + if untagged then ( + let literal_case = + E.is_a_literal_case + ~literal_cases:(get_literal_cases sw_names) + ~block_cases e + in + Printf.eprintf "LLL literal_case: %s\n\n" + (Js_dump.string_of_expression literal_case); + literal_case) else E.is_int_tag ~has_null_undefined_other:(has_null_undefined_other sw_names) e in - S.if_ is_a_literal_case - (compile_cases ~cxt ~switch_exp:e ~block_cases - ~default:sw_num_default ~get_tag:get_const_tag sw_consts) - ~else_: - (compile_cases ~untagged ~cxt - ~switch_exp:(if untagged then e else E.tag ~name:tag_name e) - ~block_cases ~default:sw_blocks_default - ~get_tag:get_block_tag sw_blocks) + let qconsts = + use_compile_literal_cases sw_consts ~get_tag:get_const_tag + in + let qblocks = + use_compile_literal_cases sw_blocks ~get_tag:get_block_tag + in + match (qconsts, qblocks) with + | Some consts_cases, Some blocks_cases when untagged -> + let untagged_cases = consts_cases @ blocks_cases in + let z = + compile_untagged_cases ~cxt ~switch_exp:e ~block_cases + ~default:sw_num_default untagged_cases + in + z + | _ -> + [ + S.if_ is_a_literal_case + (compile_cases ~cxt ~switch_exp:e ~block_cases + ~default:sw_num_default ~get_tag:get_const_tag sw_consts) + ~else_: + (compile_cases ~untagged ~cxt + ~switch_exp: + (if untagged then e else E.tag ~name:tag_name e) + ~block_cases ~default:sw_blocks_default + ~get_tag:get_block_tag sw_blocks); + ] in match e.expression_desc with - | J.Var _ -> [dispatch e] + | J.Var _ -> dispatch e | _ -> let v = Ext_ident.create_tmp () in (* Necessary avoid duplicated computation*) - [S.define_variable ~kind:Variable v e; dispatch (E.var v)]) + [S.define_variable ~kind:Variable v e] @ dispatch (E.var v)) in match lambda_cxt.continuation with (* Needs declare first *) @@ -756,15 +784,19 @@ let compile output_prefix = when branches are minimial (less than 2) *) let v = Ext_ident.create_tmp () in + let res = compile_whole {lambda_cxt with continuation = Assign v} in + Printf.eprintf "XXX res 1: %s\n\n" (Js_dump.string_of_block res); Js_output.make - (S.declare_variable ~kind:Variable v - :: compile_whole {lambda_cxt with continuation = Assign v}) + (S.declare_variable ~kind:Variable v :: res) ~value:(E.var v) | Declare (kind, id) -> - Js_output.make - (S.declare_variable ~kind id - :: compile_whole {lambda_cxt with continuation = Assign id}) - | EffectCall _ | Assign _ -> Js_output.make (compile_whole lambda_cxt) + let res = compile_whole {lambda_cxt with continuation = Assign id} in + Printf.eprintf "XXX res 2: %s\n\n" (Js_dump.string_of_block res); + Js_output.make (S.declare_variable ~kind id :: res) ~value:(E.var id) + | EffectCall _ | Assign _ -> + let res = compile_whole lambda_cxt in + Printf.eprintf "XXX res 3: %s\n\n" (Js_dump.string_of_block res); + Js_output.make res and compile_string_cases ~cxt ~switch_exp ~default cases : initialization = cases |> compile_general_cases ~make_exp:E.tag_type From f23b19b8d6054ab7219351bed7f8d2eddf06a57e Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Sun, 3 Nov 2024 16:08:16 +0100 Subject: [PATCH 2/4] Fuse const and block cases when the defaults are equal. --- compiler/core/lam_compile.ml | 45 +++++++++++-------- tests/tests/src/UntaggedVariants.mjs | 52 +++++++++------------- tests/tests/src/and_or_simplify.mjs | 12 ++--- tests/tests/src/core/Core_JsonTests.mjs | 18 ++++---- tests/tests/src/json_decorders.mjs | 59 +++++++++++++++++++++++++ tests/tests/src/json_decorders.res | 45 +++++++++++++++++++ tests/tests/src/pattern_match_json.mjs | 16 +++---- 7 files changed, 171 insertions(+), 76 deletions(-) create mode 100644 tests/tests/src/json_decorders.mjs create mode 100644 tests/tests/src/json_decorders.res diff --git a/compiler/core/lam_compile.ml b/compiler/core/lam_compile.ml index db3f92d2a2..f7db97d7e5 100644 --- a/compiler/core/lam_compile.ml +++ b/compiler/core/lam_compile.ml @@ -673,8 +673,8 @@ let compile output_prefix = also if last statement is throw -- should we drop remaining statement? *) - Printf.eprintf "XXX switch_arg: %s\n\n" - (Lam_print.lambda_to_string switch_arg); + (* Printf.eprintf "XXX switch_arg: %s\n\n" + (Lam_print.lambda_to_string switch_arg); *) let ({ sw_consts_full; sw_consts; @@ -715,28 +715,28 @@ let compile output_prefix = block @ if sw_consts_full && sw_consts = [] then - let _ = Printf.eprintf "QQQ sw_consts_full\n\n" in + (* let _ = Printf.eprintf "QQQ sw_consts_full\n\n" in *) compile_cases ~block_cases ~untagged ~cxt ~switch_exp:(if untagged then e else E.tag ~name:tag_name e) ~default:sw_blocks_default ~get_tag:get_block_tag sw_blocks else if sw_blocks_full && sw_blocks = [] then - let _ = Printf.eprintf "QQQ sw_blocks_full\n\n" in + (* let _ = Printf.eprintf "QQQ sw_blocks_full\n\n" in *) compile_cases ~cxt ~switch_exp:e ~block_cases ~default:sw_num_default ~get_tag:get_const_tag sw_consts else - let _ = Printf.eprintf "QQQ else\n\n" in + (* let _ = Printf.eprintf "QQQ else\n\n" in *) (* [e] will be used twice *) let dispatch e = let is_a_literal_case = - if untagged then ( + if untagged then let literal_case = E.is_a_literal_case ~literal_cases:(get_literal_cases sw_names) ~block_cases e in - Printf.eprintf "LLL literal_case: %s\n\n" - (Js_dump.string_of_expression literal_case); - literal_case) + (* Printf.eprintf "LLL literal_case: %s\n\n" + (Js_dump.string_of_expression literal_case); *) + literal_case else E.is_int_tag ~has_null_undefined_other:(has_null_undefined_other sw_names) @@ -748,14 +748,21 @@ let compile output_prefix = let qblocks = use_compile_literal_cases sw_blocks ~get_tag:get_block_tag in + let eq_default d1 d2 = + match (d1, d2) with + | Default lam1, Default lam2 -> Lam.eq_approx lam1 lam2 + | Complete, Complete -> true + | NonComplete, NonComplete -> true + | _ -> false + in match (qconsts, qblocks) with - | Some consts_cases, Some blocks_cases when untagged -> - let untagged_cases = consts_cases @ blocks_cases in - let z = - compile_untagged_cases ~cxt ~switch_exp:e ~block_cases - ~default:sw_num_default untagged_cases - in - z + | Some consts_cases, Some blocks_cases + when untagged + && List.length blocks_cases >= 1 + && List.length consts_cases = 0 + && eq_default sw_num_default sw_blocks_default -> + compile_cases ~untagged ~cxt ~switch_exp:e ~block_cases + ~default:sw_blocks_default ~get_tag:get_block_tag sw_blocks | _ -> [ S.if_ is_a_literal_case @@ -785,17 +792,17 @@ let compile output_prefix = *) let v = Ext_ident.create_tmp () in let res = compile_whole {lambda_cxt with continuation = Assign v} in - Printf.eprintf "XXX res 1: %s\n\n" (Js_dump.string_of_block res); + (* Printf.eprintf "XXX res 1: %s\n\n" (Js_dump.string_of_block res); *) Js_output.make (S.declare_variable ~kind:Variable v :: res) ~value:(E.var v) | Declare (kind, id) -> let res = compile_whole {lambda_cxt with continuation = Assign id} in - Printf.eprintf "XXX res 2: %s\n\n" (Js_dump.string_of_block res); + (* Printf.eprintf "XXX res 2: %s\n\n" (Js_dump.string_of_block res); *) Js_output.make (S.declare_variable ~kind id :: res) ~value:(E.var id) | EffectCall _ | Assign _ -> let res = compile_whole lambda_cxt in - Printf.eprintf "XXX res 3: %s\n\n" (Js_dump.string_of_block res); + (* Printf.eprintf "XXX res 3: %s\n\n" (Js_dump.string_of_block res); *) Js_output.make res and compile_string_cases ~cxt ~switch_exp ~default cases : initialization = cases diff --git a/tests/tests/src/UntaggedVariants.mjs b/tests/tests/src/UntaggedVariants.mjs index 3dfee9a956..95d20f5767 100644 --- a/tests/tests/src/UntaggedVariants.mjs +++ b/tests/tests/src/UntaggedVariants.mjs @@ -376,10 +376,6 @@ let TestFunctionCase = { let someJson = '[{"name": "Haan"}, {"name": "Mr"}, false]'; function check$1(s) { - if (s === undefined || s === null || s === false || s === true) { - console.log("Nope..."); - return; - } if (Array.isArray(s)) { if (s.length !== 3) { console.log("Nope..."); @@ -388,46 +384,40 @@ function check$1(s) { let match = s[0]; if (match === true) { let match$1 = s[1]; - if (match$1 === false) { - let match$2 = s[2]; - if (match$2 === undefined || match$2 === null || match$2 === false || match$2 === true) { - console.log("Nope..."); - return; - } - if (Array.isArray(match$2)) { - if (match$2.length !== 2) { - console.log("Nope..."); - return; - } - let match$3 = match$2[0]; - if (match$3 === undefined || match$3 === null || match$3 === false || match$3 === true) { - console.log("Nope..."); - return; - } - if (match$3 === "My name is") { - let match$4 = match$2[1]; - if (match$4 === undefined || match$4 === null || match$4 === false || match$4 === true) { + if (match$1 === undefined || match$1 === null || match$1 === false || match$1 === true) { + if (match$1 === false) { + let match$2 = s[2]; + if (Array.isArray(match$2)) { + if (match$2.length !== 2) { console.log("Nope..."); return; } - if (typeof match$4 === "number") { - if (match$4 !== 10) { + let match$3 = match$2[0]; + if (typeof match$3 === "string") { + if (match$3 === "My name is") { + let match$4 = match$2[1]; + if (typeof match$4 === "number") { + if (match$4 !== 10) { + console.log("Nope..."); + } else { + console.log("yup"); + } + return; + } console.log("Nope..."); - } else { - console.log("yup"); + return; } + console.log("Nope..."); return; } console.log("Nope..."); return; - } else { - console.log("Nope..."); - return; } - } else { console.log("Nope..."); return; } + console.log("Nope..."); + return; } else { console.log("Nope..."); return; diff --git a/tests/tests/src/and_or_simplify.mjs b/tests/tests/src/and_or_simplify.mjs index 968359e1b8..dd7011f8b0 100644 --- a/tests/tests/src/and_or_simplify.mjs +++ b/tests/tests/src/and_or_simplify.mjs @@ -6,10 +6,10 @@ function check_null_eq_typeof(x) { } function check_null_neq_typeof(x) { - if (typeof x !== "boolean") { - return 4; - } else { + if (typeof x === "boolean") { return 3; + } else { + return 4; } } @@ -18,10 +18,10 @@ function check_undefined_eq_typeof(x) { } function check_undefined_neq_typeof(x) { - if (typeof x !== "boolean") { - return 4; - } else { + if (typeof x === "boolean") { return 3; + } else { + return 4; } } diff --git a/tests/tests/src/core/Core_JsonTests.mjs b/tests/tests/src/core/Core_JsonTests.mjs index 1f4ff3bfc5..a830175589 100644 --- a/tests/tests/src/core/Core_JsonTests.mjs +++ b/tests/tests/src/core/Core_JsonTests.mjs @@ -5,19 +5,17 @@ import * as Test from "./Test.mjs"; function decodeJsonTest() { let json = {"someProp":{"otherProp": null, "thirdProp": [true, false]}}; let decodedCorrectly; - if (json === null || !(typeof json === "object" && !Array.isArray(json))) { - decodedCorrectly = false; - } else { + if (typeof json === "object" && !Array.isArray(json)) { let match = json["someProp"]; - if (match !== undefined && !(match === null || !(typeof match === "object" && !Array.isArray(match)))) { + if (match !== undefined && typeof match === "object" && !Array.isArray(match)) { let match$1 = match["thirdProp"]; - if (match$1 !== undefined && !(match$1 === null || !(Array.isArray(match$1) && match$1.length === 2))) { + if (match$1 !== undefined && Array.isArray(match$1) && match$1.length === 2) { let match$2 = match$1[0]; - if (match$2 === null || !(typeof match$2 === "boolean" && match$2)) { - decodedCorrectly = false; - } else { + if (typeof match$2 === "boolean" && match$2) { let match$3 = match$1[1]; - decodedCorrectly = match$3 === null ? false : typeof match$3 === "boolean" && !match$3; + decodedCorrectly = typeof match$3 === "boolean" && !match$3; + } else { + decodedCorrectly = false; } } else { decodedCorrectly = false; @@ -25,6 +23,8 @@ function decodeJsonTest() { } else { decodedCorrectly = false; } + } else { + decodedCorrectly = false; } Test.run([ [ diff --git a/tests/tests/src/json_decorders.mjs b/tests/tests/src/json_decorders.mjs new file mode 100644 index 0000000000..cac0277cc7 --- /dev/null +++ b/tests/tests/src/json_decorders.mjs @@ -0,0 +1,59 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as $$Array from "rescript/lib/es6/Array.js"; + +function decodeUser(json) { + if (!(typeof json === "object" && !Array.isArray(json))) { + return; + } + let id = json.id; + if (typeof id !== "string") { + return; + } + let name = json.name; + if (typeof name !== "string") { + return; + } + let age = json.age; + if (typeof age !== "number") { + return; + } + let email = json.email; + let tmp; + tmp = typeof email === "string" ? email : undefined; + return { + id: id, + name: name, + age: age | 0, + email: tmp + }; +} + +function decodeGroup(json) { + if (!(typeof json === "object" && !Array.isArray(json))) { + return; + } + let id = json.id; + if (typeof id !== "string") { + return; + } + let name = json.name; + if (typeof name !== "string") { + return; + } + let users = json.users; + if (Array.isArray(users)) { + return { + id: id, + name: name, + users: $$Array.filterMap(users, decodeUser) + }; + } + +} + +export { + decodeUser, + decodeGroup, +} +/* No side effect */ diff --git a/tests/tests/src/json_decorders.res b/tests/tests/src/json_decorders.res new file mode 100644 index 0000000000..3f792eaaf0 --- /dev/null +++ b/tests/tests/src/json_decorders.res @@ -0,0 +1,45 @@ +type user = { + id: string, + name: string, + age: int, + email: option, +} + +type group = { + id: string, + name: string, + users: array, +} + +let decodeUser = json => { + switch json { + | JSON.Object(dict{ + "id": JSON.String(id), + "name": String(name), + "age": Number(age), + "email": ?email, + }) => + Some({ + id, + name, + age: age->Float.toInt, + email: switch email { + | Some(String(email)) => Some(email) + | _ => None + }, + }) + | _ => None + } +} + +let decodeGroup = json => { + switch json { + | JSON.Object(dict{"id": JSON.String(id), "name": String(name), "users": Array(users)}) => + Some({ + id, + name, + users: users->Array.filterMap(decodeUser), + }) + | _ => None + } +} diff --git a/tests/tests/src/pattern_match_json.mjs b/tests/tests/src/pattern_match_json.mjs index 378f82afeb..37b7157300 100644 --- a/tests/tests/src/pattern_match_json.mjs +++ b/tests/tests/src/pattern_match_json.mjs @@ -4,12 +4,6 @@ import * as Primitive_option from "rescript/lib/es6/Primitive_option.js"; function decodeGroup(group) { let id = group.id; - if (id == null) { - return [ - "e", - "f" - ]; - } if (typeof id !== "string") { return [ "e", @@ -17,15 +11,15 @@ function decodeGroup(group) { ]; } let name = group.name; - if (typeof name !== "string") { + if (typeof name === "string") { return [ - "e", - "f" + id, + name ]; } else { return [ - id, - name + "e", + "f" ]; } } From 9c8cee2e350e7352998a8d859c4480db9d4861ab Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Mon, 4 Nov 2024 05:36:20 +0100 Subject: [PATCH 3/4] clean up code --- compiler/core/lam_compile.ml | 59 ++++++++++++------------------------ 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/compiler/core/lam_compile.ml b/compiler/core/lam_compile.ml index f7db97d7e5..22b3ffa2b8 100644 --- a/compiler/core/lam_compile.ml +++ b/compiler/core/lam_compile.ml @@ -673,8 +673,6 @@ let compile output_prefix = also if last statement is throw -- should we drop remaining statement? *) - (* Printf.eprintf "XXX switch_arg: %s\n\n" - (Lam_print.lambda_to_string switch_arg); *) let ({ sw_consts_full; sw_consts; @@ -715,39 +713,25 @@ let compile output_prefix = block @ if sw_consts_full && sw_consts = [] then - (* let _ = Printf.eprintf "QQQ sw_consts_full\n\n" in *) compile_cases ~block_cases ~untagged ~cxt ~switch_exp:(if untagged then e else E.tag ~name:tag_name e) ~default:sw_blocks_default ~get_tag:get_block_tag sw_blocks else if sw_blocks_full && sw_blocks = [] then - (* let _ = Printf.eprintf "QQQ sw_blocks_full\n\n" in *) compile_cases ~cxt ~switch_exp:e ~block_cases ~default:sw_num_default ~get_tag:get_const_tag sw_consts else - (* let _ = Printf.eprintf "QQQ else\n\n" in *) (* [e] will be used twice *) let dispatch e = let is_a_literal_case = if untagged then - let literal_case = - E.is_a_literal_case - ~literal_cases:(get_literal_cases sw_names) - ~block_cases e - in - (* Printf.eprintf "LLL literal_case: %s\n\n" - (Js_dump.string_of_expression literal_case); *) - literal_case + E.is_a_literal_case + ~literal_cases:(get_literal_cases sw_names) + ~block_cases e else E.is_int_tag ~has_null_undefined_other:(has_null_undefined_other sw_names) e in - let qconsts = - use_compile_literal_cases sw_consts ~get_tag:get_const_tag - in - let qblocks = - use_compile_literal_cases sw_blocks ~get_tag:get_block_tag - in let eq_default d1 d2 = match (d1, d2) with | Default lam1, Default lam2 -> Lam.eq_approx lam1 lam2 @@ -755,15 +739,16 @@ let compile output_prefix = | NonComplete, NonComplete -> true | _ -> false in - match (qconsts, qblocks) with - | Some consts_cases, Some blocks_cases - when untagged - && List.length blocks_cases >= 1 - && List.length consts_cases = 0 - && eq_default sw_num_default sw_blocks_default -> - compile_cases ~untagged ~cxt ~switch_exp:e ~block_cases - ~default:sw_blocks_default ~get_tag:get_block_tag sw_blocks - | _ -> + if + untagged + && List.length sw_consts = 0 + && eq_default sw_num_default sw_blocks_default + then + compile_cases ~untagged ~cxt + ~switch_exp:(if untagged then e else E.tag ~name:tag_name e) + ~block_cases ~default:sw_blocks_default ~get_tag:get_block_tag + sw_blocks + else [ S.if_ is_a_literal_case (compile_cases ~cxt ~switch_exp:e ~block_cases @@ -781,7 +766,7 @@ let compile output_prefix = | _ -> let v = Ext_ident.create_tmp () in (* Necessary avoid duplicated computation*) - [S.define_variable ~kind:Variable v e] @ dispatch (E.var v)) + S.define_variable ~kind:Variable v e :: dispatch (E.var v)) in match lambda_cxt.continuation with (* Needs declare first *) @@ -791,19 +776,15 @@ let compile output_prefix = when branches are minimial (less than 2) *) let v = Ext_ident.create_tmp () in - let res = compile_whole {lambda_cxt with continuation = Assign v} in - (* Printf.eprintf "XXX res 1: %s\n\n" (Js_dump.string_of_block res); *) Js_output.make - (S.declare_variable ~kind:Variable v :: res) + (S.declare_variable ~kind:Variable v + :: compile_whole {lambda_cxt with continuation = Assign v}) ~value:(E.var v) | Declare (kind, id) -> - let res = compile_whole {lambda_cxt with continuation = Assign id} in - (* Printf.eprintf "XXX res 2: %s\n\n" (Js_dump.string_of_block res); *) - Js_output.make (S.declare_variable ~kind id :: res) ~value:(E.var id) - | EffectCall _ | Assign _ -> - let res = compile_whole lambda_cxt in - (* Printf.eprintf "XXX res 3: %s\n\n" (Js_dump.string_of_block res); *) - Js_output.make res + Js_output.make + (S.declare_variable ~kind id + :: compile_whole {lambda_cxt with continuation = Assign id}) + | EffectCall _ | Assign _ -> Js_output.make (compile_whole lambda_cxt) and compile_string_cases ~cxt ~switch_exp ~default cases : initialization = cases |> compile_general_cases ~make_exp:E.tag_type From 6072c175103154d7b1b7c93208a1b8eea31a45ab Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Mon, 4 Nov 2024 05:38:17 +0100 Subject: [PATCH 4/4] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30da409643..977198bd4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ - Improve negation handling in combination with and/or to simplify generated code (especially coming out of pattern matching). https://github.com/rescript-lang/rescript-compiler/pull/7138 - optimize JavaScript code generation by using x == null checks and improving type-based optimizations for string/number literals. https://github.com/rescript-lang/rescript-compiler/pull/7141 - Improve pattern matching on optional fields. https://github.com/rescript-lang/rescript-compiler/pull/7143 https://github.com/rescript-lang/rescript-compiler/pull/7144 +- Optimize compilation of switch statements for untagged variants when there are no literal cases. https://github.com/rescript-lang/rescript-compiler/pull/7135 #### :house: Internal