Changeset - b06a29504c82
[Not reviewed]
0 2 0
mh - 4 years ago 2021-06-03 15:52:43
contact@maxhenger.nl
more documentation of language validation
2 files changed with 10 insertions and 3 deletions:
0 comments (0 inline, 0 general)
docs/spec/definitions.md
Show inline comments
 
@@ -187,39 +187,41 @@ func PickAnInt(u32 left, u32 right, bool choose_left) -> u32 {
 

	
 
func PickASide<T>(Pair<T, T> pair, bool choose_left) -> T {
 
    if (choose_left) {
 
        return pair.left;
 
    } else {
 
        return pair.right;
 
    }
 
}
 
```
 

	
 
## Component Definition
 

	
 
A component definition is the definition of a Reo connector. Currently there are two variants. The meaning of these variants will be introduced in a later section. A component is defined much in the same way as a function, except that it doesn't have a return type. Is is defined as:
 

	
 
```
 
CompVariant = KwPrim | KwComp
 
DeclComp = CompVariant Ident PolyVars? "("
 
        (FuncArgDef ",")* FuncArgDef?
 
    ")"
 
    StmtBlock
 
```
 

	
 
We'll delay examples of components until we've introduced the concept of connectors in this document.
 

	
 
**note**: It might be that the distinction between primitive and composite connectors (and the restrictions they place on the available language features inside each of them) will be removed in the future.
 

	
 
## Combining all Declarations
 

	
 
A module is the combination of any of the above declarations. So we may specify the possible contents of a module as:
 

	
 
```
 
Module = (
 
        DeclPragma | 
 
        DeclImport | 
 
        DeclEnum | 
 
        DeclUnion | 
 
        DeclStruct |
 
        DeclFunc |
 
        DeclComp
 
    )*
 
```
 
\ No newline at end of file
docs/spec/validation.md
Show inline comments
 
@@ -159,52 +159,52 @@ The `TypeRef` for a function call should resolve to either a builtin function, o
 
The `TypeRef` for a component call should resolve to either a builtin component, or a user-defined component. Component calls, like function calls, must following the rules for polymorphic arguments and the arguments to the components themselves. Furthermore component "call" expressions may only be placed with a `StmtNew` as parent. That is to say: one doesn't really call components, instead one instantiates them.
 

	
 
## Builtin Procedures
 

	
 
Several functions are builtin procedures in the language. We'll shortly provide their meaning and their syntax here. Some of these functions cannot be expressed in PDL itself, so some ad-hoc syntax is used instead.
 

	
 
### Get(...)
 

	
 
The `get` function receives a value from an input port. This function may only be called in primitive components and may only be called within sync-blocks. If no value is present then the execution halts until a value becomes available. Upon receiving a value the execution forks in two. One branch will remain waiting for any potentially other messages, the other branch will actually obtain the sent message and continue execution.
 

	
 
If a `get` function is called in a branch that has previously assumed that nothing will ever be sent through the port provided as argument, then that branch is considered inconsistent and will be removed. If a `get` function is called in a branch that has not decided on the firing state of a port then it will be forced to fire without forking of execution.
 

	
 
The get function would be written in PDL as:
 

	
 
```
 
func get<T>(in<T> input_port) -> T { /* ... */ }
 
```
 

	
 
### Put(...)
 

	
 
The `put` function may put a value into an output port. This function may only be called in primitive components and may only be called within sync-blocks. 
 

	
 
If a `put` function is called in a branch that has previously assumed that nothing will ever be sent through the port provided as argument, then that branch is considered inconsistent and will be removed. If a `put` function is called in a branch that has not decided on the firing state of a port then it will be forced to fire without forking of execution.
 

	
 
The put function would be written in PDL as:
 
The put function would be written in PDL as, if it would support the C-like `void` type:
 

	
 
```
 
func put<T>(out<T> output_port, T value_to_put) -> T { /* ... */ }
 
func put<T>(out<T> output_port, T value_to_put) -> void { /* ... */ }
 
```
 

	
 
**note**: Whether the `put` statement blocks until a corresponding `get` has been performed has not yet been decided. 
 

	
 
### Fires(...)
 

	
 
The `fires` function will check if a port has previously been assumed to fire or not fire. If such a decision has not yet been reached then the execution forks. One branch assumes that the port will fire and the other branch assumes it will not. Otherwise this function returns the firing state of the port: true if it fires, false if it does not.
 

	
 
This function may only be called in primitive components and may only occur inside sync-blocks.
 

	
 
The `fires` function would be written in PDL, if the language would support function overloading, as:
 

	
 
```
 
func fires<T>(in<T> input_port) -> bool { /* ... */ }
 
func fires<T>(out<T> output_port) -> bool { /* ... */ }
 
```
 

	
 
### Create(...)
 

	
 
The `create` function creates a value of the type `msg`. Its argument is the length of the `msg` type. It would be written in PDL as:
 

	
 
```
 
func create(u32 length) -> msg { /* ... */ }
 
```
 
@@ -218,27 +218,32 @@ The `length` function returns the length of arrays and strings. If PDL would sup
 
```
 
func length<T>(T[] v) -> u32 { /* ... */ }
 
func length(string v) -> u32 { /* ... */ }
 
func length(msg v) -> u32 { /* ... */ }
 
```
 

	
 
**note**: As stated above, the `msg` type will likely be removed. The `string` implementation is tentative, so might be changed as well.
 

	
 
### Assert(...)
 

	
 
The `assert` function is used to prune execution branches within components. It works much like an assert would in another language: the assert statement excepts an expression as argument that resolves to a boolean value. If the boolean value is `true` then execution continues. If the boolean value is `false` then the execution branch is removed.
 

	
 
The `assert` function may only appear in components (primitive or composite) and may only be called in sync-blocks. It would be written in PDL, if it would support the C-like "void" type, as:
 

	
 
```
 
func assert(bool test) -> void { /* ... */ }
 
```
 

	
 
**note**: Perhaps the name of this function will change in the future.
 

	
 
## Statement Rules
 

	
 
### Synchronous Blocks
 

	
 
Synchronous blocks may only be placed in primitive components. Synchronous blocks may not be nested. One may not jump into or out of a synchronous block.
 

	
 
### Use of Builtin Procedures
 

	
 
### Control-Flow Rules
 
\ No newline at end of file
 
Builtin procedures that do not have a return value (currently only `put` and `assert`) may not be called at the expression level and must be called at the statement level. i.e. the parent of the builtin call expression may only be the `StmtExpr` statement.
 

	
 
### Control-Flow Rules
 

	
0 comments (0 inline, 0 general)