Table of Contents

Statements

Module

<hiphop.module>

Module is the programming unit of a Hiphop.js program. Therefore, any Hiphop.js statement must be embedded inside a module.

<hiphop.module>
  <!-- Hiphop.js instructions -->
<hiphop.module>

Basic control statement

<hiphop.nothing/>

Terminates instantaneously when started. It a kind of nop instruction, in assembly languages.

<hiphop.pause/>

Pauses the branch where it is defined for the current instant. The following instructions of the branch will be executed at the next instant.

<hiphop.halt/>

Pauses forever the branch where it is defined. It never terminates, but it can be preempted.

<hiphop.if>

Attributes and children of the node:

Instantaneously evaluates the expression and gives control to the then or else branch according to the result of the test.

The following example will emit O1 if the signal I1 is present, and O2 if the value of the signal O2 is superior or equals to 2.

        <hh.if apply=${function() {return this.present.I1}}>
          <hh.emit O1/>
        </hh.if>
        <hh.if apply=${function() {return this.value.I2 > 2}}>
          <hh.emit O2/>
        </hh.if>

Warning: each child of the If instruction is considered as a branch. Hence, the first child is the then branch, and the second child is the else branch. On the following example, <foo/> will be evaluated if delay-expr is true, and <bar/> will be evaluated if delay-expr is false:

<hh.if delay-expr>
  <foo/>
  <bar/>
</hh.if>

If one want to evaluate <foo/> and <bar/> when delay-expr is true, an explicit sequence must be used:

<hh.if delay-expr>
  <hh.sequence>
    <foo/>
    <bar/>
  </hh.sequence>
</hh.if>

Signal emission

<hiphop.emit/>

Attributes of the node:

Instantaneously sets given signals present in the current instant and terminates. In an expression is given, it is evaluated and its return value is affected to each given signal according the following rules:

If a conditional expression is given (via ifApply or ifValue), and if the result of this expression is false, the Emit instruction instantaneously terminates without emit any signal.

In the following example O is emitted:

<hh.emit O/>

In the following example O is emitted with value 10:

<hh.emit O value=${10}/>

In the following example O and J are emitted with the value of L:

<hh.emit O J apply=${function() {return this.value.L}}/>

In the following example, A is emitted if B is present during the reaction:

          <hh.emit A ifApply=${function(){return this.present.B}}/>

<hiphop.sustain/>

Attributes of the node:

Instantaneously emit given signals, but never terminates, and will always re-emit the signal on following reactions. The rules of Emit statement applies here. If a conditional expression is given (via ifApply or ifValue), given signals are emitted only if the result of the expression is true.

It supports the same attributes than Emit statement.

In the following example, J is emitted at each reaction until the emission of I:

          <hh.abort I>
            <hh.sustain J/>
          </hh.abort>

Looping

<hiphop.loop>

Children of the node:

The body of the Loop statement is instantaneously started, and then instantaneously restarted when it reach the end of the loop. The Loop never terminates, but can be preempted.

Because the loop is instantaneously restarted, ones must take care of avoid instantaneous loop (a body that will terminate instantaneously, without implicit of explicit pause instruction), which is forbidden by the language.

In the following example O is emitted at each instant:

<hh.loop>
   <hh.emit O/>
   <hh.pause/>
</hh.loop>

In the following example O is emitted at each instant that the signal I is present. The loop isn't instantaneous since the Await instruction includes an implicit pause:

<hh.loop>
   <hh.await I/>
   <hh.emit O/>
</hh.loop>

The following example is not legal since the loop is instantaneous (it will re-loop at the same instant):

<hh.loop>
   <hh.emit O/>
</hh.loop>

<hiphop.loopeach>

Attributes and children of the node:

The body of the LoopEach statement is instantaneously started, and then restarted each at each instant where the delay expression elapses. This statement can't make instantaneous loop, so the body can instantaneously terminates. LoopEach never terminates, but can be preempted.

In the following example, O is emitted the first instant, and at each following instants where I is present:

      <hh.loopeach I>
        <hh.emit O/>
      </hh.loopeach>

<hiphop.every>

Attributes and children of the node:

The body of the Every statement is instantaneously started at each instant where the delay expression elapses. However, on the first instant, the body of Every is never started.

In the following example, O is not be emitted at the first instant. It is emitted on the following instants if I is present:

      <hh.every I>
        <hh.emit O/>
      </hh.every>

Preemption

<hiphop.trap>

Attribute and children of the node:

The body of the Trap instruction is instantaneously started, and can be instantaneously exited at a specific point, via the Exit instruction.

<hiphop.exit/>

Attribute of the node:

The exit point of a trap. It must be enclosed in the Trap instruction. This instruction immediately terminate and jump to the following instruction of the exited trap.

In the following example, the signal B is never emitted, whereas A and C are emitted:

    <hh.emit A/>
    <hh.trap T>
      <hh.sequence>
        <hh.exit T/>
        <hh.emit B/>
      </hh.sequence>
    </hh.trap>
    <hh.emit C/>

<hiphop.abort>

Attributes and children of the node:

The Abort statement instantaneously start its body. The body is instantaneously preempted and the Abort terminates at the instant where the delay expression elapses.

In the following example, S is emitted at the first instant. On the following reaction, O is not emitted, but W is emitted:

<hh.abort pre S>
   <hh.emit S/>
   <hh.pause/>
   <hh.emit O/>
</hh.abort>
<hh.emit W/>

<hiphop.weakabort>

Attributes and children of the node:

The WeakAbort statement instantaneously start its body. The body is preempted and the Abort terminates at the instant where the delay expression elapses, but left the control to its body during this instant.

In the following example, S is emitted at the first instant. On the following reaction, both O and W are emitted:

<hh.weakabort pre S>
   <hh.emit S/>
   <hh.pause/>
   <hh.emit O/>
</hh.weakabort>
<hh.emit W/>

<hiphop.suspend>

Attributes and children of the node:

Instantaneously suspend its body when the delay expression elapses. The state of the body is saved, and is restore of following reaction, when the guard is not true.

In the following example, O is emitted at each reaction if I is not present. However, J is never emitted:

<hh.suspend I>
   <hh.loop>
      <hh.emit O/>
      <hh.pause/>
   </hh.loop>
</hh.suspend>
<hh.emit J/>

One of the following attribute can be used in the Suspend instruction, which represent a delay expression:

If any one of the previous form is used, the body is suspended, even is the suspend delay expression is not true anymore. The body is restarted when the until delay expression is true.

Others statements

<hiphop.await/>

Attributes of the node:

Instantaneously terminates when the delay expression elapses.

Note that if the delay expression elapses of the first time the await has control, it will be ignored, except if immediate keyword is set.

The following example will emit O when I has been emitted on the two previous reactions, and during the current reaction:

<hh.await I/>
<hh.await I/>
<hh.await I/>
<hh.emit O/>

However, because of the immediate keyword, the following example will emit O on the same instant where I is emitted :

<hh.await immediate I/>
<hh.await immediate I/>
<hh.await immediate I/>
<hh.emit O/>

The following example waits for the presence of signal I an aleatory number of times:

<hh.await I countApply=${function() {return Math.trunc(Math.randrom() * 10)}}/>

<hiphop.atom/>

Attribute of the node:

Instantaneously evaluate the given JavaScript expression.

The following example will display atom works! value of L is foo bar during the second reaction:

          <hh.emit L value=${"foo bar"}/>
          <hh.pause/>
          <hh.atom apply=${function() {
             console.log("atom works! value of L is", this.value.L);
          }}/>

<hiphop.parallel>

Children of the node:

Gives instantaneously the control to its branches in parallel. It terminates when all its branches have terminated.

The following example will emit O only when A and B have been emitted (on current or previous reactions):

    <hh.parallel>
      <hh.await A/>
      <hh.await B/>
    </hh.parallel>
    <hh.emit O/>

<hiphop.sequence>

Children of the node:

Gives sequentially the control to each of its children, in the order there are defined. The sequence is usually implicit. However, it can be used to avoid ambiguous situations:

<hiphop.parallel>
  <instruction1/>
  <instruction2/>
  <instruction3/>
  ...
  <instructionN/>
</hiphop.parallel>

Here, there will be N branches executed in parallel. But if the instruction 2 and 3 must be sequentially executed, the sequence is mandatory:

<hiphop.parallel>
  <instruction1/>
  <hiphop.sequence>
    <instruction2/>
    <instruction3/>
  </hiphop.sequence>
  ...
  <instructionN/>
</hiphop.parallel>

<hiphop.run/>

Attributes of the node:

Instantaneously execute module. Terminates when module as terminated. Signals in the callee module which have a same name of signals in the caller module are automatically bound. Signals with different name can be bound as the following:

<hh.run module=${fooModule} X=A Y=B/>

Signals X and Y for fooModule are respectively bound to signals A and B of the caller module.

In the following example, the module run2 calls m1 :

var m1 = <hh.module S U W Z>
  <hh.parallel>
    <hh.if S>
      <hh.emit W/>
    </hh.if>
    <hh.if U>
      <hh.emit Z/>
    </hh.if>
  </hh.parallel>
</hh.module>;

var inSig={accessibility: hh.IN}
var run2 = <hh.module S=${inSig} U=${inSig} A B>
  <hh.run module=${m1} W=A Z=B/>
</hh.module>;

<hiphop.exec/>

Attributes of the node:

The exec statement immediately call apply function. The apply function must return immediately. It usually makes an asynchronous call, or spawn a worker. One the asynchronous call, or worker, has finish its work, it must notify the runtime by calling one of this terminating functions:

Exec statement is not instantaneous. It returns on the following reaction after one terminating function call.

Note that this.notify() and this.notifyAndReact() can take an optional value, if signal is given. In that case signal will be instantaneously emitted when exec returns, which the given value.

The following example emit the signal O (with value 5) 3 seconds after the reaction:

        <hh.exec O apply=${function() {
           setTimeout(() => this.notifyAndReact(5), 3000);
        }}/>
      </hh.module>

Signal declarations

Global signals

Global signals indent to send and received values between the environment (JavaScript) and the reactive Hiphop.js program, on which any instruction can access to them. The definition of global signal are in the Module instruction. The name of the signal must be a valid JavaScript symbol. The following example define a reactive program with 4 global signals, namely A, B, C and signalD:

<hiphop.module A B C signalD>
  <!-- Hiphop.js instructions -->
</hiphop.module>

Global signal are instantiated only one, when the reactive program is compiled.

Local signals

Local signals are invisible from the host language. A local signal is defined in a Local instruction. The following example defines two local signals, local1 and local2:

<hh.local local1 local2>
  <!-- Hiphop.js instructions -->
<hh.local>

The body of the Local instruction is a scope. Only the instructions embedded on it can access to signal local1 and local2.

Local signal are instantiated when the control reach the Local instruction. Therefore, if local signal are defined inside a Loop instruction, new instances of signals will be made each time the Loop re-loop. Any value or status of local signal of the previous iteration are dropped.

For instance, in the following program, the output S present is never display. Indeed, even is S is emitted before re-looping, a new local signal S is instantiated when re-looping. Therefore, the state of S of the previous instance is lost:

<hh.local S>
   <hh.if S>
      <hh.atom apply=${function() {console.log("S present")}}/>
   </hh.if>
   <hh.pause/>
   <hh.emit S/>
</hh.local>

Signal properties

Signals can be tuned by several specific properties. The properties are given to the signal during its definition, through a JavaScript object, as in the following examples:

<hh.module sig=${{initValue: 5}}> ... </hh.module>
<hh.local sig=${{initValue: 5}}> ... </hh.local>

Accessibility of a signal

By default, global signals can be read and write by the JavaScript world. However, it is possible to restrict the access to write-only or read-only. Accessibility attribute is ignored for local signals, as they are by definition hidden from the JavaScript world.

The accessibility is defined by the following attribute:

This attribute can takes one of the following values:

Initialization of signal

Signal can be automatically initialized with a value. If the signal is global and has not been emitted via input method of the ReactiveMachine, it is initialized before the first reaction. If the signal is local, it is initialized when the control reach the Local statement that defines the signal.

initApply works like JavaScript expression when apply is used. Therefore, value of presence status of signal can be used in the given JavaScript function.

Re-initialization of signal

Signal can be automatically re-initialized with a value. If the signal is global and has not been emitted via input method of the ReactiveMachine, it is re-initialized before each reaction. If the signal is local, it is re-initialized before each reaction where the control was left on the previous reaction into Local statement that defines the signal.

reinitApply works like JavaScript expression when apply is used. Therefore, value of presence status of signal can be used in the given JavaScript function.

Combine signal

In order to be allowed to make multiple valued emission of the same signal during the same instant, a combination function can be given. It must be commutative, and takes two parameters: the former is the value of the signal before the emission, and the last, the emitted value:

For instance, the following example emits the signal S with the value 6:

<hh.module S=${{combine: (x, y) => x + y}}>
   <hh.emit S value=${2}/>
   <hh.emit S value=${1}/>
   <hh.emit S value=${3}/>
</hh.module>

Expression

JavaScript Expression

In Hiphop.js, a JavaScript expression is defined by one of the following attribute:

If value is used, the given JavaScript value is given to the instruction using it. Therefore, this value never change during the whole life of the program (except if the value is a reference to a JavaScript object, and if this object is modified).

For instance, the following program emits the value 7 to signal S at each reaction:

var x = 7;

<hh.module S>
   <hh.sustain S value=${x++}/>
</hh.module>

If apply is used, the given JavaScript functional value is evaluated at runtime at each instant, if and when the Hiphop.js using it has control. The return value is then given to the instruction. As this expression is evaluated during the runtime, it can read signal status and values which are in the scope. Those properties can be acceded via the this object of the given function:

The value returned by the expression is given to Hiphop.js instruction. It can be used (in Emission statements, for instance) or ignored (in Atom statement, for instance).

The following example show an expression used for conditional branching test. O1 is emitted if I1 is present, and O2 is emitted if the value of I2 more that 2:

      <hh.loop>
        <hh.if apply=${function() {return this.present.I1}}>
          <hh.emit O1/>
        </hh.if>
        <hh.if apply=${function() {return this.value.I2 > 2}}>
          <hh.emit O2/>
        </hh.if>
        <hh.pause/>
      </hh.loop>

The following example, signal S is emitted with its value on previous instant incremented by 1, and signal O is emitted with the S value:

          <hh.emit S apply=${function() {return this.preValue.S + 1}}/>
          <hh.emit O apply=${function() {return this.value.S}}/>

Delay Expression

A delay expression is a JavaScript expression. However, its return value is used as the expression of a boolean test. The delay expressions elapses if the test is true. The following behavior depends of the instruction using this delay.

A delay expression can be specialized for signals status, using a different syntax of the JavaScript expression. It contains a signal name and an optional pre attribute. For instance, the following instructions use a signal expression.

<hh.await SignalFoo/>

The signal expression is the name of the signal SignalFoo. It returns true if SignalFoo is present in the instant, false otherwise.

<hh.await pre SignalBar/>

The signal expression is pre SignalBar. It returns true if SignalBar was present on the previous instant, false otherwise.

Counter Expression

Each time an instruction using a counter expression is started, it initializes an internal counter with the return value of this counter expression. That value must be a positive integer. It is defined with one of the following attribute:

As for JavaScript expressions, countApply can accesses to signal presence and values, via the receiver of the given JavaScript function.

Runtime & Reactive machine

A reactive machine is an instance of a Hiphop.js program. It provides a JavaScript API allowing interactions between imperative world and reactive world:

Callbacks given to addEventListener must take exactly one argument. This argument is an object containing the following properties:

The following example show how is build a reactive machine, and how to start a reaction.

const hh = require("hiphop");

const prg =
   <hh.module>
     <!-- Hiphop.js program -->
   <hh.module>

var machine = new hh.ReactiveMachine(prg, "prgName");

machine.react(); // trigger a reaction of the program