Table of Contents
- Signal Declarations
- Variable Declarations
- Using Signals in Expressions
- Test, Await, and Emit
- Examples
Signals enable HipHop components to communicate with one another. They also implement outside world communications. A signal is identified by its name. It can be local, i.e., defined locally inside a module 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. A same signal can be emitted several times during a reaction but it that signal is valued, 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.
Signal Declarations
Signals are declared in module signatures, possibly via an interface declaration or inside an HipHop statement, with the signal construct.
signal [direction] ident [= value], ..., interface, ...
Variable Declarations
let ident [= value], ...,
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.
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 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.
"use hopscript"
hiphop machine prg( in A = "_", in B ) {
loop {
hop {
console.log( "A.now=" + A.now, "A.pre=" + A.pre,
"A.nowval=" + A.nowval, "A.preval=" + A.preval );
console.log( "B.now=" + B.now, "B.pre=" + B.pre,
"B.nowval=" + B.nowval, "B.preval=" + B.preval );
}
yield;
}
}
exports.prg = prg;
When executed with the following input signals:
;
A(1) B(1);
A(2) B(2);
B(3);
B(4);
A(5);
A(6);
It generates the following output:
undefined> ;
A.now=false A.pre=false A.nowval=_ A.preval=_
B.now=false B.pre=false B.nowval=undefined B.preval=undefined
--- Output:
undefined> A(1) B(1);
A.now=true A.pre=false A.nowval=1 A.preval=_
B.now=true B.pre=false B.nowval=1 B.preval=undefined
--- Output:
undefined> A(2) B(2);
A.now=true A.pre=true A.nowval=2 A.preval=1
B.now=true B.pre=true B.nowval=2 B.preval=1
--- Output:
undefined> B(3);
A.now=false A.pre=true A.nowval=2 A.preval=2
B.now=true B.pre=true B.nowval=3 B.preval=2
--- Output:
undefined> B(4);
A.now=false A.pre=false A.nowval=2 A.preval=2
B.now=true B.pre=true B.nowval=4 B.preval=3
--- Output:
undefined> A(5);
A.now=true A.pre=false A.nowval=5 A.preval=2
B.now=false B.pre=true B.nowval=4 B.preval=4
--- Output:
undefined> A(6);
A.now=true A.pre=true A.nowval=6 A.preval=5
B.now=false B.pre=false B.nowval=4 B.preval=4
--- Output:
Test, Await, and Emit
if( expr ) { ... } [else { ... }]
The presence or absence of a signal can be checked with the if
conditional construct. The value of a signal can be checked too. The
expr
argument is any Hop expression agumented with the signal
API. For instance, the presence of a signal can be checked with:
if( !SIG.now ) { hop { console.log( "signal not emitted in reaction" ) } }
A particular value of a signal can be checked. For instance:
if( SIG.nowval > 10 && SIG.nowval < 100 ) { hop { console.log( "signal in range" ) } }
await delay
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
can be:
- an simple HipHop expression as the one used in the
if
construct. - an HipHop expression prefixed with
immediate
. Ifimmediate
is specified, the waiting starts during the same reaction. Otherwise it only starts one reaction later. That is the formawait expr
is equivalent to{ yield; await immediate expr }
. count( counter, expression )
, this waits for expression to be truecounter
times.
emit signal( [ value ] )
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 ] )
Similar to emit
but the emission is repeated at each instant. The
statement
sustain sig( expr )
is equivalent to
loop {
sustain 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
"use hiphop";
"use hopscript";
var hh = require( "hiphop" );
hiphop module prg( in A, in B, out O ) {
await( A.now );
await( B.now );
emit O();
}
exports.prg = new hh.ReactiveMachine( prg, "awaitseq" );
A module that waits the event I
to be present in three distinctive instants.
await-count.hh.js
"use hiphop"
"use hopscript"
const hh = require( "hiphop" );
hiphop module prg( in I, out O ) {
loop {
await count( 3, I.now );
emit O();
}
}
exports.prg = new hh.ReactiveMachine( prg, "await3" );
A module using Hop variable inside HipHop statements.
variable.hh.js
"use hiphop"
"use hopscript"
var hh = require( "hiphop" );
hiphop module prg( in sig ) {
let v = 1;
every( sig.now ) {
if( sig.nowval > v ) hop { v = sig.nowval + 1 };
hop { console.log( "v=", v ) }
yield;
}
}
const m = new hh.ReactiveMachine( prg, "variable" );
exports.prg = prg;
m.react()
m.inputAndReact( "sig", 0 );
m.inputAndReact( "sig", 10 );