Skip to content

Commit 566afff

Browse files
CAG2MarkAnsonYeung
andauthored
Miscellaneous Fixes (hkust-taco#280)
Co-authored-by: Anson Yeung <nanolify@gmail.com>
1 parent 7fbe62c commit 566afff

File tree

7 files changed

+53
-17
lines changed

7 files changed

+53
-17
lines changed

hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,14 @@ sealed abstract class Block extends Product with AutoLocated:
106106
case AssignDynField(_, _, _, rhs, rest) => rhs.subBlocks ::: rest :: Nil
107107
case Define(d, rest) => d.subBlocks ::: rest :: Nil
108108
case HandleBlock(_, _, par, args, _, handlers, body, rest) => par.subBlocks ++ args.flatMap(_.subBlocks) ++ handlers.map(_.body) :+ body :+ rest
109+
case Label(_, body, rest) => body :: rest :: Nil
109110

110111
// TODO rm Lam from values and thus the need for these cases
111112
case Return(r, _) => r.subBlocks
112113
case HandleBlockReturn(r) => r.subBlocks
113114
case Throw(r) => r.subBlocks
114115

115-
case _: Return | _: Throw | _: Label | _: Break | _: Continue | _: End | _: HandleBlockReturn => Nil
116+
case _: Return | _: Throw | _: Break | _: Continue | _: End | _: HandleBlockReturn => Nil
116117

117118
// Moves definitions in a block to the top. Only scans the top-level definitions of the block;
118119
// i.e, definitions inside other definitions are not moved out. Definitions inside `match`/`if`

hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,13 @@ class BlockTransformer(subst: SymbolSubst):
8585
(cls2 is cls) && (hdr2 is hdr) && (bod2 is bod) && (rst2 is rst)
8686
then b else HandleBlock(l2, res2, par2, args2, cls2, hdr2, bod2, rst2)
8787
case AssignDynField(lhs, fld, arrayIdx, rhs, rest) =>
88-
val lhs2 = applyPath(lhs)
89-
val fld2 = applyPath(fld)
90-
val rhs2 = applyResult(rhs)
91-
val rest2 = applyBlock(rest)
92-
if (lhs2 is lhs) && (fld2 is fld) && (rhs2 is rhs) && (rest2 is rest)
93-
then b
94-
else AssignDynField(lhs2, fld2, arrayIdx, rhs2, rest2)
88+
applyResult2(rhs): rhs2 =>
89+
val lhs2 = applyPath(lhs)
90+
val fld2 = applyPath(fld)
91+
val rest2 = applyBlock(rest)
92+
if (lhs2 is lhs) && (fld2 is fld) && (rhs2 is rhs) && (rest2 is rest)
93+
then b
94+
else AssignDynField(lhs2, fld2, arrayIdx, rhs2, rest2)
9595

9696

9797
def applyResult2(r: Result)(k: Result => Block): Block = k(applyResult(r))

hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
5959
.assignFieldN(state.res, tailIdent, state.res.tail.next)
6060
.ret(state.res))
6161
private val functionHandlerCtx = funcLikeHandlerCtx(N)
62+
private val topLevelCtx = HandlerCtx(true, true, N, _ => rtThrowMsg("Unhandled effects"))
6263
private def ctorCtx(ctorThis: Path) = funcLikeHandlerCtx(S(ctorThis))
6364
private def handlerCtx(using HandlerCtx): HandlerCtx = summon
6465
private val predefPath: Path = State.globalThisSymbol.asPath.selN(Tree.Ident("Predef"))
@@ -267,6 +268,9 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
267268
case blk @ AssignField(lhs, nme, rhs, rest) =>
268269
val PartRet(head, parts) = go(rest)
269270
PartRet(AssignField(lhs, nme, rhs, head)(blk.symbol), parts)
271+
case AssignDynField(lhs, fld, arrayIdx, rhs, rest) =>
272+
val PartRet(head, parts) = go(rest)
273+
PartRet(AssignDynField(lhs, fld, arrayIdx, rhs, head), parts)
270274
case Return(_, _) => PartRet(blk, Nil)
271275
// ignored cases
272276
case TryBlock(sub, finallyDo, rest) => ??? // ignore
@@ -336,7 +340,7 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
336340
override def applyLam(lam: Value.Lam): Value.Lam = Value.Lam(lam.params, translateBlock(lam.body, functionHandlerCtx))
337341
override def applyDefn(defn: Defn): Defn = defn match
338342
case f: FunDefn => translateFun(f)
339-
case c: ClsLikeDefn => translateCls(c)
343+
case c: ClsLikeDefn => translateCls(c, handlerCtx.isTopLevel)
340344
case _: ValDefn => super.applyDefn(defn)
341345
transformer.applyBlock(b)
342346

@@ -356,9 +360,11 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
356360
private def translateFun(f: FunDefn): FunDefn =
357361
FunDefn(f.owner, f.sym, f.params, translateBlock(f.body, functionHandlerCtx))
358362

359-
private def translateCls(cls: ClsLikeDefn): ClsLikeDefn =
363+
private def translateCls(cls: ClsLikeDefn, isTopLevel: Bool): ClsLikeDefn =
364+
val curCtorCtx = if isTopLevel && (cls.k is syntax.Mod) then topLevelCtx else
365+
ctorCtx(cls.sym.asClsLike.getOrElse(wat("asClsLike", cls.sym)).asPath)
360366
cls.copy(methods = cls.methods.map(translateFun),
361-
ctor = translateBlock(cls.ctor, ctorCtx(cls.sym.asClsLike.getOrElse(wat("asClsLike", cls.sym)).asPath)))
367+
ctor = translateBlock(cls.ctor, curCtorCtx))
362368

363369
// Handle block becomes a FunDefn and CallPlaceholder
364370
private def translateHandleBlock(h: HandleBlock): Block =
@@ -548,5 +554,5 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
548554
transform.applyBlock(b)
549555

550556
def translateTopLevel(b: Block): Block =
551-
translateBlock(b, HandlerCtx(true, true, N, _ => rtThrowMsg("Unhandled effects")))
557+
translateBlock(b, topLevelCtx)
552558

hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class StackSafeTransform(depthLimit: Int)(using State):
9898
override def applyFunDefn(fun: FunDefn): FunDefn = rewriteFn(fun)
9999

100100
override def applyDefn(defn: Defn): Defn = defn match
101-
case defn: ClsLikeDefn => rewriteCls(defn)
101+
case defn: ClsLikeDefn => rewriteCls(defn, isTopLevel)
102102
case _: FunDefn | _: ValDefn => super.applyDefn(defn)
103103

104104
override def applyBlock(b: Block): Block = b match
@@ -143,12 +143,13 @@ class StackSafeTransform(depthLimit: Int)(using State):
143143
walker.applyBlock(b)
144144
trivial
145145

146-
def rewriteCls(defn: ClsLikeDefn): ClsLikeDefn =
146+
def rewriteCls(defn: ClsLikeDefn, isTopLevel: Bool): ClsLikeDefn =
147147
val ClsLikeDefn(owner, isym, sym, k, paramsOpt,
148148
parentPath, methods, privateFields, publicFields, preCtor, ctor) = defn
149149
ClsLikeDefn(
150150
owner, isym, sym, k, paramsOpt, parentPath, methods.map(rewriteFn), privateFields,
151-
publicFields, rewriteBlk(preCtor), rewriteBlk(ctor)
151+
publicFields, rewriteBlk(preCtor),
152+
if isTopLevel && (defn.k is syntax.Mod) then transformTopLevel(ctor) else rewriteBlk(ctor)
152153
)
153154

154155
def rewriteBlk(blk: Block) =

hkmc2/shared/src/test/mlscript/codegen/While.mls

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,19 +239,23 @@ f(Cons(1, Cons(2, Cons(3, 0))))
239239
//│ > Cons(3, 0)
240240
//│ > 0
241241

242+
while false do
243+
class A
244+
new A
245+
242246

243247
// ——— FIXME: ———
244248

245249

246250
() => while true then 0
247-
//│ = [function block$res26]
251+
//│ = [function block$res27]
248252

249253
:fixme
250254
while print("Hello World"); false
251255
then 0(0)
252256
else 1
253257
//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here
254-
//│ ║ l.251: then 0(0)
258+
//│ ║ l.255: then 0(0)
255259
//│ ╙── ^^^^
256260
//│ ═══[ERROR] Unrecognized term split (false literal).
257261
//│ > Hello World

hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,17 @@ let oops =
127127
oops.h
128128
//│ = Handler$h$
129129

130+
let obj = {}
130131

132+
handle h = Effect with
133+
fun perform(arg)(k) =
134+
k()
135+
print(arg)
136+
set obj.["s"] = h.perform("k")
137+
//│ > k
138+
139+
fun f() = ()
140+
141+
module A with
142+
f()
143+
() // defeats tail call optimization

hkmc2/shared/src/test/mlscript/handlers/StackSafety.mls

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,17 @@ in
424424
foo(h)
425425
//│ = 50005000
426426

427+
:effectHandlers
428+
:stackSafe 100
429+
:expect 50005000
430+
module A with
431+
val f = n =>
432+
if n <= 0 then 0
433+
else n + f(n-1)
434+
val x = f(10000)
435+
A.x
436+
//│ = 50005000
437+
427438
:re
428439
:effectHandlers
429440
fun foo(h) = h.perform(2)

0 commit comments

Comments
 (0)