Skip to content

Support "match only" mode in pattern compilation#421

Open
chengluyu wants to merge 39 commits intohkust-taco:hkmc2from
chengluyu:ups/match-only
Open

Support "match only" mode in pattern compilation#421
chengluyu wants to merge 39 commits intohkust-taco:hkmc2from
chengluyu:ups/match-only

Conversation

@chengluyu
Copy link
Copy Markdown
Member

No description provided.

Copy link
Copy Markdown
Contributor

@LPTK LPTK left a comment

Choose a reason for hiding this comment

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

Ok, let's get this merged, thanks. However there is a pre-existing problem with the difference between compiled and interpreted patterns (see #422).

LPTK and others added 6 commits March 21, 2026 10:09
# Conflicts:
#	hkmc2/shared/src/test/mlscript/ups/MatchResult.mls
# Conflicts:
#	hkmc2/shared/src/test/mlscript/codegen/BlockPrinter.mls
#	hkmc2/shared/src/test/mlscript/ups/MatchResult.mls
#	hkmc2/shared/src/test/mlscript/ups/SimpleTransform.mls
#	hkmc2/shared/src/test/mlscript/ups/TransformFree.mls
pi is @compile IncFst
//│ = true

pattern Char = (Str as s where s.length is 1) => s
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Char should probably be a builtin pattern, right? Otherwise, because of the where clause, I guess it won't behave as expected within compiled string patterns with concatenation.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I placed it into Char.mls for now. When I implement the string compilation later, I will make it a built-in pattern.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm leaving this "unresolved" for reference. We'll still merge the PR.

@chengluyu chengluyu requested a review from LPTK April 3, 2026 05:56
# Conflicts:
#	hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala
#	hkmc2/shared/src/test/mlscript/ups/MatchResult.mls
Copy link
Copy Markdown
Contributor

@LPTK LPTK left a comment

Choose a reason for hiding this comment

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

Do you have any tests that shows the IR of a match-only pattern? So we can make sure it doesn't regress later.

Otherwise LGTM, thanks!

Comment on lines +24 to +26

// :sir
fun toSumPair(t) = if t is (@compile SumPair) as s then s else null
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// :sir
fun toSumPair(t) = if t is (@compile SumPair) as s then s else null
// :sir
fun toSumPair(t) = if t is (@compile SumPair) as s then s else null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why did you close this? You haven't applied the change.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends UPS pattern compilation to support a “match only” result mode, allowing compiled patterns to return booleans (and reuse the original scrutinee as the output) when no transformed output/bindings are required. This reduces generated code size and avoids constructing MatchSuccess/MatchFailure objects in common is @compile P cases, while adding/adjusting diagnostics and updating the test suite accordingly.

Changes:

  • Add ResultMode to UPS pattern compilation and propagate an outputNeeded flag through SplitCompiler to enable boolean-only matching when safe.
  • Improve constructor-pattern handling to avoid rebuilding outputs when not needed, and add warnings when extraction-argument transformation results are implicitly discarded.
  • Update/add a large set of MLscript tests and compilation examples to reflect new runtime shapes (e.g. MatchSuccess(..., null)), new warnings/errors, and new match-only behavior.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
hkmc2/shared/src/main/scala/hkmc2/semantics/ups/SplitCompiler.scala Thread outputNeeded through matching/compilation; choose match-only vs full compilation; add warnings for discarded extraction outputs; refine inaccessible-field diagnostics.
hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala Introduce ResultMode and boolean match-only matcher generation; refactor field matcher plumbing; support transform-free reuse of scrutinee outputs.
hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Pattern.scala Add MatchedClassLike specialized node and preservesOriginalScrutinee analysis; adjust specialization/printing/field collection.
hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala Make empty bindings represent as null (and standardize MatchSuccess bindings emission).
hkmc2/shared/src/main/scala/hkmc2/semantics/Split.scala When expanding SimpleSplit, call makeMatchSplit with outputNeeded = false.
hkmc2/shared/src/test/mlscript/ups/TransformFree.mls New test for compiled patterns whose output can reuse the scrutinee when transform-free.
hkmc2/shared/src/test/mlscript/ups/transformation/BindingLess.mls New tests around transformations in subpatterns and match-only behavior.
hkmc2/shared/src/test/mlscript/ups/syntax/PatternBody.mls New/updated diagnostics tests for inaccessible constructor params during rebuild.
hkmc2/shared/src/test/mlscript/ups/syntax/MixedParameters.mls New warning test for implicitly discarded extraction-argument transformations.
hkmc2/shared/src/test/mlscript/ups/specialization/SimpleLiterals.mls Add logging/side-effect tests demonstrating match-only compilation skipping transforms.
hkmc2/shared/src/test/mlscript/ups/SimpleTransform.mls Update IR expectations and add transform side-effect tests in compiled patterns.
hkmc2/shared/src/test/mlscript/ups/SimpleConjunction.mls Add conjunction test ensuring both sides’ transforms run when output is demanded.
hkmc2/shared/src/test/mlscript/ups/regex/Separation.mls Update expected MatchSuccess bindings shape ({}null).
hkmc2/shared/src/test/mlscript/ups/recursion/NatBox.mls Update lowered IR expectation for boolean match-only compilation path.
hkmc2/shared/src/test/mlscript/ups/parametric/EtaConversion.mls Update normalized output expectation for module/pattern references.
hkmc2/shared/src/test/mlscript/ups/MatchResult.mls Expand coverage around @compile usage and update expected MatchSuccess bindings.
hkmc2/shared/src/test/mlscript/ups/LocalPatterns.mls Update expected MatchSuccess bindings shape (null).
hkmc2/shared/src/test/mlscript/ups/Future.mls Update MatchSuccess expectations and line-numbered diagnostics.
hkmc2/shared/src/test/mlscript/ups/examples/Extraction.mls Add tests for biased disjunction + transforms and adjust outputs to preserve constructor tags when transform-free.
hkmc2/shared/src/test/mlscript/ups/examples/EvaluationContext2.mls Adjust evaluation-context patterns/tests to align with match-only output behavior.
hkmc2/shared/src/test/mlscript/ups/examples/DoubleOrSum.mls Update expected list output representation to preserve constructor structure.
hkmc2/shared/src/test/mlscript/ucs/patterns/where.mls Update expected MatchSuccess bindings shape (null).
hkmc2/shared/src/test/mlscript/ucs/patterns/Parameters.mls Add tests ensuring “keep scrutinee” works with private params when no rebuild is needed; refine rebuild error.
hkmc2/shared/src/test/mlscript/codegen/BlockPrinter.mls Update printed block output to reflect null bindings and simplified output.
hkmc2/shared/src/test/mlscript/basics/PrefixOps.mls Update expected MatchSuccess bindings shape (null).
hkmc2/shared/src/test/mlscript-compile/ups/TruthyFalsy.mls New compilation-size example program exercising match-only entrypoints.
hkmc2/shared/src/test/mlscript-compile/ups/README.md New documentation summarizing SLOC deltas for match-only vs full compiled patterns.
hkmc2/shared/src/test/mlscript-compile/ups/EvenOddTree.mls New compilation-size example for mutually recursive tree patterns.
hkmc2/shared/src/test/mlscript-compile/ups/EvaluationContext.mls New compilation-size example for evaluation-context patterns.
hkmc2/shared/src/test/mlscript-compile/ups/DnfCnf.mls New compilation-size example for recursive logical-formula patterns.
hkmc2/shared/src/test/mlscript-compile/Char.mls Add AnyChar pattern used by compilation examples/tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

LPTK and others added 7 commits April 3, 2026 19:08
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Comment on lines +46 to +47
:sir
// Keep the IR output to prevent regressions.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the one below is enough.

pattern ToFahrenheit =
((Celsius(c)) => Fahrenheit((c * 9 / 5) + 32)) |
((Fahrenheit as f) => f)
| ((Celsius(c)) => Fahrenheit((c * 9 / 5) + 32))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You don't need parentheses in all these examples.

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.

3 participants