A First Reactor
This article has examples in the following target languages:
- C
- C++
- Python
- Rust
- TypeScript
Minimal Example​
A minimal but complete Lingua Franca file with one reactor is this:
Every Lingua Franca program begins with a target declaration that specifies the language in which reactions are written. This is also the language of the program(s) generated by the Lingua Franca code generator.
Every LF program also has a main
or federated
(depending on the target support) reactor, which is the top level of a hierarchy of contained and interconnected reactors. The above simple example has no contained reactors.
The main
reactor above has a single reaction
, which is triggered by the startup
trigger. This trigger causes the reaction to execute at the start of the program. The body of the reaction, delimited by {= ... =}
, is ordinary $target-language$ code which, as we will see, has access to a number of functions and variables specific to Lingua Franca.
Examples​
Examples of Lingua Franca programs can be found in the Lingua Franca Playground.
The regression tests have a rich set of examples that illustrate every feature of the language.
Structure of an LF Project​
The Lingua Franca tools assume that LF programs are put into a file with a .lf
extension that is stored somewhere within a directory called src
. To compile and run the above example, choose a project root directory, create a src
directory within that, and put the above code into a file called, say, src/HelloWorld.lf
. You can compile the code on the command line or within Visual Studio Code. On the command line this will look like this:
> lfc src/HelloWorld.lf
... output from the code generator and compiler ...
After this completes, two additional directories will have been created within
the project root, bin
and src-gen
. The bin
directory has an
executable file called HelloWorld
. Executing that file will result, not
surprisingly, in printing "Hello World". The generated source files will be
in a subdirectory called HelloWorld
within src-gen
.
After this completes, two additional directories will have been created within
the project root, bin
and src-gen
. The bin
directory has an
executable file called HelloWorld
. Executing that file will result, not
surprisingly, in printing "Hello World". The generated source files will be
in a subdirectory called HelloWorld
within src-gen
.
After this completes, two additional directories will have been created within
the project root, bin
and src-gen
. The bin
directory has an
executable file called HelloWorld
. Executing that file will result, not
surprisingly, in printing "Hello World". The generated source files will be
in a subdirectory called HelloWorld
within src-gen
.
After this completes, an additional src-gen
directory will have been created within the project root. The generated code will be in subdirectory called HelloWorld
within src-gen
. The output from the code generator will include instructions for executing the generated code:
#####################################
To run the generated program, use:
node ...path-to-project.../src-gen/HelloWorld/dist/HelloWorld.js
#####################################
#####################################
To run the generated program, use:
python3 ...path-to-project.../src-gen/HelloWorld/HelloWorld.py
#####################################
After this completes, an additional src-gen
directory will have been created within the project root. The generated code will be in subdirectory called HelloWorld
within src-gen
. The output from the code generator will include instructions for executing the generated code:
#####################################
To run the generated program, use:
node ...path-to-project.../src-gen/HelloWorld/dist/HelloWorld.js
#####################################
#####################################
To run the generated program, use:
python3 ...path-to-project.../src-gen/HelloWorld/HelloWorld.py
#####################################
Reactor Block​
A reactor
is a software component that reacts to input events, timer events, and internal events. It has private state variables that are not visible to any other reactor. Its reactions can consist of altering its own state, sending messages to other reactors, or affecting the environment through some kind of actuation or side effect (e.g., printing a message, as in the above HelloWorld
example).
The general structure of a reactor definition is as follows:
Contents within square brackets are optional, contents within <...>
are user-defined, and each line may appear zero or more times, as explained in the next pages. Parameters, inputs, outputs, timers, actions, and contained reactors all have names, and the names are required to be distinct from one another.
If the reactor
keyword is preceded by main
or federated
, then this reactor will be instantiated and run by the generated code.
Any number of reactors may be defined in one file, and a main
or federated
reactor need not be given a name, but if it is given a name, then that name must match the file name.
Reactors may extend other reactors, inheriting their properties, and a file may import reactors from other files. If an imported LF file contains a main
or federated
reactor, that reactor is ignored (it will not be imported). This makes it easy to create a library of reusable reactors that each come with a test case or demonstration in the form of a main reactor.
Comments​
Lingua Franca files can have C/C++/Java-style comments and/or Python-style comments. All of the following are valid comments:
// Single-line C-style comment.
/*
* Multi-line C-style comment.
*/
# Single-line Python-style comment.