home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-03-11 | 70.4 KB | 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
-