On this page:
halt
sustain
loop
abort
await
every
for/  par
for*/  par

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

Pauses in every instant, forever.

procedure

(sustain s v)  any/c

  s : signal?
  v : any/c
Emits s and pauses in every instant, forever.

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.

Examples:
> (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))

syntax

(loop body-expr ...+)

(loop body-expr ...+ #:each test-expr)
In the first form, runs body-expr over and over. In the second form, starts by running body-expr and then halting. Restarts body-expr when test-expr becomes true.

For example, this program emits S1 in every instant that S2 is not present.
> (define-signal S1 S2)
> (define r
    (esterel
     (loop (emit S1)
           #:each (not (present? S2)))))
> (react! r)

'#hash((#<signal: S1> . #t))

> (react! r)

'#hash((#<signal: S1> . #t) (#<signal: S2> . #f))

> (react! r #:emit (list S2))

'#hash((#<signal: S2> . #t))

> (react! r #:emit (list S2))

'#hash((#<signal: S2> . #t))

> (react! r)

'#hash((#<signal: S1> . #t) (#<signal: S2> . #f))

> (react! r)

'#hash((#<signal: S1> . #t) (#<signal: S2> . #f))

syntax

(abort body-expr ...+ #:when when-expr)

(abort #:weak body-expr ...+ #:when when-expr)
(abort #:weak body-expr ...+ #:when-immediate when-expr)
Terminates when body-expr terminates or when when-expr returns a true value. If #:weak is present, the body-exprs are executed when when-expr is true; they are skipped if #:weak is not present. If #:when is used, the body-exprs are executed at least once and the abort runs for at least one instant; if #:when-immediate is used, the when-expr is tested in the first instant and the expression terminates in the first instant if when-expr returns a true value.

For example, this repeatedly emits S1 until S2 is present, in which case the entire loop terminates and we fall through to the emit of S3.
> (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: S1> . #t) (#<signal: S2> . #f))

> (react! r1)

'#hash((#<signal: S1> . #t) (#<signal: S2> . #f))

> (react! r1)

'#hash((#<signal: S1> . #t) (#<signal: S2> . #f))

> (react! r1 #:emit (list S2))

'#hash((#<signal: S3> . #t) (#<signal: S2> . #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: S1> . #t) (#<signal: S2> . #t))

> (react! r2 #:emit (list S2))

'#hash((#<signal: S3> . #t) (#<signal: S2> . #t))

To terminate in the first instant, use #:when-immediate, so that the test-expr is evaluated in the first instant
> (define r3
    (esterel
     (abort #:weak
            (let loop ()
              (emit S1)
              (pause)
              (loop))
            #:when-immediate (present? S2))
     (emit S3)))
> (react! r3 #:emit (list S2))

'#hash((#<signal: S1> . #t) (#<signal: S3> . #t) (#<signal: S2> . #t))

but note that #:when-immediate requires #:weak, so S1 is also emitted.

syntax

(await when-expr)

(await when-expr #:n n-expr)
(await #:immediate when-expr)
In the first form, pauses until when-expr returns a true value, but at least one instant. In the second form, pause until when-expr returns a true value n-expr times. In the third form, the value of when-expr is tested in the first instant, and thus the await might terminate immediately.

For example, this program waits two instants before emitting S1. When that happens, the await terminates and thus so does the par, leading to the emission of S2.
> (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: S1> . #t) (#<signal: S2> . #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: S2> . #t) (#<signal: S1> . #t))

As an example of the third form, this program emits O in the first instant, as both of the awaits terminate in the first instant.
> (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))

syntax

(every test-expr #:do body-expr ...+)

(every test-expr #:n n-expr #:do body-expr ...+)
(every #:immediate test-expr #:do body-expr ...+)
In the first form, awaits test-expr evaluating to a true value and then starts running the body-exprs; when whenever test-expr becomes true, restarts body-expr. The second form is similar to the first, except that it waits for test-expr to be true n-expr times before restarting body-expr. In the third form, if test-expr evaluates to a true value in the current instant, the body-exprs are evaluated in the current instant.

For example, this program emits S2 whenever S1 is present.
> (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))

Whereas, this program emits S2 every second time S1 is present.
> (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: S2> . #t) (#<signal: every-n (0)> . #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: S2> . #t) (#<signal: every-n (0)> . #t))

When using #:immediate, we can emit S2 in the first instant.
> (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: S2> . #t) (#<signal: every-n (0)> . #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: S2> . #t) (#<signal: every-n (0)> . #t))

syntax

(for/par (for-clause ...) body-or-break ... body)

syntax

(for*/par (for-clause ...) body-or-break ... body)

Like for and for*, but combines the iterations of the loop with par.

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: 9> . 0)

       (#<signal: 0> . 9)

       (#<signal: 1> . 8)

       (#<signal: 2> . 7)

       (#<signal: 3> . 6)

       (#<signal: 4> . 5)

       (#<signal: 5> . 4)

       (#<signal: 6> . 3)

       (#<signal: 7> . 2)

       (#<signal: 8> . 1))