Imp
Copyright (c) 1998-1999 Redshift Software Inc. All Rights Reserved

5

Statements

 
 
Statements execute in textual order within a statement block. The following are statements; conditional, if, case, loop, routines with no returned values, assignment, declarations, and assembly blocks.

5.1
Assignment
 
 
IMP is unusual since it allows multiple assignment. This means that the programmer may assign multiple values to multiple variables in one statement. For example, two variables x and y could be swapped with the following statement:

x,y <- y,x;

Multiple assignment allows elegant programming constructs when combined with routines. A routine can return multiple values into appropriate variables and save quite a lot of ugly record passing common in other languages.

When used with an inline operator this features lets us write out what would otherwise require assembly to construct... vector operations. This is especially important now because of the increasing number of consumer CPUs that have (or are planning to) such built in operations. For example a vector multiplication would look like:

x: [5]int <- coerce(1,2,3,4,5);
y: [5]int <- coerce(50,40,30,20,10);

x * <- y;

Resulting in x having: 50,80,90,80,50.


5.2
Routine
 
 
A routine can only appear by itself if it has no return values. Otherwise it can only appear where an expression would be legal.

5.3
Assembly
 
 
Assembly statements provide a programmer with the ability to use assembly for tasks which require machine specific information. Such code is typically used in controlling real hardware such as disk drives. IMP expressions may be embedded in the assembly code to provide a mechanism to "glue" the assembly and IMP code together i.e. asm: { mov {&foo},a0 };

5.4
Exceptions
 
 

Guard and handle statements provide a programmer the ability to handle exceptions. The programmer writes a guard statement that declares a variable that stores the exception type. Inside the guard block, the programmer writes a set of statement blocks each followed by a conditional statement that invokes a handler (an inline routine that may accept a record from from the fail or recover calls)

Fail and recover are special language constructs that resemble routine calls. When invoked, a programmer passes the exception type and possibly a record containing program state (e.g. variable references) that the handle statement may use for recovery. After a handle call executes control may go to one of two places, for a fail call execution continues in the textual block following the handler, for a recover call execution returns to just after the recover statement in the textual block generating the exception. If fail or recover are not invoked (i.e. normal execution) control continues after the end of the guard statement.

An example to clarify the use of these constructs follows:

exception:type enumeration register (OK;DivideByZero;GoHome) -> (0;1;2);
IntegerDivisionException:type record
{
    numerator: &integer;
    denominator: &integer;
};

guard (e:register <- OK)
{
    x:integer <- 0;
    y:integer <- 0;
    {
        ...

        fail(GoHome);

        ...
        divByZero: IntegerDivisionException <- coerce(&x,&y);
        on (y = 0) recover(DivideByZero,divByZero);
        xDivY <- x/y;
        
        ...
    }
    on (e = DivideByZero * e > 2) handle(divByZero:IntegerDivisionException)
    {
        @(divByZero.y) <- 1;
        @(divByZero.x) <- 1;
    }
    or (e = GoHome) handle()
    {
        ...
    }
    
    
    {
        fail(GoHome);
    }
    on (e = GoHome) handle()
    {
        ...
    }
}

 
Reference
 
1 Lexical
2 Programs
3 Declarations
4 Expressions
5 Statements
6 Preprocessor
7 EBNF