diff --git a/docs/developer/regression-tests.mdx b/docs/developer/regression-tests.mdx index 6234af60b..749bad84f 100644 --- a/docs/developer/regression-tests.mdx +++ b/docs/developer/regression-tests.mdx @@ -5,7 +5,7 @@ description: Regression Tests for Lingua Franca. Lingua Franca comes with an extensive set of regression tests that are executed on various platforms automatically whenever an update is pushed to the LF repository. There are two categories of tests: -- **Unit tests** are Java or Kotlin methods in our code base that are labeled with the `@Test` directive. These tests check individual functions of the code generation infrastructure. These are located in the `src/test` directory of each subproject within the repository. +- **Unit tests** are Java methods in our code base that are labeled with the `@Test` directive. These tests check individual functions of the code generation infrastructure. These are located in the `core/src/test` directory. - **Integration tests** are complete Lingua Franca programs that are compiled and executed automatically. A test passes if it successfully compiles and runs to completion with normal termination (return code 0). These tests are located in the `test` directory at the root of the LF repo, with one subdirectory per target language. Their implementation can be found in the `core/src/integrationTest` directory. The integration tests are also executed through JUnit using methods with `@Test` directives, but they are executed separately. @@ -26,7 +26,7 @@ You can specify any valid target. If you run the task without specifying the tar The `targetTest` task is essentially a convenient shortcut for the following: ``` -./gradew core:integrationTest --test org.lflang.tests.runtime.Test.* +./gradlew core:integrationTest --tests "org.lflang.tests.runtime.Test.*" ``` If you prefer have more control over which tests are executed, you can also use this more verbose version. diff --git a/docs/reference/target-declaration.mdx b/docs/reference/target-declaration.mdx index cd8916db2..f7304910f 100644 --- a/docs/reference/target-declaration.mdx +++ b/docs/reference/target-declaration.mdx @@ -11,6 +11,8 @@ import { +# Target Declaration + Every Lingua Franca program begins with a statement of this form: ```lf @@ -19,7 +21,7 @@ Every Lingua Franca program begins with a statement of this form: The `` gives the name of some Lingua Franca target language, which is the language in which reactions are written. This is also the language of the program(s) generated by the Lingua Franca compiler. The target languages currently supported are C, C++, Python, TypeScript, and Rust. There is also a target CCpp that is just like the C target except that it uses a C++ compiler to compile the code, thereby allowing inclusion of C++ code. -# Summary of Parameters +# Summary of Target Parameters A target specification may have optional parameters, the names and values of which depend on which specific target you are using. Each parameter is a key-value pair, where the supported keys are a subset of the following: diff --git a/docs/reference/target-language-details.mdx b/docs/reference/target-language-details.mdx index 49a4d1c30..187335bbc 100644 --- a/docs/reference/target-language-details.mdx +++ b/docs/reference/target-language-details.mdx @@ -24,19 +24,12 @@ import { -The C target for Lingua Franca is used when you specify either `C` or `CCpp` in the `target` declaration in your `.lf` file: -```lf -target C -``` -or -```lf -target CCpp -``` +The C target for Lingua Franca is used when you specify either `C` or `CCpp` in the `target` declaration in your `.lf` file. In the latter case, a C++ compiler will be used, and hence your reaction bodies can written in C++ and you can include and link to C++ code. Unlike the Cpp target, you will still access the LF API through a C API. -In the C reactor target, reaction bodies are written in C and the code generator generates one or more standalone C programs that can be compiled and run on several platforms. It has been tested on macOS, Linux, Windows, Arduino, Zephyr, and several bare-metal embedded platforms. +In the C reactor target, reaction bodies are written in C and the code generator generates one or more standalone C programs that can be compiled and run on several platforms. Full documentation of the API and runtime infrastructure is available [on the code documentation site](https://lf-lang.org/reactor-c/). See particularly the [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html). This system has been tested on macOS, Linux, Windows, Arduino, Zephyr, and several bare-metal embedded platforms. The single-threaded version (which you get by setting the `threading` target parameter to `false`) is the most portable, requiring only a handful of common C libraries (see [Included Libraries](#included-libraries) below). The multithreaded version requires a small subset of the POSIX thread library (`pthreads`) and transparently executes in parallel on a multicore machine while preserving the deterministic semantics of Lingua Franca. @@ -79,9 +72,9 @@ In terms of raw performance on CPU intensive operations, TypeScript reactors are **Important:** The Rust target is still quite preliminary. This is early WIP documentation to let you try it out if you're curious -In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rust), and depends on the Rust standard library. +In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rs), and depends on the Rust standard library. -Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rust/ +Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rs/ LF-Rust generates a Cargo project per compiled main reactor. This specification assumes in some places that the user is somewhat familiar with how Cargo works. If you're not, here's a primer: @@ -213,7 +206,7 @@ To have Lingua Franca generate C code, start your `.lf` file with one of the fol Note that for all LF statements, a final semicolon is optional. If you are writing your code in C, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). The second form, `CCpp`, is used when you wish to use a C++ compiler to compile the generated code, thereby allowing your reaction bodies to be written in C++ and to call C++ code. @@ -250,7 +243,7 @@ To have Lingua Franca generate C++ code, start your `.lf` file with the followin Note that for all LF statements, a final semicolon is optional. If you are writing your code in C++, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -263,7 +256,7 @@ To have Lingua Franca generate Python code, start your `.lf` file with the follo Note that for all LF statements, a final semicolon is optional. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -1073,7 +1066,7 @@ reactor Print { ### Dynamically Allocated Data -A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/SetDestructor.lf) example. +A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/TokenSetToken.lf) example. Suppose the data structure of interest, its constructor, destructor, and copy_constructor are defined as follows: @@ -1618,11 +1611,11 @@ Inputs and outputs in the Rust target are accessed using the `set` and `get` met In the C target, the value of a time instant or interval is an integer specifying a number of nanoseconds. An instant is the number of nanoseconds that have elapsed since January 1, 1970. An interval is the difference between two instants. When an LF program starts executing, logical time is (normally) set to the instant provided by the operating system. (On some embedded platforms without real-time clocks, it will be set instead to zero.) -Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. +Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. Lingua Franca uses a superdense model of time. A reaction is invoked at a logical **tag**, a struct consisting of a `time` value (an `instant_t`, which is a `int64_t`) and a `microstep` value (a `microstep_t`, which is an `uint32_t`). The tag is guaranteed to not increase during the execution of a reaction. Outputs produced by a reaction have the same tag as the inputs, actions, or timers that trigger the reaction, and hence are **logically simultaneous**. -The time structs and functions for working with time are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h). The most useful functions are: +The time structs and functions for working with time are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html). The most useful functions are: - `tag_t lf_tag()`: Get the current tag at which this reaction has been invoked. - `int lf_tag_compare(tag_t, tag_t)`: Compare two tags, returning -1, 0, or 1 for less than, equal, and greater than. @@ -2619,7 +2612,7 @@ This version carries an `int` value. The data type of the action is required to > `lf_schedule_token(, , );` -This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: +This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: ```lf-c reactor DelayPointer(delay:time(100 ms)) { @@ -2711,7 +2704,7 @@ FIXME: List them here -Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html#method.schedule) function: +Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html#method.schedule) function: ```rust // schedule without additional delay @@ -2769,7 +2762,7 @@ FIXME: Details needed here. -A suite of useful functions is provided in [util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. +A suite of useful functions is provided in [logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. - `LF_PRINT_DEBUG(format, ...)`: Use this for verbose messages that are only needed during debugging. Nothing is printed unless the [target](target-declaration.mdx#logging) parameter `logging` is set to `debug`. THe overhead is minimized when nothing is to be printed. @@ -2846,9 +2839,9 @@ Note that when building with a release profile (i.e., target property `build-typ #### Libraries Available in All Programs -Reactions in C can use a number of pre-defined functions, macros, and constants without having to explicitly include any header files: +Reactions in C can use a number of [pre-defined functions](https://www.lf-lang.org/reactor-c/group__API.html), macros, and constants without having to explicitly include any header files: -- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/d2/dcd/tag_8h.html)): +- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html)): - Specifying time value, such as `MSEC` and `FOREVER` - Time data types, such as `tag_t` and `instant_t` @@ -2856,12 +2849,12 @@ Reactions in C can use a number of pre-defined functions, macros, and constants - **Ports** - - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/da/d00/port_8h.html)) + - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/port_8h.html)) - **Scheduling actions** - - Schedule future events, such as `lf_schedule` and `lf_schedule_value` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) + - Schedule future events, such as `lf_schedule` and `lf_schedule_value` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) - **Reactor Names** @@ -2884,11 +2877,11 @@ These are useful when your application needs to open and read additional files. - **Miscellaneous** - - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Checking deadlines, `lf_check_deadline` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) - - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` ([trace.h](https://www.lf-lang.org/reactor-c/d1/d1b/trace_8h.html)) - - Printing utilities, such as `lf_print` and `lf_print_error` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) - - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) + - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Checking deadlines, `lf_check_deadline` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) + - Defining and recording tracepoints, such as `lf_tracing_register_trace_event` and `lf_tracing_tracepoint` (See [Tracing API](https://www.lf-lang.org/reactor-c/group__Tracing.html)) + - Printing utilities, such as `lf_print` and `lf_print_error` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) + - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) #### Standard C Libraries @@ -2905,7 +2898,7 @@ Hence, programmers are free to use functions from these libraries without explic #### Available Libraries Requiring #include More sophisticated library functions require a `#include` statement in a `preamble`. -Specifically, [platform.h](https://www.lf-lang.org/reactor-c/de/d03/platform_8h.html) includes the following: +Specifically, [the platform API](https://www.lf-lang.org/reactor-c/group__Platform.html) includes the following: - Sleep functions such as `lf_sleep` - Mutual exclusion such as `lf_critial_section_enter` and `lf_critical_section_exit` @@ -2918,10 +2911,12 @@ The threading functions are only available for platforms that support multithrea A few utility libraries are provided, but require considerably more setup. These also help to illustrate how to incorporate your own libraries. -- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/d1/dcb/audio__loop_8h.html) -- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/d3/d8a/wave__file__reader_8h.html) -- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/dc/d44/deque_8h.html) -- An ncurses terminal interface for I/O: [sensor_simulator.h](https://www.lf-lang.org/reactor-c/dc/de9/sensor__simulator_8h.html) +- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/audio__loop_8h.html) +- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/wave__file__reader_8h.html) +- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/deque_8h.html) +- A hashmap implementation: [hashmap.h](https://www.lf-lang.org/reactor-c/hashmap_8h.html) (with a [specialization for pointers](https://www.lf-lang.org/reactor-c/pointer__hashmap_8h.html)) +- A hashset implementation: [hashset.h](https://www.lf-lang.org/reactor-c/hashset_8h.html) (with a [hashset_iterator](https://www.lf-lang.org/reactor-c/hashset__iterator_8h.html)) +- An ncurses terminal interface for I/O: [sensor_simulator.h](https://www.lf-lang.org/reactor-c/sensor__simulator_8h.html) @@ -3038,7 +3033,7 @@ The execution algorithm ensures that no reaction executes until all reactions th ### Single Threaded Implementation -By giving the `single-threaded` [target option](target-declaration.mdx#single-threaded) or the `--single-threaded` [command-line argument](target-declaration.mdx#command-line-arguments), the generated program will execute the program using only a single thread. This option is most useful for creating programs to run on bare-metal microprocessors that have no threading support. On such platforms, mutual exclusion is typically realized by disabling interrupts. +By giving the `single-threaded` [target option](./target-declaration.mdx) or the `--single-threaded` [command-line argument](target-declaration.mdx#command-line-arguments), the generated program will execute the program using only a single thread. This option is most useful for creating programs to run on bare-metal microprocessors that have no threading support. On such platforms, mutual exclusion is typically realized by disabling interrupts. The execution strategy is to have two queues of pending accessor invocations, one that is sorted by tag (the **event queue**) and one that is sorted by priority (the **reaction queue**). @@ -3247,7 +3242,7 @@ The Lingua Franca compiler automatically invokes other programs as it compiles a ### package.json -Node.js uses a [package.json](https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. +Node.js uses a [package.json](https://nodesource.com/blog/the-basics-of-package-json) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. ### tsconfig.json @@ -3531,7 +3526,7 @@ cargo-dependencies: { ``` The dependency is always included, with defaults picked by LFC. The location information (_path_/_git_/_version_ key) is optional. -See [reactor_rt](https://lf-lang.github.io/reactor-rust/reactor_rt/index.html) for the supported features. +See [reactor_rt](https://lf-lang.github.io/reactor-rs/reactor_rt/index.html) for the supported features. #### Linking support files @@ -3589,7 +3584,7 @@ Reactions are each generated in a separate method of the reactor struct. Reactio Undeclared dependencies, and dependencies on timers and `startup` or `shutdown`, do not generate a parameter. -The [`ReactionCtx`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. +The [`ReactionCtx`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. For instance: diff --git a/docs/writing-reactors/reactions.mdx b/docs/writing-reactors/reactions.mdx index e6a2a9356..6f0ca4c6c 100644 --- a/docs/writing-reactors/reactions.mdx +++ b/docs/writing-reactors/reactions.mdx @@ -28,7 +28,7 @@ Reactions may optionally be named. The name is cosmetic and may serve as additio The reaction's behavior is defined by its body, which should be given in the target programming language. Note that the reaction body may only read from actions and ports that it has declared as triggers or uses, and it may only write to actions and ports that it has declared as an effect. The target code generators implement a scoping mechanism, such that only variables that are declared in the reaction signature are accessible in the reaction body. -In some targets, the reaction body may be omitted and the body can be defined natively in the target language in an external file. See the section on [Bodyless Reactions](#bodyless-reactions) for details. +In some targets, the reaction body may be omitted and the body can be defined natively in the target language in an external file. See the section on [Reaction Declarations](./reaction-declarations.mdx) for details. ## Reaction Order @@ -124,8 +124,3 @@ For details, see the [Modal Reactors](../writing-reactors/modal-models.mdx) sect - - -## Bodyless Reactions - -See [Reaction Declarations](./reaction-declarations.mdx). \ No newline at end of file diff --git a/versioned_docs/version-0.5.0/reference/target-language-details.mdx b/versioned_docs/version-0.5.0/reference/target-language-details.mdx index e207a0d0f..c320ffead 100644 --- a/versioned_docs/version-0.5.0/reference/target-language-details.mdx +++ b/versioned_docs/version-0.5.0/reference/target-language-details.mdx @@ -67,9 +67,9 @@ In terms of raw performance on CPU intensive operations, TypeScript reactors are **Important:** The Rust target is still quite preliminary. This is early WIP documentation to let you try it out if you're curious -In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rust), and depends on the Rust standard library. +In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rs), and depends on the Rust standard library. -Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rust/ +Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rs/ LF-Rust generates a Cargo project per compiled main reactor. This specification assumes in some places that the user is somewhat familiar with how Cargo works. If you're not, here's a primer: @@ -199,7 +199,7 @@ To have Lingua Franca generate C code, start your `.lf` file with one of the fol Note that for all LF statements, a final semicolon is optional. If you are writing your code in C, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). The second form, `CCpp`, is used when you wish to use a C++ compiler to compile the generated code, thereby allowing your C reactors to call C++ code. @@ -238,7 +238,7 @@ To have Lingua Franca generate C++ code, start your `.lf` file with the followin Note that for all LF statements, a final semicolon is optional. If you are writing your code in C++, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -251,7 +251,7 @@ To have Lingua Franca generate Python code, start your `.lf` file with the follo Note that for all LF statements, a final semicolon is optional. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -1061,7 +1061,7 @@ reactor Print { ### Dynamically Allocated Data -A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/SetDestructor.lf) example. +A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/TokenSetToken.lf) example. Suppose the data structure of interest, its constructor, destructor, and copy_constructor are defined as follows: @@ -1576,11 +1576,11 @@ Inputs and outputs in the Rust target are accessed using the `set` and `get` met In the C target, the value of a time instant or interval is an integer specifying a number of nanoseconds. An instant is the number of nanoseconds that have elapsed since January 1, 1970. An interval is the difference between two instants. When an LF program starts executing, logical time is (normally) set to the instant provided by the operating system. (On some embedded platforms without real-time clocks, it will be set instead to zero.) -Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. +Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. Lingua Franca uses a superdense model of time. A reaction is invoked at a logical **tag**, a struct consisting of a `time` value (an `instant_t`, which is a `int64_t`) and a `microstep` value (a `microstep_t`, which is an `uint32_t`). The tag is guaranteed to not increase during the execution of a reaction. Outputs produced by a reaction have the same tag as the inputs, actions, or timers that trigger the reaction, and hence are **logically simultaneous**. -The time structs and functions for working with time are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h). The most useful functions are: +The time structs and functions for working with time are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html). The most useful functions are: - `tag_t lf_tag()`: Get the current tag at which this reaction has been invoked. - `int lf_tag_compare(tag_t, tag_t)`: Compare two tags, returning -1, 0, or 1 for less than, equal, and greater than. @@ -2577,7 +2577,7 @@ This version carries an `int` value. The data type of the action is required to > `lf_schedule_token(, , );` -This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: +This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: ```lf-c reactor DelayPointer(delay:time(100 ms)) { @@ -2669,7 +2669,7 @@ FIXME: List them here -Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html#method.schedule) function: +Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html#method.schedule) function: ```rust // schedule without additional delay @@ -2727,7 +2727,7 @@ FIXME: Details needed here. -A suite of useful functions is provided in [util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. +A suite of useful functions is provided in [logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. - `LF_PRINT_DEBUG(format, ...)`: Use this for verbose messages that are only needed during debugging. Nothing is printed unless the [target](target-declaration.mdx#logging) parameter `logging` is set to `debug`. THe overhead is minimized when nothing is to be printed. @@ -2804,9 +2804,9 @@ Note that when building with a release profile (i.e., target property `build-typ #### Libraries Available in All Programs -Reactions in C can use a number of pre-defined functions, macros, and constants without having to explicitly include any header files: +Reactions in C can use a number of [pre-defined functions](https://www.lf-lang.org/reactor-c/group__API.html), macros, and constants without having to explicitly include any header files: -- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/d2/dcd/tag_8h.html)): +- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html)): - Specifying time value, such as `MSEC` and `FOREVER` - Time data types, such as `tag_t` and `instant_t` @@ -2814,12 +2814,12 @@ Reactions in C can use a number of pre-defined functions, macros, and constants - **Ports** - - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/da/d00/port_8h.html)) + - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/port_8h.html)) - **Scheduling actions** - - Schedule future events, such as `lf_schedule` and `lf_schedule_value` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) + - Schedule future events, such as `lf_schedule` and `lf_schedule_value` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) - **File Access** @@ -2836,11 +2836,11 @@ These are useful when your application needs to open and read additional files. - **Miscellaneous** - - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Checking deadlines, `lf_check_deadline` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) - - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` ([trace.h](https://www.lf-lang.org/reactor-c/d1/d1b/trace_8h.html)) - - Printing utilities, such as `lf_print` and `lf_print_error` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) - - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) + - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Checking deadlines, `lf_check_deadline` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) + - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` (See [Tracing API](https://www.lf-lang.org/reactor-c/group__Tracing.html)) + - Printing utilities, such as `lf_print` and `lf_print_error` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) + - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) #### Standard C Libraries @@ -2857,7 +2857,7 @@ Hence, programmers are free to use functions from these libraries without explic #### Available Libraries Requiring #include More sophisticated library functions require a `#include` statement in a `preamble`. -Specifically, [platform.h](https://www.lf-lang.org/reactor-c/de/d03/platform_8h.html) includes the following: +Specifically, [the platform API](https://www.lf-lang.org/reactor-c/group__Platform.html) includes the following: - Sleep functions such as `lf_sleep` - Mutual exclusion such as `lf_critial_section_enter` and `lf_critical_section_exit` @@ -2870,9 +2870,9 @@ The threading functions are only available for platforms that support multithrea A few utility libraries are provided, but require considerably more setup. These also help to illustrate how to incorporate your own libraries. -- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/d1/dcb/audio__loop_8h.html) -- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/d3/d8a/wave__file__reader_8h.html) -- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/dc/d44/deque_8h.html) +- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/audio__loop_8h.html) +- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/wave__file__reader_8h.html) +- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/deque_8h.html - An ncurses terminal interface for I/O: [sensor_simulator.h](https://www.lf-lang.org/reactor-c/dc/de9/sensor__simulator_8h.html) @@ -3179,7 +3179,7 @@ The Lingua Franca compiler automatically invokes other programs as it compiles a ### package.json -Node.js uses a [package.json](https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. +Node.js uses a [package.json](https://nodesource.com/blog/the-basics-of-package-json) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. ### tsconfig.json @@ -3463,7 +3463,7 @@ cargo-dependencies: { ``` The dependency is always included, with defaults picked by LFC. The location information (_path_/_git_/_version_ key) is optional. -See [reactor_rt](https://lf-lang.github.io/reactor-rust/reactor_rt/index.html) for the supported features. +See [reactor_rt](https://lf-lang.github.io/reactor-rs/reactor_rt/index.html) for the supported features. #### Linking support files @@ -3521,7 +3521,7 @@ Reactions are each generated in a separate method of the reactor struct. Reactio Undeclared dependencies, and dependencies on timers and `startup` or `shutdown`, do not generate a parameter. -The [`ReactionCtx`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. +The [`ReactionCtx`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. For instance: diff --git a/versioned_docs/version-0.6.0/reference/target-language-details.mdx b/versioned_docs/version-0.6.0/reference/target-language-details.mdx index 954493df5..9bf75a23c 100644 --- a/versioned_docs/version-0.6.0/reference/target-language-details.mdx +++ b/versioned_docs/version-0.6.0/reference/target-language-details.mdx @@ -67,9 +67,9 @@ In terms of raw performance on CPU intensive operations, TypeScript reactors are **Important:** The Rust target is still quite preliminary. This is early WIP documentation to let you try it out if you're curious -In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rust), and depends on the Rust standard library. +In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rs), and depends on the Rust standard library. -Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rust/ +Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rs/ LF-Rust generates a Cargo project per compiled main reactor. This specification assumes in some places that the user is somewhat familiar with how Cargo works. If you're not, here's a primer: @@ -199,7 +199,7 @@ To have Lingua Franca generate C code, start your `.lf` file with one of the fol Note that for all LF statements, a final semicolon is optional. If you are writing your code in C, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). The second form, `CCpp`, is used when you wish to use a C++ compiler to compile the generated code, thereby allowing your C reactors to call C++ code. @@ -238,7 +238,7 @@ To have Lingua Franca generate C++ code, start your `.lf` file with the followin Note that for all LF statements, a final semicolon is optional. If you are writing your code in C++, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -251,7 +251,7 @@ To have Lingua Franca generate Python code, start your `.lf` file with the follo Note that for all LF statements, a final semicolon is optional. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -1061,7 +1061,7 @@ reactor Print { ### Dynamically Allocated Data -A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/SetDestructor.lf) example. +A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/TokenSetToken.lf) example. Suppose the data structure of interest, its constructor, destructor, and copy_constructor are defined as follows: @@ -1576,11 +1576,11 @@ Inputs and outputs in the Rust target are accessed using the `set` and `get` met In the C target, the value of a time instant or interval is an integer specifying a number of nanoseconds. An instant is the number of nanoseconds that have elapsed since January 1, 1970. An interval is the difference between two instants. When an LF program starts executing, logical time is (normally) set to the instant provided by the operating system. (On some embedded platforms without real-time clocks, it will be set instead to zero.) -Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. +Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. Lingua Franca uses a superdense model of time. A reaction is invoked at a logical **tag**, a struct consisting of a `time` value (an `instant_t`, which is a `int64_t`) and a `microstep` value (a `microstep_t`, which is an `uint32_t`). The tag is guaranteed to not increase during the execution of a reaction. Outputs produced by a reaction have the same tag as the inputs, actions, or timers that trigger the reaction, and hence are **logically simultaneous**. -The time structs and functions for working with time are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h). The most useful functions are: +The time structs and functions for working with time are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html). The most useful functions are: - `tag_t lf_tag()`: Get the current tag at which this reaction has been invoked. - `int lf_tag_compare(tag_t, tag_t)`: Compare two tags, returning -1, 0, or 1 for less than, equal, and greater than. @@ -2577,7 +2577,7 @@ This version carries an `int` value. The data type of the action is required to > `lf_schedule_token(, , );` -This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: +This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: ```lf-c reactor DelayPointer(delay:time(100 ms)) { @@ -2669,7 +2669,7 @@ FIXME: List them here -Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html#method.schedule) function: +Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html#method.schedule) function: ```rust // schedule without additional delay @@ -2727,7 +2727,7 @@ FIXME: Details needed here. -A suite of useful functions is provided in [util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. +A suite of useful functions is provided in [logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. - `LF_PRINT_DEBUG(format, ...)`: Use this for verbose messages that are only needed during debugging. Nothing is printed unless the [target](target-declaration.mdx#logging) parameter `logging` is set to `debug`. THe overhead is minimized when nothing is to be printed. @@ -2804,9 +2804,9 @@ Note that when building with a release profile (i.e., target property `build-typ #### Libraries Available in All Programs -Reactions in C can use a number of pre-defined functions, macros, and constants without having to explicitly include any header files: +Reactions in C can use a number of [pre-defined functions](https://www.lf-lang.org/reactor-c/group__API.html), macros, and constants without having to explicitly include any header files: -- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/d2/dcd/tag_8h.html)): +- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html)): - Specifying time value, such as `MSEC` and `FOREVER` - Time data types, such as `tag_t` and `instant_t` @@ -2814,12 +2814,12 @@ Reactions in C can use a number of pre-defined functions, macros, and constants - **Ports** - - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/da/d00/port_8h.html)) + - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/port_8h.html)) - **Scheduling actions** - - Schedule future events, such as `lf_schedule` and `lf_schedule_value` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) + - Schedule future events, such as `lf_schedule` and `lf_schedule_value` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) - **File Access** @@ -2836,11 +2836,11 @@ These are useful when your application needs to open and read additional files. - **Miscellaneous** - - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Checking deadlines, `lf_check_deadline` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) - - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` ([trace.h](https://www.lf-lang.org/reactor-c/d1/d1b/trace_8h.html)) - - Printing utilities, such as `lf_print` and `lf_print_error` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) - - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) + - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Checking deadlines, `lf_check_deadline` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) + - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` (See [Tracing API](https://www.lf-lang.org/reactor-c/group__Tracing.html)) + - Printing utilities, such as `lf_print` and `lf_print_error` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) + - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) #### Standard C Libraries @@ -2857,7 +2857,7 @@ Hence, programmers are free to use functions from these libraries without explic #### Available Libraries Requiring #include More sophisticated library functions require a `#include` statement in a `preamble`. -Specifically, [platform.h](https://www.lf-lang.org/reactor-c/de/d03/platform_8h.html) includes the following: +Specifically, [the platform API](https://www.lf-lang.org/reactor-c/group__Platform.html) includes the following: - Sleep functions such as `lf_sleep` - Mutual exclusion such as `lf_critial_section_enter` and `lf_critical_section_exit` @@ -2870,9 +2870,9 @@ The threading functions are only available for platforms that support multithrea A few utility libraries are provided, but require considerably more setup. These also help to illustrate how to incorporate your own libraries. -- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/d1/dcb/audio__loop_8h.html) -- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/d3/d8a/wave__file__reader_8h.html) -- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/dc/d44/deque_8h.html) +- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/audio__loop_8h.html) +- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/wave__file__reader_8h.html) +- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/deque_8h.html - An ncurses terminal interface for I/O: [sensor_simulator.h](https://www.lf-lang.org/reactor-c/dc/de9/sensor__simulator_8h.html) @@ -3179,7 +3179,7 @@ The Lingua Franca compiler automatically invokes other programs as it compiles a ### package.json -Node.js uses a [package.json](https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. +Node.js uses a [package.json](https://nodesource.com/blog/the-basics-of-package-json) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. ### tsconfig.json @@ -3463,7 +3463,7 @@ cargo-dependencies: { ``` The dependency is always included, with defaults picked by LFC. The location information (_path_/_git_/_version_ key) is optional. -See [reactor_rt](https://lf-lang.github.io/reactor-rust/reactor_rt/index.html) for the supported features. +See [reactor_rt](https://lf-lang.github.io/reactor-rs/reactor_rt/index.html) for the supported features. #### Linking support files @@ -3521,7 +3521,7 @@ Reactions are each generated in a separate method of the reactor struct. Reactio Undeclared dependencies, and dependencies on timers and `startup` or `shutdown`, do not generate a parameter. -The [`ReactionCtx`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. +The [`ReactionCtx`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. For instance: diff --git a/versioned_docs/version-0.7.0/reference/target-language-details.mdx b/versioned_docs/version-0.7.0/reference/target-language-details.mdx index 210af2eba..c58b96a2b 100644 --- a/versioned_docs/version-0.7.0/reference/target-language-details.mdx +++ b/versioned_docs/version-0.7.0/reference/target-language-details.mdx @@ -67,9 +67,9 @@ In terms of raw performance on CPU intensive operations, TypeScript reactors are **Important:** The Rust target is still quite preliminary. This is early WIP documentation to let you try it out if you're curious -In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rust), and depends on the Rust standard library. +In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rs), and depends on the Rust standard library. -Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rust/ +Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rs/ LF-Rust generates a Cargo project per compiled main reactor. This specification assumes in some places that the user is somewhat familiar with how Cargo works. If you're not, here's a primer: @@ -199,7 +199,7 @@ To have Lingua Franca generate C code, start your `.lf` file with one of the fol Note that for all LF statements, a final semicolon is optional. If you are writing your code in C, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). The second form, `CCpp`, is used when you wish to use a C++ compiler to compile the generated code, thereby allowing your C reactors to call C++ code. @@ -238,7 +238,7 @@ To have Lingua Franca generate C++ code, start your `.lf` file with the followin Note that for all LF statements, a final semicolon is optional. If you are writing your code in C++, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -251,7 +251,7 @@ To have Lingua Franca generate Python code, start your `.lf` file with the follo Note that for all LF statements, a final semicolon is optional. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -1061,7 +1061,7 @@ reactor Print { ### Dynamically Allocated Data -A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/SetDestructor.lf) example. +A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/TokenSetToken.lf) example. Suppose the data structure of interest, its constructor, destructor, and copy_constructor are defined as follows: @@ -1606,11 +1606,11 @@ Inputs and outputs in the Rust target are accessed using the `set` and `get` met In the C target, the value of a time instant or interval is an integer specifying a number of nanoseconds. An instant is the number of nanoseconds that have elapsed since January 1, 1970. An interval is the difference between two instants. When an LF program starts executing, logical time is (normally) set to the instant provided by the operating system. (On some embedded platforms without real-time clocks, it will be set instead to zero.) -Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. +Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. Lingua Franca uses a superdense model of time. A reaction is invoked at a logical **tag**, a struct consisting of a `time` value (an `instant_t`, which is a `int64_t`) and a `microstep` value (a `microstep_t`, which is an `uint32_t`). The tag is guaranteed to not increase during the execution of a reaction. Outputs produced by a reaction have the same tag as the inputs, actions, or timers that trigger the reaction, and hence are **logically simultaneous**. -The time structs and functions for working with time are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h). The most useful functions are: +The time structs and functions for working with time are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html). The most useful functions are: - `tag_t lf_tag()`: Get the current tag at which this reaction has been invoked. - `int lf_tag_compare(tag_t, tag_t)`: Compare two tags, returning -1, 0, or 1 for less than, equal, and greater than. @@ -2607,7 +2607,7 @@ This version carries an `int` value. The data type of the action is required to > `lf_schedule_token(, , );` -This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: +This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: ```lf-c reactor DelayPointer(delay:time(100 ms)) { @@ -2699,7 +2699,7 @@ FIXME: List them here -Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html#method.schedule) function: +Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html#method.schedule) function: ```rust // schedule without additional delay @@ -2757,7 +2757,7 @@ FIXME: Details needed here. -A suite of useful functions is provided in [util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. +A suite of useful functions is provided in [logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. - `LF_PRINT_DEBUG(format, ...)`: Use this for verbose messages that are only needed during debugging. Nothing is printed unless the [target](target-declaration.mdx#logging) parameter `logging` is set to `debug`. THe overhead is minimized when nothing is to be printed. @@ -2834,9 +2834,9 @@ Note that when building with a release profile (i.e., target property `build-typ #### Libraries Available in All Programs -Reactions in C can use a number of pre-defined functions, macros, and constants without having to explicitly include any header files: +Reactions in C can use a number of [pre-defined functions](https://www.lf-lang.org/reactor-c/group__API.html), macros, and constants without having to explicitly include any header files: -- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/d2/dcd/tag_8h.html)): +- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html)): - Specifying time value, such as `MSEC` and `FOREVER` - Time data types, such as `tag_t` and `instant_t` @@ -2844,12 +2844,12 @@ Reactions in C can use a number of pre-defined functions, macros, and constants - **Ports** - - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/da/d00/port_8h.html)) + - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/port_8h.html)) - **Scheduling actions** - - Schedule future events, such as `lf_schedule` and `lf_schedule_value` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) + - Schedule future events, such as `lf_schedule` and `lf_schedule_value` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) - **File Access** @@ -2866,11 +2866,11 @@ These are useful when your application needs to open and read additional files. - **Miscellaneous** - - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Checking deadlines, `lf_check_deadline` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) - - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` ([trace.h](https://www.lf-lang.org/reactor-c/d1/d1b/trace_8h.html)) - - Printing utilities, such as `lf_print` and `lf_print_error` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) - - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) + - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Checking deadlines, `lf_check_deadline` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) + - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` (See [Tracing API](https://www.lf-lang.org/reactor-c/group__Tracing.html)) + - Printing utilities, such as `lf_print` and `lf_print_error` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) + - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) #### Standard C Libraries @@ -2887,7 +2887,7 @@ Hence, programmers are free to use functions from these libraries without explic #### Available Libraries Requiring #include More sophisticated library functions require a `#include` statement in a `preamble`. -Specifically, [platform.h](https://www.lf-lang.org/reactor-c/de/d03/platform_8h.html) includes the following: +Specifically, [the platform API](https://www.lf-lang.org/reactor-c/group__Platform.html) includes the following: - Sleep functions such as `lf_sleep` - Mutual exclusion such as `lf_critial_section_enter` and `lf_critical_section_exit` @@ -2900,9 +2900,9 @@ The threading functions are only available for platforms that support multithrea A few utility libraries are provided, but require considerably more setup. These also help to illustrate how to incorporate your own libraries. -- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/d1/dcb/audio__loop_8h.html) -- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/d3/d8a/wave__file__reader_8h.html) -- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/dc/d44/deque_8h.html) +- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/audio__loop_8h.html) +- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/wave__file__reader_8h.html) +- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/deque_8h.html - An ncurses terminal interface for I/O: [sensor_simulator.h](https://www.lf-lang.org/reactor-c/dc/de9/sensor__simulator_8h.html) @@ -3209,7 +3209,7 @@ The Lingua Franca compiler automatically invokes other programs as it compiles a ### package.json -Node.js uses a [package.json](https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. +Node.js uses a [package.json](https://nodesource.com/blog/the-basics-of-package-json) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. ### tsconfig.json @@ -3493,7 +3493,7 @@ cargo-dependencies: { ``` The dependency is always included, with defaults picked by LFC. The location information (_path_/_git_/_version_ key) is optional. -See [reactor_rt](https://lf-lang.github.io/reactor-rust/reactor_rt/index.html) for the supported features. +See [reactor_rt](https://lf-lang.github.io/reactor-rs/reactor_rt/index.html) for the supported features. #### Linking support files @@ -3551,7 +3551,7 @@ Reactions are each generated in a separate method of the reactor struct. Reactio Undeclared dependencies, and dependencies on timers and `startup` or `shutdown`, do not generate a parameter. -The [`ReactionCtx`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. +The [`ReactionCtx`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. For instance: diff --git a/versioned_docs/version-0.8.0/reference/target-language-details.mdx b/versioned_docs/version-0.8.0/reference/target-language-details.mdx index 210af2eba..c58b96a2b 100644 --- a/versioned_docs/version-0.8.0/reference/target-language-details.mdx +++ b/versioned_docs/version-0.8.0/reference/target-language-details.mdx @@ -67,9 +67,9 @@ In terms of raw performance on CPU intensive operations, TypeScript reactors are **Important:** The Rust target is still quite preliminary. This is early WIP documentation to let you try it out if you're curious -In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rust), and depends on the Rust standard library. +In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rs), and depends on the Rust standard library. -Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rust/ +Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rs/ LF-Rust generates a Cargo project per compiled main reactor. This specification assumes in some places that the user is somewhat familiar with how Cargo works. If you're not, here's a primer: @@ -199,7 +199,7 @@ To have Lingua Franca generate C code, start your `.lf` file with one of the fol Note that for all LF statements, a final semicolon is optional. If you are writing your code in C, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). The second form, `CCpp`, is used when you wish to use a C++ compiler to compile the generated code, thereby allowing your C reactors to call C++ code. @@ -238,7 +238,7 @@ To have Lingua Franca generate C++ code, start your `.lf` file with the followin Note that for all LF statements, a final semicolon is optional. If you are writing your code in C++, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -251,7 +251,7 @@ To have Lingua Franca generate Python code, start your `.lf` file with the follo Note that for all LF statements, a final semicolon is optional. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -1061,7 +1061,7 @@ reactor Print { ### Dynamically Allocated Data -A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/SetDestructor.lf) example. +A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/TokenSetToken.lf) example. Suppose the data structure of interest, its constructor, destructor, and copy_constructor are defined as follows: @@ -1606,11 +1606,11 @@ Inputs and outputs in the Rust target are accessed using the `set` and `get` met In the C target, the value of a time instant or interval is an integer specifying a number of nanoseconds. An instant is the number of nanoseconds that have elapsed since January 1, 1970. An interval is the difference between two instants. When an LF program starts executing, logical time is (normally) set to the instant provided by the operating system. (On some embedded platforms without real-time clocks, it will be set instead to zero.) -Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. +Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. Lingua Franca uses a superdense model of time. A reaction is invoked at a logical **tag**, a struct consisting of a `time` value (an `instant_t`, which is a `int64_t`) and a `microstep` value (a `microstep_t`, which is an `uint32_t`). The tag is guaranteed to not increase during the execution of a reaction. Outputs produced by a reaction have the same tag as the inputs, actions, or timers that trigger the reaction, and hence are **logically simultaneous**. -The time structs and functions for working with time are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h). The most useful functions are: +The time structs and functions for working with time are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html). The most useful functions are: - `tag_t lf_tag()`: Get the current tag at which this reaction has been invoked. - `int lf_tag_compare(tag_t, tag_t)`: Compare two tags, returning -1, 0, or 1 for less than, equal, and greater than. @@ -2607,7 +2607,7 @@ This version carries an `int` value. The data type of the action is required to > `lf_schedule_token(, , );` -This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: +This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: ```lf-c reactor DelayPointer(delay:time(100 ms)) { @@ -2699,7 +2699,7 @@ FIXME: List them here -Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html#method.schedule) function: +Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html#method.schedule) function: ```rust // schedule without additional delay @@ -2757,7 +2757,7 @@ FIXME: Details needed here. -A suite of useful functions is provided in [util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. +A suite of useful functions is provided in [logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. - `LF_PRINT_DEBUG(format, ...)`: Use this for verbose messages that are only needed during debugging. Nothing is printed unless the [target](target-declaration.mdx#logging) parameter `logging` is set to `debug`. THe overhead is minimized when nothing is to be printed. @@ -2834,9 +2834,9 @@ Note that when building with a release profile (i.e., target property `build-typ #### Libraries Available in All Programs -Reactions in C can use a number of pre-defined functions, macros, and constants without having to explicitly include any header files: +Reactions in C can use a number of [pre-defined functions](https://www.lf-lang.org/reactor-c/group__API.html), macros, and constants without having to explicitly include any header files: -- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/d2/dcd/tag_8h.html)): +- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html)): - Specifying time value, such as `MSEC` and `FOREVER` - Time data types, such as `tag_t` and `instant_t` @@ -2844,12 +2844,12 @@ Reactions in C can use a number of pre-defined functions, macros, and constants - **Ports** - - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/da/d00/port_8h.html)) + - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/port_8h.html)) - **Scheduling actions** - - Schedule future events, such as `lf_schedule` and `lf_schedule_value` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) + - Schedule future events, such as `lf_schedule` and `lf_schedule_value` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) - **File Access** @@ -2866,11 +2866,11 @@ These are useful when your application needs to open and read additional files. - **Miscellaneous** - - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Checking deadlines, `lf_check_deadline` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) - - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` ([trace.h](https://www.lf-lang.org/reactor-c/d1/d1b/trace_8h.html)) - - Printing utilities, such as `lf_print` and `lf_print_error` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) - - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) + - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Checking deadlines, `lf_check_deadline` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) + - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` (See [Tracing API](https://www.lf-lang.org/reactor-c/group__Tracing.html)) + - Printing utilities, such as `lf_print` and `lf_print_error` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) + - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) #### Standard C Libraries @@ -2887,7 +2887,7 @@ Hence, programmers are free to use functions from these libraries without explic #### Available Libraries Requiring #include More sophisticated library functions require a `#include` statement in a `preamble`. -Specifically, [platform.h](https://www.lf-lang.org/reactor-c/de/d03/platform_8h.html) includes the following: +Specifically, [the platform API](https://www.lf-lang.org/reactor-c/group__Platform.html) includes the following: - Sleep functions such as `lf_sleep` - Mutual exclusion such as `lf_critial_section_enter` and `lf_critical_section_exit` @@ -2900,9 +2900,9 @@ The threading functions are only available for platforms that support multithrea A few utility libraries are provided, but require considerably more setup. These also help to illustrate how to incorporate your own libraries. -- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/d1/dcb/audio__loop_8h.html) -- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/d3/d8a/wave__file__reader_8h.html) -- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/dc/d44/deque_8h.html) +- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/audio__loop_8h.html) +- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/wave__file__reader_8h.html) +- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/deque_8h.html - An ncurses terminal interface for I/O: [sensor_simulator.h](https://www.lf-lang.org/reactor-c/dc/de9/sensor__simulator_8h.html) @@ -3209,7 +3209,7 @@ The Lingua Franca compiler automatically invokes other programs as it compiles a ### package.json -Node.js uses a [package.json](https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. +Node.js uses a [package.json](https://nodesource.com/blog/the-basics-of-package-json) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. ### tsconfig.json @@ -3493,7 +3493,7 @@ cargo-dependencies: { ``` The dependency is always included, with defaults picked by LFC. The location information (_path_/_git_/_version_ key) is optional. -See [reactor_rt](https://lf-lang.github.io/reactor-rust/reactor_rt/index.html) for the supported features. +See [reactor_rt](https://lf-lang.github.io/reactor-rs/reactor_rt/index.html) for the supported features. #### Linking support files @@ -3551,7 +3551,7 @@ Reactions are each generated in a separate method of the reactor struct. Reactio Undeclared dependencies, and dependencies on timers and `startup` or `shutdown`, do not generate a parameter. -The [`ReactionCtx`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. +The [`ReactionCtx`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. For instance: diff --git a/versioned_docs/version-0.9.0/reference/target-language-details.mdx b/versioned_docs/version-0.9.0/reference/target-language-details.mdx index e7a31c263..e5551f54b 100644 --- a/versioned_docs/version-0.9.0/reference/target-language-details.mdx +++ b/versioned_docs/version-0.9.0/reference/target-language-details.mdx @@ -67,9 +67,9 @@ In terms of raw performance on CPU intensive operations, TypeScript reactors are **Important:** The Rust target is still quite preliminary. This is early WIP documentation to let you try it out if you're curious -In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rust), and depends on the Rust standard library. +In the Rust reactor target for Lingua Franca, reactions are written in Rust and the code generator generates a standalone Rust program that can be compiled and run on platforms supported by rustc. The program depends on a runtime library distributed as the crate [reactor_rt](https://github.com/lf-lang/reactor-rs), and depends on the Rust standard library. -Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rust/ +Documentation for the runtime API is available here: https://lf-lang.github.io/reactor-rs/ LF-Rust generates a Cargo project per compiled main reactor. This specification assumes in some places that the user is somewhat familiar with how Cargo works. If you're not, here's a primer: @@ -199,7 +199,7 @@ To have Lingua Franca generate C code, start your `.lf` file with one of the fol Note that for all LF statements, a final semicolon is optional. If you are writing your code in C, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). The second form, `CCpp`, is used when you wish to use a C++ compiler to compile the generated code, thereby allowing your C reactors to call C++ code. @@ -238,7 +238,7 @@ To have Lingua Franca generate C++ code, start your `.lf` file with the followin Note that for all LF statements, a final semicolon is optional. If you are writing your code in C++, you may want to include the final semicolon for uniformity. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -251,7 +251,7 @@ To have Lingua Franca generate Python code, start your `.lf` file with the follo Note that for all LF statements, a final semicolon is optional. -For options to the target specification, see [detailed documentation of the target options](../introduction.md). +For options to the target specification, see [detailed documentation of the target options](./target-declaration.mdx). @@ -1061,7 +1061,7 @@ reactor Print { ### Dynamically Allocated Data -A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/SetDestructor.lf) example. +A much more flexible way to communicate complex data types is to set dynamically allocated memory on an output port. This can be done in a way that automatically handles freeing the memory when all users of the data are done with it. The reactor that allocates the memory cannot know when downstream reactors are done with the data, so Lingua Franca provides utilities for managing this using reference counting. You can specify a destructor on a port and pass a pointer to a dynamically allocated object as illustrated in the [SetDestructor](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/TokenSetToken.lf) example. Suppose the data structure of interest, its constructor, destructor, and copy_constructor are defined as follows: @@ -1606,11 +1606,11 @@ Inputs and outputs in the Rust target are accessed using the `set` and `get` met In the C target, the value of a time instant or interval is an integer specifying a number of nanoseconds. An instant is the number of nanoseconds that have elapsed since January 1, 1970. An interval is the difference between two instants. When an LF program starts executing, logical time is (normally) set to the instant provided by the operating system. (On some embedded platforms without real-time clocks, it will be set instead to zero.) -Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. +Time in the C target is a `int64_t`, which is a 64-bit signed number. Since a 64-bit number has a limited range, this measure of time instants will overflow in approximately the year 2262. For better code clarity, two types are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html), `instant_t` and `interval_t`, which you can use for time instants and intervals respectively. These are both equivalent to `int64_t`, but using those types will insulate your code against changes and platform-specific customizations. Lingua Franca uses a superdense model of time. A reaction is invoked at a logical **tag**, a struct consisting of a `time` value (an `instant_t`, which is a `int64_t`) and a `microstep` value (a `microstep_t`, which is an `uint32_t`). The tag is guaranteed to not increase during the execution of a reaction. Outputs produced by a reaction have the same tag as the inputs, actions, or timers that trigger the reaction, and hence are **logically simultaneous**. -The time structs and functions for working with time are defined in [tag.h](https://github.com/lf-lang/reactor-c/blob/main/include/core/tag.h). The most useful functions are: +The time structs and functions for working with time are defined in [tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html). The most useful functions are: - `tag_t lf_tag()`: Get the current tag at which this reaction has been invoked. - `int lf_tag_compare(tag_t, tag_t)`: Compare two tags, returning -1, 0, or 1 for less than, equal, and greater than. @@ -2607,7 +2607,7 @@ This version carries an `int` value. The data type of the action is required to > `lf_schedule_token(, , );` -This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: +This version carries a **token**, which has type `token_t` and points to the value, which can have any type. There is a `create_token()` function that can be used to create a token, but programmers will rarely need to use this. Instead, you can use `lf_schedule_value()` (see below), which will automatically create a token. Alternatively, for inputs with types ending in `*` or `[]`, the value is wrapped in a token, and the token can be obtained using the syntax `inputname->token` in a reaction and then forwarded using `lf_schedule_token()` (see [Dynamically Allocated Data](#dynamically-allocated-data) above). If the input is mutable, the reaction can then even modify the value pointed to by the token and/or use `lf_schedule_token()` to send the token to a future logical time. For example, the [DelayPointer](https://github.com/lf-lang/lingua-franca/blob/master/test/C/src/token/DelayPointer.lf) reactor realizes a logical delay for any data type carried by a token: ```lf-c reactor DelayPointer(delay:time(100 ms)) { @@ -2699,7 +2699,7 @@ FIXME: List them here -Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html#method.schedule) function: +Within a reaction, actions may be scheduled using the [`schedule`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html#method.schedule) function: ```rust // schedule without additional delay @@ -2757,7 +2757,7 @@ FIXME: Details needed here. -A suite of useful functions is provided in [util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. +A suite of useful functions is provided in [logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html) for producing messages to be made visible when the generated program is run. Of course, you can always use `printf`, but this is not a good choice for logging or debug information, and it is not a good choice when output needs to be redirected to a window or some other user interface (see for example the [sensor simulator](https://github.com/lf-lang/reactor-c/blob/main/util/sensor_simulator.h)). Also, in federated execution, these functions identify which federate is producing the message. The functions are listed below. The arguments for all of these are identical to `printf` with the exception that a trailing newline is automatically added and therefore need not be included in the format string. - `LF_PRINT_DEBUG(format, ...)`: Use this for verbose messages that are only needed during debugging. Nothing is printed unless the [target](target-declaration.mdx#logging) parameter `logging` is set to `debug`. THe overhead is minimized when nothing is to be printed. @@ -2834,9 +2834,9 @@ Note that when building with a release profile (i.e., target property `build-typ #### Libraries Available in All Programs -Reactions in C can use a number of pre-defined functions, macros, and constants without having to explicitly include any header files: +Reactions in C can use a number of [pre-defined functions](https://www.lf-lang.org/reactor-c/group__API.html), macros, and constants without having to explicitly include any header files: -- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/d2/dcd/tag_8h.html)): +- **Time and tags** ([tag.h](https://www.lf-lang.org/reactor-c/tag_8h.html)): - Specifying time value, such as `MSEC` and `FOREVER` - Time data types, such as `tag_t` and `instant_t` @@ -2844,12 +2844,12 @@ Reactions in C can use a number of pre-defined functions, macros, and constants - **Ports** - - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/da/d00/port_8h.html)) + - Writing to output ports, such as `lf_set` and `lf_set_token` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Iterating over sparse multiports, such as `lf_multiport_iterator` and `lf_multiport_next` ([port.h](https://www.lf-lang.org/reactor-c/port_8h.html)) - **Scheduling actions** - - Schedule future events, such as `lf_schedule` and `lf_schedule_value` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) + - Schedule future events, such as `lf_schedule` and `lf_schedule_value` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) - **File Access** @@ -2867,11 +2867,11 @@ These are useful when your application needs to open and read additional files. - **Miscellaneous** - - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/d4/d13/set_8h.html)) - - Checking deadlines, `lf_check_deadline` ([api.h](https://www.lf-lang.org/reactor-c/dc/d65/api_8h.html)) - - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` ([trace.h](https://www.lf-lang.org/reactor-c/d1/d1b/trace_8h.html)) - - Printing utilities, such as `lf_print` and `lf_print_error` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) - - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([util.h](https://www.lf-lang.org/reactor-c/d8/d3c/util_8h.html)) + - Changing modes in modal models, `lf_set_mode` ([set.h](https://www.lf-lang.org/reactor-c/group__API.html)) + - Checking deadlines, `lf_check_deadline` (See [API for Reactions](https://www.lf-lang.org/reactor-c/group__API.html)) + - Defining and recording tracepoints, such as `register_user_trace_event` and `tracepoint` (See [Tracing API](https://www.lf-lang.org/reactor-c/group__Tracing.html)) + - Printing utilities, such as `lf_print` and `lf_print_error` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) + - Logging utilities, such as `LF_PRINT_LOG` and `LF_PRINT_DEBUG` ([logging.h](https://www.lf-lang.org/reactor-c/logging_8h.html)) #### Standard C Libraries @@ -2888,7 +2888,7 @@ Hence, programmers are free to use functions from these libraries without explic #### Available Libraries Requiring #include More sophisticated library functions require a `#include` statement in a `preamble`. -Specifically, [platform.h](https://www.lf-lang.org/reactor-c/de/d03/platform_8h.html) includes the following: +Specifically, [the platform API](https://www.lf-lang.org/reactor-c/group__Platform.html) includes the following: - Sleep functions such as `lf_sleep` - Mutual exclusion such as `lf_critial_section_enter` and `lf_critical_section_exit` @@ -2901,9 +2901,9 @@ The threading functions are only available for platforms that support multithrea A few utility libraries are provided, but require considerably more setup. These also help to illustrate how to incorporate your own libraries. -- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/d1/dcb/audio__loop_8h.html) -- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/d3/d8a/wave__file__reader_8h.html) -- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/dc/d44/deque_8h.html) +- Audio functions (for Linux and Mac only): [audio_loop.h](https://www.lf-lang.org/reactor-c/audio__loop_8h.html) +- Audio file reader: [wave_file_reader.h](https://www.lf-lang.org/reactor-c/wave__file__reader_8h.html) +- A double-ended queue: [deque.h](https://www.lf-lang.org/reactor-c/deque_8h.html - An ncurses terminal interface for I/O: [sensor_simulator.h](https://www.lf-lang.org/reactor-c/dc/de9/sensor__simulator_8h.html) @@ -3230,7 +3230,7 @@ The Lingua Franca compiler automatically invokes other programs as it compiles a ### package.json -Node.js uses a [package.json](https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. +Node.js uses a [package.json](https://nodesource.com/blog/the-basics-of-package-json) file to describe metadata relevant to a Node project. This includes a list of project dependencies (i.e. modules) used by the project. When the Lingua Franca compiler copies a default package.json file into a Lingua Franca project that doesn't already have a package.json, the compiler runs the command `npm install` to create a node_modules directory. The default package.json only lists dependencies for the [reactor-ts](https://github.com/lf-lang/reactor-ts) submodule. [Follow these instructions](../writing-reactors/preambles.mdx#using-node-modules) to modify package.json if you want to use other Node modules in your reactors. ### tsconfig.json @@ -3514,7 +3514,7 @@ cargo-dependencies: { ``` The dependency is always included, with defaults picked by LFC. The location information (_path_/_git_/_version_ key) is optional. -See [reactor_rt](https://lf-lang.github.io/reactor-rust/reactor_rt/index.html) for the supported features. +See [reactor_rt](https://lf-lang.github.io/reactor-rs/reactor_rt/index.html) for the supported features. #### Linking support files @@ -3572,7 +3572,7 @@ Reactions are each generated in a separate method of the reactor struct. Reactio Undeclared dependencies, and dependencies on timers and `startup` or `shutdown`, do not generate a parameter. -The [`ReactionCtx`](https://lf-lang.github.io/reactor-rust/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. +The [`ReactionCtx`](https://lf-lang.github.io/reactor-rs/reactor_rt/struct.ReactionCtx.html) object is a mediator to manipulate all those dependency objects. It has methods to set ports, schedule actions, retrieve the current logical time, etc. For instance: