home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HomeWare 14
/
HOMEWARE14.bin
/
prog
/
proxy14.arj
/
PROXY.DOC
< prev
next >
Wrap
Text File
|
1994-03-11
|
72KB
|
1,932 lines
PROXY USERS GUIDE
Version 1.4
EDL Software Design
23419 S. Mirabella Circle
Boca Raton, FL 33433
Copyright (c) 1991 - 1994 by Burt Leavenworth
All Rights Reserved
COPYRIGHT NOTICE
Proxy is not a public domain program. It is Copyright (C) 1991 -
1994 by Burt Leavenworth.
LICENSE
Non-registered users are granted a limited license to use Proxy
on a trial basis for the purpose of determining whether Proxy is
suitable for their needs. Use of Proxy, except for this limited
purpose, requires registration (see the file PROXY.REG). Any
non-registered use, other than the above, is strictly prohibited.
No user may modify Proxy in any way, including but not limited to
decompiling, disassembling or otherwise reverse engineering the
program. All users are granted a limited license to copy Proxy
only for the trial use of others subject to the above limitations
provided that the full Proxy documentation, including license,
warranty and registration information, must be copied. No fee,
charge or other compensation may be accepted or requested by
any licensee.
Operators of electronic bulletin board systems (BBSs) may post
Proxy for downloading by their users only as long as the above
conditions are met. Distributors of user supported software
(disk vendors) may also distribute copies of Proxy subject to
the above conditions.
WARRANTY INFORMATION
The author hereby disclaims all warranties relating to this
software, whether express or implied, including without
limitation any implied warranties of merchantability or fitness
for a particular purpose. The author will not be liable for any
special, incidental, consequential, indirect or similar damages
including any lost profits or lost savings, arising from the use
of, or inability to use, this software, even if the author has
been advised of the possibility of such damages.
TABLE OF CONTENTS
Introduction ............................................ 1
Getting Started ......................................... 1
Using Commands .......................................... 2
Primitive Types ....................................... 2
Identifiers ........................................... 2
Operators ............................................. 2
Sets .................................................. 3
Maps .................................................. 4
Sequences ............................................. 6
Strings ............................................... 8
Structs ............................................... 8
Operator Precedence ................................... 8
Function Definition ................................... 9
Class Definition ...................................... 10
System Commands ....................................... 12
Using Statements ........................................ 16
Assignment Statement .................................. 16
Conditional Statement ................................. 16
While Statement ....................................... 16
For Statement ......................................... 16
Return Statements ..................................... 16
I/O Statements ........................................ 17
Function Call ......................................... 17
Block ................................................. 18
Comments .............................................. 18
Type Predicates ......................................... 18
Class Constructors ...................................... 18
Inheritance ............................................. 19
Scheme Interface ........................................ 20
An Example .............................................. 20
Another Example ......................................... 22
Tasking ................................................. 25
Start Statement ........................................ 25
Skip Statement ......................................... 26
Input Statement ........................................ 26
Output Statement ....................................... 26
Select Statement ....................................... 26
Builtin Functions ...................................... 26
Examples ............................................... 27
Proxy Keywords .......................................... 27
References .............................................. 27
Index ................................................... 27
Page 1
INTRODUCTION
Proxy is an interpreter for a rapid prototyping language with C
and C++ like syntax based on modelling software using data
structures such as sets, maps, sequences, and objects. There are
no pointers or arrays in Proxy (although maps can be thought of
as a high level generalized array), which avoids the temptation
to use these rather low level types. Proxy has been influenced
to a great extent by the "me too"[1], VDM [3], EPROL [4], and
SETL [5] languages. Proxy allows the developer to make incremental
changes to a design, and test them immediately. It therefore
follows Fred Brooks' injunction: "Plan to throw one away: you
will, anyhow" [2].
A software system can be represented as a "state" and a collection of
functions which operate on components of the state. The user may
develop these operations incrementally or define them in files which
are loaded prior to execution. It is also possible to manipulate
objects (defined by classes) which encapsulate local states; this
allows the user to define a software model as a hierarchy of submodels.
GETTING STARTED
The following files are provided with the Proxy system:
PROXY.EXE CROSS.PRX H1.HLP
PROXY.DAT EMAIL.PRX H2.HLP
PROXY.INI MERGE.PRX H3.HLP
PROXY.DOC COPY.PRX H4.HLP
FINANCE.PRX NODUP.PRX H5.HLP
SIEVE.PRX FRINGE.PRX H6.HLP
MERGE2.PRX PROXY.REG H7.HLP
SORT.PRX READ.ME H8.HLP
Copy the files into a subdirectory of your choice. To install Proxy,
move to that subdirectory, type
proxy install
and press <enter>.
The install process will end with the message:
loading-ended
To run Proxy, type
proxy
After the copyright notice, the following will be displayed
on your screen:
Continue? : (run) / (exit)
>
Type (run) and press <enter>. Make sure that run is enclosed by
parentheses. A prompt ? will be displayed. You may now type
Page 2
expressions and function definitions. To print out the
documentation, type printdoc and press <enter>. To get help
at any prompt, type: help; and press <enter>. To exit the
interpreter from any prompt, type exit; and press <enter>. Whenever
the Continue? : (run) / (exit) prompt appears, you may exit the
interpreter by typing (exit) and pressing <enter>.
Note - If you change to a new memory mapping scheme, for example,
upgrading to DOS 5.0, it will be necessary to re-install Proxy.
USING COMMANDS
There are two types of commands: "desk calculator" type commands,
and system commands. There are four system commands: load (to load
a Proxy file), transcript (to store in a file a transcript of all
subsequent keystrokes), help (to obtain the syntax of different
commands, statements, and composite data structures), and exit (to
return to the DOS prompt). "Desk calculator" commands are the expressions,
assignments, and definitions that can be typed at the Proxy prompt for
immediate evaluation and execution.
Commands are typed at the Proxy prompt. The simplest command is an
expression to be evaluated, i.e. 2+2;. Note that every command
must be terminated with a semi-colon. There are four (primitive)
types of expressions.
Primitive types
The primitive data types are integer, real, boolean, and string.
Real literals are written in decimal form, i.e. 3.14159; there
must be at least one digit before the decimal point. Boolean
literals are written true, false, and strings are written with
double quotes, i.e. "This is a string".
Slightly more complicated expressions involve identifiers (variables):
Identifiers
All identifiers must start with a letter. The rest of the identifier
can consist of letters, underscores or digits. Identifiers are not
case sensitive, i.e. aBcD is considered to be the same identifier as
abcd.
Operators
The standard arithmetic, relational and Boolean operators are supported
wuth their relative precedence given by the following table:
! unary - highest
* / % && |
+ - || v
== != < > <= >= lowest
where ! represents logical negation, % is the modulo operator, && is
logical conjunction, || is logical disjunction, == represents equal
and != represents not equal.
Another command is assigning a value to an identifier. For example,
Page 3
x=2;
We can then invoke the expression x+3;
More complicated expressions can be formed using the composite data
types provided by Proxy: sets, maps, sequences and structs.
Sets
A mathematical set is, of course, an unordered collection of elements.
From a formal point of view, each element should have the same type.
However, since Proxy has latent types, i.e. types are not declared by
the programmer, set elements are not restricted to have the same type.
The simplest operation is to enumerate a set by delimiting its elements
by curly brackets:
{1,2,3,4,5}
This same set can be constructed by using the range notation
(not to be confused with the range of a map to be defined later)
{1..5}
Ranges can only be used when the elements are consecutive. Another
example of enumeration would be
smallprimes = {2,3,5,7};
To find the number of elements in the set smallprimes, we use the
cardinality operator card:
card smallprimes; returns 4
Two sets can be tested for equality using the equality operator ==.
Another simple operation is membership:
3 in smallprimes; returns true
3 notin smallprimes: returns false
To illustrate the standard operations of union, intersection, difference
subset and equality, we assume two sets s1 and s2 to have the values
s1={1,2,4,6};
s2={1,2,3,4,5};
s1 U s2; returns {1,2,3,4,5,6}
s1 inter s2; returns {1,2,4}
s1 diff s2; returns {6}
s1 subset s2; returns false
s1 == s2; returns false
The distributed union is the union of a set of sets. For example,
Page 4
union {s1,s2,{6,7,8}}; returns {1,2,3,4,5,6,7,8}
The 'the' operator returns the only element of a singleton set. If
the argument is not a singleton set, an error message is returned.
the {13}; returns 13
The oneof operator applied to a set returns an 'arbitrary' element
of the set. However, Proxy always returns the 'first' element.
oneof smallprimes; returns 2
The existential quantifier applied to a set and a predicate returns
true if there is at least one element of the set that satisfies the
predicate, and false otherwise. The universal quantitifer applied
to a set and a predicate returns true only if all elements of the set
satify the predicate.
(exists x in {2,3,5,7};even(x)); returns true
(all x in {2,3,5,7};even(x)); returns false
where the function even(x) returns true if x is even. The existential
quantifier above returns true because 2 satisfies even(2) and the
universal quantifier returns false because only even(2) is satisfied.
A more general way of constructing sets is given by the form:
{ f(x): x<- expr ; pred(x) }
where the syntax x<- expr is called a generator, and the syntax
; pred(x) is optional. The expression expr is evaluated to
yield a set. The values of the set are successively assigned to x
and a new set is formed from elements obtained by applying the function
f to the successive values of x which satisfy pred(x) (if pred(x) occurs).
Several examples will make this clearer.
{ x: x<- {1,2,3,4,5}}; returns {1,2,3,4,5}
This is the simplest case where f(x) is just x and a predicate does
not appear.
{ x: x <- {1,2,3,4,5};x>2}; returns {3,4,5}
{ x*x: x <- {1,2,3,4,5}}; returns {1,4,9,16,25}
It is possible to have two generators in which case an example is:
{ x+y: x <- {1,2}, y <- {3,4}} returns {4,5,6}
Only three elements are returned because two additions (1+4) and (2+3)
yield duplicate values.
Maps
Maps are also enumerated by delimiting their elements with curly
brackets (because formally maps are sets of ordered pairs). The
Page 5
syntax is given by the following example.
m = {1->2,3->4,5->6};
where the first and second elements of each ordered pair is separated
by the mapping symbol ->.
Maps can be constructed using map construction. In the following
example, len returns the length of a string.
{x->len x:x <- {"abc","defg","hijkl"}};
returns {"abc"->3,"defg"->4,"hijkl"->5}
The domain (range) of a map is obtained by forming a set composed
of all the first (second) elements of the ordered pairs
dom m; returns {1,3,5}
rng m; returns {2,4,6}
A single-valued map must have all its first elements unique. Notice
that, in general, card (rng m) <= card (dom m). The cardinality of
the range would be less, for example if
m = {1->2,3->2,5->6};
In this case, card(dom m) = 3, and card(rng m) = 2 (because of the
duplicate elements in the range).
Given a domain element, we can obtain the corresponding range element
using application (this is like a table lookup).
m[1]; returns 2
m[5]; returns 6
If a domain element is given which does not exist in the map, a false
value will be returned. However, it is possible to supply your own
value to be returned in this situation. This is done by supplying an
additional argument (called the default error return). For example,
m[7]; returns false
m[7,"not found"]; returns "not found"
Given a set of domain elements as a second argument, the image operation
(im) produces a set of the corresponding range elements (again assuming
m={1->2,3->4,5->6})
m im {3,5}; returns {4,6}
Domain restriction (dr) and domain subtraction (ds) produce new maps
from a given map by either allowing only certain domain elements in
the given map to appear in the result map, or taking away certain
domain elements from the given map. The domain elements are given
in a set which is the second argument of these operations.
{1->2,3->2,5->6} dr {3,5}; returns {3->2,5->6}
{1->2,3->2,5->6} ds {3,5}; returns {1->2}
Page 6
The inverse operation just interchanges the domain and range elements
of a map.
inverse {1->2,3->2,5->6}; returns {2->1,2->3,6->5}
Note that the result of the above operation is a multi-valued map.
The overwrite operation m1 overwr m2 is defined as follows: Each
mapping in m1 is included in the result, unless its domain element
occurs in the domain of m2. In that case, it is replaced by the
mapping from m2. Every mapping in m2 whose domain element does not
occur in the domain of m1 is included in the result. Example:
{1->2,3->4} overwr {3->5,4->6}; returns {1->2,3->5,4->6}
The map update m[d]=r is an assignment and a special case of
overwrite where the second operand (of overwrite) contains a
single ordered pair. Assuming that m is equal to {1->2,3->4},
m[3]=5; is equivalent to m overwr {3->5} and assigns to m the map
{1->2,3->5}.
Sequences
A sequence is a collection of ordered elements which may be
selected by their ordinal position (index) in the sequence. The
types of the elements are not necessarily the same.
A sequence can be enumerated by delimiting its elements by square
brackets:
[1,2,3,4,5]
This same sequence can be constructed by using the range (not to be
confused with the range of a map) notation:
[1..5]
Ranges can only be used when the elements are consecutive. Another
example of enumeration would be
s1 = [1,2,2,3,4];
Note the duplicate elements. To find the number of elements in the
sequence s1, we use the length operator len:
len s1; returns 5
Two sequences can be tested for equality using the equality operator
==. Concatenation of two sequences is performed used the concatenation
operator conc.
[1,2,3,4] conc [3,4,5]; returns [1,2,3,4,3,4,5]
If s=[3,4,5], then an element of the sequence can be selected using
its index in the sequence. For example,
s[1]; returns 3
s[3]; returns 5
Page 7
s[4]; returns false
s[4,0]; returns 0
The last example uses the default error return.
Other selection operators on sequences are hd, tl, last and butlast.
Hd returns the first element of the sequence. Tl returns a sequence
consisting of every element but the first. Last returns a sequence
consisiting of only the last element. Butlast returns a sequence
consisting of every element but the last.
hd s; returns 3
tl s; returns [4,5]
last s; returns [5]
butlast s; returns [3,4]
A sequence of length n can be represented by a map whose range elements
are the elements of the sequence, and whose domain elements are the
integers from 1 to n. Consequently, the domain operator applied to a
sequence will return the index elements {1..n}, and the range operator
will return the elements of the sequence contained in a set.
dom s; returns {1,2,3}
rng s; returns {3,4,5}
A sequence can be converted explicitly to its corresponding map and
conversely. Thus
m=seq2map s; assigns to m the map {1->3,2->4,3->5}
map2seq m; returns [3,4,5]
A more general way of constructing sequences, analogous to set
construction is given by the following form
[ f(x): x<- expr ; pred(x) ]
where the syntax x<- expr is called a generator, and the syntax
; pred(x) is optional. The expression expr is evaluated to
yield a sequence. The values of the sequence are successively assigned
to x and a new sequence is formed from elements obtained by applying the
function f to the successive values of x which satisfy pred(x) (if pred(x)
occurs). An example:
[len x: x<-["abc","defg","hijkl"];len x > 3]; returns [4,5]
Before concluding a discussion of sequences, it is important to point
out a distinction between a sequence of length two and an orderd pair.
Remember that a map may be considered to be a set of ordered pairs.
There are cases when one needs to access the components of an ordered
pair. Proxy provides two operators for this purpose, first and second.
{first x:x<-{1->2,3->4,5->6}}; returns {1,3,5}
Suppose now that we have a set of sequences, say y={[1,2],[3,4]}
and we wish to obtain a set of the first elements of the sequences.
It would be wrong to write {first x:x<-y}. The correct solution is to
write {x[1]:x<-y}.
Page 8
Strings
Strings can be considered to be sequences of characters, although
a character is not a primitive type in Proxy. Since the string
operators are similar to the sequence operators already discussed,
their use will be shown below in examples.
len "abcd"; returns 4
"abc" == "abc"; returns true
"abc" == "aBc"; returns false
"abc" < "abcd"; returns true
"abc" conc "defg"; returns "abcdefg"
s="abc";
s[2]; returns "b"
s[4]; returns false
s[4,0]; returns 0
hd "abc"; "a"
tl "abc"; "bc"
last "abc"; "c"
butlast "abc"; "ab"
Structs
Structs are data structures whose components may be selected by name.
The typical operations are declaration, instantiation, selection and
update.
A struct declaration is essentially a class declaration which defines
the names of the components of the struct. The syntax of the declaration
is best shown by an example.
struct item {partno, code, quantity;};
The above declaration defines item to be a struct with the (field)
names partno, code and quantity. Various items can be instantiated
(created) by providing the struct name and values for the fields.
(but a struct component may not be a function).
i1=new item(124,"receipt",15);
i2=new item(126,"issue",7);
Components of structs may be selected using a dot notation similar
to records in Pascal and structures in C.
i1.code; returns "receipt"
i2.quantity; returns 7
Component values may be updated using assignment and dot notation.
i1.quantity=22; assigns 22 as the new value of the quantity
field.
Operator Precedence
The precedence of Proxy operators from highest to lowest are
shown below.
unary operators HIGHEST
Page 9
* / % && inter conc dr ds im |
+ - || U overwr diff v
== != < > <= >= in notin subset equiv implies LOWEST
where the unary operators are:
- + ! hd tl last butlast card len first dom rng
union the oneof map2seq seq2map new inverse
Function Definition
The syntax of function definition in Proxy is the same as that in C
with minor differences: (1) the declaration of local variables is different
mainly due to the fact that the types of variables are not declared in
Proxy and (2) each function declaration in Proxy is terminated with a
semi-colon, (3) it is not necessary to name the top level function 'main',
(4) procedures do not require the prefix 'void'; in what follows we will
use the generic term function to apply as well to procedures. The syntax
is now shown:
identifier ( op-param-list op-decl) block ;
The definition consists of the function name (identifier) followed by
an optional parameter-list and an optional list of local variables
delimited by parentheses. The parameter-list consists of identifiers
separated by commas. The list of local variables consists of a semi-
colon followed by identifiers separated by commas. The block consists
of a statement-list (see the section on statements) delimited by
curly brackets. Finally, the definition must be terminated with a
semi-colon. Examples follow (the return statement is described in the
section on statements).
even(n) {return n%2==0;};
odd(n) {return !even(n);};
Given a subset of the integers, say digits={0..9};, we can define
a function to obtain the odd integers from this set.
odddigits() {return {n:n<-digits;odd(n)};};
The following example illustrates a simple recursive function to
add up the elements in an integer sequence.
reduce(s) { if(s==[]) return 0; else return hd s + reduce(tl s);};
The next example illustrates the definition of a doubly recursive
function, and the declaration of a local variable x.
quicksort(s;x) { if(len s<2) return s;
x=s[1];
return quicksort([y:y<-s;y<x]) conc [x]
conc quicksort([y:y<-tl s;y>=x]);};
An example showing the use of the existential quantifier:
primes(max) {return [n:n<-[2..max];
!(exists m in {2..n-1};(n % m)==0)];};
Page 10
An example of a procedure (a function which does not contain a return
statement) which has no parameters.
init() {x["a"]="b";};
This procedure initializes the variable x to the map {"a"->"b"}. The
same effect could have been achieved at the command level by the
assignment x["a"]="b";.
Class Definition and Instantiation
A class is defined by giving the class name, followed by an
enumeration of instance variables in the form of a
parameter list, followed by a collection of function definitions
(also called methods). Classes, contrary to C++, may only contain
functions.
In order to motivate the definition and usage of a class, let us first
define a simple queue. It does not matter what type of item the queue
contains; we will assume a queue of integers. In the specification
below, the state component q (a global variable) represents the queue
as a sequence, which is initialized as the empty sequence.
q=[];
enqueue(x) {q=q conc [x];};
dequeue(;x) {x=hd q;q=tl q;return x;};
empty() {return q==[];};
length() {return len q;};
A typical sequence of operations is:
? enqueue(3);
? enqueue(5);
? length();
2
? dequeue();
3
? empty();
false
? dequeue();
5
? empty();
true
There are drawbacks to this approach. Only one queue is available, and
its representation is completely exposed. The problem can be solved by
defining a queue class.
class queue(rep) {
enqueue(x) {rep=rep conc [x];}
dequeue(;y) {y=hd rep;rep=tl rep; return y;}
Page 11
empty() {return rep==[];}
length() {return len rep;}};
The coding is very similar except now the state component (rep) is local
and is hidden inside the class definition. The representation is
initialized from the outside and may only be changed indirectly by
invoking either the enqueue or dequeue operation. The analogous sequence
of operations is:
? q=new queue([]);
? q.enqueue(3);
? q.enqueue(5);
? q.length; or q.length();
2
? q.dequeue; or q.dequeue();
3
? q.empty; or q.empty();
false
? q.dequeue; or q.dequeue();
5
? q.empty; or q.empty();
true
? q;
object this shows the printed representation of an object
A second queue may be instantiated by using the new operation again.
p=new queue([]);
and an arbitrary number of queues may be created in this way.
An example of a priority queue follows.
class pqueue(rep) {
insrt(x,y) {if(y == []) {rep = [x]; return rep;} else
if(x < hd y) {rep = [x] conc y;return rep;} else
{rep = [hd y] conc insrt(x,tl y);
return rep;}}
insert(x) {rep = insrt(x,rep); return rep;}
remove(;x) { if(rep == []) return "queue empty";
x = hd rep; rep = tl rep; return x;} };
The last statement in the insert function returns the value of rep
so that the user can see that the items are inserted in sorted
order.Alternatively, the string "ok" could be returned. Note the
declaration of the local variable x in the header of the remove
function. The following sequence of operations show calls to
Page 12
the insert and remove functions:
? q= new pqueue([]);
? q.insert(3);
[3]
? q.insert(2);
[2,3]
? q.insert(9);
[2,3,9]
? q.insert(7);
[2,3,7,9]
? q.remove;
2
? q.remove;
3
? q.remove;
7
? q.remove;
9
? q.remove;
queue empty
System Commands
The help command produces the following menu:
1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
7 structs 8 classes 9 quit
A "quick reference" screen showing functionality and syntax of Proxy
constructs is obtained by selecting one of the above numbers. The results
of selecting individual numbers is shown below.
1
COMMANDS
Type of Command Example
(1) an expression x + 3 ;
(2) function definition fun(y) {return y+1;};
(3) assignment y = 17;
(4) function call fun(3);
(5) struct declaration struct empl {age,citizen;};
(6) struct instantiation p = new empl(25, true);
(7) struct component update p.age = 26;
(8) map update table[3]= 4;
(9) class definition class stack(rep) {
push(x) {rep = [x] conc rep}
top() {return hd rep;}
pop() {rep= tl rep;} };
(10) class instantiation s= new stack([]);
(11) load command load "topsort.prx";
(12) transcript command transcript "session.txt";
(13) help command help;
(14) exit command exit;
Page 13
1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
7 structs 8 classes 9 quit
2
FUNCTIONS
iden ( op-param-list op-decl) function definition
block ; where op-param-list is an
optional parameter list,
op-decl is an optional list
of local variables with the
form ;iden-list and block
consists of one or more
statements enclosed by
braces
Example
fact(n) { if (n=0) return 1;
else return n*fact(n-1);};
1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
7 structs 8 classes 9 quit
3
STATEMENTS
left-hand-value = expr ; simple assignment, map update,
or struct component update
if ( expr ) stat1 conditional statement - form1
if ( expr ) stat1 ; conditional statement - form2
else stat2
while ( expr ) stat while statement
for iden <- expr ; stat for statament
return ; return statement - form1
return expr; return statement - form2
iden ( expr-list ); function call
{ stat1 ; ... statn ; } block
open(iden,"r") ; open read statement
open(iden,"w") ; open write statement
close(iden) ; close statement
readln(v1,...,vn) ; readln statement
readln(iden,v1,...vn) ; readln file statement
writeln(v1,...,vn) ; writeln statement
writeln(iden,v1,...,vn) ; writeln file statement
1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
7 structs 8 classes 9 quit
4
SETS
{ e1, e2, ..., en} set enumeration
{ e1 .. ek} set of integers from e1 to ek
{} empty set
{ e : x <- s } set comprehension
{ e : x <- s ; b } set comprehension with boolean
{ e : x <- s1 , y <- s2 } s1, s2 are sets
{ e : x <- s1 , y <- s2 ; b } b is a boolean
Page 14
e in s set membership
e notin s set nonmembership
s1 inter s2 set intersection
s1 U s2 set union
s1 diff s2 set difference
s1 subset s2 subset
union s distributed union
card s cardinality of a set
s1 == s2 set equality
the s element of singleton set
oneof s arbitrary member of set
(all x in s ; b ) universal quantifier
(exists x in s ; b ) existential quantifier
1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
7 structs 8 classes 9 quit
5
MAPS
{ d1 -> r1, ..., dn -> rn } map enumeration
{} empty map
{ x -> e1 : x <- e2 } map construction
{ x -> e1 : x <- e2 ; b } map construction with boolean
dom m domain of map m
rng m range of map m
m dr s domain restriction (s is a set)
m ds s domain subtraction (s is a set)
inverse m inverse of m
m im s image of m (s is a set)
m[x] application
m[x,r] application with default error return
m1 overwr m2 overwrite
m[d]= r map update
first p first element of ordered pair
second p second element of ordered pair
1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
7 structs 8 classes 9 quit
6
SEQUENCES
[ e1, e2, ..., en] sequence enumeration
[ e1 .. ek ] sequence of integers from e1 to ek
[] empty sequence
[ e : x <- s ] sequence construction
[ e : x <- s ; b ] sequence construction with boolean
[ e : x <- s1 , y <- s2 ] s1, s2 are sequences
[ e : x <- s1 , y <- s2 ; b ] b is a boolean
len s length of a sequence
s1 == s2 sequence equality
s1 conc s2 concatenation
s[i] selection
s[i,r] selection with default error return
hd s head of a sequence
tl s tail of a sequence
butlast s first n-1 elements
last s [s[len s]]
dom s set of indices of s
rng s set of elements of s
Page 15
seq2map s convert sequence to a map
map2seq m convert map to a sequence
1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
7 structs 8 classes 9 quit
7
STRUCTS
struct sname { f1,...,fn; }; struct declaration
new sname(e1, ..., en) struct instantiation
s . fi ; struct component selection
s . fi = e ; struct component update
1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
7 structs 8 classes 9 quit
8
CLASSES
class iden ( op-param-list op-decl) class definition
{ where op-param-list is an
iden ( op-param-list ) block optional parameter list, op-decl
} ; is an optional list of local
variables with the form ; iden-list
and block consists of one or more
statements enclosed by braces
Example
class queue (;rep) {
queue() {rep = [];}
enqueue(x) {rep = rep conc [x];}
dequeue(;y) {y = hd rep;
rep = tl rep;
return y;}};
Inheritance
class iden1 ( ... ) : iden2 where iden2 is the superclass name
{ ...
Example
class deque (;rep) : queue {
...
The load command (an example of which is given above) is used to load
Proxy commands from a file. The commands are inserted in a file as
if they were being typed at the command line, the only difference being
that the last line in the file must contain the single token: end.
Be careful not to insert more than one command on a line. For example,
x=2; y=3; is wrong because only the first assignment would be executed.
A function or class definition, however, consists of only a single
command, although it can take up more than one line.
The transcript command (an example of which is given above) is used to
record in a file all subsequent interactions of user inputs (keystrokes)
and resulting Proxy outputs.
The exit command terminates execution of the Proxy interpreter and
Page 16
returns to the DOS prompt.
USING STATEMENTS
A statement is either a simple statement or a block (see below),
which is a sequence of statements delimited by curly brackets.
Assignment Statement
identifier = expression ; expression is evaluated and the
resulting value is stored in
identifier. Examples are:
x = {2, 3, 5, 7} ; simple assignment
m["Joe"] = 30; map update
p.r = {1->2, 3->4}; struct update
Conditional Statement
The conditional or if-statement may take one of the following
forms:
if ( expr ) stat1 in both cases, expr is evaluated;
if it evaluates to true then stat1
if ( expr ) stat1 ; else stat2 is executed. If it evaluates to
false, in the first case nothing
happens; in the second case stat2
is executed. Examples are:
if (x < 2) y = 0;
if (n == 0 ) f = 1; else f = n * f;
While statement
while ( expr ) stat expr is evaluated; as long as its
value is true, stat is executed,
and expr is reevaluated; when its
value is false, the following
statement is executed. Example:
while (n <= 10) n=n+1;
For statement
for identifier <- expr ; stat expr is evaluated and identifier
is assigned the values of the
resulting set or sequence; stat
is executed for each of these
assignments. Example:
for i <- {1..10}; writeln(i);
Return statement
The return statement may take one of the following forms:
Page 17
return ; the enclosing function is terminated.
return expr ; expr is evaluated and the enclosing
function is terminated with the value
of expr as its returned value. Example
return n+1;
I/O statements:
open(string,"r"); Opens a file for reading given by
string, and returns a file handle.
h = open("data.txt","r");
open(string,"w") ; Opens a file for writing given by
string, and returns a file handle.
open(string,"s"); Returns the contents of the file
given by string.
close(identifier) ; Closes the file whose handle is
given by identifier.
close(h);
writeln(v1,...,vn) ; The scalar values or scalar valued
variables vi (integer, real, string,
boolean) are printed on one line
separated by spaces. If vi is a
variable, it must be a global.
writeln(123,r,"order");
writeln(identifier,v1,...,vn) ; The values v1,...vn are output to
the file whose handle is given by
identifier. If vi is a variable,
it must be a global.
writeln(h,123,r,"order");
readln(v1,...,vn) ; The variables v1,...vn (which must be
global) are assigned the corresponding
values input at the keyboard.
readln(a,b,c);
readln(identifier,v1,...vn) ; The variables v1,...vn are assigned
the corresponding values in the file
whose handle is given by identifier.
If there are no more values in the file
to read, the global variable eof has
the value true, otherwise it has the
value false.
fun() {readln(h,a,b,c);
while(!eof) {writeln(a,b,c);
readln(h,a,b,c);}
Page 18
};
Function call
identifier ( expr-list ) ; Each expr in expr-list is evaluated
and the function represented by
identifier is called with the
resulting arguments. If the function
call is not contained in an expression
i.e. it appears in a statement
context, the resulting value is
discarded.
Block
A sequence of statements may be grouped together to form a block
by enclosing them within curly brackets:
{ stat1 ;
stat2 ;
...
statn ;
} Notice that there is no semi-colon
after the closing bracket. Example:
while (bal>0) {int=bal*r;am=pay-int;bal=bal-am;n=n+1;}
Comments
The delimiter // starts a comment that terminates at the end of the
line on which it occurs. It may be preceded by a statement (not an
expression), whitespace or may appear at the beginning of the line.
TYPE PREDICATES
The following predicates are supplied to test the type of a given value.
is_number is_map
is_boolean is_seq
is_string is_struct
is_set
Example:
is_number 3.14159; returns true
CLASS CONSTRUCTORS
When a class constructor is defined by the user, by declaring a method
with the same name as the class, the corresponding class object will
be initialized automatically when it is instantiated. Taking the queue
example again:
class queue(;rep) {
queue() {rep=[];}
enqueue(x) {rep = rep conc [x];}
Page 19
dequeue(;y) {y = hd rep; rep = tl rep; return y;}};
An instantiation for this class would have the syntax
iden = new queue();
where iden represents the name of the instantiated object.
Note that rep is defined as a local variable of the class, and that
the first method, named queue, initializes rep to the empty sequence.
When an object is instantiated, i.e. q = new queue(), the rep of that
object will be initialized.
INHERITANCE
A class can inherit instance variables and operations from another
class, called the superclass (or base class). The inheriting class
is called the subclass (or derived class). Suppose that we first
define a queue class:
class queue(;rep) {
queue() {rep=[];}
insert(x) {rep=rep conc [x];}
remove(;y) {y=hd rep;rep=tl rep; return y;}
empty() {return rep==[];}};
The characteristics of a queue is that items are inserted at one
end and removed from the other end. The queue is represented by a
sequence which is initialized by the empty sequence. Suppose we wish
to define a deque by specializing the operations which are already
provided by the queue. A deque is characterized by allowing insertions
and removals to be performed at either end. We can obtain a deque class
by defining it to be a subclass of queue:
class deque (;rep) : queue {
deque() {rep=[];}
insert_front(x) {rep=[x] conc rep;}
remove_rear(;y) {y=hd (last rep);rep=butlast rep;return y;}
empty(;x) {if(rep==[]) return "yes";}};
Since insertions to and removals from the queue were made from the
rear and front respectively, we define two new operations insert_front
and remove_rear. So the new class deque inherits the operations insert
and remove from queue, its superclass and defines the two new operations.
The syntax ": queue" which appears in the header defines queue as the
superclass. Since the operation empty has the same name as an operation
in the super class, the new definition of empty supercedes the previous
one.
Consider the following class definitions.
class rec (;value) {
rec() {value=0;}
get() {return value;}};
class newrec () : rec {
newrec() {value=0;}
get() {return value;}
Page 20
setval(x) {value=x;}};
Class rec has the instance variable value which is set to 0 by the
class constructor. The class newrec defines no instance variables itself
but inherits value from its superclass. Value is also initialized by
the class constructor of rec.
SCHEME INTERFACE
Proxy is implemented by translating expressions and function definitions
into Scheme which is then executed by a Scheme interpreter. This
implementation allows Proxy functions to call Scheme functions which
can then send back results to the Proxy program. Since the list is the
quintessential data structure in Scheme, and since sets, maps and
sequences in Proxy are implemented in terms of lists, we provide
transition functions to perform the conversions. In going from Proxy
to Scheme, we use
$set2lst, $seq2lst, $map2lst (set, seq, map to list)
and from Scheme to Proxy, we use
$mkset, $mkseq, $mkmap (list to set, seq, map)
The $ prefix tells the translator that the function is to be found
in the Scheme name space rather than in the Proxy name space. By the
same token, variables in the Scheme name space must also be prefixed
by a $.
Consider the following artificial example. We first define a Scheme
function called fun, which when applied to a list of lists, returns
a list of all the second elements. In other words,
(fun '((1 2) (3 4))) returns (2 4)
Fun is defined at the Proxy prompt, i.e.
Continue? : (run) / (exit)
> (define (fun x) (map (lambda (x) (cadr x)) x))
(run)
? $mkseq ( $fun ( $map2lst ( {1 -> 2, 3 -> 4} ))); returns [2, 4]
First, $map2lst is applied to the map to produce the list of lists:
((1 2) (3 4)). Then the Scheme function fun is applied to this to
produce the list (2 4). Finally $mkseq is applied to this to produce
the Proxy sequence [2, 4].
AN EXAMPLE
A "financial history" supports the following transactions:
receive(amount,source) records that amount (an integer) was
received from source (a string)
spend(amount,reason) records that amount (an integer) was
Page 21
spent for reason (a string)
totalrec(source) returns the total amount received from
source
totalspent(reason) returns the total amount spent for
reason
cashonhand records the cash on hand (an integer)
There are three variables representing the state: cash, inc (a map
from source to amount), and exp (a map from reason to amount). The
financial history will be represented by a class with a parameter
cash, and two instance variables inc and exp. These variables
are the state variables of a finance object wwich is instantiated by
invoking the new operation with an initial value for cash.
class finance (cash;inc,exp) {
receive(amount,source) {cash=cash+amount;
inc[source]=inc[source,0]+amount;
return "ok";}
spend(amount,reason) {if(amount>cash) return "Insufficient funds";
cash=cash-amount;
exp[reason]=exp[reason,0]+amount;
return "ok";}
totalrec(source) {return inc[source,0];}
totalspent(reason) {return exp[reason,0];}
cashonhand() {return cash;}};
The cashonhand is initialized to 100 and is incremented in the receive
function and decremented in the spend function. If the amount to be
spent is greater than the cashonhand, the spend function returns
"Insufficient funds". The map 'inc' consists of a set of ordered pairs
where the first element of a pair is the source of a receipt, and the
second element is the total amount received from this source. The map
'exp' contains the pairs where the first element is the reason for the
expense and the second element is the total amount spent. The default
error return, for example inc[source,0], handles the case where a
source appears for the first time and therefore does not occur as a
domain element in the map. The totalrec and totalspent functions use map
application to return the total amounts received and spent respectively.
Here again, the default error return will return 0 if the source or
reason does not appear in the map.
Another way of writing the program is to leave out the return "ok"
statements in the spend and receive functions. The effect of these
changes is that no output will be obtained when they are invoked,
except in the case of insufficient funds.
A possible sequence of operations follows.
? f = new finance(1000);
? f.cashonhand;
1000
? f.spend(50,"food");
"ok"
? f.receive(200,"salary");
"ok"
? f.cashonhand;
1150
Page 22
? f.spend(100,"food");
"ok"
? f.totalspent("food");
150
? f.spend(1200,"rent");
"Insufficient funds"
We now wish to model a financial history which will record the amount
of tax-deductible expenditures. This is a specialization or refinement
of the finance class. Class deduct_hist has four new operations: init
which initializes the instance variable deductible to zero, spend_deduct,
spend_for_deduct, and total_deduct. Their effect is illustrated by
the class definition and examples of applying the operations.
class deduct_hist (cash;deductible) : finance {
init() {deductible = 0;}
spend_deduct(amount,reason) {deductible = deductible + amount;
spend(amount,reason);
return "ok";}
spend_for_deduct(amount,reason,deduct) {deductible = deductible + deduct;
spend(amount,reason);
return "ok";}
total_deduct() {return deductible;}};
? d = new deduct_hist(1000);
? d.init();
? d.spend(50,"insurance");
"ok"
? d.receive(200,"salary");
"ok"
? d.cashonhand;
1150
? d.total_deduct;
0
? d.spend_deduct(100,"mortgage");
"ok"
? d.cashonhand;
1050
? d.total_deduct;
100
? d.spend_for_deduct(100,"lunch",50);
"ok"
? d.cashonhand;
950
? d.total_deduct;
150
ANOTHER EXAMPLE
An Electronic Mail System (Email) is to be designed to provide
communication between users of the system. The following operations
must be supported:
Signon(u,p) - By giving a valid user name and user-selected password,
a user should be permitted access to the system.
Signoff(u) - The user may remove himself from the system
Page 23
Add(u,n,p) - The "super" user may supply a name and password in order
to add a new user to the list of authorized users.
Drop(u,n) - The "super" user may delete a user name from the list
of authorized users.
Send(u,t,n) - By giving the text of a message and name of a receiver,
a user can place a message into a receiver's queue.
Read(u) - A user can issue a Read command to examine his/her queue.
The response should be the sender's name and text of the
first message (if any). Successive reads will return
additional messages (if any).
Delete(u) - After reading a message, the user may issue a Delete
command to delete the message just read.
Reset(u) - This causes the next Read command to begin at the head
of the queue.
Notice that the first parameter of each operation represents the
name of the user invoking the operation.
A Proxy program for this application is contained in the file EMAIL.PRX.
This solution illustrates the use of return messages to signal exceptions.
A queue class is first defined with the following operations: read,
write, reset and delete. This class has two instance variables: procd
and remdr, both sequences. procd represents the queue of mail messages
already processed, and remdr represents the queue of messages not
yet read. The queue class acts like a sequential file and can be
used in any application requiring a data structure with these character-
istics. The state components are:
up (map from user to password)
uq (map from user to mail-queue)
so (set of users who are signed on)
// state components
// up: map(string,string)
// uq: map(string,queue)
// so: set(string)
class queue(procd,remdr) {
read() {var x;
if(len remdr==0) return "empty queue";
x=hd remdr;
remdr=tl remdr;
procd=procd conc [x];
return x;}
write(msg) {remdr=remdr conc [msg];}
reset() {remdr=procd conc remdr;
procd=[];}
delete() {if(len procd==0) return "empty queue";
procd=butlast procd;} };
up:={"super" -> "super"}; // initialize super user with pw "super"
Page 24
uq:={"super" -> new queue([],[])};// initialize mail-queue so super user
// can send mail to him
mail :: sender text; // mail is a struct with two fields:
// sender and text
add(u,n,pw) {if (u != "super") return {"not authorized",u};
uq[n]=new queue([],[]); // initializes mail-queue
up[n]=pw; // initializes password
return "ok";};
drop(u,n) {if (u != "super") return {"not authorized",u};
if (n notin dom up) return {"unknown user",n};
up=up ds {n}; // remove user and password
uq=uq ds {n}; // remove user and mail-queue
if(n in so) so=so diff {n}; // if user signed on, sign
return "ok";}; // him off
signon(u,pw) {if (up[u,""] != pw) return {"incorrect password",pw};
so=so U {u}; // sign him on
return "ok";};
signoff(u) {if (u notin so) return {"not signed on",u};
so=so diff {u}; // sign him off
return "ok";};
send(u,t,r;x) {if (u notin so) return {"not signed on",u};
if (r notin dom up) return {"unknown user",r};
x=uq[r];
x.write(mk_mail(u,t)); // create mail and send
return "ok";};
read(u;x) {if (u notin so) return {"not signed on",u};
x=uq[u];
return x.read;}; // read mail
reset(u;x) {x;if (u notin so) return {"not signed on",u};
x=uq[u];
x.reset; // reset mail-queue
return "ok";};
delete(u;x) {if (u notin so) return {"not signed on",u};
x=uq[u];
x.delete; // delete mail
return "ok";};
so= {};
end
The following sequence of messages and responses shows the application
of the Email operations.
? add("super","joe",123);
"ok"
? add("super","mike",456);
"ok"
? signon("joe",123);
"ok"
? signon("mike",455);
"incorrect password"
? signon("mike",456;
"ok"
? send("joe","hello","mike");
"ok"
? send("joe","there","mike");
"ok"
? send("joe","meet me","tom");
{"unknown user","tom"}
Page 25
? read("mike");
< "joe", "hello" >
? read("mike");
< "joe", "there" >
? read("mike");
"empty queue"
? reset("mike");
"ok"
? read("mike");
< "joe", "hello">
? delete("mike");
"ok"
? read("mike");
< "joe", "there" >
? reset("mike");
"ok"
? read("mike");
< "joe", "there" >
? drop("joe","mike");
{"not authorized","joe"}
? signoff("joe");
"ok"
This example illustrates the "me too" paradigm [1] for producing
prototypes in three steps:
(1) model step - identify the entities and associated operations of
an application. In this case, we selected mail and
queue as entities, and read, write, reset and
delete as operations on the queue.
(2) specification step - implement the entities and operations in
terms of sets, maps, sequences, etc.
We represented queue by a class with instance
variables procd and remdr. Mail was represented
by a struct with fields sender and text.
(3) validation step - the operations are executed to determine if the
model and implementation are appropriate.
The above steps are iterated as necessary until a satisfactory version
is obtained.
TASKING
Proxy provides a tasking facility using the message passing paradigm.
The basic constructs are tasks and channels. A task is defined by
prefixing the 'task' modifier to a function definition. There is a
distinguished task, which must be named 'main', which is invoked in
order to begin execution. Channels are created by invoking the
built-in function of no parameters channel(). Five statements and two
built-in functions used with tasks are described below.
Start statement
start task-id ( expr-list ) ; The expressions in expr-list are
evaluated and the corresponding
values (some of which will be
Page 26
channels) are passed to the task
named by task-id, which is
started.
Skip statement
skip ; The enclosing task is terminated
(normally, a task terminates
when it reaches the end of the
task body.
Input statement
channel ? identifier ; The current task is blocked until
a message is available in channel
(either an identifier or map
application). Then the message is
stored in identifier.
Output statement
channel ! expression ; The current task is blocked until
another task is ready to accept
(with an input statement) the
message produced by evaluating the
expression.
Select statement
select {
case conjunct : statement-list The select statement consists of one
... or more case statements. A case
case conjunct : statement-list statement consists of a conjunct
} followed by a colon (:), followed
by a statement list. A conjunct is
one or more terms separated by an
and (&&) symbol. A term is either
an input or output statement, or
a boolean expression. A term is true
if the input/output statement can
take place, or if the boolean
expression is true. The case statements
are examined sequentially until one is
found where all terms are true. Then
the input/output statement(s) is (are)
executed followed by execution of the
statement list. If none of the case
statements is true, the task is blocked.
Builtin functions
channel() This function returns a new
channel.
avail ( channel-id ) This function returns true if a
message is available on the
channel denoted by channel-id,
and false otherwise.
Page 27
The use of these constructs is explained by a number of examples.
The first example copies a stream of integers from an input (source)
task to an output (sink) task which prints the integers.
eos="eos"; //1
ch1=channel(); //2
ch2=channel(); //3
task source(right) {right!2;right!3;right!4;right!eos;}; //4
task sink(left;x) {while (x!=eos) {writeln(x);left?x;}; //5
task copy(left,right;x) {left?x;while (x!=eos) //6
{right!x;left?x;} //7
right!eos;}; //8
task main() {start source(ch1); start copy(ch1,ch2);start sink(ch2);}; //9
We will use the comments to refer to specific lines in the program.
The variable eos serves as an end-of-stream indicator - //1
Two channels are created and assigned to variables ch1 and ch2 - //2 //3
The Source task sends the integers 2, 3 , 4 followed by eos - //4
The Sink task prints incoming values until eos is received - //5
The Copy task reads and outputs incoming values - //6, //7 and //8
The Main task starts Source with output channel ch1, starts Copy
with input and output channels ch1 and ch2, and starts Sink with
input channel ch2 - //9. This example is contained in COPY.PRX.
The second example copies a stream of integers from Source to Sink
but suppresses duplicates.
ch1=channel(); //1
ch2=channel(); //2
eos="eos"; //3
task nodup(inp,out;x,y) {inp?x;if(x==eos) {out!x;skip;} //4
while (true) {inp?y;if(y==eos) {out! x; out!y;skip;} //5
if(x!=y) {out!x;x=y;} }}; //6
task source(out) {out!1;out!2;out!2;out!3;out!4; //7
out!4;out!4;out!eos;}; //8
task sink(inp;msg) {inp?msg;while(msg!=eos) {print msg;inp?msg;}}; //9
task main() {start source(ch1);start nodup(ch1,ch2); //10
start sink(ch2);}; //11
This example is contained in NODUP.PRX.
The third example merges two input streams of integers into one output
stream.
eos="eos";
ch1=channel();
ch2=channel();
ch3=channel();
task merge(inp1,inp2,out;x) {
n=0;
while (true) {
if(n==2) {out!eos;skip;}
if(avail(inp1)) {inp1?x;if(x==eos) n=n+1;
else out!x;}
if(avail(inp2)) {inp2?x;if(x==eos) n=n+1;
else out!x;}
Page 28
}};
task source1(out) {out!1;out!3;out!eos;};
task source2(out) {out!2;out!4;out!5;out!eos;};
task sink(inp;x) {inp?x;while(x!=eos) {print x;inp?x;}};
task main() {start source1(ch1); start source2(ch2);start merge(ch1,ch2,ch3);
start sink(ch3);};
If the avail functions were not present, the function would block on
channel inp1, even if a message was available on channel inp2. This
way, messages are input on either channel when available. This example
is contained in MERGE.PRX.
The fourth example is a simpler solution to the merge problem, using the
select statement (contained in MERGE2.PRX.
eos="eos";
ch1=channel();
ch2=channel();
ch3=channel();
n=0;
task merge(inp1,inp2,out;x) {
select {case inp1?x:if(x==eos) n=n+1; else out!x;if(n==2) exit;
case inp2?x:if(x==eos) n=n+1; else out!x;if(n==2) exit;
}};
task source1(out) {out!1;out!3;out!eos;};
task source2(out) {out!2;out!4;out!5;out!eos;};
task sink(inp;x) {while (true) {inp?x;print x;}};
task main() {start source1(ch1); start source2(ch2);start merge(ch1,ch2,ch3);
start sink(ch3);};
The final example tests if two binary trees have the same leaves.
The trees are represented by sequences of sequences. For example,
two trees with the same leaves but with a different structure are
tree1 = [1,[2,[3],4]] and tree2 = [[1,2],3,[4]]. There are three tasks.
Task p1 outputs the next leaf of tree1, p2 outputs the next leaf of
tree2 and task p3 inputs two values and tests for equality. There
is also a function next which tests its first argument; if a leaf,
it outputs the value on the channel which is its second argument.
Otherwise, it calls itself recursively with the head and tail of its
first argument. If the two values input to p3 do not compare, it prints
"not equal" and terminates. It is not necessary to compare any further
values. This example is contained in FRINGE.PRX.
next(x,out) {if(x==[]) return;
if(is_number x) {out!x;return;}
next(hd x,out);
next(tl x,out);};
eos="eos";
ch1=channel();
ch2=channel();
tree1=[1,[2,3]];
tree2=[[1,2],3];
task p1(out) {print "starting p1";next(tree1,out);
out!eos;};
task p2(out) {print "starting p2";next(tree2,out);
out!eos;};
Page 29
task p3(in1,in2;x,y) {print "starting p3";in1?x;in2?y;
while((x!=eos) || (y!=eos))
{if(x!=y) {print "not equal";skip;}
in1?x;in2?y;
}
print "equal";};
task main() {start p1(ch1);
start p2(ch2);
start p3(ch1,ch2);};
PROXY KEY WORDS
all len
butlast map2seq
card new
class last
close notin
conc oneof
dom open
dr overwr
ds readln
else return
eof rng
equiv second
exists seq2map
false struct
first subset
for the
hd tl
if true
im U
implies union
in while
inter writeln
inverse
REFERENCES
[1] Alexander, H. and Jones, V., Software Design and Prototyping using
me too, Prentice-Hall, New York, 1990.
[2] Brooks, F.,The Mythical Man-Month. Addison-Wesley, Reading, MA, 1975.
[3] Jones, C.B., Systematic Software Development Using VDM, Prentice-Hall,
New York, 1986.
[4] Hekmatpour, S. and Ince, D., Software Prototyping, Formal Methods and
VDM, Addison-Wesley, Reading, MA, 1988.
[5] Schwartz, J.T. et al, Programming with Sets: An Introduction to SETL,
Springer-Verlag, New York, 1986.
INDEX
assignment statement .............. 16
block ............................. 18
Page 30
boolean type ...................... 2
butlast operator .................. 7,8,14
cardinality operator .............. 3,14
class definition .................. 10
classes ........................... 10
close statement ................... 13,17
commands .......................... 12-16
comments .......................... 18
concatenation operator ............ 6
conditional statement ............. 13,16
default error return .............. 5,7,14
difference operator ............... 3,14
distributed union operator ........ 3,14
domain operator ................... 5,14
domain restriction operator ....... 5,14
domain subtraction operator ....... 5,14
existential quantifier ............ 4,14
exit command ...................... 2,12,14
first operator .................... 7
for statement .................... 13,16
function call .................... 12,17
function definition ............... 9,13
generator ......................... 4
hd operator ....................... 7,14
help command ...................... 2,12
identifiers ...................... 2
image operator .................... 5,14
inheritance ....................... 15,19
instantiation, class .............. 10,18,19
instantiation, struct ............. 8,15
intersection operator ............. 3,14
inverse operator .................. 6,14
i/o statement ..................... 13,17
integer type ...................... 2
last operator ..................... 7,8,14
len operator ..................... 7,8,14
load command ..................... 2,12
local variables ................... 9,13,15
logical conjunction ............... 2
logical disjunction ............... 2
logical negation .................. 2
main .............................. 9
map application ................... 5,14
map construction .................. 5,14
map enumeration .................. 4,5,14
map update ........................ 6,14
map2seq operator .................. 7,15
maps .............................. 4,14
membership operator ............... 3,14
modulo operator ................... 2
oneof operator .................... 4,14
open statement .................... 13,17
operators ......................... 2
operator precedence ............... 2,8
overwrite operator ................ 6,14
primitive types ................... 2
procedures ........................ 10
range operator .................... 5,14
Page 31
readln statement .................. 13,17
real type ......................... 2
return statement .................. 13,16
second operator ................... 7
seq2map operator .................. 7,15
sequence construction ............. 6,14
sequence enumeration .............. 6,14
sequence selection ................ 6,14
sequence range .................... 6,14
sequences ......................... 6,14
set constructor ................... 3,4
set enumeration ................... 3,13
set range ......................... 3,13
sets .............................. 3,13
statements ........................ 13,16
strings ........................... 8
structs ........................... 8,15
system commands ................... 2,12
the operator ...................... 4,14
tl operator ...................... 7,14
transcript command ................ 2,12
unary operators ................... 2,9
union operator ................... 2,14
universal quantifier .............. 4,14
void .............................. 9
while statement ................... 13,16
writeln statement ................. 13,17