PLANC User Guide

About this chapter

This chapter will teach you to read and make PLANC code.

The first two sections

The first subsection will introduce you to the language features that make PLANC programs look unfamiliar at first sight.

The rest builds on these basics and your previous knowledge

When you have a grasp of these basics, you will be shown how the cornmon ingredients in block-structured languages have been implemented in PLANC. There will be sections about:

Learn by examples

The manual contains extensive and complete code examples that can be compiled into executable programs. Much information is given as cornments inside the examples. There are three reasons for this approach:

Use tools while learning PLANC

It is common practice in textbook examples of code to include numerous 1/0 statements which print results during execution of the prograrns. These I/0 statements do not contribute to the readability of the examples, and can be made superfluous if the you use a good debugger (such as the ND Symbolic Debugger) to observe the state of the programs during execution. It is also a good idea to use LED, as it is designed with features that facilitate development of programs in PLANC (indentation, pretty-print, compilations to locate errors and so on).

Getting used to reading PLANC

For the most part. PLANC is a conventional block-structured language. However, it has a few features that set it a apart from other languages such as C and Pascal and which will obscure the more familiar features of the language until you know more about them. This section contains a couple of profusely commented programs that demonstrate those features.

M1 - Your first PLANC program

Introduction

This subsection contains a simple program. It shows how all statements are contained in a block delimited by the keywords MODULE and ENDMODULE. You will also notice PLANC's explicit stack initiation, how to use the PROGRAM declaration, how PLANC assignments are written, and a little about type checking.

Before you start reading the example

What you need to know before you read the following code is that end-ofline also denotes end-of-statement, and that the percent sign, (%), marks the beginning of a comment that ends at the end of the line. To give emphasis to the comments to important module and routine declarations, they have been placed inside LED header frames. When using LED, you make such frames by pressing the F4 key on the TDV keyboard. There are percentage signs at the end of some comments too, but they are there for cosmetic purposes only. The points demonstrated by the example are summarized immediately after it.

%=============================================================%
% m1
% Your first PLANC module.
%=============================================================%
MODULE ml
% The following INTEGER ARRAY will contain the stack space
% of the program. It will be initialized as such in the
% main program. A program may have any number of
% stacks, although you rarely need more than one.
INTEGER ARRAY : StackSpace (0:255)
%=============================================================%
% Main %
% %
% The keyword PROGRAM tells the compiler that what %
% follows is a routine in which program execution will start. %
%=============================================================%
PROGRAM : Main
% These are declarations of a couple of variables; one
% is an integer which will occupy two bytes of memory,
% the next is a real number.
INTEGER2 : i
REAL : r
% Before the program can run, it needs a stack for
% storing stackframes, parameters and intermediate
% results during execution. The StackSpace array is
% prepared for that use in the next declaration.
INISTACK StackSpace
% This is the first executable statement in the program.
%
% In PLANC, the operator =: is used to store values
% into data elements during evaluation of an expression.
% The store operator works from left to right: The
% result of the expression on the left is stored into
% the variable on the right.
% In the following statement, the value 7 is stored
% into the variable i.
7 =: i
% There is type checking In PLANC. For Instance, only
% values that are INTEGER can be stored into variables
% declared as INTEGER. If It is necessary to store an
% INTEGER value Into a REAL variable, it must be con
% verted to REAL before It can be stored, as follows:
(i * i) CONVERT REAL =: r
% The keyword ENDROUTINE ends the PROGRAM.
% In the comment to the PROGRAM declaration, we said that
% the keyword PROGRAM designates the start of the routine
% where program execution will begin. Both PROGRAMs and
% all other routine declarations end with the ENDROUTINE
% statement. Just to make it clear which routine ends
% where, you can write the name of the routine after its
% ENDROUTINE statement.
ENDROUTINE Main
% Just like ENDROUTINE ends routines, ENDMODULE ends
% modules.
ENDMODULE
% The next line contains a compiler command that signals
% the end of the current file. This command is not strictly
% necessary, only useful. If it were not used, you would
% have to type EXIT to the compiler to leave it, but the
% next line stops the compiler for you. (If this file were
% included as part of another file, the compiler would
% resume compilation of the other file instead of stopping.)
$EOF

Comments

Most PLANC code comes in modules. (Only CONSTANT, TYPE and macro declarations plus compiler commands are allowed outside modules, as we shall see later.)

Variables (and routines) are declared by first writing their type followed by a colon (:), followed by the name of the variable(s). In the example, INTEGER ARRAY, INTEGER2 and REAL were used to declare the StackSpace, i and r variables.

All keywords that mark the beginning of a block of code are matched with a similar keyword marking the end of the block. In this example, MODULE was matched with ENDMODULE, while PROGRAM was matched with ENDPROGRAM.

A program must contain one, and only one, PROGRAM declaration to indicate where execution will start.

The stack is handled explicitly. The programmer must declare a suitable INTEGER ARRAY for it, and initialize the stack before the first executable statement in the PROGRAM.

M2 - Presenting PLANC

The first example contained only one routine, which happened to be the simplest of routine declarations, the PROGRAM. Now meet some more complex routines: a record with a routine inside it and an exceptionhandler .

%=============================================================
% M 2
%
% This module shows more PLANC features, with emphasis
% on routines and records this time. The code here
% shows how vector arithmetic can be implemented. (Vectors
% are records consisting of real numbers that are handy in
% three-dimensional mathematics, in case you haven't met
% the term before.)
%=============================================================
MODULE m2
INTEGER ARRAY : Stack (0:1027)
%=============================================================
% S q r t
%
% PLANC does not have built-in mathematical functions, so
% an iterative algorithm for computing square roots of
% reals is implemented as a PLANC routine.
%
% All routines except the main PROGRAMs are defined using
% the keyword ROUTINE. PLANC has a couple of specialties:
% the in-value and the out-value. In Sqrt, the in-value is
% not used, as indicated with the keyword VOID, while the
% routine has an out-value that is REAL. That is the value
% that the routine will return to where it was called.
% Next comes parentheses, inside which the parameters to
% the ROUTINE are declared. There is one parameter here,
% namely the real number for which the square root is to
% be computed. Following the parameters comes a colon
% and the name that the routine will be known by in the
% program.
%=============================================================
ROUTINE VOID, REAL (REAL : r) : Sqrt
% Declaring a couple of variables to work with. These
% variables are only known locally, i.e. between
% the enclosing ROUTINE ... ENDROUTINE statements.
REAL : xn, xp
% We cannot compute the square root of a negative number.
IF r >= 0.0 THEN
% Giving initial values to the local variables.
r =: xn
0.0 =: xp
% The DO ... ENDDO construction makes an endless loop.
% One or more WHILE statements are needed inside the loop
% to exit from it.
DO
% This is the iterative formula.
(xn + r/xn) / 2.0 =: xn
% Iterations are to continue until there is no
% significant improvement relative to the previous
% value.
WHILE ABS(xn - xp) > 1.OE-6
% This statement is executed as long as the above
% condition holds. If the condition does not hold,
% execution continues at the first statement after
% the keyword ENDDO.
xn =: xp
ENDDO
% Now, the value of xn is good enough to be returned
% as the out-value of the routine.
xn RETURN
ELSE
% If r is negative, return to the calling routine
% with an ERRETURN statement which signals that something
% is wrong. If a routine exits through ERRETURN, an
% exception handler in the calling program (see below)
% can be invoked to take appropriate action.
0 ERRETURN
ENDIF
ENDROUTINE Sqrt
%=============================================================
% OldSqrt
%
% In PLANC versions up to H, another ROUTINE declaration
% layout was used. In it, the parameter types were decla-
% red before the :, while the parameter names were decla-
% red after the routine name. Sqrt uses a new layout which
% is easier to read, but the old layout can still be used,
% and this is how an old style Sqrt declaration looks:
%=============================================================
ROUTINE VOID, REAL (REAL) : OldSqrt (r)
REAL : xn, xp
% ... et cetera.
xn RETURN
ENDROUTINE
%=============================================================
% V e c t o r
%
% This is a record describing a vector as a record with
% three components. This vector definition also contains a
% routine that computes a real number that is called the
% length of the vector.
%=============================================================
TYPE Vector = RECORD
% The vector's three real components:
REAL : x, y, z
% L e n g t h returns a real out-value computed by
% applying the Sqrt routine to the sum of the square
% of the real components of the vector.
ROUTINE VOID, REAL : Length
% ON ... ENDON is an exception handler for use if Sgrt
% exits via its ERRETURN statement. When an exception
% occurs and handlers for it exist, the closest handler
% before the offending statement is activated. When the
% exception handler statements have been executed, the
% program will continue on the statement immediately
% after the offending statement - unless the exception
% handler changes the flow of control.
ON ROUTINEERROR DO
% & is the line continuation sign. It makes the
% current statement continue on the next line.
Output(1, 'a', &
'You cannot get the square root of a negative number!$')
ENDON
Sqrt(x*x + y*y + z*z) RETURN
ENDROUTINE Length
ENDRECORD
%=============================================================
% +
%
% You are probably not used to routines having names such
% as the next routine, which is called +. It has an
% in-value, an out-value and a parameter which are all
% Vectors.
%
% The in-value to a routine represents a dataelement that
% can be written to the left of the routine when it is
% called, and used inside the routine together with the
% parameters.
%
% Furthermore, if a routine has only one parameter, the
% parameter can be written without an enclosing paren-
% theses when the routine is called.
%
% To uniquely identify a routine, the type of the
% in-value and the number and types of the parameter(s)
% are used together with the name of the routine. So when
% the compiler sees a Vector followed by a + followed by
% another Vector, it knows that + is the name of a routine
% that takes a Vector on each side of it - i.e. the +
% works like a binary operator. This + also has the same
% priority as the operator + when used in expressions.
%=============================================================
ROUTINE Vector, Vector (Vector : b) : +
% A local Vector dataelement to put the desired
% out-value in.
Vector : Result
% The in-value is accessed using the special character
% Here, the x-component of the in-value is added to the
% x-component of the parameter, the result being stored
% into the x-component of the local Vector.
@.x + b.x =: Result.x
@.y + b.y =: Result.y
@.z + b.z =: Result.z
% ... Result's components contain the desired values,
% and Result can be returned as the routine's out-value.
Result RETURN
ENDROUTINE +
% All variables declared on the outermost level of the
% module are called global, while variables declared
% inside routines (Including PROGRAMs) are called local.
% Global variables (and local variables with READ access
% only, see later) can be given Initial values. Each
% variable of type Vector has three real numbers as
% components, and the three initial values for the compo-
% nents must be grouped together as a list of reals
% enclosed by parentheses. Statement continuation
% signs are not needed if you insert a CrLf in the middle
% of a list, like this:
Vector : xAxis := (1.0, 0.0, 0.0),
yAxis := (0.0, 1.0, 0.0),
zAxis := (0.0, 0.0, 1.0),
Composite
% The following global variable is also initialized. Its
% single initial value need not be enclosed in parentheses.
REAL : l := 0.0
PROGRAM : Main
% ... Important: always remember to initialize the stack
% in your PROGRAM!
INISTACK Stack
% In the next statement,
% zAxis is a Vector used as in-value,
% + is a routine name,
% yAxis is a Vector used as parameter,
% Composite is a Vector into which the out-value is
% stored.
zAxis + YAxis =: Composite
% All records of the type Vector contain a Length routine
% which has a real number representing its length as
% out-value. This routine is accessed via the usual dot
% notation for record component access. Let us compute
% the length of the Vector called Composite and store it
% into 1.
Composite.Length =: l
ENDROUTINE Main
ENDMODULE
$EOF

Comments

This program demonstrated how routines and records are made and used. Routines can be used like operators because of the in-/out-value mechanism and naming convention, while records can have routines as components.

Routines

The keyword ROUTINE is used for defining all routines except the main PROGRAM.

ROUTINEs always have an in-value and an out-value.

The in-value and the out-value can be declared as being of any valid type, or of the special type VOID if you do not want to use one or both of them. The keyword VOID can only be used in routine declaration.

When routines with non-void in-values are called, the name of the variable/constant/expres- sion you want to use as in-value is written to the left of the routine name, and can subsequently be accessed (but not changed) using the special variable name @ inside the routine.

If the out-value is not declared as VOID, the routine returns to the calling statement with a value that can be stored in a variable or used in further calculations. If the out-value is void, then no value is returned.

Routines can have zero or more parameters, and the parameters can be of any type. The parameter names can either be declared together with their type declarations to the left of the : (new style), or separately after the routine name (old style).

When the routine is called, the parameters are written as a list enclosed in parentheses to the right of the routine name, with one exception: if the routine has one parameter, the parameter can optionally be written without enclosing parentheses.

To identify the routine declaration used in a routine call when the routine name is overloaded, the compiler uses the type of the in-value, the number and the types of the parameters, and the name of the routine.

The out-value is not used for routine identification when overloading. This is because the out-value is not necessarily used. The routine name may be written as a statement all by itself, if necessary preceded by an in-value only. On the other hand, the routine name may be written as invalue to other routines. The latter routines have the same name, but have different types of in-value. The compiler, which uses the routine declarations to identify overloaded routines, will not get enough information about the out-value of the first routine from the context of the call to decide which of the latter is to be used.

Records

Records can contain routines as components.

Routines that are part of records are called using the customary dot notation for record component access.

Such routines can access the components of the record they are declared in directly (without the use of dot notation).

Exception handlers

If specific error conditions occur in the program, execution of exception handler code tailored to the condition can be invoked. Such specific conditions can be errors in the routines called, attempts to divide by zero, stack overflows, and when evaluation of conditional expressions in ASSERT statements yields the value FALSE.

Exception handler code is enclosed between the keywords ON and ENDON.

When an exception condition arises, the statements in the first relevant exception handler before the offending statement are executed.

If the exception handler does not contain statements that affect flow of control, the first statement after the offending statement will be executed after the exception-handler statements.