diff --git a/examples/stdlib/control.check b/examples/stdlib/control.check new file mode 100644 index 000000000..87dc9916c --- /dev/null +++ b/examples/stdlib/control.check @@ -0,0 +1,3 @@ +5 +Some(-1) +() \ No newline at end of file diff --git a/examples/stdlib/control.effekt b/examples/stdlib/control.effekt new file mode 100644 index 000000000..ed24d8a0d --- /dev/null +++ b/examples/stdlib/control.effekt @@ -0,0 +1,53 @@ + +type Term { + Add(x: Int, k: Term) + Return(v: Int) +} + +def interp(t: Term): Int = { + var st = t + var pre = 0 + loop{ {l} => + st match { + case Add(x, k) => + pre = pre + x + st = k + case Return(v) => l.break(pre + v) + } + } +} + +def ctl_min(l: List[Int]): Option[Int] = { + var c_min = None() + var c_l = l + loop{ {l} => + c_l match { + case Nil() => l.break() + case Cons(x, k) and c_min is None() => + c_min = Some(x) + c_l = k + case Cons(x, k) and c_min is Some(m) and x < m => + c_min = Some(x) + c_l = k + case Cons(x, k) => c_l = k + } + } + c_min +} + +effect exit(): Unit +def nobreak(): Unit = { + var x = 12 + try{ + loop{ {l} => + do exit() + l.continue() + } + } with exit { () => () } +} + +def main() = { + println(interp(Add(2, Add(3, Return(0))))) + println(ctl_min(Cons(0, Cons(1, Cons(-1, Nil()))))) + println(nobreak()) +} \ No newline at end of file diff --git a/libraries/common/effekt.effekt b/libraries/common/effekt.effekt index 1a73cb767..3e74cc4fa 100644 --- a/libraries/common/effekt.effekt +++ b/libraries/common/effekt.effekt @@ -736,6 +736,19 @@ def loop { f: {Control} => Unit }: Unit = try { def continue() = loop { f } } +interface ControlAt[T] { + def break(t: T): Unit + def continue(): Unit +} + +def loop[T] { f: {ControlAt[T]} => Unit }: T = try { + def go(): T = { f{label}; go() } + go() +} with label: ControlAt[T] { + def break(v) = v + def continue() = loop{f} +} + /// Calls provided action repeatedly. `start` is inclusive, `end` is not. def each(start: Int, end: Int) { action: (Int) => Unit } = { def loop(i: Int): Unit =