1
0
mirror of https://github.com/janet-lang/janet synced 2025-02-03 02:39:09 +00:00

Add prompt and return.

User friendly delimited continuations. While this was doable with
signals before, this does not require C and will play nicely with
existing error handling, defers, and with statements.
This commit is contained in:
Calvin Rose 2020-02-23 16:35:33 -06:00
parent 8c41c0b6a7
commit 59d288c429
3 changed files with 39 additions and 0 deletions

View File

@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
- Correct arity for `next`
- Correct arity for `marshal`
- Add `flush` and `eflush`
- Add `prompt` and `return` on top of signal for user friendly delimited continuations.
## 1.7.0 - 2020-02-01
- Remove `file/fileno` and `file/fdopen`.

View File

@ -299,6 +299,24 @@
,r
(propagate ,r ,f)))))
(defmacro prompt
"Set up a prompt point that can be aborted to. Tag should be a value
that is used in a return statement, like a keyword."
[tag & body]
(with-syms [res target payload fib]
~(do
(def ,fib (,fiber/new (fn [] [,tag (do ,;body)]) :i0))
(def ,res (,resume ,fib))
(def [,target ,payload] ,res)
(if (,= ,tag ,target)
,payload
(propagate ,res ,fib)))))
(defn return
"Return to a prompt point."
[to value]
(signal 0 [to value]))
(defmacro with
"Evaluate body with some resource, which will be automatically cleaned up
if there is an error in body. binding is bound to the expression ctor, and

View File

@ -70,4 +70,24 @@
(test-bf "+[+[<<<+>>>>]+<-<-<<<+<++]<<.<++.<++..+++.<<++.<---.>>.>.+++.------.>-.>>--."
"Hello, World!")
# Prompts
(assert (= 10 (prompt :a (for i 0 10 (if (= i 5) (return :a 10))))) "prompt 1")
(defn- inner-loop
[i]
(if (= i 5)
(return :a 10)))
(assert (= 10 (prompt :a (for i 0 10 (inner-loop i)))) "prompt 2")
(defn- inner-loop2
[i]
(try
(if (= i 5)
(error 10))
([err] (return :a err))))
(assert (= 10 (prompt :a (for i 0 10 (inner-loop2 i)))) "prompt 3")
(end-suite)