ColdC: Language Structure: Statements


Statements are instructions to the interpreter. Statements can be simple (such as comments), or they can be complex (such as loops and conditionals). However, most statement types in ColdC have simple structures. Because statements can include other statements, you can use these simple statement types to build complex directives.

The following sections describe simple statements, which perform simple actions once, conditional statements, which perform different actions depending on the value of an expression, looping statements, which perform an action multiple times, and error-handling statements, which affect how the interpreter handles error conditions.

Simple Statements

comment statement

The comment statement does nothing at all. A comment statement is just a comment token, which is a sequence of two slashes (`//') followed by any characters up to the end of the lines. For instance:

// This is a comment.

The interpreter ignores comment statements completely; they are for the benefit of human readers. Note that comments in ColdC are actual statements, unlike comments in C, which are filtered out by the preprocessor.

expression statement

The expression statement evaluates an expression and discards its value. The syntax of the expression statement is:

expression;

The following are expression statements:

3;
sender().tell($sys.who());

compound statement

The compound statement allows you to treat one or more statements as a single statement. The compound statement has the following syntax:

{
    statement1
    statement2
    .
    .
    .
}

The interpreter executes each of statement1, statement2, ... in turn.

return statement

The return statement allows a method to stop exeuting statements and to return a value other than the default return value of this(). The return statement can have either of the following two forms:

return expression;
return;

The interpreter stops executing statements in the method and returns the value of expression, or the objnum of the current object if expression is not given.

Conditional Statements

There are three types of conditional statements in ColdC. The

if statement

if statement has the following syntax:
if (expression)
    statement

The interpreter evaluates expression. If the value of expression is true (see section Data Types), then the interpreter executes statement.

if-else statement

The if-else statement is similar to the if statement. The if-else statement has the following syntax:

if (expression)
    true-statement
else
    false-statement

The interpreter evaluates expression, as before. If the value of expression is true, then the interpreter executes true-statement; otherwise, it executes false-statement.

Because the if statement and the if-else statement are similar, they can sometimes be ambiguous. The following code will produce unexpected results:

if (a)
    if (b) c;
else
    d;

The indentation suggests that the else clause should apply to the first if clause, but in fact it applies to the more recent one. You can avoid ambiguities like this by using braces to create compound statements out of conditional and looping statements, even if there is only one of them. In this case, you might write:

if (a) {
    if (b)
        c;
} else {
    d;
}

switch statement

The third type of conditional statement is the switch statement, which allows you to compare one value against a series of other values. The switch statement is the most complicated statement type in ColdC, and does vary from it's counterpart in C, so we'll start with an example:

switch (val) {
    case 0:
        echo("The value is zero.");
    case 1 .. 10:
        echo("The value is between one and ten inclusive.");
    case 11 .. a:
        echo("The value is between eleven and a inclusive.");
    case "foo", "bar".."baz":
	echo("The value is \"foo\" or between \"bar\" and \"baz\"");
    case a .. b, c .. d, 42:
        count = count + 1;
        echo("The value is in the counted area.");
    case ~perm:
        echo("Permission denied while getting the value.");
    default:
        echo("Did not recognize value.");
}

This example illustrates all of the capabilities of the switch statement. The expression given by val in the example is the controlling expression, and is compared against each of the cases inside the switch body. Each case has a value or list of values to compare against. The values can be of any type, and need not be constant expressions. You can also specify ranges, using two dots (`..') to separate the lower and upper bounds. The keyword default specifies an action to perform if no cases were matched by the controlling expression.

Here is a more formal description of the syntax of the switch statement:

switch (controlling-expression) {
    case expr-or-range, expr-or-range, ...:
        statements
    case expr-or-range, expr-or-range, ...:
        statements
    .
    .
    .
    default:
        default-statement
}

When executing a switch statement, the interpreter scans through the list of cases and compares controlling-expression against each of the lists of values in the cases, evaluating the value lists from left to right until there is a match. The lower and upper bounds of ranges must be of the same type and must be either integers or strings, or the interpreter will throw a ~type error. When the interpreter finds a match, it will execute the statement for that case. The interpreter will not continue checking cases after a match.

If the interpreter does not find a match, it will execute default-statement, the statement corresponding to the default case. You do not need to provide a default case if you do not wish to provide a default action.

C programmers should note that switch statements in ColdC differ from switch statements in C in several respects. Because case values do not have to be constants, they may conflict, in which case the first match will take precedence. Also, there is no fall-through in ColdC switch statements; only the statements corresponding to the matching case will be executed. Because there is no fall-through, the break statement does not apply to switch statements. Finally, the default case must be placed last in the list of cases if it is given.

Looping Statements

ColdC provides three kinds of looping statements. These statements allow you to traverse a list or a range of numbers, or to execute a statement as long as a certain condition is true. ColdC also provides two kinds of jump statements which allow you to prematurely exit from a loop or continue onto the next iteration.

for-list statement

The for-list statement allows you to traverse a list. It has the following syntax:

for variable in (what)
    statement

variable must be a local variable (it cannot be an object variable), and what must be an expression resulting in a list or dictionary type. The interpreter executes statement once for each element in what, assigning the value of the element to variable during the iteration. Here is an example of using a for-list statement on a list:

for s in (["foo", "bar", "baz"])
    .tell(s);

When executed, the method tell is called three times, the first time with an argument of "foo" (the first element in the list), the second time with "bar" (the second element in the list), and the third time with "baz" (the last element in the list).

When using a dictionary as what, the interpreter assigns each association in the dictionary to variable (see Data Types: Dictionaries). For example, if the dictionary #[['count, 21], ['name, "foo"]] were to be used in a for-list statement, the first iteration would set variable to ['count, 21], and the second iteration would set it to ['name, "foo"].

Assigning to variable within a for-list statement will not change the status of the loop; the interpreter remembers where it is at in what.

for-range statement

The for-range statement allows you to traverse a range of integers. The range is specified by seperating the lower and upper bounds of the range with the range operator (..), contained within the left and right square brackets ([ and ]). A for-list statement of this nature would look like:

for variable in [lower .. upper]
    statement

lower and upper must be expressions resulting in an integer type (unlike a range in a switch). The interpreter executes statement once for each number from lower to upper, with variable being assigned the current number in the range. An example of using a range in a list follows:

for i in [1 .. 10]
    .tell("iteration " + i);

Assigning to variable within a for-list statement will not change the status of the loop; the interpreter remembers where it is at in what.

while statement

The while statement allows you to execute code as long as the condition expression is true. The while statement has the following syntax:

while (expression)
    statement

The interpreter continually evaluates expression and executes statement until the return value of expression is false. Here is an example using a while statement:

a = 1;
while (a < 35)
    a = a * 2;
.tell("total: " + a);

break statement

The break statement allows you to exit a looping statement prematurely. The break statement has the following syntax:
break;

The interpreter jumps to the end of the innermost for-list, for-range, or while statement. It is important to note that using the break statement within nested looping statements only breaks out of the innermost looping statement.

continue statement

The continue statement allows you to jump to the next iteration of a loop. The continue statement has the following syntax:

continue;

The interpreter skips the remainder of the loop body and begins another iteration of the innermost looping statement. As with the break statement the continue statement only is relevant to the innermost looping statement.

Error-Handling Statements

The catch statement allows you to indicate how errors should be handled. This statement can be used to anticipate an error and handle it gracefully. The catch statement has the following syntax:

catch error code, error code, ...
    body-statement
with handler
    handler-statement

You can substitute the keyword any for the list of errors to indicate that you wish to catch all errors. You can leave out the with handler and the handler statement if you do not wish to do anything in the handler.

If an error listed in the error list is thrown inside body-statement, the interpreter will execute the handler rather than aborting the method. After the handler is done, control continues after the end of the catch statement, as if body-statement had completed with no errors.

Inside the handler, you can use the function error() to determine the error code which triggered the handler, the function throw() can be used to initiate an error, and the function traceback() can be used to retrieve the propagated error stack. You can use the function rethrow() to continue propagating an error.

Here is an example of how you might use a catch statement to intelligently handle a ~methodnf error from the list_method() function:

catch ~methodnf {
    code = list_method(method_name);
} with handler {
    .tell("There is no method named " + tostr(method_name) + ".");
}

Note that critical expressions inside body-statement will override the behavior of the catch statement.


Last Modified on Feb 26 1996
Copyright © 1995, 1996, Brandon Gillespie