HipHop Signals and Variables
============================
Signals enable HipHop components to communicate with one another. They
play a role akin to variables in traditional programming
languages. They are the central component to store and exchange
information between componnents. They also implement outside world
communications. A signal is identified by its name. It can be local,
i.e., defined locally inside a [module](./module.md) and invisible
outside this module, or global, that is defined as an input or as an
output of the main module. Signals have a direction. A signal may be
an input from the outside world, an output to the outside world, or
used in both directions.
A signal can also carry a value. The value is specified by the
_emitter_ and transmitted to the _receiver_. If a same signal is to be
emitted several times during a reaction with different values,
a combination used to accumulate all the values must be specified when
the signal is declared. The combination function is an arbitrary
JavaScript but it _must_ be associative and commutative.
A signal has four attributes that are **invariant** during a reaction:
* `now`: a boolean which is true if the signal is emitte during the reaction,
and false otherwise.
* `pre`: a boolean which is true if the signal is emitte during the
previous reaction, and false otherwise.
* `nowval`: the value of the most recent emission of that signal.
* `preval`: the value of the signal during the previous instant.
> [!NOTE]
> Note the asymmetry between `nowval` and `preval`. The attribute `nowval`
> _stores_ the most recent value emitted and it changes when a new emission
> happens. The attribute `preval` stores the value of the signal only at
> the previous reaction.
Variables are regular JavaScript variables. Assignments to variables
should never be observed during a reaction. That is, a variable should never
been read after having being assigned during a reaction. It is the
responsibility of the program that ensure that this property holds.
Signal Declarations
-------------------
Signals are declared in [module signatures](./module.md), possibly
via an [interface declaration](./module.md##hiphop-interfaces) or inside an
HipHop statement, with the [signal](./syntax/hiphop.bnf#HHSignal) construct.
### signal [direction] ident [= value] [combine function] ... ###
### signal [direction] ... ident, ident [= value] [combine function] ... ###
### signal implements [mirror] intf ... ###
☆ [Formal syntax](../syntax/hiphop.bnf#HHSignal)
See the [module documentation](./module.md) for module signals.
The `signal` form enables to define local signals whose visibility is
restricted to the block that define them. Example:
```javascript
hiphop module M() {
in S1; // module bound signal
yield;
signal L; // local signal only visible in the current block
fork {
await (S1.now);
emit L(true);
par {
await (L.now);
}
}
```
[Module signals](./module.md) are declared with the keywords `in`,
`out`, and `inout`. The signals can be used from outside of the
machine to pass values in or to receive values after a reaction.
★ Example: [samelocalname.hh.js](../../test/samelocalname.hh.js)
** Multiple emission with combine functions **:
Signals can only be emitted once per instant, unless they are declared
with a default value and a combination function. If such a function
is specified, it must be associative and commutative. Signals associated
with a combination function can be emitted several time during the reaction.
The `.nowval` will contain all the values emitted during the reaction.
★ Example: [incr-branch.hh.js](../../test/incr-branch.hh.js)
★ Example: [toggle.hh.js](../../test/toggle.hh.js)
The form `signal implements [mirror] intf` declares locally the
signals declared in the interface `intf`. The optional keyword
`mirror` swaps the input and output signals.
★ Example: [imirror.hh.js](../../test/imirror.hh.js)
Transient signals are declared with the addition of the `transient` keyword.
They do not save their `nowval` value from one instant to the other,
contrary to plain signals that do.
★ Example: [transient.hh.js](../../test/transient.hh.js)
The form using the `...` syntax enables several signals to share the
same attributes. For instance in the declaration `in ... x, y, z = 1`,
the three signals `x`, `y, and `z` will be initialized to 1.
★ Example: [incr-branch2.hh.js](../../test/incr-branch2.hh.js)
Variable Declarations
---------------------
### let ident [= value], ..., ###
☆ [Formal syntax](../syntax/hiphop.bnf#HHLet)
Along with signals, HipHop supports local Hop variables. They are
local variable carrying Hop values. These variable can be used in all the
Hop expressions HipHop might used, for instance, for computing a delay,
for producing an emission value, or for running asynchronous computation.
★ Example: [variable.hh.js](../../test/variable.hh.js)
Using Signals in Expressions
----------------------------
Signals presence (has a signal been emitted or not during the
reaction) and signal values can be used in HipHop JavaScript
expressions. For that, HipHop analyses Hop expressions and detect
signal accesses. It recognizes
[four syntactic constructs](./syntax/hiphop.bnf#HHExpression) that
correspond to signal access. Notice that these detections are only
executed within the syntactic context of an HipHop expression:
### signal.now ###
A predicate that is true if and only if `signal` has been emitted
during the reaction.
### signal.pre ###
A predicate that is true if and only if `signal` has been emitted
during the _previous_ reaction.
### signal.nowval ###
The current value of the signal. Note that values are preserved from
reaction to reaction so if a signal is emitted during reaction r1 and
not at reaction i1 + 1, getting the value at reaction i1 + 1 will
return the same value as reaction i1, although `signal.now` at
reaction i1 + 1 will be false.
### signal.preval ###
The previous value of the signal. The previous value corresponds to
the value of the previous signal emission. Notice that the previous
emission is not supposed to have happened during the previous
reaction.
The following example illustrates the various values of `now`, `pre`, `nowval`,
and `preval` along instants.
★ Example: [npnvpv.hh.js](../../test/npnvpv.hh.js)
When executed with the following [input](/../../test/npnvpv.in) signals.
It generates the following [output](/../../test/npnvpv.out).
### signal.signame ###
Returns the JavaScript name of a signal. This is useful when dealing
with `async` forms (see [async documentation](./async.md)).
Await, and Emit
---------------
### await delay ###
☆ [Formal syntax](../syntax/hiphop.bnf#HHAwait)
It is frequent for a program to wait for one or several signals to be
emitted. This can be acheived with the `await` construct, which waits
for a condition to be true. The `delay`
[expression](./syntax/hiphop.bnf#HHDelay) can be:
* an simple HipHop expression as the one used in the `if` construct.
* an HipHop expression prefixed with `immediate`. If `immediate` is
specified, the waiting starts during the same reaction. Otherwise it only
starts one reaction later. That is the form `await expr` is equivalent to `{
yield; await immediate expr }`.
* `count(counter, expression)`, this waits for expression to be true
`counter` times.
The `await` form is derived form from the elementary `if` and `loop` constructs.
The form:
```javascript
await immediate (expr);
```
is equivalent to:
```javascript
loop {
if (!expr) yield;
}
```
The form:
```javascript
await (expr)
```
is equivalent to:
```javascript
yield;
await immediate (expr);
```
The form:
```javascript
await count(5, expr)
```
is equivalent to:
```javascript
await (expr);
await (expr);
await (expr);
await (expr);
await (expr);
```
The form `await (delay)` is equivalent to:
```hiphop
endif: loop {
yield;
if (delay) break endif;
}
```
### emit signal([ value ]) ###
☆ [Formal syntax](../syntax/hiphop.bnf#HHEmit)
The `emit` form emit the value in the instant. The form `emit sig1()` emits
a signal without value. The form `emit sig2(val)` emits a signal with
a value.
> [!NOTE]
> If a valued signal
> is to be emitted several times within a single reaction it must be
> declared with a combinaison function that is a Hop function that
> __must__ be commutative and associative. It is up to the Hop program
> to check and satisfy this requirement.
### sustain signal([ value ]) ###
☆ [Formal syntax](../syntax/hiphop.bnf#HHSustain)
Similar to `emit` but the emission is repeated at each instant. The
statement
```javascript
sustain sig(expr);
```
is equivalent to
```javascript
loop {
emit sig(expr);
yield;
}
```
Examples
--------
A module waiting sequentially for `A` and `B` to be emitted during
distinct reactions and that emits `O` right after `B` is received.
★ [await-seq.hh.js](../../test/await-seq.hh.js)
A module that waits the event `I` to be present in three distinctive instants.
★ [await-count.hh.js](../../test/await-count.hh.js)
A module using Hop variable inside HipHop statements.
★ [variable.hh.js](../../test/variable.hh.js)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[[main page]](../../README.md) | [[documentation]](../README.md) | [[language]](./README.md) | [[license]](../license.md)