Commit d828b04e authored by Matthias Simon's avatar Matthias Simon
Browse files

More parameterization

parent 83856896
Loading
Loading
Loading
Loading
+140 −50
Original line number Diff line number Diff line
@@ -34,11 +34,16 @@ extension].
> The term _parameterization_ will be used interchangeably with _value
> parameterization_ in this document, unless stated differently.

> NOTE: Parameters are very similar to variables in the sense they
> provide a memory location to store the value of a specific type.
> NOTE: Parameters are very similar to variables in the sense they provide a
> memory location to store the value of a specific type. Parameters also have a
> initial value assignment (default parameter) and follow assignment rules as
> variables.

TTCN-3 language elements that support value parameterization are: [functions],
[external functions], [testcases], [altsteps] and [parameterized templates].

**Examples**

**Examples**

```ttcn3 example="type parameterization"
function f<type T>() { /* ... */ }
@@ -79,7 +84,7 @@ control {

### Formal parameters

A _formal parameter list_ specifies the parameters that are accepted.
A _formal parameter list_ specifies what parameters are accepted.

**Syntactical Description**

@@ -90,26 +95,117 @@ FormalPar ::= [ "in" | "out" | "inout" ] TypeExpr name {"[" integer "]"} ["..."]

**Semantic description**

A _formal parameter_ may be declared for [functions], [testcases], [altsteps],
[external functions], [methods] and [parameterized templates].

The _formal parameter_ declaration adds a new parameter with given _name_ into
the scope of the parameterized language element (see [uniqueness of
identifiers]).

A _formal parameter_ has a static type associated with it.
The type of the parameter shall be specified using a _[type expression]_
and shall not change during its [lifetime].
and shall not change during its [invocation].

A _formal parameter_ may be declared as array by using the [array short-hand
notation].

The _type expression_, _default value assignment_ and _array notation_ of a
_formal parameter_ shall not reference any formal parameters defined in the
A _formal parameter_ shall not reference any formal parameters defined in the
same _formal parameter list_.

A _formal parameter_ may have an _initial value assignment_. Such a parameter
is called _default parameter_ and is described in [default parameters].

A _formal parameter_ is either an _in-parameter_ (indicated by the `in`
keyword), _inout-parameter_ (indicated by the `inout` keyword) or
_out-parameter_ (indicated by the `out` keyword).
A _formal parameter_ without any of these keywords is considered an _in-parameter_.

A _in-parameter_ is _passed by value_. Each invocation of the parameterized
TTCN-3 language object has its own copy.

A _out-parameter_ is passed by value_.

A [default value] may the speficied.
> TODO: Hat ein out-parameter sein egienen memory (wie in-parameter). Wann passiert expansion,
> 

A _inout-parameter_ is _passed by reference_.

**Examples**

```ttcn3 example="scope"
function f(integer p) {
    log(p) // p is in the scope of function f
}
```

```ttcn3 example="array"
function f(integer a[3]) {
    // expect: typeof(a) == "array of integer"
}
```

```ttcn3 example="cannot reference a parameter from the same formal parameter list"
external function f(integer n, integer a[n]); // error
external function g(integer n, integer a := n*2); // error
external function h(integer n, record length(n) of integer a); // error
```

```ttcn3 example="each invocation has its own copy"

// each invocation of function `fib` has its own copy of parameter n.
function fib(in integer n) return integer {
    if (n < 2) {
        return 1
    }
    return fib(n-2) + fib(n-1)
}

control {
    var integer v := fib(2); // expect: v == 2
}
```

```ttcn3 example="pass by value: changes not visible"
function f(in integer i) {
}
```

```ttcn3 example="pass by reference"
function f(inout integer i) {
    i := i + 1;
}

control {
    var integer i := 0;
    f(i)
    log(i) // expected output: 1
}
```

```ttcn3 example="pass reference by reference"
// TODO: write test to change the passed inout variable to
type component PTC {}

testcase tc() {
    var PTC a := PTC.create("a");
    var PTC b := PTC.create("b");

    var PTC c;



}
```



### Actual parameters


When a parameterized TTCN-3 language element is invoked

- actual parameters are mapped on the
- evaluated in the order they are passed
- evaluated in the scope of the caller
- assignment list notation
- special rules altsteps, templates

- direction
    - in (default):
@@ -125,37 +221,54 @@ A [default value] may the speficied.
      - by reference (type euqality, strong typing)
      - incremential changes visible
      - implcit deference
      - no reference to elements of string types

**Examples**
- semantically a parameter is a local variable
- each activate frame is its own location
- default parameter
- assignment list notation allowed (evaluated in order of actual arguments)

```ttcn3 example="scope"
function f(integer p) {
    log(p) // p is in the scope of function f

- expanding rules for referencing the elemnt on the left hand side. (6.2, 15.6)

It is allowed to pass elements of structured values or templates (record, set, record of, set of, union and anytype values
or templates) by reference. Modification of parameters passed this way affects the original structured value or template.
Before passing the actual parameter, the rules for referencing the element on the left hand side of assignments are
applied, expanding the structured value so that the referenced element becomes accessible (see clauses 6.2 and 15.6 for
more details).


```ttcn3 example = "unintended side-effects"
type component C {
    var integer cVar
}
```

```ttcn3 example="array"
function f(integer a[3]) {
    // expect: typeof(a) == "array of integer"
function f(inout integer p) runs on C {
    cVar := 10;
    p := 99; // changing p also changes cVar, because both are
             // references to the same piece of data.
    
    log(cVar); // expected output: 99
}
```

```ttcn3 example="cannot reference a parameter from the same formal parameter list"
external function f(integer n, integer a[n]); // error
external function g(integer n, integer a := n*2); // error
external function h(integer n, record length(n) of integer a); // error
testcase tc() runs on C {
    f(cVar);
}
```

> NOTE: Passing variables of components as inout-parameter can cause unintended
> side-effects, and should be avoided.


### Default parameters

### Variadic parameters

The last formal parameter of _formal parameter list_ may have a suffix `...`
The last formal parameter of a _formal parameter list_ may have the suffix `...`
(three dots). Such formal parameter is called variadic parameter and accepts
zero or more values of the specified type.

The _variadic formal parameter_ shall be an `in` parameter. Using of `inout` or
`out` kind of parameterization for variadic parameters is forbidden.
The _variadic formal parameter_ shall be an _in-parameter_.

A _variadic formal parameter_ may declare array-types using the array-notation.

@@ -237,29 +350,6 @@ function f(integer args... := {1,2,3}) {
}
```

### Actual parameters

- semantically a parameter is a local variable
- each activate frame is its own location
- default parameter
- assignment list notation allowed

> NOTE 1: Reference to a string element cannot be passed by reference as string types are not structured types.

what does this mean?

It is allowed to pass elements of structured values or templates (record, set, record of, set of, union and anytype values
or templates) by reference. Modification of parameters passed this way affects the original structured value or template.
Before passing the actual parameter, the rules for referencing the element on the left hand side of assignments are
applied, expanding the structured value so that the referenced element becomes accessible (see clauses 6.2 and 15.6 for
more details).
NOTE 2: Because inout parameters are passed by reference and component variables are effectively also accessed
by reference within a called function or altstep, passing parts of a structured component variable as an
actual inout parameter may have confusing effects inside the parameterized behaviour: changing either
the inout parameter or the component variable may also change the other simultaneously, which might
break the intended algorithm. For this reason, such situations should be avoided.


## Invoking functions
- evaluate arguments in caller scope
- pass arguments to callee scope