Statements

In this chapter, we deal with the statements of Pascal. These statements control most of the actions performed by a program.

Note that Alice can only handle lines shorter than 256 characters. If you have a very long line, you will have to break it up into smaller pieces.

Comments

Comments are not really statements at all, but it is convenient to deal with them at this time. Comments are enclosed in brace brackets. Everything between the "{" and the "}" is ignored.

Because of Alice's tight structure, comments may only appear in two places: as part of a template (where they are included automatically) and on a line all on their own. If you have a comment that extends over several lines, each line must be enclosed in brace brackets, as in

{    This}
{    is}
{    a}
{    comment!}

The Assignment Statement

The most basic statement type in Pascal is the assignment. It has the form

variable := expression

where the type of expression is assignment-compatible with the type of variable. An assignment statement stores the value of the expression in the given variable.

You may not assign values to variables that have a file type, or records or arrays that contain a file type.

If a string value (constant or variable) is assigned to a variable of a string type, the result depends on the relative lengths of the two strings. If you assign a longer string to a shorter one, the assigned string will be truncated to the appropriate length. For example, if str3 is a string variable of length 3,

str3 := 'abcde';

stores the string "abc" in str3.

If you assign a shorter string to a longer one, the characters of the shorter string are placed in the longer string, and then the special StrEnd character is placed after the last character to mark the end of the string. For example, if str5 is a string of length 5,

str5 := 'abc';

gives str5 the following elements.

str5[1] = 'a'
str5[2] = 'b'
str5[3] = 'c'
str5[4] = StrEnd
str5[5] is undefined

Alice also lets you assign string constants to Pointer variables. The string is created in memory and the Pointer variable receives a pointer to the first character in the string. For example, you might write

type
    str10 = packed array [1..10] of char;
var
    p : Pointer;
    sp : ^str10;
begin
p := 'SMILE!';
sp := p;
writeln(sp^[1]);

This will write out the letter S.

You can also assign variables of type String to Pointer variables; the resulting pointer points at the first character of the string (not at the 0th element).

The assignment statement is also used in functions (subprograms that return values to their callers). The function indicates its return value by assigning the value to the name of the function. For example, in a function called func

func := 3;

means that the function should return the value 3. The type of the value assigned to the function name should be assignment compatible with the type declared for the function.

This sort of assignment does not cause the function to return immediately. The function may have several statements that assign values to the function name. The return value for the function will be the last value that was assigned to the function name.

Procedure Calls

A procedure call is another common kind of statement. The general form of a procedure call is

procname( argument,argument,... )

where procname is the name of the procedure that is being called. If no arguments are being passed to the procedure, the parentheses are omitted, as in

writeln;

Chapter 6 discusses function calls in more detail.

The goto Statement

The goto statement can be used to jump to a labelled statement. The label must be a positive integer constant that has been declared in the label declaration section of the program or subprogram that contains the goto. (Note that the label cannot be a constant expression or a variable.) A typical goto statement might be

goto 12;

The scope of a label is the subprogram in which it was defined. It is not possible to jump from a subprogram into an entirely separate subprogram. However, if one subprogram is declared inside another subprogram, you may jump out of the inner subprogram to the outer -- simply declare a label in the outside subprogram and the scope of the label will include the inner subprogram.

You cannot jump into a begin block or any statement whose template contains a begin block. You can, however, jump out of a begin block, provided that you are not superstepping or using Alice's EXECUTE command.

Structured Statements

The statements we have discussed up to this point were simple statements. The ones that follow are known as structured statements. Structured statements are ones that can contain other statements.

Compound Statements

A compound statement is made up of one or more other statements. A compound statement may be used anywhere a simple statement may be used.

Compound statements start with the keyword begin and end with the keyword end. Statements inside a compound statement are separated with semicolons. The standard form of a compound statement is

begin

statement;

statement;

statement;

...

statement

end

(Note that the block can contain a single statement as well as a number of statements.)

Normally, compound statements are not used explicitly in Alice, since all structured statements automatically contain a compound statement. This is shown in the sections that follow.

The if Statement

There are two forms of the Pascal if statement. The first is

if Condition then begin
    Statement
    Statement
          ...
    Statement
    end;

The Condition is a Boolean expression. If the result is true, the statement(s) in the begin block are executed. If the result is false, Alice will skip to whatever follows the end of the block. For example,

if A > B then begin
    C := A;
    end;

will do the assignment C:=A if A is greater than B. If A is not greater than B, control will skip to whatever follows the end.

The second form of the if statement is

if Condition then begin
    Statement
      ...
    end
 else begin
    Statement
      ...
    end;

Again, the Condition is a Boolean expression. If this result is true, the statement(s) in the first begin block are executed. If the result is false, the statements in the second begin block are executed.

You may nest ifs and elses if you wish. Alice will show how ifs and elses pair up by indentation.

The case Statement

The case statement contains several blocks of code. It decides which of these blocks should be executed by looking at the value of an expression. The statement has the form

case Value of
    Case-Instance
    Case-Instance
    Case-Instance
        ...
    Case-Instance
    end;

The Case-Instance blocks take the form

Constant : begin
    Statement
    end;

or

Constant, Constant, ... : begin
    Statement
    Statement
        ...
    Statement
    end;

or

Constant..Constant: begin
    Statement
    Statement
        ...
    Statement
    end;

The first step in executing the case statement is to evaluate the Value that follows the keyword case. This expression may have any scalar type.

The next step is to see if the result of the expression matches any of the constants that begin individual case instances. These constants are known as case labels. The case label values must be of the same scalar type as the expression that follows the keyword case. The result of this expression matches a case label if it is equal to one of the constant values given in the label, or if it falls in the range of a

Constant..Constant

form. The first time that a case label matches the result of the expression, the begin block following the case label will be executed. Once this statement has been executed, Alice will jump to whatever follows the end that marks the end of the whole case statement.

As a simple example, suppose the variable i is a integer variable.

case i%3 of
  0 : begin
      writeln('Number is multiple of three');
      end;
  1,2 : begin
      writeln('Number is not a multiple of three');
      end;
  end;

This code determines whether i is an even multiple of three and prints out the result.

In addition to normal case instances, every case statement can contain a special case instance of the form

else begin
    Statement
    Statement
        ...
    Statement
    end;

The begin block in this case instance is executed if the case expression does not match any of the other case labels. For example, you might have

case c of
  'a'..'z' : begin
      writeln('Lower case');
      end;
  'A'..'Z' : begin
      writeln('Upper case');
      end;
  else begin
      writeln('Not a letter');
      end;
  end;

If c is an upper or lower case letter, an appropriate message is printed. Otherwise, the Not a letter message is printed.

The else does not have to be the last in the list of cases. If a case statement has two else clauses, you will be given an error message when you run the program. If a case statement has no else clause and the case expression value does not match any of the case labels, you will also be given an error at run-time.

The while Statement

The while statement has the form

while Condition do begin
    Statement
    Statement
        ...
    Statement
    end;

The Condition is a Boolean expression. The statements in the begin block will be executed over and over again as long as the condition is true at the beginning of the block. The looping stops when the condition is found to be false at the beginning of the block. For example,

i := 1;
while arr[i] > 0 do begin
    i := i + 1;
    end;

begins with the index i at 1 and loops until it finds an element of the array arr that is less than or equal to zero.

If the expression at the beginning of the while loop is false to begin with, the begin block is not executed. In the example above, if arr1 was not greater than 0, the statement inside the while loop would not even be executed once.

The repeat Statement

The repeat statement is similar to the while statement. It has the form

repeat
    Statement
    Statement
    Statement
        ...
    Statement
until Condition;

The Condition is a Boolean expression. The statements between the repeat and until will be repeated until the result of the condition is true at the end of an execution of the block.

The statements between repeat and until will always be executed at least once -- the condition is tested after the statements have been executed, unlike while, where the condition is tested before the statements are executed. For example, in

i := 0;
repeat
    i := i + 1
until arr[i] <= 0;

the assignment incrementing i will always be executed at least once.

The for Statement

The for statement is another way of repeating a block of statements. It has the form

for variable := start to finish do begin
    Statement
    Statement
    Statement
        ...
    Statement
    end;

The variable is called the control variable of the for loop. It may have any scalar type. The expressions start and finish must have the same scalar type.

The first step in executing the for statement is comparing the expressions start and finish. If start is greater than finish, the begin block that comes after the keyword do will not be executed at all.

If start is less than or equal to finish, the value of start will be assigned to the control variable. The begin block after the do will then be executed. When the statement is finished, Alice will change the value of the control variable to its successor using the succ function and the statement will be executed again. (The succ function is described in Chapter 8.) This process will be repeated, until Alice has finished executing the statement with the control variable having the value given by finish. When this is finished, Alice will go on to whatever follows the end of the for loop block.

As an example,

for i := 1 to 10 do begin
    arr[i] := 0;
    end;

zeroes the first 10 elements of an array arr. The statement after do is executed once for every value of i between 1 and 10 (inclusive).

At the end of a for loop, the value of the control variable is undefined. If control passes out of the loop by means of a goto, the value of the control variable will be whatever it was when the goto was encountered.

The for statement can also be written as

for variable := start downto finish do begin
    Statement
    Statement
    Statement
        ...
    Statement
    end;

In this case, start should be greater than finish. The control variable begins at start and goes down step by step (using the pred function) until it reaches finish. (The pred function is described in Chapter 8.) Apart from this, the downto form is the same as the to form.

You should not assign values to the control variable inside a for block, and you may not pass the control variable as a var argument to a subprogram.

The with Statement

The with statement is used to simplify work with record variables. It has the form

with record-variable do begin
    Statement
    Statement
    Statement
        ...
    Statement
    end;

Inside a with block, you can refer to fields of the given record variable without putting the usual

record-variable.

prefix in front of them. For example, suppose we have declared

type
    personnel = record
                    name : packed array [1..40] of char;
                    empno, age : integer;
                    income : real
                end;
var
    Bob, Rick, Nancy : personnel;

We might have a with statement of the form

with Bob do begin
    name := 'Bob Jones';
    age := 35;
    income := 30000.00
    end;

This is equivalent to

begin
    Bob.name := 'Bob Jones';
    Bob.age := 35;
    Bob.income := 30000.00
    end;

Inside the with statement, we can use field names without the usual prefix. If a field name happens to be the same as the name of another variable, the reference inside the with statement will always be to the field, not the variable with the same name.

Note that some versions of Pascal let you write

with A,B do ...

to represent

with A do begin
    with B do begin...

The abbreviated form is not used in Alice. However, the APIN program recognizes the form and will convert it properly if you are reading in a program for some other version of Pascal.