Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack safe recursion #259

Merged
merged 130 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
9e2c4cd
Changes IR
AnsonYeung Dec 8, 2024
e7813a9
initial changes
CAG2Mark Dec 10, 2024
4444d4e
Update elaborator
CAG2Mark Dec 10, 2024
4f26189
update lowering
CAG2Mark Dec 10, 2024
942922d
fix whitespace
CAG2Mark Dec 10, 2024
827c5e7
refactor some code
CAG2Mark Dec 10, 2024
eef7131
Simplify test cases
AnsonYeung Dec 12, 2024
5b26719
Hide handlers behind a flag
AnsonYeung Dec 12, 2024
421b640
Implement transformation for non-resumptive effects
AnsonYeung Dec 16, 2024
76695ba
Continuation class transformation
AnsonYeung Dec 16, 2024
2263ddf
Port tests to new branch
AnsonYeung Dec 16, 2024
bdbee0a
Resume non tail resumptive handlers
AnsonYeung Dec 16, 2024
e9bab2b
Implement final pieces for nested handlers
AnsonYeung Dec 17, 2024
4bb2d73
Implement Match codegen for multiple arms
AnsonYeung Dec 17, 2024
7395b4c
Moved most wiring code to Predef
AnsonYeung Dec 17, 2024
5ef77f2
Changes to IR
AnsonYeung Dec 19, 2024
018dedd
Changes IR
AnsonYeung Dec 19, 2024
dac193e
Patch for JSBuilder
AnsonYeung Dec 19, 2024
68be072
Fix link error
AnsonYeung Dec 19, 2024
ab69c37
Merge branch 'hkmc2' into ir-handler
AnsonYeung Dec 19, 2024
6a71972
Changes to handler syntax
AnsonYeung Dec 19, 2024
ea621a9
Add class inheritance in IR
AnsonYeung Dec 20, 2024
d07371e
Add class inheritance in IR and fixed spacing
AnsonYeung Dec 20, 2024
6b74a07
Merge branch 'hkmc2' into ir-handler
AnsonYeung Dec 20, 2024
be15486
Remove unnecessary newline in JS Codegen
AnsonYeung Dec 20, 2024
db5aa6d
Random typo fix
AnsonYeung Dec 20, 2024
2b67aba
Merge branch 'ir-handler' into ir-handler-transform
AnsonYeung Dec 20, 2024
ef1eabc
Small fix
AnsonYeung Dec 20, 2024
61d2a27
Add mildly interesting test
LPTK Dec 21, 2024
564f020
Add more test cases and reveal some issues
LPTK Dec 21, 2024
9bc81df
Merge branch 'hkmc2' into ir-handler-transform
AnsonYeung Dec 21, 2024
4905f8a
Use subclass for effect and separate internal class
AnsonYeung Dec 24, 2024
c66c73d
Change how elaboration of handlers work
AnsonYeung Dec 24, 2024
f876483
add test
CAG2Mark Dec 24, 2024
879eece
Fixed one example
AnsonYeung Dec 25, 2024
f4e728e
add minimal example of effects in handler bug
CAG2Mark Dec 25, 2024
643ec6f
Fixed another test
AnsonYeung Dec 25, 2024
dc516cd
Fix missing thisProxy
AnsonYeung Dec 25, 2024
e6cd1ec
Fix generator
AnsonYeung Dec 25, 2024
8a6d15c
Fix typo
AnsonYeung Dec 25, 2024
2e07058
Fix function calls and clases sometimes not being in scope after tran…
CAG2Mark Dec 27, 2024
6339e8b
Update hkmc2/shared/src/test/mlscript/handlers/RecursiveHandlers.mls
CAG2Mark Dec 27, 2024
a2900ec
Update hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala
CAG2Mark Dec 27, 2024
7596cf3
set up infrastructure
CAG2Mark Dec 31, 2024
4b837eb
Changed and added broken test
AnsonYeung Jan 6, 2025
0864f27
Update tests
AnsonYeung Jan 6, 2025
e6a819b
Minor style changes (? debatable improvement)
LPTK Jan 6, 2025
af17307
Fix elaboration scoping
AnsonYeung Jan 7, 2025
08a4d4c
Merge branch 'hkmc2' into ir-handler-transform
AnsonYeung Jan 7, 2025
2da74c0
Fixed some bugs
AnsonYeung Jan 7, 2025
80e9fba
Fix consistency
AnsonYeung Jan 7, 2025
964c146
Fixed comments
AnsonYeung Jan 7, 2025
6722e1a
initial
CAG2Mark Jan 7, 2025
edee182
Merge branch 'ir-handler-transform' into stack-safety
CAG2Mark Jan 7, 2025
b8c6120
move helper function outside
CAG2Mark Jan 7, 2025
9dfc35d
Merge branch 'ir-handler-transform' into stack-safety
CAG2Mark Jan 7, 2025
cb68929
initial stack safety working
CAG2Mark Jan 7, 2025
eb71e32
fix return leaked
CAG2Mark Jan 7, 2025
fe076e3
remove fixme
CAG2Mark Jan 7, 2025
67617c1
update test
CAG2Mark Jan 7, 2025
2393ea5
Remove usage of dummy class symbol
AnsonYeung Jan 8, 2025
810a639
Remove some unused code
AnsonYeung Jan 10, 2025
74fb276
Merge branch 'hkmc2' into ir-handler-transform
AnsonYeung Jan 10, 2025
b04031a
revert parser workaround
AnsonYeung Jan 10, 2025
e8113c7
predef clean up
AnsonYeung Jan 10, 2025
78f6f54
Simplify Predef
AnsonYeung Jan 10, 2025
d3fedd2
Rewriting most of Predef for clean up
AnsonYeung Jan 10, 2025
b30d8ca
Change test case to todo
AnsonYeung Jan 10, 2025
c9057ea
remove unused code
AnsonYeung Jan 11, 2025
4b73be5
Merge branch 'hkmc2' into ir-handler-transform
AnsonYeung Jan 13, 2025
235a6ec
Added codegen examples
AnsonYeung Jan 13, 2025
ed895eb
use SymbolSubst
CAG2Mark Jan 13, 2025
be37739
Update tests
CAG2Mark Jan 13, 2025
b8d0da8
fix whitespace
CAG2Mark Jan 13, 2025
7da8101
Fix symbol map issues
CAG2Mark Jan 13, 2025
41105c1
Merge upstream
CAG2Mark Jan 13, 2025
21843b4
Fix overriding hack
LPTK Jan 14, 2025
862bd6a
Address PR comments
CAG2Mark Jan 14, 2025
ac70aea
Address PR comments
CAG2Mark Jan 14, 2025
051bc09
Fix inaccurate inheritance clause.
LPTK Jan 14, 2025
e4f4922
style change
AnsonYeung Jan 14, 2025
b89eb90
revert whitespace change
CAG2Mark Jan 14, 2025
b22ac0b
Merge branch 'ir-handler-transform' of github.com:CAG2Mark/mlscript i…
CAG2Mark Jan 14, 2025
05a8623
Merge branch 'hkmc2' into ir-handler-transform
AnsonYeung Jan 15, 2025
2b3e83e
Eliminate many tail calls to Lowering#term to reduce stack usage
LPTK Jan 16, 2025
e901993
Make Handle a statement, as it should be
LPTK Jan 16, 2025
3131154
merge from ir-handler-transform
CAG2Mark Jan 16, 2025
e8c690f
preserve tail-calls
CAG2Mark Jan 16, 2025
0c5d205
deal with lambdas, logic fixes
CAG2Mark Jan 16, 2025
5d54505
fix some cases, don't optimise trivial fns
CAG2Mark Jan 16, 2025
a6cdfc9
initial merge
CAG2Mark Jan 16, 2025
8a1af99
fix merge
CAG2Mark Jan 16, 2025
edbbe95
Clean up
CAG2Mark Jan 16, 2025
944f499
merge from ir-handler-transform
CAG2Mark Jan 16, 2025
c1816ce
merge from hkmc2
CAG2Mark Jan 22, 2025
45d3e1d
clean up and document floatOutDefns
CAG2Mark Jan 22, 2025
d0bac71
Merge from hkmc2
CAG2Mark Jan 22, 2025
68d7a2b
complete refactor
CAG2Mark Jan 22, 2025
a812181
fix some things and clean up
CAG2Mark Jan 22, 2025
c2ce877
merge hkmc2
CAG2Mark Jan 22, 2025
9f94638
merge hkmc2
CAG2Mark Jan 22, 2025
5460729
update tests
CAG2Mark Jan 22, 2025
2ef0f4e
Add problematic test cases
LPTK Jan 23, 2025
1dafc9c
fix one bug
CAG2Mark Jan 23, 2025
2bdb70a
Merge branch 'hkmc2' into stack-safety
CAG2Mark Jan 23, 2025
23768b3
update tests
CAG2Mark Jan 23, 2025
7f6378e
Style fix and remove symbol.defn
AnsonYeung Jan 23, 2025
f259fe3
changes to transformation code
AnsonYeung Jan 23, 2025
ab55e5a
update tests
CAG2Mark Jan 23, 2025
70c502d
Fix top level effectful check
AnsonYeung Jan 23, 2025
c93e844
revert scratch changes
AnsonYeung Jan 23, 2025
8baa3fc
revert scratch changes
AnsonYeung Jan 23, 2025
5470a9e
Add broken test
AnsonYeung Jan 23, 2025
aae14de
Fix unhandled tail call optimization case
AnsonYeung Jan 23, 2025
434b705
Increased depth
AnsonYeung Jan 23, 2025
8dcd3de
Update obselete comment
AnsonYeung Jan 23, 2025
5beec3c
Removed comment
AnsonYeung Jan 23, 2025
4e2f460
Fix transformation code
AnsonYeung Jan 23, 2025
203fcf0
Change comment to match codegen
AnsonYeung Jan 23, 2025
8275e31
Minor changes
AnsonYeung Jan 23, 2025
692dfb9
address PR comments
CAG2Mark Jan 23, 2025
dfaab8e
remove obselete comment
CAG2Mark Jan 23, 2025
c2099a2
remove symbol remapping code due to symbol refactor
CAG2Mark Jan 23, 2025
39050cd
make stack limit a variable
CAG2Mark Jan 23, 2025
e3630b6
Removed fixme
AnsonYeung Jan 23, 2025
cb8b917
Make minor improvements
LPTK Jan 24, 2025
1f1ce3f
address PR comments
CAG2Mark Jan 24, 2025
8d92050
add parameter names to llirdiffmaker
CAG2Mark Jan 24, 2025
ea34066
Fix constructor bug and add broken test
AnsonYeung Jan 24, 2025
9d1ef86
Added comment for HandlerCtx
AnsonYeung Jan 24, 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
27 changes: 8 additions & 19 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -288,24 +288,24 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
case b: HandleBlock =>
val rest = applyBlock(b.rest)
translateHandleBlock(b.copy(rest = rest))
case Return(c: Call, implct) if handlerCtx.isHandleFree =>
val fun2 = applyPath(c.fun)
val args2 = c.args.map(applyArg)
val c2 = if (fun2 is c.fun) && (args2 zip c.args).forall(_ is _) then c else Call(fun2, args2)(c.isMlsFun)
case Return(c @ Call(fun, args), implct) if handlerCtx.isHandleFree && !handlerCtx.isTopLevel =>
LPTK marked this conversation as resolved.
Show resolved Hide resolved
val fun2 = applyPath(fun)
val args2 = args.map(applyArg)
val c2 = if (fun2 is fun) && (args2 zip args).forall(_ is _) then c else Call(fun2, args2)(c.isMlsFun)
CAG2Mark marked this conversation as resolved.
Show resolved Hide resolved
if c2 is c then b else Return(c2, implct)
case _ => super.applyBlock(b)
override def applyResult2(r: Result)(k: Result => Block): Block = r match
case r @ Call(Value.Ref(_: BuiltinSymbol), _) => super.applyResult2(r)(k)
case c @ Call(fun, args) =>
val res = freshTmp("res")
val fun2 = applyPath(fun)
val args2 = c.args.map(applyArg)
val args2 = args.map(applyArg)
CAG2Mark marked this conversation as resolved.
Show resolved Hide resolved
val c2 = if (fun2 is fun) && (args2 zip args).forall(_ is _) then c else Call(fun2, args2)(c.isMlsFun)
ResultPlaceholder(res, freshId(), false, c2, k(Value.Ref(res)))
case c @ Instantiate(cls, args) =>
val res = freshTmp("res")
val cls2 = applyPath(cls)
val args2 = c.args.map(applyPath)
val args2 = args.map(applyPath)
CAG2Mark marked this conversation as resolved.
Show resolved Hide resolved
val c2 = if (cls2 is cls) && (args2 zip args).forall(_ is _) then c else Instantiate(cls2, args2)
ResultPlaceholder(res, freshId(), false, c2, k(Value.Ref(res)))
case r => super.applyResult2(r)(k)
Expand Down Expand Up @@ -374,7 +374,6 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
case b1 -> b2 => b1.asCls match
case Some(value) =>
val newSym = ClassSymbol(value.tree, Tree.Ident(b2.nme))
newSym.defn = value.defn
S(value -> newSym)
case None => None
.collect:
Expand All @@ -386,7 +385,6 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
case b1 -> b2 => b1.asMod match
case Some(value) =>
val newSym = ModuleSymbol(value.tree, Tree.Ident(b2.nme))
newSym.defn = value.defn
S(value -> newSym)
case None => None
.collect:
Expand Down Expand Up @@ -455,7 +453,7 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
h.cls,
BlockMemberSymbol(h.cls.id.name, Nil),
syntax.Cls,
h.cls.defn.get.paramsOpt,
N,
S(h.par), handlers, Nil, Nil,
Assign(freshTmp(), SimpleCall(Value.Ref(State.builtinOpsMap("super")), Nil), End()), End())

Expand All @@ -478,15 +476,6 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
)

val pcVar = VarSymbol(Tree.Ident("pc"))
clsSym.defn = S(ClassDef(
N,
syntax.Cls,
clsSym,
BlockMemberSymbol(clsSym.nme, Nil),
Nil,
S(PlainParamList(Param(FldFlags.empty, pcVar, N) :: Nil)),
ObjBody(Term.Blk(Nil, Term.Lit(Tree.UnitLit(true)))),
List()))

var trivial = true
def prepareBlock(b: Block): Block =
Expand Down Expand Up @@ -582,7 +571,7 @@ class HandlerLowering(using TL, Raise, Elaborator.State, Elaborator.Ctx):
clsSym,
BlockMemberSymbol(clsSym.nme, Nil),
syntax.Cls,
clsSym.defn.get.paramsOpt,
S(PlainParamList(Param(FldFlags.empty, pcVar, N) :: Nil)),
S(contClsPath),
resumeFnDef :: Nil,
Nil,
Expand Down
68 changes: 28 additions & 40 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ class StackSafeTransform(depthLimit: Int)(using State):
private val STACK_OFFSET_IDENT: Tree.Ident = Tree.Ident("__stackOffset")
private val STACK_HANDLER_IDENT: Tree.Ident = Tree.Ident("__stackHandler")

private val stackDelayClsPath: Path = State.globalThisSymbol.asPath.selN(Tree.Ident("Predef")).selN(Tree.Ident("__StackDelay")).selN(Tree.Ident("class"))
private val stackDepthPath: Path = State.globalThisSymbol.asPath.selN(Tree.Ident("Predef")).selN(STACK_DEPTH_IDENT)
private val stackOffsetPath: Path = State.globalThisSymbol.asPath.selN(Tree.Ident("Predef")).selN(STACK_OFFSET_IDENT)
private val stackHandlerPath: Path = State.globalThisSymbol.asPath.selN(Tree.Ident("Predef")).selN(STACK_HANDLER_IDENT)
private val predefPath: Path = State.globalThisSymbol.asPath.selN(Tree.Ident("Predef"))
private val stackDelayClsPath: Path = predefPath.selN(Tree.Ident("__StackDelay")).selN(Tree.Ident("class"))
private val stackDepthPath: Path = predefPath.selN(STACK_DEPTH_IDENT)
private val stackOffsetPath: Path = predefPath.selN(STACK_OFFSET_IDENT)
private val stackHandlerPath: Path = predefPath.selN(STACK_HANDLER_IDENT)

private def intLit(n: BigInt) = Value.Lit(Tree.IntLit(n))

Expand Down Expand Up @@ -53,7 +53,6 @@ class StackSafeTransform(depthLimit: Int)(using State):
Tree.TypeDef(syntax.Cls, Tree.Error(), N, N),
Tree.Ident("StackDelay$")
)
clsSym.defn = S(ClassDef(N, syntax.Cls, clsSym, BlockMemberSymbol(clsSym.nme, Nil), Nil, N, ObjBody(Term.Blk(Nil, Term.Lit(Tree.UnitLit(true)))), Nil))

// the global stack handler is created here
HandleBlock(
Expand Down Expand Up @@ -96,33 +95,25 @@ class StackSafeTransform(depthLimit: Int)(using State):

val extract = if isTopLevel then extractResTopLevel else extractRes

val transform = new BlockTransformerShallow(SymbolSubst()):
override def applyDefn(defn: Defn): Defn = rewriteDefn(defn)
val transform = new BlockTransformer(SymbolSubst()):

override def applyFunDefn(fun: FunDefn): FunDefn = rewriteFn(fun)
override def applyDefn(defn: Defn): Defn = defn match
case defn: ClsLikeDefn => rewriteCls(defn)
case _: FunDefn | _: ValDefn => super.applyDefn(defn)

override def applyBlock(b: Block): Block = b match
case Return(res, implct) if usesStack(res) =>
applyResult2(res): res =>
extract(res, true, Return(_, implct))
case Assign(lhs, rhs, rest) if usesStack(rhs) =>
applyResult2(rhs): res =>
extract(res, false, Assign(lhs, _, applyBlock(rest)))
case b @ AssignField(lhs, nme, rhs, rest) if usesStack(rhs) =>
applyResult2(rhs): res =>
extract(res, false, AssignField(lhs, nme, _, applyBlock(rest))(b.symbol))
case Define(defn, rest) =>
Define(rewriteDefn(defn), applyBlock(rest))
case HandleBlock(lhs, res, par, cls, handlers, body, rest) =>
HandleBlock(
lhs, res, par, cls, handlers.map(h => Handler(h.sym, h.resumeSym, h.params, applyBlock(h.body))),
applyBlock(body), applyBlock(rest)
)
case HandleBlockReturn(res) if usesStack(res) =>
applyResult2(res): res =>
extract(res, true, HandleBlockReturn(_))
case Return(res, implct) if usesStack(res) =>
extract(applyResult(res), true, Return(_, implct))
case _ => super.applyBlock(b)

override def applyValue(v: Value): Value =
v match

override def applyResult2(r: Result)(k: Result => Block): Block =
if usesStack(r) then
extract(r, false, k)
else
super.applyResult2(r)(k)

override def applyValue(v: Value): Value = v match
case Value.Lam(params, body) =>
Value.Lam(params, rewriteBlk(body))
case _ => super.applyValue(v)
Expand Down Expand Up @@ -153,16 +144,13 @@ class StackSafeTransform(depthLimit: Int)(using State):
case HandleBlockReturn(res) => true
case End(msg) => true

def rewriteDefn(defn: Defn) =
defn match
case d: FunDefn => rewriteFn(d)
case _: ValDefn => defn
case ClsLikeDefn(owner, isym, sym, k, paramsOpt,
parentPath, methods, privateFields, publicFields, preCtor, ctor) =>
ClsLikeDefn(
owner, isym, sym, k, paramsOpt, parentPath, methods.map(rewriteFn), privateFields,
publicFields, rewriteBlk(preCtor), rewriteBlk(ctor)
)
def rewriteCls(defn: ClsLikeDefn): ClsLikeDefn =
val ClsLikeDefn(owner, isym, sym, k, paramsOpt,
parentPath, methods, privateFields, publicFields, preCtor, ctor) = defn
ClsLikeDefn(
owner, isym, sym, k, paramsOpt, parentPath, methods.map(rewriteFn), privateFields,
publicFields, rewriteBlk(preCtor), rewriteBlk(ctor)
)

def rewriteBlk(blk: Block) =
val newBody = transform(blk)
Expand Down Expand Up @@ -192,4 +180,4 @@ class StackSafeTransform(depthLimit: Int)(using State):

def rewriteFn(defn: FunDefn) = FunDefn(defn.owner, defn.sym, defn.params, rewriteBlk(defn.body))

def transformTopLevel(b: Block) = transform(b, true)
def transformTopLevel(b: Block) = transform(b, true)
41 changes: 24 additions & 17 deletions hkmc2/shared/src/test/mlscript-compile/Predef.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ const Predef$class = class Predef {
}
__resume(cur2, tail) {
return (value) => {
let scrut, cont, scrut1, scrut2, tmp, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
let scrut, cont, scrut1, scrut2, scrut3, tmp, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
scrut = cur2.resumed;
if (scrut === true) {
throw globalThis.Error("Multiple resumption");
Expand All @@ -428,43 +428,50 @@ const Predef$class = class Predef {
}
cur2.resumed = true;
cont = cur2.next;
tmp7: while (true) {
tmp8: while (true) {
if (cont instanceof this.__Cont.class) {
tmp1 = cont.resume(value) ?? null;
value = tmp1;
if (value instanceof this.__EffectSig.class) {
value.tail = tail;
scrut1 = cur2.handleBlockList.next !== null;
scrut1 = value.tail.next === null;
if (scrut1 === true) {
value.handleBlockList.tail.next = cur2.handleBlockList.next;
value.handleBlockList.tail = cur2.handleBlockList.tail;
value.tail.next = cont.next;
tmp2 = null;
} else {
tmp2 = null;
}
value.tail = tail;
scrut2 = cur2.handleBlockList.next !== null;
if (scrut2 === true) {
value.handleBlockList.tail.next = cur2.handleBlockList.next;
value.handleBlockList.tail = cur2.handleBlockList.tail;
tmp3 = null;
} else {
tmp3 = null;
}
return value;
} else {
cont = cont.next;
tmp3 = null;
tmp4 = null;
}
tmp4 = tmp3;
continue tmp7;
tmp5 = tmp4;
continue tmp8;
} else {
tmp4 = null;
tmp5 = null;
}
break;
}
scrut2 = cur2.handleBlockList.next === null;
if (scrut2 === true) {
scrut3 = cur2.handleBlockList.next === null;
if (scrut3 === true) {
return value;
} else {
tmp5 = this.__resumeHandleBlocks(cur2.handleBlockList.next, cur2.handleBlockList.tail, value);
cur2 = tmp5;
tmp6 = this.__resumeHandleBlocks(cur2.handleBlockList.next, cur2.handleBlockList.tail, value);
cur2 = tmp6;
if (cur2 instanceof this.__EffectSig.class) {
cur2.tail = tail;
tmp6 = null;
tmp7 = null;
} else {
tmp6 = null;
tmp7 = null;
}
return cur2;
}
Expand All @@ -478,7 +485,7 @@ const Predef$class = class Predef {
tmp = handleBlock.contHead.next.resume(value) ?? null;
value = tmp;
if (value instanceof this.__EffectSig.class) {
scrut2 = handleBlock.contHead.next !== value.tail.next;
scrut2 = value.tail.next === null;
if (scrut2 === true) {
handleBlock.contHead.next = handleBlock.contHead.next.next;
tmp1 = null;
Expand Down
9 changes: 7 additions & 2 deletions hkmc2/shared/src/test/mlscript-compile/Predef.mls
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ fun __resume(cur, tail)(value) =
cont is __Cont do
set value = cont.resume(value)
if value is __EffectSig then
// in tail call optimization, the continuation is not appended, we append it here
if value.tail.next === null do
// since it is a tail call, it is already completed so we append the continuation after it
set value.tail.next = cont.next
// we are returning to handler, which performs unwinding so tail is needed
set value.tail = tail
if cur.handleBlockList.next !== null do
Expand Down Expand Up @@ -234,7 +238,8 @@ fun __resumeHandleBlocks(handleBlock, tailHandleBlock, value) =
set value = handleBlock.contHead.next.resume(value)
if value is __EffectSig then
// this checks when continuation resume results in tail call to effectful func
if handleBlock.contHead.next !== value.tail.next do
// when a tail call happens, the continuation will not be appended so this will be null
if value.tail.next === null do
// if this is a tail call that results in effect, the continuation is already completed
// and should be removed
set handleBlock.contHead.next = handleBlock.contHead.next.next
Expand All @@ -255,4 +260,4 @@ val __stackDepth = 0 // Tracks the virtual + real stack depth
val __stackOffset = 0 // How much to offset __stackDepth by to get the true stack depth (i.e. the virtual depth)
val __stackHandler = null
abstract class __StackDelay() with
fun perform()// Private definitions for algebraic effects
fun perform()
Loading
Loading