Seed7 
 FAQ 
 Manual 
 Screenshots 
 Examples 
 Algorithms 
 Download 
 Links 

 Manual 
 Introduction 
 Tutorial 
 Syntax 
 Statements 
 Types 
 Parameters 
 Objects 
 File System 
 Declarations 
 Tokens 
 Expressions 
 OS access 
 Actions 
 Errors 

 Parameters 
 val 
 ref 
 in 
 in var 
 inout 
 Symbol 
 attr 

6. PARAMETERS

The following subchapters introduce the parameter types of Seed7.

6.1 'val' parameter

This function appends a comma and a string to the globalStri variable:

    const proc: appendStri (val string: stri) is func
      begin
        globalStri &:= ",";
        globalStri &:= stri;
      end func;

After doing

    globalStri &:= "a";
    appendStri(globalStri);

the globalStri variable contains the value "a,a". If the function header would be

    const proc: appendStri (in string: stri) is func

the globalStri variable would contain the value "a,a,". This difference is because of the following reasons:

For arrays 'in' parameters are equal to 'ref' parameters. When appendStri called with globalStri as parameter an unwanted side effect takes place: Every change of globalStri changes also the 'ref' parameter stri. Changes to the 'ref' parameter would also change the global variable. Such unwanted side effects can also take place between parameters (when at least one parameter is an 'inout' parameter).

In most cases such unwanted side effects are impossible or can be avoided easily. When possible 'in' parameters should be preferred over 'val' parameters.

Semantics:
When calling a function a formal 'val' parameter gets its value from the corresponding actual parameter. This is done with a create procedure ( ::= ). In the function it is only possible to read a formal 'val' parameter. Changing a formal 'val' parameter is not possible. When a function is left a 'destr' procedure is called for every 'val' parameter. Formal 'val' parameters have the access right 'const'.

Syntax:

    val_parameter ::=
      'val' type_expression ':' identifier_declaration |
      'val' type_expression 'param' .

Declaration:

    $ syntax expr: .val.().param is                   -> 40;
    $ syntax expr: .val.(). : .(expr) is              -> 40;

    const func f_param: val (ref type param) param is               action "DCL_VAL1";
    const func f_param: val (ref type param) : (ref expr param) is  action "DCL_VAL2";

6.2 'ref' parameter

The following function defines the primitive action for the semicolon operator:

    const proc: (ref void param) ; (ref void param) is noop;

In this definition and other definitions of primitive actions 'ref' parameters are used. For normal functions usually 'in' parameters are used instead of 'ref' parameters:

    const func integer: total_length (in array string: arr) is func
      result
        var integer: result is 0;
      local
        var integer: index is 0;
      begin
        for index range 1 to length(arr) do
          result +:= length(arr[index]);
        end for;
      end func;

Above function could also be defined with the following function head:

    const func integer: total_length (ref array string: arr) is func

Since for array types (and also for struct types) 'in' parameters are defined to act as 'ref' parameters both definitions are equal. When possible 'in' parameters should be preferred over 'ref' parameters.

Semantics:
When calling a function a formal 'ref' parameter is set to refer to the corresponding actual parameter. In the function it is only possible to read a formal 'ref' parameter. Changing a formal 'ref' parameter is not possible. Formal 'ref' parameters have the access right 'const'.

Syntax:

    ref_parameter ::=
      'ref' type_expression ':' identifier_declaration |
      'ref' type_expression 'param' .

Declaration:

    $ syntax expr: .ref.().param is                   -> 40;
    $ syntax expr: .ref.(). : .(expr) is              -> 40;

    const func f_param: ref (ref type param) param is               action "DCL_REF1";
    const func f_param: ref (ref type param) : (ref expr param) is  action "DCL_REF2";

6.3 'in' parameter

This function checks if a given number is a prime number:

    const func boolean: is_prime (in integer: number) is func
      result
        var boolean: result is FALSE;
      local
        var integer: count is 2;
      begin
        if number = 2 then
          result := TRUE;
        elsif number >= 3 then
          while number rem count <> 0 and count * count <= number do
            incr(count);
          end while;
          result := number rem count <> 0;
        end if;
      end func;

The following function defines the ex (outer) product:

    const func array array integer:
        (in array integer: a) ex (in array integer: b) is func
      return
        var array array integer: result is 0 times 0 times 0;
      local
        var integer: index1 is 1;
      begin
        result := length(a) times length(b) times 0;
        for index1 range 1 to length(a) do
          for index2 range 1 to length(b) do
            result[index1][index2] := a[index1] * b[index2];
          end for;
        end for;
      end func;

Although both examples use 'in' parameters the parameter in the first example is actually a 'val' parameter while the parameters in the second example are actually 'ref' parameters. When a new type is created with the 'newtype' function it is necessary to specify the meaning of the 'in' parameter. This is done with a call of the IN_PARAM_IS_VALUE or the IN_PARAM_IS_REFERENCE function with the new generated type as parameter. If a new type is created with the 'subtype' function this specification is optional since the base type has already a specification of the 'in' parameter.

Semantics:
Depending on the type an 'in' parameter is equivalent to an 'val' (call by value) parameter or to an 'ref' (call by reference) parameter. Formal 'in' parameters have the access right 'const'.

Syntax:

    in_parameter ::=
      'in' type_expression ':' identifier_declaration .

Declaration:

    $ syntax expr: .in.().param is                    -> 40;
    $ syntax expr: .in.(). : .(expr) is               -> 40;

    const func f_param: in (ref type param) param is                action "DCL_REF1";

    const proc: IN_PARAM_IS_VALUE (ref type: aType) is func
      begin
        const func f_param: in (attr aType) : (ref expr param) is   action "DCL_VAL2";
      end func;

    const proc: IN_PARAM_IS_REFERENCE (ref type: aType) is func
      begin
        const func f_param: in (attr aType) : (ref expr param) is   action "DCL_REF2";
      end func;

6.4 'in var' parameter

This function computes the greatest common divisor:

    const func integer: gcd (in var integer: a, in var integer: b) is func
      result
        var integer: result is 0;
      local
        var integer: help is 0;
      begin
        while a <> 0 do
          help := b rem a;
          b := a;
          a := help;
        end while;
        result := b;
      end func;

Semantics:
When calling a function a formal 'in var' parameter gets its value from the corresponding actual parameter. This is done with a create procedure ( ::= ). In the function it is possible to read and change a formal 'in var' parameter. Changing a formal 'in var' parameter has no effect on the actual parameter. When a function is left a 'destr' procedure is called for every 'in var' parameter. Formal 'in var' parameters have the access right 'var'.

Syntax:

    in_var_parameter ::=
      'in var' type-expression ':' identifier_declaration .

Declaration:

    $ syntax expr: .in.var.().param is                -> 40;
    $ syntax expr: .in.var.(). : .(expr) is           -> 40;

    const func f_param: in var (ref type param) param is               action "DCL_IN1VAR";
    const func f_param: in var (ref type param) : (ref expr param) is  action "DCL_IN2VAR";

6.5 'inout' parameter

This procedure doubles the given parameter 'number':

    const proc: double (inout integer: number) is func
      begin
        number := 2 * number;
      end func;

Semantics:
When calling a function a formal 'inout' parameter is set to refer to the corresponding actual parameter. In the function it is possible to read and change a formal 'inout' parameter. Changing a formal 'inout' parameter changes the actual parameter as well. Formal 'inout' parameters have the access right 'var'.

Syntax:

    inout_parameter ::=
      'inout' type_expression ':' identifier_declaration .

Declaration:

    $ syntax expr: .inout.().param is                 -> 40;
    $ syntax expr: .inout.(). : .(expr) is            -> 40;

    const func f_param: inout (ref type param) param is                action "DCL_INOUT1";
    const func f_param: inout (ref type param) : (ref expr param) is   action "DCL_INOUT2";

6.6 Symbol parameter

Some functions need symbols at fixed places in the parameter list. The following IF-statement requests the keywords 'THEN', 'END' and 'IF' at specific places:

    IF condition THEN
      statement
    END IF;

After defining the syntax of this IF-statement with

    $ syntax expr: .IF.().THEN.().END.IF is -> 25;

the semantic can be defined with:

    const proc: IF (in boolean: condition) THEN
                  (in proc: statement)
                END IF is func

                  begin
                    case condition of
                      when {TRUE}: statement;
                    end case;
                  end func;

The symbol parameters are just written outside the parentheses. A call of this statement could be:

    IF value < maximum THEN
      write(value)
    END IF;

Semantics:
Symbol parameters must be defined in a syntax definition and in a corresponding semantic definition. In the semantic definition symbol parameters are written outside of the parentheses. In the actual parameter list the corresponding symbol of the formal parameter list must be written.

Syntax:

    symbol_parameter ::=
      name_identifier | special_identifier .

6.7 'attr' parameter

This declaration associates a name to the type 'char':

    const string: name (attr char) is "char";

This 'name' can be used as follows:

    writeln(name(char));

It is possible to overload such declarations:

    const string: name (attr boolean) is "boolean";
    const string: name (attr float) is "float";

An 'attr' parameter can be used in a function also:

    const func char: (attr char) parse (in string: stri) is func
      result
        var char: result is ' ';
      begin
        if length(stri) >= 1 then
          result := stri[1];
        else
          raise RANGE_ERROR;
        end if;
      end func;

Semantics:
The actual parameter which corresponds to an 'attr' parameter must be the type mentioned in the declaration of the 'attr' parameter. An 'attr' parameter does not declare a formal parameter variable which could be used inside a function.

Syntax:

    attr_parameter ::=
      'attr' type_expression .