Skip to content

Commit

Permalink
Support bidirectional effects
Browse files Browse the repository at this point in the history
  • Loading branch information
b-studios committed Nov 28, 2023
1 parent 74d4158 commit 4be8355
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
7 changes: 1 addition & 6 deletions effekt/jvm/src/test/scala/effekt/JavaScriptTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,7 @@ class JavaScriptTests extends EffektTests {
// ---------------------------------------------

// trampolining
examplesDir / "pos" / "stacksafe.effekt",

// bidirectional
examplesDir / "pos" / "bidirectional" / "iterators.effekt",
examplesDir / "pos" / "bidirectional" / "pingpong.effekt",

examplesDir / "pos" / "stacksafe.effekt"
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,21 @@ object TransformerDS {

def toJS(handler: core.Implementation, prompt: JSName)(using DeclarationContext, Locals, Continuations, Context): js.Expr =
js.Object(handler.operations.map {
// () => $effekt.suspend(this, (resume_730) => { return $effekt.unit; })
// (args...cap...) => $effekt.suspend(prompt, (resume) => { ... body ... resume((cap...) => { ... }) ... })
case Operation(id, tps, cps, vps, bps,
Some(BlockParam(resume, core.BlockType.Function(_, _, _, List(core.BlockType.Function(_, _, _, bidirectionalTpes, _)), _), _)),
body) =>
// add parameters for bidirectional arguments
val biParams = bidirectionalTpes.map { _ => freshName("cap") }
val biArgs = biParams.map { p => js.Variable(p) }

val lambda = js.Lambda((vps ++ bps).map(toJS) ++ biParams,
js.Return(js.builtin("suspend_bidirectional", js.Variable(prompt), js.ArrayLiteral(biArgs), js.Lambda(List(nameDef(resume)),
js.Block(toJS(body)(x => js.Return(x)))))))

nameDef(id) -> lambda

// (args...) => $effekt.suspend(prompt, (resume) => { ... BODY ... resume(v) ... })
case Operation(id, tps, cps, vps, bps, Some(resume), body) =>
val lambda = js.Lambda((vps ++ bps) map toJS,
js.Return(js.builtin("suspend", js.Variable(prompt), js.Lambda(List(toJS(resume)), js.Block(toJS(body)(x => js.Return(x)))))))
Expand Down
4 changes: 4 additions & 0 deletions libraries/js/effekt_runtime.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const $runtime = (function() {

// Regions
// TODO maybe use weak refs (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef)
function Cell(init) {
var _value = init;
const cell = ({
Expand Down Expand Up @@ -178,6 +179,9 @@ function Arena() {
suspend: function(prompt, body) {
throw new Suspension(prompt, body, Nil, Empty)
},
suspend_bidirectional: function(prompt, caps, body) {
throw new Suspension(prompt, body, Cons(thunk => thunk.apply(null, caps), Nil), Empty)
},

push: function(suspension, frame) {
// Assuming `suspension` is a value or variable you want to return
Expand Down

0 comments on commit 4be8355

Please sign in to comment.