HipHop Staging
==============
> [!WARNING]
> Using staging requires familiarities with code generation and
> compilation techniques and a deep understanding of HipHop's behavior.
> HipHop beginners should refrain from using staging until they
> have acquired that knowledge.
HipHop is a _staged_ programming language. That is, although hidden
by the syntax, _all_ HipHop programs are the result of a JavaScript
execution and _all_ HipHop programs are first class values in the
JavaScript world.
From the JavaScript standpoint, the `hiphop` construct (see
[Syntax](./syntax/hiphop.bnf)) is an expression, which evaluates to
a HipHop programs. This value representing a HipHop program can be
manipulated as any other JavaScript value. It can be stored in variables
or data structures, passed and returned from functions, etc. For instance,
evaluating the following program:
```hiphop
const f = hiphop fork { await (a.now); } par { await (b.now) };
console.log(f);
```
Displays something such as:
```hiphop
hiphop.FORK { ... }
```
A HipHop program being a JavaScript value, it can be used as any ordinary
value. Hence, we can modify the previous example for:
```hiphop
function makeFork() {
return hiphop fork { await (a.now); } par { await (b.now) };
}
const f = makeFork();
```
HipHop values can be assembled together to form more complex HipHop programs.
Example:
```hiphop
const aa = hiphop { await (a.now) };
const ab = hiphop { await (be.now) };
function makeFork(s1, s2) {
return hiphop fork { ${s1} } par { ${s2} };
}
const f = makeFork(aa, ab);
```
To use this program fragment it has be installed in a HipHop machine.
This can be acheived with:
```hiphop
import * as hh from "@hop/hiphop";
const aa = hiphop { await (a.now) };
const ab = hiphop { await (be.now) };
function makeFork(s1, s2) {
return hiphop fork { ${s1} } par { ${s2} };
}
const f = makeFork(aa, ab);
const prgm = hiphop module() {
in a, b;
${f}
}
const m = new hh.ReactiveMachine(prgm);
m.react({a: 1, b: 2});
```
Generating statements
---------------------
The HipHop syntax provides _escapes_ that enable HipHop programs to be
assembled from separately developed statements. Within HipHop, the
escape sequence ${...} (similar to the escape sequence of
JavaScript string templates), _inserts_ a HipHop statement into the
program being build. For instance, compare the two equivalent
programs. The first one uses any stagging facility.
★ [staging-abro.hh.js](../test/staging-abro.hh.js)
The second one, which executes similarly and produces the same result does not:
★ [abro.hh.js](../test/abro.hh.js)
Note in this example, how HipHop statments are stored in JavaScript
variables and then inserted into the main program.
Inside a Hiphop statement an escape sequence ${...} is replaced
at compile-time by the corresponding value. The type of the inserted
value depends on the context of the escape sequence.
* an *array of statements*, when used, after the `fork` keyword;
of HipHop statement;
* a *statement* or an *array of statements*, when used inside a sequence;
* a *string*, when used in the signal position of an `emit` statement;
* a *HipHop statement* otherwise.
In the following example, the three arms of a `fork` construct are first
stored in a JavaScript array and then inserted into the constructed
HipHop program.
★ [staging-abcro.hh.js](../test/staging-abcro.hh.js)
In the second example:
★ [staging-emit-if2.hh.js](../test/staging-emit-if2.hh.js)
The `emit` statements uses generated signal names.
This last example illustrates many of the staging features, included
those described in the next sections. It shows how to generate a `fork`
construct with as many branches as values contained in a JavaScript
array. It shows how to wait for and emit signals whose names are generated.
★ [staging-fork.hh.js](../test/staging-fork.hh.js)
Dynamic Signal Names in Delay Expressions
-----------------------------------------
When HipHop programs are generated dynamically using the staging facilities,
it happens that delay expressions (e.g., used in `if` or `await` statements)
should used dynamically generated signal names. This is accomplished
using the JavaScript `this[expre]` syntax. For instance, in the following
example:
★ [staging-emit-if2.hh.js](../test/staging-emit-if2.hh.js)
The two HipHop `if` statements uses dynamic signal expressions for
refering to signals `B` and `C`.
Generated Modules
-----------------
This example uses a module generator (the function `Timer`). HipHop modules are
lexically scopped with regard to Hop environment so all the expressions they
contain can refer to Hop variables bound in the environment. In this example,
the function parameter `timeout` is used in the `async` form to set the
timeout duration.
The new modules are directly created when run, using the dollar-form
in the main HipHop program.
★ [run3.hh.js](../test/run3.hh.js)
The input/output signal declaration syntax enables staging. The
`...` form can be followed by a _dollar_ expression that should evaluate
to an array of strings that will denote the names of the declared signals.
★ Example: [staging-incr-branch2.hh.js](../test/staging-incr-branch2.hh.js)
Dynamic Signal Names in Run Expressions
---------------------------------------
Signals aliased in a `run` command can declared with a dollar-form. This
enables a generated signal name on the main module to be bound to a static
signal name on the ran module. Example:
★ Example: [run6.hh.js](../test/run6.hh.js)
Generated Interfaces
--------------------
Staged interfaces are created by using regular objects whose properites
are HipHop signal descriptor. An signal descriptor is described by the
following properties:
* `direction`: a string that might either be `"IN"`, `"OUT"`, or `"INOUT"`;
* `init`: a JavaScript thunk (a function with no argument) that initializes
the signal during the reaction;
* `combine`: an associated binary function used for multiple emissions
during a reaction.
* `transient`: a boolean to declare transient signals, i.e., signales not
preserving their `nowval` value accross instants.
In a `run` statement, the signal bindings can also being staged using
JavaScript objects associating bound names. In these binding objects,
special properties `*` and `+` play the same role as the `*` and
`+` operators of the non-staged binders (see [modules](./lang/module.md)).
Example:
★ [staging-interface.hh.js](../test/staging-interface.hh.js)
which can be compared to the non-staged version:
★ [interface.hh.js](../test/interface.hh.js).
Dynamic Program Modifications
-----------------------------
HipHop `fork` and `sequence` statements can be modified in between two
reactions using the function `appendChild`.
### mach.getElementById(id) ###
Returns the HipHop `fork` or `sequence` labeld with `id`.
### mach.appendChild(node, hhstmt) ###
Append a child to a statement. If `node` is a `fork` construct, the
child is added as a new parallel branch. If node is a sequence, the
child is added after the node children.
### mach.removeChild(node, child) ###
Remove a child.
★ Example [appendseqchild.hh.js](../test/appendseqchild.hh.js)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[[main page]](../README.md) | [[documentation]](./README.md) | [[license]](./license.md)