|
|
|
|
|
6. PARAMETERS
The following subchapters introduce the parameter types of Seed7. 6.1 'val' parameterThis 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.
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.
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.
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;
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;
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;
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;
Syntax:
attr_parameter ::=
'attr' type_expression .
|
|