Skip to content

Make Lambda-to-Lam conversion structural - #8604

Merged
cristianoc merged 13 commits into
masterfrom
lam-convert-cleanup
Aug 31, 2026
Merged

Make Lambda-to-Lam conversion structural#8604
cristianoc merged 13 commits into
masterfrom
lam-convert-cleanup

Conversation

@cristianoc

Copy link
Copy Markdown
Collaborator

Summary

  • make Lambda-to-Lam conversion structural for lets, switches, static exits, recursive binding groups, exception packing, and eliminated identity operations
  • move alias collapsing and recursive-group analysis to their owning IR stages, removing obsolete conversion state and Lam_scc
  • remove dead Lambda/Lam primitives and align scalar constant representations, including storing parsed string delimiters directly on Lambda constants

This PR is based on #8598 so the refreshed compiler documentation describes the contracts used by this cleanup. It is intentionally not registered as a GitHub stack.

Generated output audit

Every generated JavaScript change was reviewed:

  • recursive binding snapshots reflect intentional SCC grouping, declaration ordering, and direct aliases exposed by earlier normalization
  • exception snapshots call the same internalToException implementation through the normal runtime binding after removal of Pwrap_exn
  • untagged-variant snapshots cover intentional sharing of equivalent string-valued match actions and preserve the separate discriminator merge boundary
  • the Const_string delimiter change itself produces no generated JavaScript changes

Tests

  • make test
  • focused OUnit coverage for every processed string delimiter encoding

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9762eed607

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread compiler/frontend/lam_constant.ml
@cristianoc
cristianoc requested a review from cknitt August 31, 2026 12:33
Base automatically changed from docs/compiler-documentation to master August 31, 2026 13:50
Pattern matching introduces Alias lets as O(1) renames of a pattern
ident onto the scrutinee. Convert used to substitute those while
translating; do the same rewrite as a Lam pass immediately after
conversion instead, so convert stays a translation. Exported aliases
are kept for coercion. Later lets_dce is unchanged.

JS from runtime, Belt, tests/tests, belt_tests, and commonjs_tests
matched the convert-time pass (1079 files).

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
The Lam primitive was compiled to f.apply(null, args) but never
constructed. Drop it together with the JS IR constructor and the
stale Lifused/translclass comments left in convert.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
%revapply/%apply were leftover |>/@@ encodings; ReScript -> is rewritten
before typing. __LOC__ and friends still compile, but as constants in
translcore rather than a Lambda primitive.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Pack JS catch values in translcore so convert only translates Ltrywith.
Drop raise_kind/reraise tracking (JS throw is one operation) and emit
RE_EXN_ID string equality from matching instead of Pextension_slot_eq.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Exception packing, Promise.catch, and JsExn.anyToExnInternal now apply
Primitive_exceptions.internalToException instead of a dedicated primitive.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Emit nested let/letrec from transl_let and eval_rec_bindings via
Lambda_scc.bind_rec. Convert Lletrec is identity. JS compile only
sorts functions before values for dummy/updateDummy init.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Remove the dense int-switch-to-add peephole and the switcher-offset
let rewrite. Rewrite the one test that relied on the former to an
or-pattern plus add.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Drop exit_map and the catch-of-raise peephole. Matching still emits
catch body with (i) (exit j); Lam_pass_exits inlines the size-1 handler.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Lambda.mk_prim expands Peliminated so those payloads never appear as
Lprim nodes. Convert maps the constructor 1-1. Lam matches assert
false because the node cannot occur.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Replace Lambda Const_base and Const_immstring with direct int, char, string, float, and bigint constructors, and use int32-backed Const_int consistently in Lambda and Lam. Represent Lam assert-false separately from ordinary integer zero.

Remove the unreachable typedtree Const_int32 and Const_int64 variants and bump the CMT magic number for the serialized type change. Treat ReScript strings as immutable when normalizing match actions, with snapshots covering early string-action sharing and the separate untagged-discriminator merge boundary.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Give Lambda Const_string the same structured payload used by Lam, and move processed-delimiter decoding into External_arg_spec so Lambda producers can store the final delimiter directly.

Remove the inline-constant delimiter round-trip, cover every processed delimiter encoding, and consolidate the branch changelog into review-facing entries.

Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
@cristianoc
cristianoc force-pushed the lam-convert-cleanup branch from 9762eed to 262cd0b Compare August 31, 2026 13:50
@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.01156% with 83 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.44%. Comparing base (055e9e0) to head (262cd0b).

Files with missing lines Patch % Lines
compiler/ml/translcore.ml 76.63% 25 Missing ⚠️
compiler/ml/lambda_scc.ml 85.24% 9 Missing ⚠️
compiler/ml/printlambda.ml 0.00% 9 Missing ⚠️
compiler/core/lam_analysis.ml 44.44% 5 Missing ⚠️
compiler/core/lam.ml 50.00% 4 Missing ⚠️
compiler/core/lam_eta_conversion.ml 0.00% 4 Missing ⚠️
compiler/core/lam_primitive.ml 0.00% 4 Missing ⚠️
compiler/frontend/lam_constant.ml 20.00% 4 Missing ⚠️
compiler/core/lam_pass_lets_dce.ml 0.00% 3 Missing ⚠️
compiler/ml/matching.ml 76.92% 3 Missing ⚠️
... and 9 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8604      +/-   ##
==========================================
+ Coverage   76.33%   76.44%   +0.11%     
==========================================
  Files         476      478       +2     
  Lines       63253    63163      -90     
==========================================
+ Hits        48284    48286       +2     
+ Misses      14969    14877      -92     
Files with missing lines Coverage Δ
analysis/src/hint.ml 74.66% <ø> (+1.93%) ⬆️
analysis/src/hover.ml 77.12% <ø> (+0.99%) ⬆️
compiler/core/j.ml 100.00% <ø> (ø)
compiler/core/js_dump_lit.ml 100.00% <ø> (ø)
compiler/core/js_exp_make.ml 64.48% <ø> (+0.08%) ⬆️
compiler/core/js_record_fold.ml 88.67% <ø> (+1.64%) ⬆️
compiler/core/js_record_iter.ml 95.41% <ø> (+1.71%) ⬆️
compiler/core/js_record_map.ml 95.67% <ø> (+1.73%) ⬆️
compiler/core/lam_compile_main.ml 89.17% <100.00%> (-1.70%) ⬇️
compiler/core/lam_compile_primitive.ml 77.37% <ø> (+0.42%) ⬆️
... and 32 more

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pkg-pr-new

pkg-pr-new Bot commented Aug 31, 2026

Copy link
Copy Markdown

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript-lang/rescript@8604

@rescript/belt

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/belt@8604

@rescript/darwin-arm64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/darwin-arm64@8604

@rescript/darwin-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/darwin-x64@8604

@rescript/linux-arm64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/linux-arm64@8604

@rescript/linux-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/linux-x64@8604

@rescript/runtime

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/runtime@8604

@rescript/win32-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/win32-x64@8604

commit: 262cd0b

*)

(* Semantic SCC already ran in [Lambda_scc.bind_rec]. JS still wants
functions before values so dummy / updateDummy init is well-ordered. *)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is dummy / updateDummy init?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it refers to the code below -- can clean up the comment

@github-actions

Copy link
Copy Markdown

@cknitt cknitt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a large project, I got three output changes. Two were improvements (unnecessary local vars removed/inlined).

One regarding two branches in a switch statement with identical body was a bit unexpected (introducing an exit variable that was not needed before), but I think that particular case can be investigated separately later.

@cristianoc
cristianoc merged commit 59372ec into master Aug 31, 2026
29 checks passed
@cristianoc
cristianoc deleted the lam-convert-cleanup branch August 31, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants