Skip to content

Commit

Permalink
Fix generator
Browse files Browse the repository at this point in the history
  • Loading branch information
AnsonYeung committed Dec 25, 2024
1 parent dc516cd commit e6cd1ec
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 60 deletions.
113 changes: 78 additions & 35 deletions hkmc2/shared/src/test/mlscript-compile/Predef.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -216,27 +216,23 @@ const Predef$class = class Predef {
handlerCont = tmp;
handlerCont.tail = handlerCont;
tmp4: while (true) {
if (cur instanceof this.__Return.class) {
return cur;
} else {
if (cur instanceof this.__EffectSig.class) {
tmp1 = this.__handleEffect(cur, handler1, handlerCont);
nxt = tmp1;
scrut = cur === nxt;
if (scrut) {
cur.tailHandler.nextHandler = handlerCont;
cur.tailHandler = handlerCont;
cur.tail = handlerCont.tail;
return cur;
} else {
cur = nxt;
tmp2 = null;
}
tmp3 = tmp2;
continue tmp4;
} else {
if (cur instanceof this.__EffectSig.class) {
tmp1 = this.__handleEffect(cur, handler1, handlerCont);
nxt = tmp1;
scrut = cur === nxt;
if (scrut) {
cur.tailHandler.nextHandler = handlerCont;
cur.tailHandler = handlerCont;
cur.tail = handlerCont.tail;
return cur;
} else {
cur = nxt;
tmp2 = null;
}
tmp3 = tmp2;
continue tmp4;
} else {
return cur;
}
break;
}
Expand Down Expand Up @@ -287,7 +283,7 @@ const Predef$class = class Predef {
cur1.tailHandler = origTail;
return cur1;
} else {
tmp4 = this.__resume(handlerCont, null, null);
tmp4 = this.__resume(handlerCont, null);
tmp5 = tmp4(cur1) ?? null;
cur1 = tmp5;
tmp6 = null;
Expand Down Expand Up @@ -348,27 +344,25 @@ const Predef$class = class Predef {
}
__resume(cur2, tail) {
return (value) => {
let scrut, nextHandler, tailHandler, cont, scrut1, tmp, tmp1, tmp2, tmp3, tmp4;
let scrut, cont, scrut1, scrut2, scrut3, scrut4, nxt, scrut5, tmp, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18, tmp19, tmp20, tmp21, tmp22;
scrut = cur2.resumed;
if (scrut) {
throw Error("multiple resumption");
} else {
tmp = null;
}
cur2.resumed = true;
nextHandler = cur2.nextHandler;
tailHandler = cur2.tailHandler;
cont = cur2.next;
tmp5: while (true) {
tmp23: 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 = tailHandler !== cur2;
scrut1 = cur2.tailHandler !== cur2;
if (scrut1) {
value.tailHandler.nextHandler = nextHandler;
value.tailHandler = tailHandler;
value.tailHandler.nextHandler = cur2.nextHandler;
value.tailHandler = cur2.tailHandler;
tmp2 = null;
} else {
tmp2 = null;
Expand All @@ -379,20 +373,69 @@ const Predef$class = class Predef {
tmp3 = null;
}
tmp4 = tmp3;
continue tmp5;
continue tmp23;
} else {
if (nextHandler instanceof this.__HandleBlock.class) {
cont = nextHandler.next;
nextHandler = nextHandler.nextHandler;
tmp4 = null;
continue tmp5;
tmp4 = null;
}
break;
}
tmp24: while (true) {
scrut2 = cur2.nextHandler;
if (scrut2 instanceof this.__HandleBlock.class) {
scrut4 = cur2.nextHandler.next;
if (scrut4 instanceof this.__Cont.class) {
nxt = cur2.nextHandler.next;
tmp5 = nxt.resume(value) ?? null;
value = tmp5;
if (value instanceof this.__EffectSig.class) {
tmp6 = cur2.tailHandler !== cur2;
tmp7 = this.assert(tmp6) ?? null;
tmp8 = cur2.nextHandler !== null;
tmp9 = this.assert(tmp8) ?? null;
scrut5 = cur2.nextHandler.next === value.tail.next;
if (scrut5) {
value.tail.next = null;
tmp10 = null;
} else {
cur2.nextHandler.next = cur2.nextHandler.next.next;
tmp10 = null;
}
value.tail = tail;
value.tailHandler.nextHandler = cur2.nextHandler;
value.tailHandler = cur2.tailHandler;
return value;
} else {
tmp11 = cur2.nextHandler.next !== cur2.nextHandler.next.next;
tmp12 = this.assert(tmp11) ?? null;
cur2.nextHandler.next = cur2.nextHandler.next.next;
tmp13 = null;
}
tmp14 = tmp13;
continue tmp24;
} else {
tmp4 = value;
scrut3 = true;
if (scrut3) {
tmp15 = cur2.nextHandler.next === null;
tmp16 = this.assert(tmp15) ?? null;
tmp17 = cur2.nextHandler !== cur2.nextHandler.nextHandler;
tmp18 = this.assert(tmp17) ?? null;
cur2.nextHandler = cur2.nextHandler.nextHandler;
tmp14 = null;
continue tmp24;
} else {
tmp19 = cur2.nextHandler === null;
tmp20 = this.assert(tmp19) ?? null;
return value;
}
}
} else {
tmp21 = cur2.nextHandler === null;
tmp22 = this.assert(tmp21) ?? null;
return value;
}
break;
}
return tmp4;
return tmp14;
};
}
toString() { return "Predef"; }
Expand Down
89 changes: 75 additions & 14 deletions hkmc2/shared/src/test/mlscript-compile/Predef.mls
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,18 @@ fun __mkEffect(handler, handlerFun) =
set res.tailHandler = res
res

// fun checkEffectHead(cur) =
// if cur is __EffectSig then
// let hand = cur
// while hand.nextHandler !== null do
// set hand = hand.nextHandler
// assert(hand === cur.tailHandler)
// assert(cur.resumed === false)

fun __handleBlockImpl(cur, handler) =
let handlerCont = new __HandleBlock(null, null, null, handler)
set handlerCont.tail = handlerCont
while cur is
__Return then return cur
__EffectSig then
let nxt = __handleEffect(cur, handler, handlerCont)
if cur === nxt then
Expand Down Expand Up @@ -122,7 +129,7 @@ fun __handleEffect(cur, handler, handlerTailList) =
set cur.tailHandler = origTail
return cur
else
set cur = __resume(handlerCont, null, null)(cur)
set cur = __resume(handlerCont, null)(cur)
else if handler === cur.handler then
let savedNext = handlerTailList.next
set cur = cur.handlerFun(__resume(cur, handlerTailList))
Expand All @@ -142,26 +149,80 @@ fun __handleEffect(cur, handler, handlerTailList) =
set cur = nxt.resume(cur)
else cur

// fun __resume(cur, tail)(value) =
// if cur.resumed do
// throw Error("multiple resumption")
// set cur.resumed = true
// let cont = cur.next
// while
// cont is __Cont then
// value = cont.resume(value)
// if value is __EffectSig then
// set value.tail = tail
// if cur.tailHandler !== cur do
// set value.tailHandler.nextHandler = cur.nextHandler
// set value.tailHandler = cur.tailHandler
// return value
// else
// set cont = cont.next
// cur.nextHandler is __HandleBlock then
// set cont = cur.nextHandler.next
// set cur.nextHandler = cur.nextHandler.nextHandler
// else value

fun __resume(cur, tail)(value) =
if cur.resumed do
throw Error("multiple resumption")
set cur.resumed = true
let nextHandler = cur.nextHandler
let tailHandler = cur.tailHandler

let cont = cur.next
while
cont is __Cont then
value = cont.resume(value)
cont is __Cont do
// NOTE: we do not need to link to cont.next again if it is effsig
// because cont.resume will not change its own next
set value = cont.resume(value)
if value is __EffectSig then
set value.tail = tail
if tailHandler !== cur do
set value.tailHandler.nextHandler = nextHandler
set value.tailHandler = tailHandler
if cur.tailHandler !== cur do
set value.tailHandler.nextHandler = cur.nextHandler
set value.tailHandler = cur.tailHandler
return value
else
set cont = cont.next
nextHandler is __HandleBlock then
set cont = nextHandler.next
set nextHandler = nextHandler.nextHandler
else value

// We're done with the head, now resume the handle blocks
while
cur.nextHandler is __HandleBlock and
cur.nextHandler.next is __Cont then
// resuming tailHandlerList or post handler continuations
let nxt = cur.nextHandler.next
set value = nxt.resume(value)
if value is __EffectSig then
// console.dir(cur.nextHandler.next)
// console.dir(value.tail.next)
// console.dir(value)
// console.dir(cur)
// console.dir(nxt)
// console.log(nxt.resume.toString())
assert(cur.tailHandler !== cur)
assert(cur.nextHandler !== null)
// This checks when continuation resume results in tail call to effectful func
if cur.nextHandler.next === value.tail.next then
set value.tail.next = null
else
set cur.nextHandler.next = cur.nextHandler.next.next
set value.tail = tail
set value.tailHandler.nextHandler = cur.nextHandler
set value.tailHandler = cur.tailHandler
return value
else
assert(cur.nextHandler.next !== cur.nextHandler.next.next)
set cur.nextHandler.next = cur.nextHandler.next.next
// here using else will emit the wrong code and cause null to be returned from the loop
true then
// the list is empty, go to next handle block
assert(cur.nextHandler.next === null)
assert(cur.nextHandler !== cur.nextHandler.nextHandler)
set cur.nextHandler = cur.nextHandler.nextHandler
else
assert(cur.nextHandler === null)
return value
29 changes: 20 additions & 9 deletions hkmc2/shared/src/test/mlscript/handlers/Generators.mls
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,37 @@ fun permutations_impl(gen, l1, l2) =
fun permutations(gen, l) =
permutations_impl(gen, [], l)

:fixme
let res = []
handle gen = Generator with
fun produce(result)(resume) =
res.push(result)
resume(())
in permutations(gen, [1, 2, 3, 4])
res
//│ ═══[RUNTIME ERROR] Error: Unhandled effects
//│ res = [ [ 1, 2, 3, 4 ] ]
//│ > [
//│ > [ 1, 2, 3, 4 ], [ 1, 2, 4, 3 ],
//│ > [ 1, 3, 2, 4 ], [ 1, 3, 4, 2 ],
//│ > [ 1, 4, 2, 3 ], [ 1, 4, 3, 2 ],
//│ > [ 2, 1, 3, 4 ], [ 2, 1, 4, 3 ],
//│ > [ 2, 3, 1, 4 ], [ 2, 3, 4, 1 ],
//│ > [ 2, 4, 1, 3 ], [ 2, 4, 3, 1 ],
//│ > [ 3, 1, 2, 4 ], [ 3, 1, 4, 2 ],
//│ > [ 3, 2, 1, 4 ], [ 3, 2, 4, 1 ],
//│ > [ 3, 4, 1, 2 ], [ 3, 4, 2, 1 ],
//│ > [ 4, 1, 2, 3 ], [ 4, 1, 3, 2 ],
//│ > [ 4, 2, 1, 3 ], [ 4, 2, 3, 1 ],
//│ > [ 4, 3, 1, 2 ], [ 4, 3, 2, 1 ]
//│ res = ]

// FIXME: result is wrong
fun permutations_foreach(l, f) =
handle gen = Generator with
fun produce(result)(resume) =
f(result)
resume(())
permutations(gen, l)

:fixme
res = permutations_foreach([1, 2, 3], print)
permutations_foreach([1, 2, 3], print)
//│ > 1,2,3
//│ ═══[RUNTIME ERROR] Error: Unhandled effects
//│ > 1,3,2
//│ > 2,1,3
//│ > 2,3,1
//│ > 3,1,2
//│ > 3,2,1
2 changes: 1 addition & 1 deletion hkmc2/shared/src/test/mlscript/handlers/NestedHandlers.mls
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ handle h = Eff with
k()
f(h, box, 10)
box.n
//│ ═══[RUNTIME ERROR] Error: Unhandled effects
//│ ═══[RUNTIME ERROR] Expected: 1023, got: 5120

handle h1 = Eff with
fun perform()(k) =
Expand Down
24 changes: 23 additions & 1 deletion hkmc2/shared/src/test/mlscript/handlers/RecursiveHandlers.mls
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,26 @@ in res.toString()
//│ > B hola amigos
//│ = '‹,‹,‹,‹,hola,friend,›,bye,›,amigos,›,adios,›'


let res =
print("A " + "hi")
handle g = Effect with
fun perform(arg1)(k1) =
print("B " + "hi" + " " + arg1)
["‹", k1("hi"), arg1, "›"]
g.perform("bye")
g.perform("adios")
print("A " + "hola")
handle g2 = Effect with
fun perform(arg1)(k1) =
print("B " + "hola" + " " + arg1)
["‹", k1("hola"), arg1, "›"]
g2.perform("adios")
g2.perform("amigos")
in res.toString()
//│ > A hi
//│ > B hi bye
//│ > B hi adios
//│ > A hola
//│ > B hola adios
//│ > B hola amigos
//│ = '‹,‹,‹,‹,hola,amigos,›,adios,›,adios,›,bye,›'

0 comments on commit e6cd1ec

Please sign in to comment.