Base: Document IPC syntax formally and informally

This commit is contained in:
kleines Filmröllchen 2023-08-08 22:00:58 +02:00 committed by Andrew Kaster
parent 73523cef2b
commit 489fce0ed2

View file

@ -21,6 +21,66 @@ In other words, in case of the synchronous calls, the IPC library will not retur
Ideally, all APIs for the server endpoint should be asynchronous.
### Syntax Overview
Each IPC endpoint definition has the form:
```ipc
endpoint MyServer
{
// messages...
}
```
You can use C++ `#include` directives before the `endpoint` keyword, which are copied to the resulting endpoint stub file. This is important if your messages use specific types of the library or application.
Each message must appear on its own line. Synchronous messages are defined with an arrow `=>` like
```ipc
message_name(arguments...) => (return values...)
```
and asynchronous messages are defined with a "stopped arrow" `=|` like
```ipc
message_name(arguments...) =|
```
The argument and return value lists define what data the message passes to the other side, and what data will be retrieved back. There is no limitation to a single return value, since it will be converted to a `Messages` struct that can hold as much data as needed. The lists are defined like normal C++ formal parameter lists:
```ipc
message_name(int first_param, bool second_param, My::Library::Type third_param) => (Optional<int> first_return, float second_return)
```
Currently, parameter types cannot contain spaces, so be careful with templates.
Parameters can contain attributes, which are a comma-separated list within a `[]` block preceding the type. The only currently implemented attribute is the `UTF8` attribute for string types, which will add a run-time validation that the string is valid UTF-8. For example:
```ipc
set_my_name([UTF8] String name) =|
```
For the String type in particular, this is not necessary.
### Formal Syntax
In Extended Backus-Naur form (and disregarding unwanted leniencies in the code generator's parser), IPC file syntax looks like the following:
```ebnf
IPCFile = { Endpoint } ;
Endpoint = Includes, "endpoint", Identifier, "{", { Message }, "}" ;
Identifier = (* C++ identifier *) ;
Includes = { (* C++ preprocessor #include directive *) } ;
Message = Identifier, "(", [ ParameterList ], ")", (SynchronousTrailer | AsynchronousTrailer) ;
SynchronousTrailer = "=>", "(", [ ParameterList ], ")";
AsynchronousTrailer = "=|" ;
ParameterList = Parameter, { ",", Parameter } ;
Parameter = [ "[", AttributeList, "]" ], TypeName, Identifier ;
AttributeList = Identifier, { ",", Identifier } ;
TypeName = (* C++ type name, without spaces *) ;
```
## Examples
To create a new connection, you first need to generate client and server endpoints.
@ -28,7 +88,7 @@ These endpoints should implement the communication logic using the IPC compiler-
Start from defining an endpoint in the IPC file in `MyServer.ipc`.
```
```ipc
endpoint MyServer
{
SyncAPI(DeprecatedString text) => (i32 status)