Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
5be4823
Sketch the `NewDesugarer`
chengluyu Aug 15, 2025
f8d040d
Prevent duplicate terms using `Label` in normalization
chengluyu Sep 3, 2025
0f9be9d
Merge branch 'origin/hkmc2'
chengluyu Sep 5, 2025
18b9b7f
Fix that `NewDesugarer` cannot handle `let` bindings
chengluyu Sep 5, 2025
5a27c9e
Check if errors from new and old desugarers are consistent
chengluyu Sep 5, 2025
0c15ac2
Fix spacing after `while` and line break before `break`
chengluyu Sep 16, 2025
a079bd9
Desugar splits using `NaiveCompiler` and fix numerous issues
chengluyu Sep 16, 2025
8d77887
Deprecate `Desugarer` and fix related issues
chengluyu Sep 16, 2025
1b8617b
Add the test from today's stand-up meeting
chengluyu Sep 17, 2025
defdc53
Deduplicate throw blocks that raise match errors
chengluyu Sep 17, 2025
e661386
Improve shorthands that were not sufficiently tested
chengluyu Sep 17, 2025
24e3f73
Comment on a test which worked before
chengluyu Sep 17, 2025
ff24d0b
Separate symbols in patterns and terms to fix `where` clauses
chengluyu Sep 18, 2025
0030549
Find dead splits after else & treat `_` as else only in splits
chengluyu Sep 20, 2025
0fb7066
Document a possible future work
chengluyu Sep 20, 2025
3ca6d55
Avoid generating unnecessary`break` in the outermost `Label`
chengluyu Sep 20, 2025
b80d4bc
Add locations to the keyword of `InfixApp`
chengluyu Sep 22, 2025
28336d7
Document the reason why we need two sets of symbols
chengluyu Sep 22, 2025
63e521d
Merge branch 'hkmc2'
chengluyu Sep 22, 2025
c58b4fd
Support annotation in the desugarer
chengluyu Sep 22, 2025
69ceb31
Remove the uses of keyword escape
chengluyu Sep 22, 2025
55da3fe
Revert the treatment of `_` in splits
chengluyu Sep 22, 2025
012da18
Revise several test files
chengluyu Sep 24, 2025
fa35be0
Remove a temporary test command
chengluyu Sep 24, 2025
719570c
Revise several comments
chengluyu Sep 24, 2025
eb6babd
Use names instead of underscores in several patterns.
chengluyu Sep 24, 2025
bfd7dc7
Move `isInvalidStringBounds`
chengluyu Sep 24, 2025
ed97e31
Partially implement `mkClone` for `SynthIf`
chengluyu Sep 24, 2025
dce1cd3
Deduplicate `SpreadKind`'s `toString` methods
chengluyu Sep 24, 2025
f57588f
Minor code cleanup
chengluyu Sep 24, 2025
ccc115b
Remove a useless file
chengluyu Sep 24, 2025
22b79b1
Fix the location of wildcard patterns
chengluyu Sep 24, 2025
dacd443
Fix inconsistent empty record patterns in shorthands
chengluyu Sep 24, 2025
659db36
Correct the typo in a file name
chengluyu Sep 24, 2025
8970563
Attach location information to error splits
chengluyu Sep 25, 2025
00466f2
Attach locations to error annotations
chengluyu Sep 25, 2025
992b36b
Revert commented code in split pretty printing
chengluyu Sep 25, 2025
7a530a0
Add tests for string patterns and `@compile` in UCS
chengluyu Sep 25, 2025
4e25640
Merge branch 'origin/hkmc2'
chengluyu Sep 27, 2025
8e0fd16
Validate arguments when expanding splits
chengluyu Sep 27, 2025
7696956
Further separate the duties of `SplitCompiler` and `Normalization`
chengluyu Oct 1, 2025
cc8a9be
Continue decluttering `FlatPattern`
chengluyu Oct 1, 2025
bdf27c0
Continue decluttering `Normalization`
chengluyu Oct 2, 2025
8ce2d07
No need to clone `Pattern` anymore
chengluyu Oct 2, 2025
d60fd0b
Fix the output of string patterns
chengluyu Oct 2, 2025
7e97a94
Add tests for cross compilation of patterns
chengluyu Oct 2, 2025
a4e9acd
Add tests for wrongly applied pattern arguments
chengluyu Oct 2, 2025
9af8eaf
Amend test changes
chengluyu Oct 2, 2025
bbee7c0
Fix that the same error messages were raised twice
chengluyu Oct 2, 2025
1f9d671
Amend test changes
chengluyu Oct 3, 2025
d6f27b9
Merge `SplitCompiler` and `NaiveCompiler` and deduplicate
chengluyu Oct 3, 2025
9f29e6b
Bring back a newline
chengluyu Oct 3, 2025
b6cad7c
Merge branch 'origin/hkmc2'
chengluyu Oct 3, 2025
a58ca96
Merge branch 'origin/hkmc2'
chengluyu Oct 21, 2025
09316dd
Keep `name` field in the lockfile stable
chengluyu Oct 21, 2025
2ca4acc
Use precise locations when reporting mixed use of `do` and `then`
chengluyu Oct 21, 2025
d5d89fa
Merge branch 'origin/hkmc2'
chengluyu Oct 27, 2025
54ce910
Represent call-by-value evaluation contexts using patterns
chengluyu Oct 28, 2025
739f4ea
Mark a problem of inconsistent origins
chengluyu Oct 28, 2025
dfead57
Add the Hindley Milner example
chengluyu Oct 31, 2025
25fca5f
Implement Hindley Milner unification using patterns
chengluyu Oct 31, 2025
a139ef7
Clean up TODOs
chengluyu Nov 2, 2025
6e53e92
A change during the standup meeting
chengluyu Nov 3, 2025
687b3b2
Document mixed parameters
chengluyu Nov 3, 2025
56289ea
Implement call-by-name evaluation context using patterns
chengluyu Nov 3, 2025
83906b4
Merge branch 'origin/hkmc2'
chengluyu Nov 5, 2025
bcf7ae8
Add a few tests
LPTK Nov 6, 2025
f49721a
Update a comment
chengluyu Nov 7, 2025
4074ce0
Merge branch 'luyu/refactoring-desugarer'
chengluyu Nov 7, 2025
0182701
Fix parentheses in a test
chengluyu Nov 7, 2025
17a201c
Document a precedence problem
chengluyu Nov 7, 2025
571f84e
Use `MutMap`
chengluyu Nov 7, 2025
274b5f9
Add changes missing in the previous commit
chengluyu Nov 7, 2025
29d221d
Update a comment
chengluyu Nov 7, 2025
ca8a1e7
Add tests & fix a couple of things
LPTK Nov 7, 2025
cab0586
Update a comment
chengluyu Nov 7, 2025
e94246e
Update a comment
chengluyu Nov 7, 2025
3af4454
Update a comment
chengluyu Nov 7, 2025
2dde445
Fix a few minor issues
chengluyu Nov 7, 2025
3e58e5f
Update a comment.
chengluyu Nov 7, 2025
8f8f656
Update a comment
chengluyu Nov 7, 2025
62a116c
Polish a warning
chengluyu Nov 7, 2025
ed8744a
Remove an overload
chengluyu Nov 7, 2025
64dad63
Rename `MatchResult` to `MatchSuccess`
chengluyu Nov 7, 2025
679d8b0
Add a comment for class `SimpleSplit`
chengluyu Nov 7, 2025
8f51cd1
Add a test
chengluyu Nov 7, 2025
20ff59c
Remove an outdated comment an unused method
chengluyu Nov 7, 2025
caabab8
Properly document a test
chengluyu Nov 7, 2025
5ae5df4
Merge branch 'hkmc2' into refactoring-desugarer
LPTK Nov 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hkmc2/shared/src/main/scala/hkmc2/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ case class Config(
sanityChecks: Opt[SanityChecks],
effectHandlers: Opt[EffectHandlers],
liftDefns: Opt[LiftDefns],
useNewDesugaring: Bool,
):

def stackSafety: Opt[StackSafety] = effectHandlers.flatMap(_.stackSafety)
Expand All @@ -28,6 +29,7 @@ object Config:
// sanityChecks = S(SanityChecks(light = true)),
effectHandlers = N,
liftDefns = N,
useNewDesugaring = false,
)

case class SanityChecks(light: Bool)
Expand Down
13 changes: 7 additions & 6 deletions hkmc2/shared/src/main/scala/hkmc2/bbml/bbML.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package bbml

import scala.collection.mutable.{HashSet, HashMap, ListBuffer}
import scala.annotation.tailrec
import sourcecode.{FileName, Line, Name}

import mlscript.utils.*, shorthands.*
import utils.*
Expand Down Expand Up @@ -73,7 +74,7 @@ object BbCtx:
end BbCtx


class BBTyper(using elState: Elaborator.State, tl: TL):
class BBTyper(using elState: Elaborator.State, tl: TL)(using Ctx):
import tl.{trace, log}

private val infVarState = new InfVarUid.State()
Expand All @@ -100,7 +101,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
state.lowerBounds = ctx.getRegEnv :: Nil
InfVar(ctx.lvl, infVarState.nextUid, state, false)(sym, "")

private def error(msg: Ls[Message -> Opt[Loc]])(using BbCtx) =
private def error(using Line, FileName, Name, Raise)(msg: Ls[Message -> Opt[Loc]])(using BbCtx) =
raise(ErrorReport(msg))
Bot // TODO: error type?

Expand Down Expand Up @@ -258,7 +259,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
val res = freshVar(new TempSymbol(S(blk), "ctx"))(using ctx)
constrain(bodyCtx, sk | res)
(bodyTy, rhsCtx | res, rhsEff | bodyEff)
case Term.IfLike(Keyword.`if`, Split.Let(_, cond, Split.Cons(Branch(_, FlatPattern.Lit(BoolLit(true)), Split.Else(cons)), Split.Else(alts)))) =>
case Term.IfLike(Keyword.`if`, SimpleSplit.IfThenElse(cond, cons, alts)) =>
val (condTy, condCtx, condEff) = typeCode(cond)
val (consTy, consCtx, consEff) = typeCode(cons)
val (altsTy, altsCtx, altsEff) = typeCode(alts)
Expand Down Expand Up @@ -363,8 +364,8 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
given BbCtx = nextCtx
constrain(ascribe(term, skolemize(pt))._2, Bot) // * never generalize terms with effects
(pt, Bot)
case (Term.IfLike(Keyword.`if`, branches), ty) => // * propagate
typeSplit(branches, S(ty))
case (Term.IfLike(Keyword.`if`, split), ty) => // * propagate
typeSplit(split.getExpandedSplit, S(ty))
case (Term.Asc(term, ty), rhs) =>
ascribe(term, typeType(ty))
ascribe(term, rhs)
Expand Down Expand Up @@ -550,7 +551,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL):
case Term.Asc(term, ty) =>
val res = typeType(ty)(using ctx)
ascribe(term, res)
case Term.IfLike(Keyword.`if`, branches) => typeSplit(branches, N)
case Term.IfLike(Keyword.`if`, split) => typeSplit(split.getExpandedSplit, N)
case reg @ Term.Region(sym, body) =>
val sk = freshReg(sym)(using ctx)
val nestCtx = ctx.nestReg(sk)
Expand Down
22 changes: 11 additions & 11 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ sealed abstract class Block extends Product with AutoLocated:
case Match(scrut, arms, dflt, rest) => scrut :: arms.map(_._2) ++ dflt.toList :+ rest
case Return(res, implct) => res :: Nil
case Throw(exc) => exc :: Nil
case Label(label, body, rest) => body :: rest :: Nil
case Label(label, _, body, rest) => body :: rest :: Nil
case Break(label) => Nil
case Continue(label) => Nil
case Begin(sub, rest) => sub :: rest :: Nil
Expand Down Expand Up @@ -77,7 +77,7 @@ sealed abstract class Block extends Product with AutoLocated:
// Note that the handler's LHS and body are not part of the current block, so we do not consider them here.
case HandleBlock(lhs, res, par, args, cls, hdr, bod, rst) => rst.definedVars + res
case TryBlock(sub, fin, rst) => sub.definedVars ++ fin.definedVars ++ rst.definedVars
case Label(lbl, bod, rst) => bod.definedVars ++ rst.definedVars
case Label(lbl, _, bod, rst) => bod.definedVars ++ rst.definedVars

lazy val size: Int = this match
case _: Return | _: Throw | _: End | _: Break | _: Continue => 1
Expand All @@ -89,7 +89,7 @@ sealed abstract class Block extends Product with AutoLocated:
1 + arms.map(_._2.size).sum + dflt.map(_.size).getOrElse(0) + rst.size
case Define(_, rst) => 1 + rst.size
case TryBlock(sub, fin, rst) => 1 + sub.size + fin.size + rst.size
case Label(_, bod, rst) => 1 + bod.size + rst.size
case Label(_, _, bod, rst) => 1 + bod.size + rst.size
case HandleBlock(lhs, res, par, args, cls, handlers, bdy, rst) => 1 + handlers.map(_.body.size).sum + bdy.size + rst.size

// TODO conserve if no changes
Expand All @@ -104,7 +104,7 @@ sealed abstract class Block extends Product with AutoLocated:
Match(scrut, arms.map(_ -> _.mapTail(f)), dflt.map(_.mapTail(f)), rst)
case Match(scrut, arms, dflt, rst) =>
Match(scrut, arms, dflt, rst.mapTail(f))
case Label(label, body, rest) => Label(label, body, rest.mapTail(f))
case Label(label, loop, body, rest) => Label(label, loop, body.mapTail(f), rest.mapTail(f))
case af @ AssignField(lhs, nme, rhs, rest) =>
AssignField(lhs, nme, rhs, rest.mapTail(f))(af.symbol)
case adf @ AssignDynField(lhs, fld, arrayIdx, rhs, rest) =>
Expand All @@ -119,7 +119,7 @@ sealed abstract class Block extends Product with AutoLocated:
(pat, arm) => arm.freeVars -- pat.freeVars
case Return(res, implct) => res.freeVars
case Throw(exc) => exc.freeVars
case Label(label, body, rest) => (body.freeVars - label) ++ rest.freeVars
case Label(label, _, body, rest) => (body.freeVars - label) ++ rest.freeVars
case Break(label) => Set(label)
case Continue(label) => Set(label)
case Begin(sub, rest) => sub.freeVars ++ rest.freeVars
Expand All @@ -139,7 +139,7 @@ sealed abstract class Block extends Product with AutoLocated:
(pat, arm) => arm.freeVarsLLIR -- pat.freeVarsLLIR
case Return(res, implct) => res.freeVarsLLIR
case Throw(exc) => exc.freeVarsLLIR
case Label(label, body, rest) => (body.freeVarsLLIR - label) ++ rest.freeVarsLLIR
case Label(label, _, body, rest) => (body.freeVarsLLIR - label) ++ rest.freeVarsLLIR
case Break(label) => Set.empty
case Continue(label) => Set.empty
case Begin(sub, rest) => sub.freeVarsLLIR ++ rest.freeVarsLLIR
Expand All @@ -161,7 +161,7 @@ sealed abstract class Block extends Product with AutoLocated:
case AssignDynField(_, _, _, rhs, rest) => rhs.subBlocks ::: rest :: Nil
case Define(d, rest) => d.subBlocks ::: rest :: Nil
case HandleBlock(_, _, par, args, _, handlers, body, rest) => par.subBlocks ++ args.flatMap(_.subBlocks) ++ handlers.map(_.body) :+ body :+ rest
case Label(_, body, rest) => body :: rest :: Nil
case Label(_, _, body, rest) => body :: rest :: Nil

// TODO rm Lam from values and thus the need for these cases
case Return(r, _) => r.subBlocks
Expand Down Expand Up @@ -206,12 +206,12 @@ sealed abstract class Block extends Product with AutoLocated:
then this
else Match(scrut, newArms, newDflt, newRest)

case Label(label, body, rest) =>
case Label(label, loop, body, rest) =>
val newBody = body.flattened
val newRest = rest.flatten(k)
if (newBody is body) && (newRest is rest)
then this
else Label(label, newBody, newRest)
else Label(label, loop, newBody, newRest)

case Begin(sub, rest) =>
sub.flatten(_ => rest.flatten(k))
Expand Down Expand Up @@ -296,7 +296,7 @@ case class Return(res: Result, implct: Bool) extends BlockTail

case class Throw(exc: Result) extends BlockTail

case class Label(label: Local, body: Block, rest: Block) extends Block
case class Label(label: Local, loop: Bool, body: Block, rest: Block) extends Block

case class Break(label: Local) extends BlockTail
case class Continue(label: Local) extends BlockTail
Expand Down Expand Up @@ -616,7 +616,7 @@ extension (k: Block => Block)
def end = k.rest(End())
def ifthen(scrut: Path, cse: Case, trm: Block, els: Opt[Block] = N): Block => Block =
k.chain(Match(scrut, cse -> trm :: Nil, els, _))
def label(label: Local, body: Block) = k.chain(Label(label, body, _))
def label(label: Local, loop: Bool, body: Block) = k.chain(Label(label, loop, body, _))
def ret(r: Result) = k.rest(Return(r, false))
def staticif(b: Boolean, f: (Block => Block) => (Block => Block)) = if b then k.transform(f) else k
def foldLeft[A](xs: Iterable[A])(f: (Block => Block, A) => Block => Block) = xs.foldLeft(k)(f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ class BlockTransformer(subst: SymbolSubst):
(arms2 is arms) &&
(dflt2 is dflt) && (rst2 is rst)
then b else Match(scrut2, arms2, dflt2, rst2)
case Label(lbl, bod, rst) =>
case Label(lbl, loop, bod, rst) =>
val lbl2 = applyLocal(lbl)
val bod2 = applySubBlock(bod)
val rst2 = applySubBlock(rst)
if (lbl2 is lbl) && (bod2 is bod) && (rst2 is rst) then b else Label(lbl2, bod2, rst2)
if (lbl2 is lbl) && (bod2 is bod) && (rst2 is rst) then b else Label(lbl2, loop, bod2, rst2)
case Begin(sub, rst) =>
val sub2 = applySubBlock(sub)
val rst2 = applySubBlock(rst)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class BlockTraverser:
applyCase(arm._1); applySubBlock(arm._2)
dflt.foreach(applySubBlock)
applySubBlock(rst)
case Label(lbl, bod, rst) => applyLocal(lbl); applySubBlock(bod); applySubBlock(rst)
case Label(lbl, _, bod, rst) => applyLocal(lbl); applySubBlock(bod); applySubBlock(rst)
case Begin(sub, rst) => applySubBlock(sub); applySubBlock(rst)
case TryBlock(sub, fin, rst) => applySubBlock(sub); applySubBlock(fin); applySubBlock(rst)
case Assign(l, r, rst) => applyLocal(l); applyResult(r); applySubBlock(rst)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise,
Match(scrut, newArms, dfltParts.map(_.head), StateTransition(restId)),
BlockState(restId, restParts.head, N) :: states
)
case l @ Label(label, body, rest) =>
case l @ Label(label, _, body, rest) =>
val startId = freshId() // start of body

val PartRet(restNew, restParts) = go(rest)
Expand Down Expand Up @@ -578,7 +578,7 @@ class HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise,
End()
)

val lbl = blockBuilder.label(loopLbl, mainMatchBlk).rest(End())
val lbl = blockBuilder.label(loopLbl, loop = true, mainMatchBlk).rest(End())

val resumedVal = VarSymbol(Tree.Ident("value$"))

Expand Down
Loading