Subsections

- 1 Expression syntax
- 2 Function calls
- 3 Set constructors
- 4 Value typecasts
- 5 The @ operator
- 6 Operators
  - 1 Arithmetic operators
  - 2 Logical operators
  - 3 Boolean operators
  - 4 String operators
  - 5 Set operators
  - 6 Relational operators

#
6 Expressions

Expressions occur in assignments or in tests. Expressions produce a value, of a certain type. Expressions are built with two components: Operators and their operands. Usually an operator is binary, i.e. it requires 2 operands. Binary operators occur always between the operands (as in `X/Y`). Sometimes an operator is unary, i.e. it requires only one argument. A unary operator occurs always before the operand, as in `-X`.

When using multiple operands in an expression, the precedence rules of table (OperatorPrecedence) are used.

Table: Precedence of operators
Operator | Precedence | Category
`Not, @` | Highest (first) | Unary operators
`* / div mod and shl shr as` | Second | Multiplying operators
`+ - or xor` | Third | Adding operators
`< <> < > <= >= in is` | Lowest (Last) | relational operators

When determining the precedence, the compiler uses the following rules:

1. In operations with unequal precedences the operands belong to the operater with the highest precedence. For example, in `5*3+7`, the multiplication is higher in precedence than the addition, so it is executed first. The result would be 22.
2. If parentheses are used in an expression, their contents is evaluated first. Thus, `5*(3+7)` would result in 50.

Remark: The order in which expressions of the same precedence are evaluated is not guaranteed to be left-to-right. In general, no assumptions on which expression is evaluated first should be made in such a case. The compiler will decide which expression to evaluate first based on optimization rules. Thus, in the following expression:

      a := g(3) + f(2);

`f(2)` may be executed before `g(3)`. This behaviour is distinctly different from or .

If one expression must be executed before the other, it is necessary to split up the statement using temporary results:

      e1 := g(3);
      a  := e1 + f(2);

# 1 Expression syntax

An expression applies relational operators to simple expressions. Simple expressions are a series of terms (what a term is, is explained below), joined by adding operators.

> Expressions

The following are valid expressions:

    GraphResult<>grError
    (DoItToday=Yes) and (DoItTomorrow=No);
    Day in Weekend

And here are some simple expressions:

    A + B
    -Pi
    ToBe or NotToBe

Terms consist of factors, connected by multiplication operators.

> Terms

Here are some valid terms:

    2 * Pi
    A Div B
    (DoItToday=Yes) and (DoItTomorrow=No);

Factors are all other constructions:

> Factors

# 2 Function calls

Function calls are part of expressions (although, using extended syntax, they can be statements too). They are constructed as follows:

> Function calls

The variable reference must be a procedural type variable reference. A method designator can only be used inside the method of an object. A qualified method designator can be used outside object methods too. The function that will get called is the function with a declared parameter list that matches the actual parameter list. This means that

1. The number of actual parameters must equal the number of declared parameters.
2. The types of the parameters must be compatible. For variable reference parameters, the parameter types must be exactly the same.

If no matching function is found, then the compiler will generate an error. Depending on the fact of the function is overloaded (i.e. multiple functions with the same name, but different parameter lists) the error will be different. There are cases when the compiler will not execute the function call in an expression. This is the case when assigning a value to a procedural type variable, as in the following example:

    Type
      FuncType = Function: Integer;
    Var A : Integer;
    Function AddOne : Integer;
    begin
      A := A+1;
      AddOne := A;
    end;
    Var F : FuncType;
        N : Integer;
    begin
      A := 0;
      F := AddOne; { Assign AddOne to F, Don't call AddOne}
      N := AddOne; { N := 1 !!}
    end.

In the above listing, the assigment to F will not cause the function AddOne to be called. The assignment to N, however, will call AddOne. A problem with this syntax is the following construction:

    If F = AddOne Then
      DoSomethingHorrible;

Should the compiler compare the addresses of `F` and `AddOne`, or should it call both functions, and compare the result ? Free Pascal solves this by deciding that a procedural variable is equivalent to a pointer. Thus the compiler will give a type mismatch error, since AddOne is considered a call to a function with integer result, and F is a pointer, Hence a type mismatch occurs. How then, should one compare whether `F` points to the function `AddOne` ? To do this, one should use the address operator `@`:

    If F = @AddOne Then
      WriteLn ('Functions are equal');

The left hand side of the boolean expression is an address. The right hand side also, and so the compiler compares 2 addresses. How to compare the values that both functions return ? By adding an empty parameter list:

      If F()=Addone then
        WriteLn ('Functions return same values ');

Remark that this behaviour is not compatible with Delphi syntax.

# 3 Set constructors

When a set-type constant must be entered in an expression, a set constructor must be given. In essence this is the same thing as when a type is defined, only there is no identifier to identify the set with. A set constructor is a comma separated list of expressions, enclosed in square brackets.

> Set constructors

All set groups and set elements must be of the same ordinal type. The empty set is denoted by `[]`, and it can be assigned to any type of set. A set group with a range `[A..Z]` makes all values in the range a set element. If the first range specifier has a bigger ordinal value than the second the set is empty, e.g., `[Z..A]` denotes an empty set. The following are valid set constructors:

    [today,tomorrow]
    [Monday..Friday,Sunday]
    [ 2, 3*2, 6*2, 9*2 ]
    ['A'..'Z','a'..'z','0'..'9']

# 4 Value typecasts

Sometimes it is necessary to change the type of an expression, or a part of the expression, to be able to be assignment compatible. This is done through a value typecast. The syntax diagram for a value typecast is as follows:

> Typecasts

Value typecasts cannot be used on the left side of assignments, as variable typecasts. Here are some valid typecasts:

    Byte('A')
    Char(48)
    boolean(1)
    longint(@Buffer)

The type size of the expression and the size of the type cast must be the same. That is, the following doesn't work:

    Integer('A')
    Char(4875)
    boolean(100)
    Word(@Buffer)

This is different from Delphi or Turbo Pascal behaviour.

# 5 The @ operator

The address operator `@` returns the address of a variable, procedure or function. It is used as follows:

> Address factor

The `@` operator returns a typed pointer if the `$T` switch is on. If the `$T` switch is off then the address operator returns an untyped pointer, which is assigment compatible with all pointer types. The type of the pointer is `^T`, where `T` is the type of the variable reference. For example, the following will compile

    Program tcast;
    {$T-} { @ returns untyped pointer }

    Type art = Array[1..100] of byte;
    Var Buffer : longint;
        PLargeBuffer : ^art;

    begin
     PLargeBuffer := @Buffer;
    end.

Changing the `{$T-}` to `{$T+}` will prevent the compiler from compiling this. It will give a type mismatch error. By default, the address operator returns an untyped pointer. Applying the address operator to a function, method, or procedure identifier will give a pointer to the entry point of that function. The result is an untyped pointer. By default, the address operator must be used if a value must be assigned to a procedural type variable. This behaviour can be avoided by using the `-So` or `-S2` switches, which result in a more compatible Delphi or Turbo Pascal syntax.

# 6 Operators

Operators can be classified according to the type of expression they operate on. We will discuss them type by type.

## 1 Arithmetic operators

Arithmetic operators occur in arithmetic operations, i.e. in expressions that contain integers or reals. There are 2 kinds of operators : Binary and unary arithmetic operators. Binary operators are listed in table (binaroperators) , unary operators are listed in table (unaroperators) .

Table: Binary arithmetic operators
Operator | Operation
`+` | Addition
`-` | Subtraction
`*` | Multiplication
`/` | Division
`Div` | Integer division
`Mod` | Remainder

With the exception of `Div` and `Mod`, which accept only integer expressions as operands, all operators accept real and integer expressions as operands. For binary operators, the result type will be integer if both operands are integer type expressions. If one of the operands is a real type expression, then the result is real. As an exception : division (`/`) results always in real values.

Table: Unary arithmetic operators
Operator | Operation
`+` | Sign identity
`-` | Sign inversion

For unary operators, the result type is always equal to the expression type. The division (`/`) and `Mod` operator will cause run-time errors if the second argument is zero. The sign of the result of a `Mod` operator is the same as the sign of the left side operand of the `Mod` operator. In fact, the `Mod` operator is equivalent to the following operation :

      I mod J = I - (I div J) * J

but it executes faster than the right hand side expression.

## 2 Logical operators

Logical operators act on the individual bits of ordinal expressions. Logical operators require operands that are of an integer type, and produce an integer type result. The possible logical operators are listed in table (logicoperations) .

Table: Logical operators
Operator | Operation
`not` | Bitwise negation (unary)
`and` | Bitwise and
`or` | Bitwise or
`xor` | Bitwise xor
`shl` | Bitwise shift to the left
`shr` | Bitwise shift to the right

The following are valid logical expressions:

    A shr 1  { same as A div 2, but faster}
    Not 1    { equals -2 }
    Not 0    { equals -1 }
    Not -1   { equals 0  }
    B shl 2  { same as B * 2 for integers }
    1 or 2   { equals 3 }
    3 xor 1  { equals 2 }

## 3 Boolean operators

Boolean operators can be considered logical operations on a type with 1 bit size. Therefore the `shl` and `shr` operations have little sense. Boolean operators can only have boolean type operands, and the resulting type is always boolean. The possible operators are listed in table (booleanoperators)

Table: Boolean operators
Operator | Operation
`not` | logical negation (unary)
`and` | logical and
`or` | logical or
`xor` | logical xor

Remark: Boolean expressions are always evaluated with short-circuit evaluation. This means that from the moment the result of the complete expression is known, evaluation is stopped and the result is returned. For instance, in the following expression:

     B := True or MaybeTrue;

The compiler will never look at the value of `MaybeTrue`, since it is obvious that the expression will always be true. As a result of this strategy, if `MaybeTrue` is a function, it will not get called ! (This can have surprising effects when used in conjunction with properties)

## 4 String operators

There is only one string operator : `+`. It's action is to concatenate the contents of the two strings (or characters) it stands between. One cannot use `+` to concatenate null-terminated (`PChar`) strings. The following are valid string operations:

      'This is ' + 'VERY ' + 'easy !'
      Dirname+'\'

The following is not:

    Var Dirname = Pchar;
    ...
      Dirname := Dirname+'\';

Because `Dirname` is a null-terminated string.

## 5 Set operators

The following operations on sets can be performed with operators: Union, difference and intersection. The operators needed for this are listed in table (setoperators) .

Table: Set operators
Operator | Action
`+` | Union
`-` | Difference
`*` | Intersection

The set type of the operands must be the same, or an error will be generated by the compiler.

## 6 Relational operators

The relational operators are listed in table (relationoperators)

Table: Relational operators
Operator | Action
`=` | Equal
`<>` | Not equal
`<` | Stricty less than
`>` | Strictly greater than
`<=` | Less than or equal
`>=` | Greater than or equal
`in` | Element of

Left and right operands must be of the same type. Only integer and real types can be mixed in relational expressions. Comparing strings is done on the basis of their ASCII code representation. When comparing pointers, the addresses to which they point are compared. This also is true for `PChar` type pointers. To compare the strings the `Pchar` point to, the `StrComp` function from the strings unit must be used. The `in` returns `True` if the left operand (which must have the same ordinal type as the set type) is an element of the set which is the right operand, otherwise it returns `False`