4 Esterel Reference
(require esterel/full) | package: esterel-lib |
The esterel/full library provides all of the names documented here as well as the names documented in esterel/kernel.
procedure
(halt) → any/c
As with emit, if s is a valued signal, two arguments must be supplied and if s is not a valued signal, two arguments may not be supplied.
> (define-signal S T #:combine +)
> (define r (esterel (par (sustain S) (sustain T 8)))) > (react! r) '#hash((#<signal: T> . 8) (#<signal: S> . #t))
> (react! r) '#hash((#<signal: T> . 8) (#<signal: S> . #t))
> (react! r) '#hash((#<signal: T> . 8) (#<signal: S> . #t))
> (define-signal S1 S2)
> (define r (esterel (loop (emit S1) #:each (not (present? S2))))) > (react! r) '#hash((#<signal: S1> . #t))
> (react! r) '#hash((#<signal: S2> . #f) (#<signal: S1> . #t))
> (react! r #:emit (list S2)) '#hash((#<signal: S2> . #t))
> (react! r #:emit (list S2)) '#hash((#<signal: S2> . #t))
> (react! r) '#hash((#<signal: S2> . #f) (#<signal: S1> . #t))
> (react! r) '#hash((#<signal: S2> . #f) (#<signal: S1> . #t))
syntax
(abort body-expr ...+ #:when when-expr)
(abort #:weak body-expr ...+ #:when when-expr) (abort #:weak body-expr ...+ #:when-immediate when-expr)
> (define-signal S1 S2 S3)
> (define r1 (esterel (abort (let loop () (emit S1) (pause) (loop)) #:when (present? S2)) (emit S3))) > (react! r1) '#hash((#<signal: S1> . #t))
> (react! r1) '#hash((#<signal: S2> . #f) (#<signal: S1> . #t))
> (react! r1) '#hash((#<signal: S2> . #f) (#<signal: S1> . #t))
> (react! r1) '#hash((#<signal: S2> . #f) (#<signal: S1> . #t))
> (react! r1 #:emit (list S2)) '#hash((#<signal: S2> . #t) (#<signal: S3> . #t))
If S2 had been present in the first instant, that program would not have terminated in the first instant, but in the second:
> (define r2 (esterel (abort (let loop () (emit S1) (pause) (loop)) #:when (present? S2)) (emit S3))) > (react! r2 #:emit (list S2)) '#hash((#<signal: S2> . #t) (#<signal: S1> . #t))
> (react! r2 #:emit (list S2)) '#hash((#<signal: S2> . #t) (#<signal: S3> . #t))
> (define r3 (esterel (abort #:weak (let loop () (emit S1) (pause) (loop)) #:when-immediate (present? S2)) (emit S3))) > (react! r3 #:emit (list S2)) '#hash((#<signal: S2> . #t) (#<signal: S1> . #t) (#<signal: S3> . #t))
syntax
(await when-expr)
(await when-expr #:n n-expr) (await #:immediate when-expr) (await #:cases case-spec ...+)
case-spec = [maybe-immediate when-expr] | [maybe-immediate when-expr do-expr] maybe-immediate =
| #:immediate
> (define-signal S1 S2)
> (define r (esterel (par (begin (pause) (pause) (emit S1)) (await (present? S1))) (emit S2))) > (react! r) '#hash()
> (react! r) '#hash((#<signal: S1> . #f))
> (react! r) '#hash((#<signal: S2> . #t) (#<signal: S1> . #t))
As an example of the second form, this program emits S2 in the fifth instant; it pauses for three instants where S1 was present and two where it is not.
> (define-signal S1 S2)
> (define r (esterel (await (present? S1) #:n 3) (emit S2))) > (react! r) '#hash()
> (react! r #:emit (list S1)) '#hash((#<signal: S1> . #t))
> (react! r) '#hash((#<signal: S1> . #f))
> (react! r #:emit (list S1)) '#hash((#<signal: S1> . #t))
> (react! r #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: S2> . #t))
> (define-signal S O)
> (define r (esterel (await #:immediate (not (present? S))) (await #:immediate (not (present? S))) (emit O))) > (react! r) '#hash((#<signal: S> . #f) (#<signal: O> . #t))
As an example of the fourth form, this program checks for the presence of C in the first instant and checks for the presence of A, B, and C in the second and third instant. In the fourth instant, the program checks for the presence of A, and since A is present, it emits a and terminates the await.
> (define-signal A B C a b c done)
> (define r (esterel (await #:cases [(present? A) (emit a)] [(present? B) (emit b)] [#:immediate (present? C) (emit c)]) (emit done))) > (react! r) '#hash((#<signal: C> . #f))
> (react! r) '#hash((#<signal: B> . #f) (#<signal: C> . #f) (#<signal: A> . #f))
> (react! r) '#hash((#<signal: B> . #f) (#<signal: C> . #f) (#<signal: A> . #f))
> (react! r #:emit (list A B))
'#hash((#<signal: B> . #t)
(#<signal: done> . #t)
(#<signal: a> . #t)
(#<signal: A> . #t))
syntax
(every test-expr #:do body-expr ...+)
(every test-expr #:n n-expr #:do body-expr ...+) (every #:immediate test-expr #:do body-expr ...+)
> (define-signal S1 S2)
> (define r1 (esterel (every (present? S1) #:do (emit S2)))) > (react! r1 #:emit (list S1)) '#hash((#<signal: S1> . #t))
> (react! r1 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: S2> . #t))
> (react! r1 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: S2> . #t))
> (react! r1) '#hash((#<signal: S1> . #f))
> (react! r1 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: S2> . #t))
> (react! r1 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: S2> . #t))
> (define r2 (esterel (every (present? S1) #:n 2 #:do (emit S2)))) > (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t))
> (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: every-n (0)> . #f))
> (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: every-n (0)> . #t) (#<signal: S2> . #t))
> (react! r2) '#hash((#<signal: S1> . #f) (#<signal: every-n (0)> . #f))
> (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: every-n (0)> . #f))
> (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: every-n (0)> . #t) (#<signal: S2> . #t))
> (define r2 (esterel (every (present? S1) #:n 2 #:do (emit S2)))) > (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t))
> (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: every-n (0)> . #f))
> (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: every-n (0)> . #t) (#<signal: S2> . #t))
> (react! r2) '#hash((#<signal: S1> . #f) (#<signal: every-n (0)> . #f))
> (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: every-n (0)> . #f))
> (react! r2 #:emit (list S1)) '#hash((#<signal: S1> . #t) (#<signal: every-n (0)> . #t) (#<signal: S2> . #t))
syntax
(for/par (for-clause ...) body-or-break ... body)
syntax
(for*/par (for-clause ...) body-or-break ... body)
Here is an example where we first create 10 signals with names from 0 to 9. Then, in parallel, we emit a value on each of the signals, where the value on signal n is one more than the value on signal n+1, except signal 9 where we simply emit a 0. Because all the emissions are happening in parallel, we get the values propagating properly from signal to signal.
> (define signal-count 10)
> (define sigs (for/hash ([i (in-range signal-count)]) (values i (make-global-signal (~a i) #:combine +))))
> (react! (esterel (for/par ([(n sig) (in-hash sigs)]) (cond [(= n (- signal-count 1)) (emit sig 0)] [else (define n+1-sig (hash-ref sigs (+ n 1))) (define n+1-value (signal-value n+1-sig #:can (set sig))) (emit sig (+ n+1-value 1))]))))
'#hash((#<signal: 3> . 6)
(#<signal: 4> . 5)
(#<signal: 5> . 4)
(#<signal: 6> . 3)
(#<signal: 7> . 2)
(#<signal: 8> . 1)
(#<signal: 9> . 0)
(#<signal: 0> . 9)
(#<signal: 1> . 8)
(#<signal: 2> . 7))