documented caveats with flow and IDE-compilation

This commit is contained in:
mpilman 2019-02-19 13:56:00 -08:00 committed by Alex Miller
parent 7730e161ae
commit cdb7c721c9
1 changed files with 61 additions and 0 deletions

View File

@ -95,3 +95,64 @@ To write the equivalent code directly in C++, a developer would have to implemen
}
}
}
Caveats
=======
Even though flow-code looks a lot like C++, it is not. It has different rules and the files are preprocessed. It is always important to keep this in mind when programming flow.
We still want to be able to use IDEs and modern editors (with language servers like cquery or clang-based completion engines like ycm). Because of this there is a header-file ``actorcompiler.h`` in flow which defines preprocessor definitions to make flow compile as normal C++ code. CMake even supports a special mode so that it doesn't preprocess flow files. This mode can be used by passing ``-DOPEN_FOR_IDE=ON`` to cmake. Additionally we generate a special ``compile_commands.json`` into the source-directory which will support opening the project in IDEs and editors that look for a compilation database.
Some preprocessor definitions will not fix all issues though. When programming flow the following things have to be taken care of by the programmer:
- Local variables don't survive a call to ``wait``. So this would be legal flow-code, but NOT legal C++-code:
.. code-block:: c
ACTOR void foo {
int i = 0;
wait(someFuture);
int i = 2;
wait(someOtherFuture)
}
In order to make this not break IDE-support one can either rename the second occurrence of this variable or, if this is not desired as it might make the code unreadable, one can use scoping:
.. code-block:: c
ACTOR void foo {
{
int i = 0;
wait(someFuture);
}
{
int i = 2;
wait(someOtherFuture)
}
}
- An ``ACTOR`` is compiled into a class internally. Which means that within an actor-function, ``this`` is a valid pointer to this class. But using them explicitely (or as described later implicitely) will break IDE support. One can use ``THIS`` and ``THIS_ADDR`` instead. But be careful as ``THIS`` will be of type ``nullptr_t`` in IDE-mode and of the actor-type in normal compilation mode.
- Lambdas and state variables are weird in a sense. After actorcompilation a state variable is a member of the compiled actor class. In IDE mode it is considered a normal local variable. This can result in some surprising side-effects. So the following code will only compile if the method ``Foo::bar`` is defined as ``const``:
.. code-block:: c
ACTOR foo() {
state Foo f;
foo([=]() { f.bar(); })
}
If it is not, one has to pass the member explictely as reference:
.. code-block:: c
ACTOR foo() {
state Foo f;
auto x = &f;
foo([x]() { x->bar(); })
}
- state variables in don't follow the normal scoping rules. So in flow a state variable can be defined in a inner scope and later it can be used in the outer scope. In order to not break compilation in IDE-mode, always define state variables in the outermost scope they will be used.