Professional Documents
Culture Documents
1984 Prefixed
1984 Prefixed
J.R. Parker
To cite this article: J.R. Parker (1984) A Practical Examination Of Prefixed Procedures,
INFOR: Information Systems and Operational Research, 22:3, 249-260, DOI:
10.1080/03155986.1984.11731926
J.R. PARKER
Department of Computer Science, University of Calgary, Calgary, Alberta
ABSTRACT
Procedure prefixing involves the extension of an already existing procedure, using a set of
rules similar to those for class prefixing in SIMULA. Here, issues involving the implementa-
tion of prefixed procedures are considered, and a set of consistent rules are applied to
prefixed procedure declarations.
RESUMi
Le proc^d^ de prefixation implique la prolongation d'une procedure deja existante, utilisant
un ensemble de regies semblables a celles de la classe de prefixation du SIMULA. Ici, les
issues embrassant I'augmentation des procedures de prefixes sont considerees, et un
ensemble de regies consistantes est applique aux declarations du procede de prefixes.
The resulting procedure prints the values of all members of the set
argument X. The procedure SET defines a class of procedures that have
the property that the first argument represents a set of items, the elements
of which are to be operated upon. The procedure SET continues to exist
and is usable as a procedure by itself. This example, while simple, does not
completely illustrate the usefulness of the prefixed procedure concept.
A more relevant example, in that it better represents the intent and
generality of the procedure prefixing, involves updating variables in a
critical region. Operations on data shared by several concurrent processes
require that some form of mutual exclusion be enforced. If the existence
of procedures P and V is assumed, where P and V perform Dijkstra's
semaphore operations'^', the procedure ENTRY can be written:
procedure ENTRY;
begin
P(semaphorel);
inner;
y(semaphorel);
end;
This again defines a class of procedures prefixed by ENTRY that will
enforce mutual exclusion on the critical region protected by semaphore 1.
For example:
ENTRY procedure UPDATE{val. real);
begin
Protected-Variable: = val;
end;
Execution of the procedure UPDATE involves a P operation before and a
V operation after, the update operation is performed, thus guaranteeing
mutual exclusion.
The most important effect of prefixed procedures is to bracket the
components of an operation that is implemented as a procedure. This
leads to better structure and more reliability, since correct initialization
and termination criteria can be promised. Prefixed procedures also
eliminate duplication of code when many procedures have similar
specifications, and they can sometimes be used to avoid procedure calls.
This is purely an efficiency consideration.
Superficially, procedure prefixing seems to resemble the use of
procedure valued parameters. The two are not the same, as is illustrated
by the following simple example. Procedure SET and procedure PRINT
could be written using procedure valued parameters such as:
252 J.R. PARKER
procedure S£r(var x: itemset; procedure DO/r(i: integer));
var i: item;
begin
for i: = firstitem to lastitem do procedure PRINT;
if i in X then begin
DOITii); write (?: 6);
x: = [ ] end;
end;
General rules
1. Any user-defined procedure may be used as a prefix and such use has
no effect on the prefixing procedure.
2. A prefixed procedure is concatenated with the prefixing procedure in
the following manner. Consider the definitions:
where 'argsA' and 'argsB' are arbitrary argument lists, locsA' and 'locsZJ'
are arbitrary local definitions, and "code..." represents arbitrary sections
of code. In this general case, procedure B resolves itself into
Recursive prefixing
A prefix chain is a list of prefix names applied to a particular procedure in
order of precedence. The prefix chain for an unprefixed procedure is
empty. For the procedure C above, the prefix chain is "A B." The prefix
level of a given procedure is the number of prefixes to which the
procedure is subject; for example, the prefix level of an un-prefixed
procedure named X is zero, and that of a procedure prefixed with only X
would be one. The prefix level can also be defined as the length of the
prefix chain.
A prefix chain is said to be recursive when it contains more than one
occurrence of the same procedure. The simplest example of recursive
prefixing is the case where a procedure is prefixed with its own name. For
example:
prefix P1 procedure PI;
PREFIXED PROCEDURES 255
This procedure definition suffers from the same problem as the PASCAL
record definition:
type REC = record
Al: integer;
R: REC;
end;
That is, the recursive definition is never properly terminated. Hence, in
both cases, an infinite amount of storage would be required to satisfy the
definition, and so both are illegal.
For the record definition REC, the field R can be replaced by a pointer
field. This allows the recursion to be controlled by the programmer, who
explicitly allocates records as needed. Similarly, the procedure Fl is
probably meant to be recursive, and not prefixed, where the programmer
could control the depth of recursion. The use of pointers and explicit
storage control allows the use of self referencing structures in most
languages. The corresponding technique for procedure prefixing seems
to be to make the recursion explicit in the calls, instead of in the definition.
Recursive prefixing should never be permitted.
program MAIN... ;
procedure J4 ... ;
procedure B;
endB;
end X;
prefix X procedure C;
end C;
procedure D;
endD;
end A;
procedure £ ... ;
procedure F;
endF;
endE;
end MAIN.
FIG. 1. A scoping example
IMPLEMENTATIONS
There are a few approaches to implementing prefixed procedures. The
two that I have practical experience with are the pre-processor imple-
mentation, and the inner table implementation, as was used in SAHARA.
The pre-processor technique is straightforward: a program reads the
user program, keeps track of all procedures, functions, variable declara-
tions, and inner statements, and generates a legal program with no
prefixed procedures, which is semantically equivalent. Such a pre-
258 J.R. PARKER
processor has been written for PASCAL at the University of Calgary. It
consists of over 1200 lines of PASCAL code and involves significant
overhead each time it is run. It is effectively a separate compiler pass that
does not profit from other passes.
There are severe restrictions associated with this approach that have
already been mentioned. The principal problem is that some forms of
nesting cannot be properly implemented. Also, the scope rules discussed
above are very difficult to accommodate, and prefix valued parameters
could not be a part of a pre-processor implementation.
The inner table technique was used in the programming language
SAHARA^^', the first language known to incorporate prefixed procedures.
The inner table solution involves a change to the compiler and run time
system for the language in question. All the information needed to
implement prefixed procedures is available at compile time. The addi-
tional complication is that of selecting the correct return address when a
procedure returns and of deciding where to pass control when an inner
statement is encountered. These addresses are available at compile time
and can be collected into a table for each procedure, which will be stored
in the heap. When a procedure is called, the relevant inner table address is
saved in a control area in the activation record where it can be referenced
for evaluation of an inner statement or return.
Figure 2 shows a possible structure for an inner table. If an inner
statement is encountered at prefix level N, then the action to take is to
branch to the address that is stored at
(Inner table address + iN*2) + 1).
For procedure X in figure 2, the prefix level is zero, so when the inner
statement is seen, we branch to the address found at inner table + 1, that
is, the location indicated by label XL The result is that nothing was done,
correct in this case. Repeating the process for the procedure Y gives the
results shown in the figure.
Procedure return is also performed through the inner table, but only if
the prefix level is non-zero. If the prefix level is zero, we return to the
location specified in the return address field in the activation record as
usual. Otherwise, we return to the location specified by
(Inner table address + iN*2)).
This backs out of one level of prefixing. All prefixed procedures begin
execution at the first line of code in the outermost (unprefixed) block.
The return addresses for prefixed procedures at levels > 1 are known
at compile time, and these entries in the inner table are simply copied into
the relevant areas of the activation record. The presence of these fields in
PREFIXED PROCEDURES 259
PX
procedure X;
PX: begin
X\
inner;
XI:
end
PX
prefix X procedure Y
(* At inner level 1 *)
PY PY: begin
X\
inner;
Y\ Y\:
end;
Fxecution of Y proceeds as follows:
PX: begin
PY: begin
inner;
Y\:
end;(*ofF*)
XI:
end;(*ofX*)
REFERENCES
(1) O.J. Dahl, B. Myrhaug, and K. Nygaard, The Simula 67 Common Base Language,
Forkningsveien I B, Oslo 3: Norwegian Computing Center, 1968.
(2) E.W. Dijkstra, "Cooperating Sequential Processes," in F. Genuys, ed., Programming
Languages, New York: Academic Press, 1968, pp. 43-112
(3) J.R. Parker, "Language Design for System. Software Development," thesis, University
of Calgary, 1980
(4) J.G. Vaucher, "Prefixed Procedures: A Structuring Concept for Operations," INFOR,
13:3, 1975, 287-95