home *** CD-ROM | disk | FTP | other *** search
/ HomeWare 14 / HOMEWARE14.bin / prog / proxy14.arj / PROXY.DOC < prev    next >
Text File  |  1994-03-11  |  72KB  |  1,932 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.                        PROXY USERS GUIDE
  8.  
  9.                          Version 1.4
  10.  
  11.                        EDL Software Design
  12.                        23419 S. Mirabella Circle
  13.                        Boca Raton, FL 33433
  14.  
  15.             Copyright (c) 1991 - 1994 by Burt Leavenworth
  16.                        All Rights Reserved
  17.  
  18.  
  19. COPYRIGHT NOTICE
  20.  
  21. Proxy is not a public domain program. It is Copyright (C) 1991 -
  22. 1994 by Burt Leavenworth.
  23.  
  24. LICENSE
  25.  
  26. Non-registered users are granted a limited license to use Proxy
  27. on a trial basis for the purpose of determining whether Proxy is
  28. suitable for their needs. Use of Proxy, except for this limited
  29. purpose, requires registration (see the file PROXY.REG). Any
  30. non-registered use, other than the above, is strictly prohibited.
  31.  
  32. No user may modify Proxy in any way, including but not limited to
  33. decompiling, disassembling or otherwise reverse engineering the
  34. program. All users are granted a limited license to copy Proxy
  35. only for the trial use of others subject to the above limitations
  36. provided that the full Proxy documentation, including license,
  37. warranty and registration information, must be copied. No fee,
  38. charge or other compensation may be accepted or requested by
  39. any licensee.
  40.  
  41. Operators of electronic bulletin board systems (BBSs) may post
  42. Proxy for downloading by their users only as long as the above
  43. conditions are met. Distributors of user supported software
  44. (disk vendors) may also distribute copies of Proxy subject to
  45. the above conditions.
  46.  
  47. WARRANTY INFORMATION
  48.  
  49. The author hereby disclaims all warranties relating to this
  50. software, whether express or implied, including without
  51. limitation any implied warranties of merchantability or fitness
  52. for a particular purpose. The author will not be liable for any
  53. special, incidental, consequential, indirect or similar damages
  54. including any lost profits or lost savings, arising from the use
  55. of, or inability to use, this software, even if the author has
  56. been advised of the possibility of such damages. 
  57.  
  58. TABLE OF CONTENTS
  59.  
  60. Introduction ............................................  1
  61. Getting Started .........................................  1
  62. Using Commands ..........................................  2
  63.   Primitive Types .......................................  2
  64.   Identifiers ...........................................  2
  65.   Operators .............................................  2
  66.   Sets ..................................................  3
  67.   Maps ..................................................  4
  68.   Sequences .............................................  6
  69.   Strings ...............................................  8
  70.   Structs ...............................................  8
  71.   Operator Precedence ...................................  8
  72.   Function Definition ...................................  9
  73.   Class Definition ...................................... 10
  74.   System Commands ....................................... 12
  75. Using Statements ........................................ 16
  76.   Assignment Statement .................................. 16
  77.   Conditional Statement ................................. 16
  78.   While Statement ....................................... 16
  79.   For Statement ......................................... 16
  80.   Return Statements ..................................... 16
  81.   I/O Statements ........................................ 17
  82.   Function Call ......................................... 17
  83.   Block ................................................. 18
  84.   Comments .............................................. 18
  85. Type Predicates ......................................... 18
  86. Class Constructors ...................................... 18
  87. Inheritance ............................................. 19
  88. Scheme Interface ........................................ 20
  89. An Example .............................................. 20
  90. Another Example ......................................... 22
  91. Tasking ................................................. 25
  92.  Start Statement ........................................ 25
  93.  Skip Statement ......................................... 26
  94.  Input Statement ........................................ 26
  95.  Output Statement ....................................... 26
  96.  Select Statement ....................................... 26
  97.  Builtin Functions ...................................... 26
  98.  Examples ............................................... 27
  99. Proxy Keywords .......................................... 27
  100. References .............................................. 27
  101. Index ................................................... 27
  102.  
  103.                                   Page 1
  104.  
  105. INTRODUCTION
  106.  
  107. Proxy is an interpreter for a rapid prototyping language with C
  108. and C++ like syntax based on modelling software using data
  109. structures such as sets, maps, sequences, and objects. There are
  110. no pointers or arrays in Proxy (although maps can be thought of
  111. as a high level generalized array), which avoids the temptation
  112. to use these rather low level types. Proxy has been influenced
  113. to a great extent by the "me too"[1], VDM [3], EPROL [4], and
  114. SETL [5] languages. Proxy allows the developer to make incremental
  115. changes to a design, and test them immediately. It therefore
  116. follows Fred Brooks' injunction: "Plan to throw one away: you
  117. will, anyhow" [2].
  118.  
  119. A software system can be represented as a "state" and a collection of
  120. functions which operate on components of the state. The user may
  121. develop these operations incrementally or define them in files which
  122. are loaded prior to execution. It is also possible to manipulate
  123. objects (defined by classes) which encapsulate local states; this
  124. allows the user to define a software model as a hierarchy of submodels.
  125.  
  126. GETTING STARTED
  127.  
  128. The following files are provided with the Proxy system:
  129.  
  130.      PROXY.EXE             CROSS.PRX             H1.HLP
  131.      PROXY.DAT             EMAIL.PRX             H2.HLP
  132.      PROXY.INI             MERGE.PRX             H3.HLP
  133.      PROXY.DOC             COPY.PRX              H4.HLP
  134.      FINANCE.PRX           NODUP.PRX             H5.HLP
  135.      SIEVE.PRX             FRINGE.PRX            H6.HLP
  136.      MERGE2.PRX            PROXY.REG             H7.HLP
  137.      SORT.PRX              READ.ME               H8.HLP
  138.  
  139. Copy the files into a subdirectory of your choice. To install Proxy,
  140. move to that subdirectory, type
  141.  
  142.      proxy install
  143.  
  144. and press <enter>.
  145.  
  146. The install process will end with the message:
  147.  
  148. loading-ended
  149.  
  150. To run Proxy, type
  151.  
  152.      proxy
  153.  
  154. After the copyright notice, the following will be displayed
  155. on your screen:
  156.  
  157.  Continue? : (run) / (exit)
  158.  
  159.  >
  160.  
  161. Type (run) and press <enter>. Make sure that run is enclosed by
  162. parentheses. A prompt ? will be displayed. You may now type
  163.                                   Page 2
  164.  
  165. expressions and function definitions. To print out the
  166. documentation, type printdoc and press <enter>. To get help
  167. at any prompt, type: help; and press <enter>. To exit the
  168. interpreter from any prompt, type exit; and press <enter>. Whenever
  169. the Continue? : (run) / (exit) prompt appears, you may exit the
  170. interpreter by typing (exit) and pressing <enter>.
  171.  
  172. Note - If you change to a new memory mapping scheme, for example,
  173. upgrading to DOS 5.0, it will be necessary to re-install Proxy.
  174.  
  175. USING COMMANDS
  176.  
  177. There are two types of commands: "desk calculator" type commands,
  178. and system commands. There are four system commands: load (to load
  179. a Proxy file), transcript (to store in a file a transcript of all
  180. subsequent keystrokes), help (to obtain the syntax of different
  181. commands, statements, and composite data structures), and exit (to
  182. return to the DOS prompt). "Desk calculator" commands are the expressions,
  183. assignments, and definitions that can be typed at the Proxy prompt for
  184. immediate evaluation and execution.
  185.  
  186. Commands are typed at the Proxy prompt. The simplest command is an
  187. expression to be evaluated, i.e. 2+2;. Note that every command
  188. must be terminated with a semi-colon. There are four (primitive)
  189. types of expressions.
  190.  
  191. Primitive types
  192.  
  193. The primitive data types are integer, real, boolean, and string.
  194. Real literals are written in decimal form, i.e. 3.14159; there
  195. must be at least one digit before the decimal point. Boolean
  196. literals are written true, false, and strings are written with
  197. double quotes, i.e. "This is a string".
  198.  
  199. Slightly more complicated expressions involve identifiers (variables):
  200.  
  201. Identifiers
  202.  
  203. All identifiers must start with a letter. The rest of the identifier
  204. can consist of letters, underscores or digits. Identifiers are not
  205. case sensitive, i.e. aBcD is considered to be the same identifier as
  206. abcd.
  207.  
  208. Operators
  209.  
  210. The standard arithmetic, relational and Boolean operators are supported
  211. wuth their relative precedence given by the following table:
  212.  
  213.      !   unary -                          highest
  214.      * / %  &&                              |
  215.      + - ||                                 v
  216.      == != < > <= >=                      lowest
  217.  
  218. where ! represents logical negation, % is the modulo operator, && is
  219. logical conjunction, || is logical disjunction, == represents equal
  220. and != represents not equal.
  221.  
  222. Another command is assigning a value to an identifier. For example,
  223.                                   Page 3
  224.  
  225.  
  226. x=2;
  227.  
  228. We can then invoke the expression x+3;
  229.  
  230. More complicated expressions can be formed using the composite data
  231. types provided by Proxy: sets, maps, sequences and structs.
  232.  
  233. Sets
  234.  
  235. A mathematical set is, of course, an unordered collection of elements.
  236. From a formal point of view, each element should have the same type.
  237. However, since Proxy has latent types, i.e. types are not declared by
  238. the programmer, set elements are not restricted to have the same type.
  239.  
  240. The simplest operation is to enumerate a set by delimiting its elements
  241. by curly brackets:
  242.  
  243. {1,2,3,4,5}
  244.  
  245. This same set can be constructed by using the range notation
  246. (not to be confused with the range of a map to be defined later)
  247.  
  248. {1..5}
  249.  
  250. Ranges can only be used when the elements are consecutive. Another
  251. example of enumeration would be
  252.  
  253. smallprimes = {2,3,5,7};
  254.  
  255. To find the number of elements in the set smallprimes, we use the
  256. cardinality operator card:
  257.  
  258. card smallprimes;      returns 4
  259.  
  260. Two sets can be tested for equality using the equality operator ==.
  261.  
  262. Another simple operation is membership:
  263.  
  264. 3 in smallprimes;      returns true
  265.  
  266. 3 notin smallprimes:   returns false
  267.  
  268. To illustrate the standard operations of union, intersection, difference
  269. subset and equality, we assume two sets s1 and s2 to have the values
  270.  
  271. s1={1,2,4,6};
  272.  
  273. s2={1,2,3,4,5};
  274.  
  275. s1 U s2;               returns {1,2,3,4,5,6}
  276. s1 inter s2;           returns {1,2,4}
  277. s1 diff s2;            returns {6}
  278. s1 subset s2;          returns false
  279. s1 == s2;              returns false
  280.  
  281. The distributed union is the union of a set of sets. For example,
  282.  
  283.                                   Page 4
  284.  
  285. union {s1,s2,{6,7,8}};       returns {1,2,3,4,5,6,7,8}
  286.  
  287. The 'the' operator returns the only element of a singleton set. If
  288. the argument is not a singleton set, an error message is returned.
  289.  
  290. the {13};              returns 13
  291.  
  292. The oneof operator applied to a set returns an 'arbitrary' element
  293. of the set. However, Proxy always returns the 'first' element.
  294.  
  295. oneof smallprimes;     returns 2
  296.  
  297. The existential quantifier applied to a set and a predicate returns
  298. true if there is at least one element of the set that satisfies the
  299. predicate, and false otherwise. The universal quantitifer applied
  300. to a set and a predicate returns true only if all elements of the set
  301. satify the predicate.
  302.  
  303. (exists x in {2,3,5,7};even(x));  returns true
  304.  
  305. (all x in {2,3,5,7};even(x));     returns false
  306.  
  307. where the function even(x) returns true if x is even. The existential
  308. quantifier above returns true because 2 satisfies even(2) and the
  309. universal quantifier returns false because only even(2) is satisfied.
  310.  
  311. A more general way of constructing sets is given by the form:
  312.  
  313. { f(x): x<- expr ; pred(x) }
  314.  
  315. where the syntax x<- expr is called a generator, and the syntax
  316. ; pred(x) is optional. The expression expr is evaluated to
  317. yield a set. The values of the set are successively assigned to x
  318. and a new set is formed from elements obtained by applying the function
  319. f to the successive values of x which satisfy pred(x) (if pred(x) occurs).
  320. Several examples will make this clearer.
  321.  
  322. { x: x<- {1,2,3,4,5}};           returns {1,2,3,4,5}
  323.  
  324. This is the simplest case where f(x) is just x and a predicate does
  325. not appear.
  326.  
  327. { x: x <- {1,2,3,4,5};x>2};      returns {3,4,5}
  328.  
  329. { x*x: x <- {1,2,3,4,5}};        returns {1,4,9,16,25}
  330.  
  331. It is possible to have two generators in which case an example is:
  332.  
  333. { x+y: x <- {1,2}, y <- {3,4}}   returns  {4,5,6}
  334.  
  335. Only three elements are returned because two additions (1+4) and (2+3)
  336. yield duplicate values.
  337.  
  338.  
  339. Maps
  340.  
  341. Maps are also enumerated by delimiting their elements with curly
  342. brackets (because formally maps are sets of ordered pairs). The
  343.                                   Page 5
  344.  
  345. syntax is given by the following example.
  346.  
  347. m = {1->2,3->4,5->6};
  348.  
  349. where the first and second elements of each ordered pair is separated
  350. by the mapping symbol ->.
  351.  
  352. Maps can be constructed using map construction. In the following
  353. example, len returns the length of a string.
  354.  
  355. {x->len x:x <- {"abc","defg","hijkl"}};
  356.  
  357.          returns {"abc"->3,"defg"->4,"hijkl"->5}
  358.  
  359. The domain (range) of a map is obtained by forming a set composed
  360. of all the first (second) elements of the ordered pairs
  361.  
  362. dom m;               returns {1,3,5}
  363. rng m;               returns {2,4,6}
  364.  
  365. A single-valued map must have all its first elements unique. Notice
  366. that, in general, card (rng m) <= card (dom m). The cardinality of
  367. the range would be less, for example if
  368.  
  369. m = {1->2,3->2,5->6};
  370.  
  371. In this case, card(dom m) = 3, and card(rng m) = 2 (because of the
  372. duplicate elements in the range).
  373.  
  374. Given a domain element, we can obtain the corresponding range element
  375. using application (this is like a table lookup).
  376.  
  377. m[1];                returns 2
  378. m[5];                returns 6
  379.  
  380. If a domain element is given which does not exist in the map, a false
  381. value will be returned. However, it is possible to supply your own
  382. value to be returned in this situation. This is done by supplying an
  383. additional argument (called the default error return). For example,
  384.  
  385. m[7];                returns false
  386. m[7,"not found"];    returns "not found"
  387.  
  388. Given a set of domain elements as a second argument, the image operation
  389. (im) produces a set of the corresponding range elements (again assuming
  390. m={1->2,3->4,5->6})
  391.  
  392. m im {3,5};        returns {4,6}
  393.  
  394. Domain restriction (dr) and domain subtraction (ds) produce new maps
  395. from a given map by either allowing only certain domain elements in
  396. the given map to appear in the result map, or taking away certain
  397. domain elements from the given map. The domain elements are given
  398. in a set which is the second argument of these operations.
  399.  
  400. {1->2,3->2,5->6} dr {3,5};     returns  {3->2,5->6}
  401. {1->2,3->2,5->6} ds {3,5};     returns {1->2}
  402.  
  403.                                   Page 6
  404.  
  405. The inverse operation just interchanges the domain and range elements
  406. of a map.
  407.  
  408. inverse {1->2,3->2,5->6};      returns {2->1,2->3,6->5}
  409.  
  410. Note that the result of the above operation is a multi-valued map.
  411.  
  412. The overwrite operation m1 overwr m2 is defined as follows: Each
  413. mapping in m1 is included in the result, unless its domain element
  414. occurs in the domain of m2. In that case, it is replaced by the
  415. mapping from m2. Every mapping in m2 whose domain element does not
  416. occur in the domain of m1 is included in the result. Example:
  417.  
  418. {1->2,3->4} overwr {3->5,4->6};    returns {1->2,3->5,4->6}
  419.  
  420. The map update m[d]=r is an assignment and a special case of
  421. overwrite where the second operand (of overwrite) contains a
  422. single ordered pair. Assuming that m is equal to {1->2,3->4},
  423. m[3]=5; is equivalent to m overwr {3->5} and assigns to m the map
  424. {1->2,3->5}.
  425.  
  426. Sequences
  427.  
  428. A sequence is a collection of ordered elements which may be
  429. selected by their ordinal position (index) in the sequence. The
  430. types of the elements are not necessarily the same.
  431.  
  432. A sequence can be enumerated by delimiting its elements by square
  433. brackets:
  434.  
  435. [1,2,3,4,5]
  436.  
  437. This same sequence can be constructed by using the range (not to be
  438. confused with the range of a map) notation:
  439.  
  440. [1..5]
  441.  
  442. Ranges can only be used when the elements are consecutive. Another
  443. example of enumeration would be
  444.  
  445. s1 = [1,2,2,3,4];
  446.  
  447. Note the duplicate elements. To find the number of elements in the
  448. sequence s1, we use the length operator len:
  449.  
  450. len s1;                   returns 5
  451.  
  452. Two sequences can be tested for equality using the equality operator
  453. ==. Concatenation of two sequences is performed used the concatenation
  454. operator conc.
  455.  
  456. [1,2,3,4] conc [3,4,5];   returns [1,2,3,4,3,4,5]
  457.  
  458. If s=[3,4,5], then an element of the sequence can be selected using
  459. its index in the sequence. For example,
  460.  
  461. s[1];                     returns 3
  462. s[3];                     returns 5
  463.                                   Page 7
  464.  
  465. s[4];                     returns false
  466. s[4,0];                   returns 0
  467.  
  468. The last example uses the default error return.
  469.  
  470. Other selection operators on sequences are hd, tl, last and butlast.
  471. Hd returns the first element of the sequence. Tl returns a sequence
  472. consisting of every element but the first. Last returns a sequence
  473. consisiting of only the last element. Butlast returns a sequence
  474. consisting of every element but the last.
  475.  
  476. hd s;                     returns 3
  477. tl s;                     returns [4,5]
  478. last s;                   returns [5]
  479. butlast s;                returns [3,4]
  480.  
  481. A sequence of length n can be represented by a map whose range elements
  482. are the elements of the sequence, and whose domain elements are the
  483. integers from 1 to n. Consequently, the domain operator applied to a
  484. sequence will return the index elements {1..n}, and the range operator
  485. will return the elements of the sequence contained in a set.
  486.  
  487. dom s;                    returns {1,2,3}
  488. rng s;                    returns {3,4,5}
  489.  
  490. A sequence can be converted explicitly to its corresponding map and
  491. conversely. Thus
  492.  
  493. m=seq2map s;              assigns to m the map {1->3,2->4,3->5}
  494. map2seq m;                returns [3,4,5]
  495.  
  496. A more general way of constructing sequences, analogous to set
  497. construction is given by the following form
  498.  
  499. [ f(x): x<- expr ; pred(x) ]
  500.  
  501. where the syntax x<- expr is called a generator, and the syntax
  502. ; pred(x) is optional. The expression expr is evaluated to
  503. yield a sequence. The values of the sequence are successively assigned
  504. to x and a new sequence is formed from elements obtained by applying the
  505. function f to the successive values of x which satisfy pred(x) (if pred(x)
  506. occurs). An example:
  507.  
  508. [len x: x<-["abc","defg","hijkl"];len x > 3];  returns [4,5]
  509.  
  510. Before concluding a discussion of sequences, it is important to point
  511. out a distinction between a sequence of length two and an orderd pair.
  512. Remember that a map may be considered to be a set of ordered pairs.
  513. There are cases when one needs to access the components of an ordered
  514. pair. Proxy provides two operators for this purpose, first and second.
  515.  
  516. {first x:x<-{1->2,3->4,5->6}};     returns {1,3,5}
  517.  
  518. Suppose now that we have a set of sequences, say y={[1,2],[3,4]}
  519. and we wish to obtain a set of the first elements of the sequences.
  520. It would be wrong to write {first x:x<-y}. The correct solution is to
  521. write {x[1]:x<-y}.
  522.  
  523.                                   Page 8
  524.  
  525. Strings
  526.  
  527. Strings can be considered to be sequences of characters, although
  528. a character is not a primitive type in Proxy. Since the string
  529. operators are similar to the sequence operators already discussed,
  530. their use will be shown below in examples.
  531.  
  532. len "abcd";                      returns 4
  533. "abc" == "abc";                  returns true
  534. "abc" == "aBc";                  returns false
  535. "abc" < "abcd";                  returns true
  536. "abc" conc "defg";               returns "abcdefg"
  537. s="abc";
  538. s[2];                            returns "b"
  539. s[4];                            returns false
  540. s[4,0];                          returns 0
  541. hd "abc";                        "a"
  542. tl "abc";                        "bc"
  543. last "abc";                      "c"
  544. butlast "abc";                   "ab"
  545.  
  546. Structs
  547.  
  548. Structs are data structures whose components may be selected by name.
  549. The typical operations are declaration, instantiation, selection and
  550. update.
  551.  
  552. A struct declaration is essentially a class declaration which defines
  553. the names of the components of the struct. The syntax of the declaration
  554. is best shown by an example.
  555.  
  556. struct item {partno, code, quantity;};
  557.  
  558. The above declaration defines item to be a struct with the (field)
  559. names partno, code and quantity. Various items can be instantiated
  560. (created) by providing the struct name and values for the fields.
  561. (but a struct component may not be a function).
  562.  
  563. i1=new item(124,"receipt",15);
  564. i2=new item(126,"issue",7);
  565.  
  566. Components of structs may be selected using a dot notation similar
  567. to records in Pascal and structures in C.
  568.  
  569. i1.code;                   returns "receipt"
  570. i2.quantity;               returns 7
  571.  
  572. Component values may be updated using assignment and dot notation.
  573.  
  574. i1.quantity=22;            assigns 22 as the new value of the quantity
  575.                            field.
  576.  
  577. Operator Precedence
  578.  
  579. The precedence of Proxy operators from highest to lowest are
  580. shown below.
  581.  
  582.      unary operators                                   HIGHEST
  583.                                   Page 9
  584.  
  585.      * / % && inter conc dr ds im                         |
  586.      + - || U overwr diff                                 v
  587.      == != < > <= >= in notin subset equiv implies      LOWEST
  588.  
  589. where the unary operators are:
  590.  
  591.      - + ! hd tl last butlast card len first dom rng
  592.      union the oneof map2seq seq2map new inverse
  593.  
  594. Function Definition
  595.  
  596. The syntax of function definition in Proxy is the same as that in C
  597. with minor differences: (1) the declaration of local variables is different
  598. mainly due to the fact that the types of variables are not declared in
  599. Proxy and (2) each function declaration in Proxy is terminated with a
  600. semi-colon, (3) it is not necessary to name the top level function 'main',
  601. (4) procedures do not require the prefix 'void'; in what follows we will
  602. use the generic term function to apply as well to procedures. The syntax
  603. is now shown:
  604.  
  605. identifier ( op-param-list op-decl) block ;
  606.  
  607. The definition consists of the function name (identifier) followed by
  608. an optional parameter-list and an optional list of local variables
  609. delimited by parentheses. The parameter-list consists of identifiers
  610. separated by commas. The list of local variables consists of a semi-
  611. colon followed by identifiers separated by commas. The block consists
  612. of a statement-list (see the section on statements) delimited by
  613. curly brackets. Finally, the definition must be terminated with a
  614. semi-colon. Examples follow (the return statement is described in the
  615. section on statements).
  616.  
  617. even(n) {return n%2==0;};
  618. odd(n) {return !even(n);};
  619.  
  620. Given a subset of the integers, say digits={0..9};, we can define
  621. a function to obtain the odd integers from this set.
  622.  
  623. odddigits() {return {n:n<-digits;odd(n)};};
  624.  
  625. The following example illustrates a simple recursive function to
  626. add up the elements in an integer sequence.
  627.  
  628. reduce(s) { if(s==[]) return 0; else return hd s + reduce(tl s);};
  629.  
  630. The next example illustrates the definition of a doubly recursive
  631. function, and the declaration of a local variable x.
  632.  
  633. quicksort(s;x) { if(len s<2) return s;
  634.               x=s[1];
  635.               return quicksort([y:y<-s;y<x]) conc [x]
  636.                 conc quicksort([y:y<-tl s;y>=x]);};
  637.  
  638. An example showing the use of the existential quantifier:
  639.  
  640. primes(max) {return [n:n<-[2..max];
  641.              !(exists m in {2..n-1};(n % m)==0)];};
  642.  
  643.                                   Page 10
  644.  
  645. An example of a procedure (a function which does not contain a return
  646. statement) which has no parameters.
  647.  
  648. init() {x["a"]="b";};
  649.  
  650. This procedure initializes the variable x to the map {"a"->"b"}. The
  651. same effect could have been achieved at the command level by the
  652. assignment x["a"]="b";.
  653.  
  654. Class Definition and Instantiation
  655.  
  656. A class is defined by giving the class name, followed by an
  657. enumeration of instance variables in the form of a
  658. parameter list, followed by a collection of function definitions
  659. (also called methods). Classes, contrary to C++, may only contain
  660. functions.
  661.  
  662. In order to motivate the definition and usage of a class, let us first
  663. define a simple queue. It does not matter what type of item the queue
  664. contains; we will assume a queue of integers. In the specification
  665. below, the state component q (a global variable) represents the queue
  666. as a sequence, which is initialized as the empty sequence.
  667.  
  668. q=[];
  669. enqueue(x) {q=q conc [x];};
  670. dequeue(;x) {x=hd q;q=tl q;return x;};
  671. empty() {return q==[];};
  672. length() {return len q;};
  673.  
  674. A typical sequence of operations is:
  675.  
  676. ? enqueue(3);
  677.  
  678. ? enqueue(5);
  679.  
  680. ? length();
  681.  2
  682.  
  683. ? dequeue();
  684.  3
  685.  
  686. ? empty();
  687.  false
  688.  
  689. ? dequeue();
  690.  5
  691.  
  692. ? empty();
  693.  true
  694.  
  695. There are drawbacks to this approach. Only one queue is available, and
  696. its representation is completely exposed. The problem can be solved by
  697. defining a queue class.
  698.  
  699. class queue(rep) {
  700.  
  701. enqueue(x) {rep=rep conc [x];}
  702. dequeue(;y) {y=hd rep;rep=tl rep; return y;}
  703.                                   Page 11
  704.  
  705. empty() {return rep==[];}
  706. length() {return len rep;}};
  707.  
  708. The coding is very similar except now the state component (rep) is local
  709. and is hidden inside the class definition. The representation is
  710. initialized from the outside and may only be changed indirectly by
  711. invoking either the enqueue or dequeue operation. The analogous sequence
  712. of operations is:
  713.  
  714. ? q=new queue([]);
  715.  
  716. ? q.enqueue(3);
  717.  
  718. ? q.enqueue(5);
  719.  
  720. ? q.length;                    or q.length();
  721.  2
  722.  
  723. ? q.dequeue;                   or q.dequeue();
  724.  3
  725.  
  726. ? q.empty;                     or q.empty();
  727.  false
  728.  
  729. ? q.dequeue;                   or q.dequeue();
  730.  5
  731.  
  732. ? q.empty;                     or q.empty();
  733.  true
  734.  
  735. ? q;
  736.  object              this shows the printed representation of an object
  737.  
  738. A second queue may be instantiated by using the new operation again.
  739.  
  740. p=new queue([]);
  741.  
  742. and an arbitrary number of queues may be created in this way.
  743.  
  744. An example of a priority queue follows.
  745.  
  746. class pqueue(rep) {
  747.  
  748.  insrt(x,y) {if(y == []) {rep = [x]; return rep;} else
  749.                      if(x < hd y) {rep = [x] conc y;return rep;} else
  750.                      {rep = [hd y] conc insrt(x,tl y);
  751.                      return rep;}}
  752.  
  753.  insert(x) {rep = insrt(x,rep); return rep;}
  754.  remove(;x) { if(rep == []) return "queue empty";
  755.                   x = hd rep; rep = tl rep; return x;} };
  756.  
  757.  
  758. The last statement in the insert function returns the value of rep
  759. so that the user can see that the items are inserted in sorted
  760. order.Alternatively, the string "ok" could be returned. Note the
  761. declaration of the local variable x in the header of the remove
  762. function. The following sequence of operations show calls to
  763.                                   Page 12
  764.  
  765. the insert and remove functions:
  766.  
  767. ? q= new pqueue([]);
  768.  
  769. ? q.insert(3);
  770.  [3]
  771. ? q.insert(2);
  772.  [2,3]
  773. ? q.insert(9);
  774.  [2,3,9]
  775. ? q.insert(7);
  776.  [2,3,7,9]
  777. ? q.remove;
  778.  2
  779. ? q.remove;
  780.  3
  781. ? q.remove;
  782.  7
  783. ? q.remove;
  784.  9
  785. ? q.remove;
  786.  queue empty
  787.  
  788.  
  789. System Commands
  790.  
  791. The help command produces the following menu:
  792.  
  793. 1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
  794.    7 structs 8 classes 9 quit
  795.  
  796. A "quick reference" screen showing functionality and syntax of Proxy
  797. constructs is obtained by selecting one of the above numbers. The results
  798. of selecting individual numbers is shown below.
  799.  
  800. 1
  801.  
  802. COMMANDS
  803. Type of Command                Example
  804.  
  805. (1) an expression              x + 3 ;
  806. (2) function definition        fun(y) {return y+1;};
  807. (3) assignment                 y = 17;
  808. (4) function call              fun(3);
  809. (5) struct declaration         struct empl {age,citizen;};
  810. (6) struct instantiation       p = new empl(25, true);
  811. (7) struct component update    p.age = 26;
  812. (8) map update                 table[3]= 4;
  813. (9) class definition           class stack(rep) {
  814.                                 push(x) {rep = [x] conc rep}
  815.                                 top() {return hd rep;}
  816.                                 pop() {rep= tl rep;} };
  817. (10) class instantiation       s= new stack([]);
  818. (11) load command              load "topsort.prx";
  819. (12) transcript command        transcript "session.txt";
  820. (13) help command              help;
  821. (14) exit command              exit;
  822.  
  823.                                   Page 13
  824.  
  825. 1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
  826.    7 structs 8 classes 9 quit
  827. 2
  828.  
  829. FUNCTIONS
  830.  
  831. iden ( op-param-list op-decl)  function definition
  832.   block ;                      where op-param-list is an
  833.                                optional parameter list,
  834.                                op-decl is an optional list
  835.                                of local variables with the
  836.                                form   ;iden-list and block
  837.                                consists of one or more
  838.                                statements enclosed by
  839.                                braces
  840.  
  841.                                Example
  842.  
  843.                                fact(n) { if (n=0) return 1;
  844.                                  else return n*fact(n-1);};
  845. 1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
  846.    7 structs 8 classes 9 quit
  847.  
  848. 3
  849.  
  850.  
  851. STATEMENTS
  852.  
  853. left-hand-value = expr ;       simple assignment, map update,
  854.                                or struct component update
  855. if ( expr ) stat1              conditional statement - form1
  856. if ( expr ) stat1 ;            conditional statement - form2
  857.    else stat2
  858. while ( expr ) stat            while statement
  859. for iden <- expr ; stat        for statament
  860. return ;                       return statement - form1
  861. return expr;                   return statement - form2
  862. iden ( expr-list );            function call
  863. { stat1 ; ... statn ; }        block
  864. open(iden,"r") ;               open read statement
  865. open(iden,"w") ;               open write statement
  866. close(iden) ;                  close statement
  867. readln(v1,...,vn) ;            readln statement
  868. readln(iden,v1,...vn) ;        readln file statement
  869. writeln(v1,...,vn) ;           writeln statement
  870. writeln(iden,v1,...,vn) ;      writeln file statement
  871. 1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
  872.    7 structs 8 classes 9 quit
  873. 4
  874.  
  875. SETS
  876. { e1, e2, ..., en}             set enumeration
  877. { e1 .. ek}                    set of integers from e1 to ek
  878. {}                             empty set
  879. { e : x <- s }                 set comprehension
  880. { e : x <- s ; b }             set comprehension with boolean
  881. { e : x <- s1 , y <- s2 }         s1, s2 are sets
  882. { e : x <- s1 , y <- s2 ; b }     b is a boolean
  883.                                   Page 14
  884.  
  885. e in s                         set membership
  886. e notin s                      set nonmembership
  887. s1 inter s2                    set intersection
  888. s1 U s2                        set union
  889. s1 diff s2                     set difference
  890. s1 subset s2                   subset
  891. union s                        distributed union
  892. card s                         cardinality of a set
  893. s1 == s2                       set equality
  894. the s                          element of singleton set
  895. oneof s                        arbitrary member of set
  896. (all x in s ; b )              universal quantifier
  897. (exists x in s ; b )           existential quantifier
  898. 1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
  899.    7 structs 8 classes 9 quit
  900. 5
  901.  
  902. MAPS
  903.  
  904. { d1 -> r1, ..., dn -> rn }    map enumeration
  905. {}                             empty map
  906. { x -> e1 : x <- e2 }          map construction
  907. { x -> e1 : x <- e2 ; b }      map construction with boolean
  908. dom m                          domain of map m
  909. rng m                          range of map m
  910. m dr s                         domain restriction (s is a set)
  911. m ds s                         domain subtraction (s is a set)
  912. inverse m                      inverse of m
  913. m im s                         image of m (s is a set)
  914. m[x]                           application
  915. m[x,r]                         application with default error return
  916. m1 overwr m2                   overwrite
  917. m[d]= r                        map update
  918. first p                        first element of ordered pair
  919. second p                       second element of ordered pair
  920. 1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
  921.    7 structs 8 classes 9 quit
  922. 6
  923.  
  924. SEQUENCES
  925. [ e1, e2, ..., en]             sequence enumeration
  926. [ e1 .. ek ]                   sequence of integers from e1 to ek
  927. []                             empty sequence
  928. [ e : x <- s ]                 sequence construction
  929. [ e : x <- s ; b ]             sequence construction with boolean
  930. [ e : x <- s1 , y <- s2 ]        s1, s2 are sequences
  931. [ e : x <- s1 , y <- s2 ; b ]    b is a boolean
  932. len s                          length of a sequence
  933. s1 == s2                       sequence equality
  934. s1 conc s2                     concatenation
  935. s[i]                           selection
  936. s[i,r]                         selection with default error return
  937. hd s                           head of a sequence
  938. tl s                           tail of a sequence
  939. butlast s                      first n-1 elements
  940. last s                         [s[len s]]
  941. dom s                          set of indices of s
  942. rng s                          set of elements of s
  943.                                   Page 15
  944.  
  945. seq2map s                      convert sequence to a map
  946. map2seq m                      convert map to a sequence
  947. 1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
  948.    7 structs 8 classes 9 quit
  949. 7
  950.  
  951. STRUCTS
  952.  
  953. struct sname { f1,...,fn; };   struct declaration
  954. new sname(e1, ..., en)         struct instantiation
  955. s . fi ;                       struct component selection
  956. s . fi = e ;                   struct component update
  957. 1 commands 2 functions 3 statements 4 sets 5 maps 6 sequences
  958.    7 structs 8 classes 9 quit
  959. 8
  960.  
  961. CLASSES
  962.  
  963. class iden ( op-param-list op-decl)    class definition
  964.   {                                    where op-param-list is an
  965.     iden ( op-param-list ) block       optional parameter list, op-decl
  966.   } ;                                  is an optional list of local
  967.                                        variables with the form ; iden-list
  968.                                        and block consists of one or more
  969.                                        statements enclosed by braces
  970.  
  971.                                        Example
  972.  
  973.                                        class queue (;rep) {
  974.                                         queue() {rep = [];}
  975.                                         enqueue(x) {rep = rep conc [x];}
  976.                                         dequeue(;y) {y = hd rep;
  977.                                                      rep = tl rep;
  978.                                                      return y;}};
  979.  
  980. Inheritance
  981.  
  982. class iden1 ( ... ) : iden2             where iden2 is the superclass name
  983.   { ...
  984.                                         Example
  985.  
  986.                                         class deque (;rep) : queue {
  987.                                          ...
  988.  
  989. The load command (an example of which is given above) is used to load
  990. Proxy commands from a file. The commands are inserted in a file as
  991. if they were being typed at the command line, the only difference being
  992. that the last line in the file must contain the single token: end.
  993. Be careful not to insert more than one command on a line. For example,
  994. x=2; y=3; is wrong because only the first assignment would be executed.
  995. A function or class definition, however, consists of only a single
  996. command, although it can take up more than one line.
  997.  
  998. The transcript command (an example of which is given above) is used to
  999. record in a file all subsequent interactions of user inputs (keystrokes)
  1000. and resulting Proxy outputs.
  1001.  
  1002. The exit command terminates execution of the Proxy interpreter and
  1003.                                   Page 16
  1004.  
  1005. returns to the DOS prompt.
  1006.  
  1007. USING STATEMENTS
  1008.  
  1009. A statement is either a simple statement or a block (see below),
  1010. which is a sequence of statements delimited by curly brackets.
  1011.  
  1012. Assignment Statement
  1013.  
  1014. identifier = expression ;       expression is evaluated and the
  1015.                                 resulting value is stored in
  1016.                                 identifier. Examples are:
  1017.  
  1018. x = {2, 3, 5, 7} ;              simple assignment
  1019. m["Joe"] = 30;                  map update
  1020. p.r = {1->2, 3->4};             struct update
  1021.  
  1022. Conditional Statement
  1023.  
  1024. The conditional or if-statement may take one of the following
  1025. forms:
  1026.  
  1027. if ( expr ) stat1                  in both cases, expr is evaluated;
  1028.                                    if it evaluates to true then stat1
  1029. if ( expr ) stat1 ; else stat2     is executed. If it evaluates to
  1030.                                    false, in the first case nothing
  1031.                                    happens; in the second case stat2
  1032.                                    is executed. Examples are:
  1033.  
  1034. if (x < 2) y = 0;
  1035. if (n == 0 ) f = 1; else f = n * f;
  1036.  
  1037. While statement
  1038.  
  1039. while ( expr ) stat                expr is evaluated; as long as its
  1040.                                    value is true, stat is executed,
  1041.                                    and expr is reevaluated; when its
  1042.                                    value is false, the following
  1043.                                    statement is executed. Example:
  1044.  
  1045. while (n <= 10) n=n+1;
  1046.  
  1047. For statement
  1048.  
  1049. for identifier <- expr ; stat      expr is evaluated and identifier
  1050.                                    is assigned the values of the
  1051.                                    resulting set or sequence; stat
  1052.                                    is executed for each of these
  1053.                                    assignments. Example:
  1054.  
  1055.  
  1056. for i <- {1..10}; writeln(i);
  1057.  
  1058.  
  1059. Return statement
  1060.  
  1061. The return statement may take one of the following forms:
  1062.  
  1063.                                   Page 17
  1064.  
  1065. return ;                           the enclosing function is terminated.
  1066.  
  1067. return expr ;                      expr is evaluated and the enclosing
  1068.                                    function is terminated with the value
  1069.                                    of expr as its returned value. Example
  1070.  
  1071. return n+1;
  1072.  
  1073. I/O statements:
  1074.  
  1075. open(string,"r");                  Opens a file for reading given by
  1076.                                    string, and returns a file handle.
  1077.  
  1078. h = open("data.txt","r");
  1079.  
  1080. open(string,"w") ;                 Opens a file for writing given by
  1081.                                    string, and returns a file handle.
  1082.  
  1083. open(string,"s");                  Returns the contents of the file
  1084.                                    given by string.
  1085.  
  1086. close(identifier) ;                Closes the file whose handle is
  1087.                                    given by identifier.
  1088.  
  1089. close(h);
  1090.  
  1091. writeln(v1,...,vn) ;               The scalar values or scalar valued
  1092.                                    variables vi (integer, real, string,
  1093.                                    boolean) are printed on one line
  1094.                                    separated by spaces. If vi is a
  1095.                                    variable, it must be a global.
  1096.  
  1097. writeln(123,r,"order");
  1098.  
  1099. writeln(identifier,v1,...,vn) ;    The values v1,...vn are output to
  1100.                                    the file whose handle is given by
  1101.                                    identifier. If vi is a variable,
  1102.                                    it must be a global.
  1103.  
  1104. writeln(h,123,r,"order");
  1105.  
  1106. readln(v1,...,vn) ;                The variables v1,...vn (which must be
  1107.                                    global) are assigned the corresponding
  1108.                                    values input at the keyboard.
  1109.  
  1110. readln(a,b,c);
  1111.  
  1112. readln(identifier,v1,...vn) ;      The variables v1,...vn are assigned
  1113.                                    the corresponding values in the file
  1114.                                    whose handle is given by identifier.
  1115.                                    If there are no more values in the file
  1116.                                    to read, the global variable eof has
  1117.                                    the value true, otherwise it has the
  1118.                                    value false.
  1119.  
  1120. fun() {readln(h,a,b,c);
  1121.        while(!eof) {writeln(a,b,c);
  1122.                     readln(h,a,b,c);}
  1123.                                   Page 18
  1124.  
  1125.       };
  1126.  
  1127. Function  call
  1128.  
  1129. identifier ( expr-list ) ;         Each expr in expr-list is evaluated
  1130.                                    and the function represented by
  1131.                                    identifier is called with the
  1132.                                    resulting arguments. If the function
  1133.                                    call is not contained in an expression
  1134.                                    i.e. it appears in a statement
  1135.                                    context, the resulting value is
  1136.                                    discarded.
  1137.  
  1138. Block
  1139.  
  1140. A sequence of statements may be grouped together to form a block
  1141. by enclosing them within curly brackets:
  1142.  
  1143. { stat1 ;
  1144.   stat2 ;
  1145.   ...
  1146.   statn ;
  1147. }                                  Notice that there is no semi-colon
  1148.                                    after the closing bracket. Example:
  1149.  
  1150. while (bal>0) {int=bal*r;am=pay-int;bal=bal-am;n=n+1;}
  1151.  
  1152.  
  1153. Comments
  1154.  
  1155. The delimiter // starts a comment that terminates at the end of the
  1156. line on which it occurs. It may be preceded by a statement (not an
  1157. expression), whitespace or may appear at the beginning of the line.
  1158.  
  1159. TYPE PREDICATES
  1160.  
  1161. The following predicates are supplied to test the type of a given value.
  1162.  
  1163. is_number                      is_map
  1164. is_boolean                     is_seq
  1165. is_string                      is_struct
  1166. is_set
  1167.  
  1168. Example:
  1169.  
  1170. is_number 3.14159;             returns true
  1171.  
  1172. CLASS CONSTRUCTORS
  1173.  
  1174. When a class constructor is defined by the user, by declaring a method
  1175. with the same name as the class, the corresponding class object will
  1176. be initialized automatically when it is instantiated. Taking the queue
  1177. example again:
  1178.  
  1179. class queue(;rep) {
  1180.  
  1181. queue() {rep=[];}
  1182. enqueue(x) {rep = rep conc [x];}
  1183.                                   Page 19
  1184.  
  1185. dequeue(;y) {y = hd rep; rep = tl rep; return y;}};
  1186.  
  1187. An instantiation for this class would have the syntax
  1188.  
  1189. iden = new queue();
  1190.  
  1191. where iden represents the name of the instantiated object.
  1192.  
  1193. Note that rep is defined as a local variable of the class, and that
  1194. the first method, named queue, initializes rep to the empty sequence.
  1195. When an object is instantiated, i.e. q = new queue(), the rep of that
  1196. object will be initialized.
  1197.  
  1198. INHERITANCE
  1199.  
  1200. A class can inherit instance variables and operations from another
  1201. class, called the superclass (or base class). The inheriting class
  1202. is called the subclass (or derived class). Suppose that we first
  1203. define a queue class:
  1204.  
  1205. class queue(;rep) {
  1206.  queue() {rep=[];}
  1207.  insert(x) {rep=rep conc [x];}
  1208.  remove(;y) {y=hd rep;rep=tl rep; return y;}
  1209.  empty() {return rep==[];}};
  1210.  
  1211. The characteristics of a queue is that items are inserted at one
  1212. end and removed from the other end. The queue is represented by a
  1213. sequence which is initialized by the empty sequence. Suppose we wish
  1214. to define a deque by specializing the operations which are already
  1215. provided by the queue. A deque is characterized by allowing insertions
  1216. and removals to be performed at either end. We can obtain a deque class
  1217. by defining it to be a subclass of queue:
  1218.  
  1219. class deque (;rep) : queue {
  1220.  deque() {rep=[];}
  1221.  insert_front(x) {rep=[x] conc rep;}
  1222.  remove_rear(;y) {y=hd (last rep);rep=butlast rep;return y;}
  1223.  empty(;x) {if(rep==[]) return "yes";}};
  1224.  
  1225. Since insertions to and removals from the queue were made from the
  1226. rear and front respectively, we define two new operations insert_front
  1227. and remove_rear. So the new class deque inherits the operations insert
  1228. and remove from queue, its superclass and defines the two new operations.
  1229. The syntax ": queue" which appears in the header defines queue as the
  1230. superclass. Since the operation empty has the same name as an operation
  1231. in the super class, the new definition of empty supercedes the previous
  1232. one.
  1233.  
  1234. Consider the following class definitions.
  1235.  
  1236. class rec (;value) {
  1237.  rec() {value=0;}
  1238.  get() {return value;}};
  1239.  
  1240. class newrec () : rec {
  1241.  newrec() {value=0;}
  1242.  get() {return value;}
  1243.                                   Page 20
  1244.  
  1245.  setval(x) {value=x;}};
  1246.  
  1247. Class rec has the instance variable value which is set to 0 by the
  1248. class constructor. The class newrec defines no instance variables itself
  1249. but inherits value from its superclass. Value is also initialized by
  1250. the class constructor of rec.
  1251.  
  1252. SCHEME INTERFACE
  1253.  
  1254. Proxy is implemented by translating expressions and function definitions
  1255. into Scheme which is then executed by a Scheme interpreter. This
  1256. implementation allows Proxy functions to call Scheme functions which
  1257. can then send back results to the Proxy program. Since the list is the
  1258. quintessential data structure in Scheme, and since sets, maps and
  1259. sequences in Proxy are implemented in terms of lists, we provide
  1260. transition functions to perform the conversions. In going from Proxy
  1261. to Scheme, we use
  1262.  
  1263.      $set2lst, $seq2lst, $map2lst     (set, seq, map to list)
  1264.  
  1265. and from Scheme to Proxy, we use
  1266.  
  1267.      $mkset, $mkseq, $mkmap           (list to set, seq, map)
  1268.  
  1269. The $ prefix tells the translator that the function is to be found
  1270. in the Scheme name space rather than in the Proxy name space. By the
  1271. same token, variables in the Scheme name space must also be prefixed
  1272. by a $.
  1273.  
  1274. Consider the following artificial example. We first define a Scheme
  1275. function called fun, which when applied to a list of lists, returns
  1276. a list of all the second elements. In other words,
  1277.  
  1278. (fun '((1 2) (3 4)))             returns (2 4)
  1279.  
  1280. Fun is defined at the Proxy prompt, i.e.
  1281.  
  1282. Continue? : (run) / (exit)
  1283.  
  1284. > (define (fun x) (map (lambda (x) (cadr x)) x))
  1285.  
  1286. (run)
  1287.  
  1288. ? $mkseq ( $fun ( $map2lst ( {1 -> 2, 3 -> 4} )));   returns [2, 4]
  1289.  
  1290. First, $map2lst is applied to the map to produce the list of lists:
  1291. ((1 2) (3 4)). Then the Scheme function fun is applied to this to
  1292. produce the list (2 4). Finally $mkseq is applied to this to produce
  1293. the Proxy sequence [2, 4].
  1294.  
  1295.  
  1296. AN EXAMPLE
  1297.  
  1298. A "financial history" supports the following transactions:
  1299.  
  1300. receive(amount,source) records that amount (an integer) was
  1301.                        received from source (a string)
  1302. spend(amount,reason)   records that amount (an integer) was
  1303.                                   Page 21
  1304.  
  1305.                        spent for reason (a string)
  1306. totalrec(source)       returns the total amount received from
  1307.                        source
  1308. totalspent(reason)     returns the total amount spent for
  1309.                        reason
  1310. cashonhand             records the cash on hand (an integer)
  1311.  
  1312. There are three variables representing the state: cash, inc (a map
  1313. from source to amount), and exp (a map from reason to  amount). The
  1314. financial history will be represented by a class with a parameter
  1315. cash, and two instance variables inc and exp. These variables
  1316. are the state variables of a finance object wwich is instantiated by
  1317. invoking the new operation with an initial value for cash.
  1318.  
  1319. class finance (cash;inc,exp) {
  1320.  
  1321. receive(amount,source) {cash=cash+amount;
  1322.                   inc[source]=inc[source,0]+amount;
  1323.                   return "ok";}
  1324. spend(amount,reason) {if(amount>cash) return "Insufficient funds";
  1325.                  cash=cash-amount;
  1326.                  exp[reason]=exp[reason,0]+amount;
  1327.                  return "ok";}
  1328. totalrec(source) {return inc[source,0];}
  1329. totalspent(reason) {return exp[reason,0];}
  1330. cashonhand() {return cash;}};
  1331.  
  1332. The cashonhand is initialized to 100 and is incremented in the receive
  1333. function and decremented in the spend function. If the amount to be
  1334. spent is greater than the cashonhand, the spend function returns
  1335. "Insufficient funds". The map 'inc' consists of a set of ordered pairs
  1336. where the first element of a pair is the source of a receipt, and the
  1337. second element is the total amount received from this source. The map
  1338. 'exp' contains the pairs where the first element is the reason for the
  1339. expense and the second element is the total amount spent. The default
  1340. error return, for example inc[source,0], handles the case where a
  1341. source appears for the first time and therefore does not occur as a
  1342. domain element in the map. The totalrec and totalspent functions use map
  1343. application to return the total amounts received and spent respectively.
  1344. Here again, the default error return will return 0 if the source or
  1345. reason does not appear in the map.
  1346.  
  1347. Another way of writing the program is to leave out the return "ok"
  1348. statements in the spend and receive functions. The effect of these
  1349. changes is that no output will be obtained when they are invoked,
  1350. except in the case of insufficient funds.
  1351.  
  1352. A possible sequence of operations follows.
  1353.  
  1354. ? f = new finance(1000);
  1355. ? f.cashonhand;
  1356.  1000
  1357. ? f.spend(50,"food");
  1358.  "ok"
  1359. ? f.receive(200,"salary");
  1360.  "ok"
  1361. ? f.cashonhand;
  1362.  1150
  1363.                                   Page 22
  1364.  
  1365. ? f.spend(100,"food");
  1366.  "ok"
  1367. ? f.totalspent("food");
  1368.  150
  1369. ? f.spend(1200,"rent");
  1370.  "Insufficient funds"
  1371.  
  1372. We now wish to model a financial history which will record the amount
  1373. of tax-deductible expenditures. This is a specialization or refinement
  1374. of the finance class. Class deduct_hist has four new operations: init
  1375. which initializes the instance variable deductible to zero, spend_deduct,
  1376. spend_for_deduct, and total_deduct. Their effect is illustrated by
  1377. the class definition and examples of applying the operations.
  1378.  
  1379. class deduct_hist (cash;deductible) : finance {
  1380.  init() {deductible = 0;}
  1381.  spend_deduct(amount,reason) {deductible = deductible + amount;
  1382.                               spend(amount,reason);
  1383.                               return "ok";}
  1384.  spend_for_deduct(amount,reason,deduct) {deductible = deductible + deduct;
  1385.                               spend(amount,reason);
  1386.                               return "ok";}
  1387.  total_deduct() {return deductible;}};
  1388.  
  1389. ? d = new deduct_hist(1000);
  1390. ? d.init();
  1391. ? d.spend(50,"insurance");
  1392.  "ok"
  1393. ? d.receive(200,"salary");
  1394.  "ok"
  1395. ? d.cashonhand;
  1396.  1150
  1397. ? d.total_deduct;
  1398.  0
  1399. ? d.spend_deduct(100,"mortgage");
  1400.  "ok"
  1401. ? d.cashonhand;
  1402.  1050
  1403. ? d.total_deduct;
  1404.  100
  1405. ? d.spend_for_deduct(100,"lunch",50);
  1406.  "ok"
  1407. ? d.cashonhand;
  1408.  950
  1409. ? d.total_deduct;
  1410.  150
  1411.  
  1412.  
  1413. ANOTHER EXAMPLE
  1414.  
  1415. An Electronic Mail System (Email) is to be designed to provide
  1416. communication between users of the system. The following operations
  1417. must be supported:
  1418.  
  1419. Signon(u,p) - By giving a valid user name and user-selected password,
  1420.               a user should be permitted access to the system.
  1421.  
  1422. Signoff(u)  - The user may remove himself from the system
  1423.                                   Page 23
  1424.  
  1425.  
  1426. Add(u,n,p)  - The "super" user may supply a name and password in order
  1427.               to add a new user to the list of authorized users.
  1428.  
  1429. Drop(u,n)   - The "super" user may delete a user name from the list
  1430.               of authorized users.
  1431.  
  1432. Send(u,t,n) - By giving the text of a message and name of a receiver,
  1433.               a user can place a message into a receiver's queue.
  1434.  
  1435. Read(u)    - A user can issue a Read command to examine his/her queue.
  1436.              The response should be the sender's name and text of the
  1437.              first message (if any). Successive reads will return
  1438.              additional messages (if any).
  1439.  
  1440. Delete(u)  - After reading a message, the user may issue a Delete
  1441.              command to delete the message just read.
  1442.  
  1443. Reset(u)   - This causes the next Read command to begin at the head
  1444.              of the queue.
  1445.  
  1446. Notice that the first parameter of each operation represents the
  1447. name of the user invoking the operation.
  1448.  
  1449. A Proxy program for this application is contained in the file EMAIL.PRX.
  1450. This solution illustrates the use of return messages to signal exceptions.
  1451. A queue class is first defined with the following operations: read,
  1452. write, reset and delete. This class has two instance variables: procd
  1453. and remdr, both sequences. procd represents the queue of mail messages
  1454. already processed, and remdr represents the queue of messages not
  1455. yet read. The queue class acts like a sequential file and can be
  1456. used in any application requiring a data structure with these character-
  1457. istics. The state components are:
  1458.  
  1459.      up (map from user to password)
  1460.      uq (map from user to mail-queue)
  1461.      so (set of users who are signed on)
  1462.  
  1463. // state components
  1464.  
  1465. // up: map(string,string)
  1466. // uq: map(string,queue)
  1467. // so: set(string)
  1468.  
  1469. class queue(procd,remdr) {
  1470.  read() {var x;
  1471.           if(len remdr==0) return "empty queue";
  1472.           x=hd remdr;
  1473.           remdr=tl remdr;
  1474.           procd=procd conc [x];
  1475.           return x;}
  1476.  write(msg) {remdr=remdr conc [msg];}
  1477.  reset() {remdr=procd conc remdr;
  1478.           procd=[];}
  1479.  delete() {if(len procd==0) return "empty queue";
  1480.            procd=butlast procd;} };
  1481.  
  1482. up:={"super" -> "super"};         // initialize super user with pw "super"
  1483.                                   Page 24
  1484.  
  1485. uq:={"super" -> new queue([],[])};// initialize mail-queue so super user
  1486.                                   // can send mail to him
  1487. mail :: sender text;              // mail is a struct with two fields:
  1488.                                   // sender and text
  1489. add(u,n,pw) {if (u != "super") return {"not authorized",u};
  1490.              uq[n]=new queue([],[]); // initializes mail-queue
  1491.              up[n]=pw;               // initializes password
  1492.              return "ok";};
  1493. drop(u,n) {if (u != "super") return {"not authorized",u};
  1494.            if (n notin dom up) return {"unknown user",n};
  1495.            up=up ds {n};                // remove user and password
  1496.            uq=uq ds {n};                // remove user and mail-queue
  1497.            if(n in so) so=so diff {n};  // if user signed on, sign
  1498.            return "ok";};                // him off
  1499. signon(u,pw) {if (up[u,""] != pw) return {"incorrect password",pw};
  1500.               so=so U {u};              // sign him on
  1501.               return "ok";};
  1502. signoff(u) {if (u notin so) return {"not signed on",u};
  1503.             so=so diff {u};             // sign him off
  1504.             return "ok";};
  1505. send(u,t,r;x) {if (u notin so) return {"not signed on",u};
  1506.              if (r notin dom up) return {"unknown user",r};
  1507.              x=uq[r];
  1508.              x.write(mk_mail(u,t));      // create mail and send
  1509.              return "ok";};
  1510. read(u;x) {if (u notin so) return {"not signed on",u};
  1511.          x=uq[u];
  1512.          return x.read;};                // read mail
  1513. reset(u;x) {x;if (u notin so) return {"not signed on",u};
  1514.           x=uq[u];
  1515.           x.reset;                       // reset mail-queue
  1516.           return "ok";};
  1517. delete(u;x) {if (u notin so) return {"not signed on",u};
  1518.            x=uq[u];
  1519.            x.delete;                     // delete mail
  1520.            return "ok";};
  1521. so= {};
  1522. end
  1523.  
  1524. The following sequence of messages and responses shows the application
  1525. of the Email operations.
  1526.  
  1527. ? add("super","joe",123);
  1528.  "ok"
  1529. ? add("super","mike",456);
  1530.  "ok"
  1531. ? signon("joe",123);
  1532.  "ok"
  1533. ? signon("mike",455);
  1534.  "incorrect password"
  1535. ? signon("mike",456;
  1536.  "ok"
  1537. ? send("joe","hello","mike");
  1538.  "ok"
  1539. ? send("joe","there","mike");
  1540.  "ok"
  1541. ? send("joe","meet me","tom");
  1542.  {"unknown user","tom"}
  1543.                                   Page 25
  1544.  
  1545. ? read("mike");
  1546.  < "joe", "hello" >
  1547. ? read("mike");
  1548.  < "joe", "there" >
  1549. ? read("mike");
  1550.  "empty queue"
  1551. ? reset("mike");
  1552.  "ok"
  1553. ? read("mike");
  1554.  < "joe", "hello">
  1555. ? delete("mike");
  1556.  "ok"
  1557. ? read("mike");
  1558.  < "joe", "there" >
  1559. ? reset("mike");
  1560.  "ok"
  1561. ? read("mike");
  1562.  < "joe", "there" >
  1563. ? drop("joe","mike");
  1564.  {"not authorized","joe"}
  1565. ? signoff("joe");
  1566.  "ok"
  1567.  
  1568. This example illustrates the "me too" paradigm [1] for producing
  1569. prototypes in three steps:
  1570.  
  1571. (1) model step - identify the entities and associated operations of
  1572.                  an application. In this case, we selected mail and
  1573.                  queue as entities, and read, write, reset and
  1574.                  delete as operations on the queue.
  1575.  
  1576. (2) specification step - implement the entities and operations in
  1577.                          terms of sets, maps, sequences, etc.
  1578.                          We represented queue by a class with instance
  1579.                          variables procd and remdr. Mail was represented
  1580.                          by a struct with fields sender and text.
  1581.  
  1582. (3) validation step - the operations are executed to determine if the
  1583.                       model and implementation are appropriate.
  1584.  
  1585. The above steps are iterated as necessary until a satisfactory version
  1586. is obtained.
  1587.  
  1588. TASKING
  1589.  
  1590. Proxy provides a tasking facility using the message passing paradigm.
  1591. The basic constructs are tasks and channels. A task is defined by
  1592. prefixing the 'task' modifier to a function definition. There is a
  1593. distinguished task, which must be named 'main', which is invoked in
  1594. order to begin execution. Channels are created by invoking the
  1595. built-in function of no parameters channel(). Five statements and two
  1596. built-in functions used with tasks are described below.
  1597.  
  1598. Start statement
  1599.  
  1600. start task-id ( expr-list ) ;       The expressions in expr-list are
  1601.                                     evaluated and the corresponding
  1602.                                     values (some of which will be
  1603.                                   Page 26
  1604.  
  1605.                                     channels) are passed to the task
  1606.                                     named by task-id, which is
  1607.                                     started.
  1608.  
  1609. Skip statement
  1610.  
  1611. skip ;                              The enclosing task is terminated
  1612.                                     (normally, a task terminates
  1613.                                     when it reaches the end of the
  1614.                                     task body.
  1615.  
  1616. Input statement
  1617.  
  1618. channel ? identifier ;              The current task is blocked until
  1619.                                     a message is available in channel
  1620.                                     (either an identifier or map
  1621.                                     application). Then the message is
  1622.                                     stored in identifier.
  1623.  
  1624. Output statement
  1625.  
  1626. channel ! expression ;              The current task is blocked until
  1627.                                     another task is ready to accept
  1628.                                     (with an input statement) the
  1629.                                     message produced by evaluating the
  1630.                                     expression.
  1631.  
  1632. Select statement
  1633.  
  1634. select {
  1635.   case conjunct : statement-list    The select statement consists of one
  1636.          ...                        or more case statements. A case
  1637.   case conjunct : statement-list    statement consists of a conjunct
  1638.        }                            followed by a colon (:), followed
  1639.                                     by a statement list. A conjunct is
  1640.                                     one or more terms separated by an
  1641.                                     and (&&) symbol. A term is either
  1642.                                     an input or output statement, or
  1643.                                     a boolean expression. A term is true
  1644.                                     if the input/output statement can
  1645.                                     take place, or if the boolean
  1646.                                     expression is true. The case statements
  1647.                                     are examined sequentially until one is
  1648.                                     found where all terms are true. Then
  1649.                                     the input/output statement(s) is (are)
  1650.                                     executed followed by execution of the
  1651.                                     statement list. If none of the case
  1652.                                     statements is true, the task is blocked.
  1653.  
  1654. Builtin functions
  1655.  
  1656. channel()                           This function returns a new
  1657.                                     channel.
  1658.  
  1659. avail ( channel-id )                This function returns true if a
  1660.                                     message is available on the
  1661.                                     channel denoted by channel-id,
  1662.                                     and false otherwise.
  1663.                                   Page 27
  1664.  
  1665.  
  1666.  
  1667. The use of these constructs is explained by a number of examples.
  1668. The first example copies a stream of integers from an input (source)
  1669. task to an output (sink) task which prints the integers.
  1670.  
  1671. eos="eos";                                                             //1
  1672. ch1=channel();                                                         //2
  1673. ch2=channel();                                                         //3
  1674. task source(right) {right!2;right!3;right!4;right!eos;};               //4
  1675. task sink(left;x) {while (x!=eos) {writeln(x);left?x;};                //5
  1676. task copy(left,right;x) {left?x;while (x!=eos)                         //6
  1677.                                  {right!x;left?x;}                     //7
  1678.                          right!eos;};                                  //8      
  1679. task main() {start source(ch1); start copy(ch1,ch2);start sink(ch2);}; //9
  1680.  
  1681. We will use the comments to refer to specific lines in the program.
  1682. The variable eos serves as an end-of-stream indicator - //1
  1683. Two channels are created and assigned to variables ch1 and ch2 - //2 //3
  1684. The Source task sends the integers 2, 3 , 4 followed by eos - //4
  1685. The Sink task prints incoming values until eos is received - //5
  1686. The Copy task reads and outputs incoming values - //6, //7 and //8
  1687. The Main task starts Source with output channel ch1, starts Copy
  1688. with input and output channels ch1 and ch2, and starts Sink with
  1689. input channel ch2 - //9. This example is contained in COPY.PRX.
  1690.  
  1691. The second example copies a stream of integers from Source to Sink
  1692. but suppresses duplicates.
  1693.  
  1694. ch1=channel();                                                     //1
  1695. ch2=channel();                                                     //2
  1696. eos="eos";                                                         //3
  1697. task nodup(inp,out;x,y) {inp?x;if(x==eos) {out!x;skip;}            //4
  1698.   while (true) {inp?y;if(y==eos) {out! x; out!y;skip;}             //5
  1699.   if(x!=y) {out!x;x=y;} }};                                        //6
  1700. task source(out) {out!1;out!2;out!2;out!3;out!4;                   //7
  1701.                   out!4;out!4;out!eos;};                           //8
  1702. task sink(inp;msg) {inp?msg;while(msg!=eos) {print msg;inp?msg;}}; //9
  1703. task main() {start source(ch1);start nodup(ch1,ch2);               //10
  1704.              start sink(ch2);};                                    //11
  1705.  
  1706. This example is contained in NODUP.PRX.
  1707.  
  1708. The third example merges two input streams of integers into one output
  1709. stream.
  1710.  
  1711. eos="eos";
  1712. ch1=channel();
  1713. ch2=channel();
  1714. ch3=channel();
  1715. task merge(inp1,inp2,out;x) {
  1716. n=0;
  1717. while (true) {
  1718.  if(n==2) {out!eos;skip;}
  1719.  if(avail(inp1)) {inp1?x;if(x==eos) n=n+1;
  1720.                          else out!x;}
  1721.  if(avail(inp2)) {inp2?x;if(x==eos) n=n+1;
  1722.                          else out!x;}
  1723.                                   Page 28
  1724.  
  1725.              }};
  1726. task source1(out) {out!1;out!3;out!eos;};
  1727. task source2(out) {out!2;out!4;out!5;out!eos;};
  1728. task sink(inp;x) {inp?x;while(x!=eos) {print x;inp?x;}};
  1729. task main() {start source1(ch1); start source2(ch2);start merge(ch1,ch2,ch3);
  1730.              start sink(ch3);};
  1731.  
  1732. If the avail functions were not present, the function would block on
  1733. channel inp1, even if a message was available on channel inp2. This
  1734. way, messages are input on either channel when available. This example
  1735. is contained in MERGE.PRX.
  1736.  
  1737. The fourth example is a simpler solution to the merge problem, using the
  1738. select statement (contained in MERGE2.PRX.
  1739.  
  1740. eos="eos";
  1741. ch1=channel();
  1742. ch2=channel();
  1743. ch3=channel();
  1744. n=0;
  1745. task merge(inp1,inp2,out;x) {
  1746.  select {case inp1?x:if(x==eos) n=n+1; else out!x;if(n==2) exit;
  1747.          case inp2?x:if(x==eos) n=n+1; else out!x;if(n==2) exit;
  1748.         }};
  1749.  
  1750. task source1(out) {out!1;out!3;out!eos;};
  1751. task source2(out) {out!2;out!4;out!5;out!eos;};
  1752. task sink(inp;x) {while (true) {inp?x;print x;}};
  1753. task main() {start source1(ch1); start source2(ch2);start merge(ch1,ch2,ch3);
  1754.              start sink(ch3);};
  1755.  
  1756.  
  1757. The final example tests if two binary trees have the same leaves.
  1758. The trees are represented by sequences of sequences. For example,
  1759. two trees with the same leaves but with a different structure are
  1760. tree1 = [1,[2,[3],4]] and tree2 = [[1,2],3,[4]]. There are three tasks.
  1761. Task p1 outputs the next leaf of tree1, p2 outputs the next leaf of
  1762. tree2 and task p3 inputs two values and tests for equality. There
  1763. is also a function next which tests its first argument; if a leaf,
  1764. it outputs the value on the channel which is its second argument.
  1765. Otherwise, it calls itself recursively with the head and tail of its
  1766. first argument. If the two values input to p3 do not compare, it prints
  1767. "not equal" and terminates. It is not necessary to compare any further
  1768. values. This example is contained in FRINGE.PRX.
  1769.  
  1770. next(x,out) {if(x==[]) return;
  1771.          if(is_number x) {out!x;return;}
  1772.          next(hd x,out);
  1773.          next(tl x,out);};
  1774. eos="eos";
  1775. ch1=channel();
  1776. ch2=channel();
  1777. tree1=[1,[2,3]];
  1778. tree2=[[1,2],3];
  1779. task p1(out) {print "starting p1";next(tree1,out);
  1780.               out!eos;};
  1781. task p2(out) {print "starting p2";next(tree2,out);
  1782.               out!eos;};
  1783.                                   Page 29
  1784.  
  1785. task p3(in1,in2;x,y) {print "starting p3";in1?x;in2?y;
  1786.                        while((x!=eos) || (y!=eos))
  1787.                         {if(x!=y) {print "not equal";skip;}
  1788.                          in1?x;in2?y;
  1789.                          }
  1790.                        print "equal";};
  1791. task main() {start p1(ch1);
  1792.              start p2(ch2);
  1793.              start p3(ch1,ch2);};
  1794.  
  1795.  
  1796. PROXY KEY WORDS
  1797.  
  1798. all                len
  1799. butlast            map2seq
  1800. card               new
  1801. class              last
  1802. close              notin
  1803. conc               oneof
  1804. dom                open
  1805. dr                 overwr
  1806. ds                 readln
  1807. else               return
  1808. eof                rng
  1809. equiv              second
  1810. exists             seq2map
  1811. false              struct
  1812. first              subset
  1813. for                the
  1814. hd                 tl
  1815. if                 true
  1816. im                 U
  1817. implies            union
  1818. in                 while
  1819. inter              writeln
  1820. inverse
  1821.  
  1822.  
  1823. REFERENCES
  1824.  
  1825. [1] Alexander, H. and Jones, V., Software Design and Prototyping using
  1826.     me too, Prentice-Hall, New York, 1990.
  1827.  
  1828. [2] Brooks, F.,The Mythical Man-Month. Addison-Wesley, Reading, MA, 1975.
  1829.  
  1830. [3] Jones, C.B., Systematic Software Development Using VDM, Prentice-Hall,
  1831.      New York, 1986.
  1832.  
  1833. [4] Hekmatpour, S. and Ince, D., Software Prototyping, Formal Methods and
  1834.      VDM, Addison-Wesley, Reading, MA, 1988.
  1835.  
  1836. [5] Schwartz, J.T. et al, Programming with Sets: An Introduction to SETL,
  1837.      Springer-Verlag, New York, 1986.
  1838.  
  1839. INDEX
  1840.  
  1841. assignment statement .............. 16
  1842. block ............................. 18
  1843.                                   Page 30
  1844.  
  1845. boolean type ......................  2
  1846. butlast operator ..................  7,8,14
  1847. cardinality operator ..............  3,14
  1848. class definition .................. 10
  1849. classes ........................... 10
  1850. close statement ................... 13,17
  1851. commands .......................... 12-16
  1852. comments .......................... 18
  1853. concatenation operator ............  6
  1854. conditional statement ............. 13,16
  1855. default error return ..............  5,7,14
  1856. difference operator ...............  3,14
  1857. distributed union operator ........  3,14
  1858. domain operator ...................  5,14
  1859. domain restriction operator .......  5,14
  1860. domain subtraction operator .......  5,14
  1861. existential quantifier ............  4,14
  1862. exit command ......................  2,12,14
  1863. first operator ....................  7
  1864. for statement  .................... 13,16
  1865. function call  .................... 12,17
  1866. function definition ...............  9,13
  1867. generator .........................  4
  1868. hd operator .......................  7,14
  1869. help command ......................  2,12
  1870. identifiers  ......................  2
  1871. image operator ....................  5,14
  1872. inheritance ....................... 15,19
  1873. instantiation, class .............. 10,18,19
  1874. instantiation, struct .............  8,15
  1875. intersection operator .............  3,14
  1876. inverse operator ..................  6,14
  1877. i/o statement ..................... 13,17
  1878. integer type ......................  2
  1879. last operator .....................  7,8,14
  1880. len operator  .....................  7,8,14
  1881. load command  .....................  2,12
  1882. local variables ...................  9,13,15
  1883. logical conjunction ...............  2
  1884. logical disjunction ...............  2
  1885. logical negation ..................  2
  1886. main ..............................  9
  1887. map application ...................  5,14
  1888. map construction ..................  5,14
  1889. map enumeration  ..................  4,5,14
  1890. map update ........................  6,14
  1891. map2seq operator ..................  7,15
  1892. maps ..............................  4,14
  1893. membership operator ...............  3,14
  1894. modulo operator ...................  2
  1895. oneof operator ....................  4,14
  1896. open statement .................... 13,17
  1897. operators .........................  2
  1898. operator precedence ...............  2,8
  1899. overwrite operator ................  6,14
  1900. primitive types ...................  2
  1901. procedures ........................ 10
  1902. range operator ....................  5,14
  1903.                                   Page 31
  1904.  
  1905. readln statement .................. 13,17
  1906. real type .........................  2
  1907. return statement .................. 13,16
  1908. second operator ...................  7
  1909. seq2map operator ..................  7,15
  1910. sequence construction .............  6,14
  1911. sequence enumeration ..............  6,14
  1912. sequence selection ................  6,14
  1913. sequence range ....................  6,14
  1914. sequences .........................  6,14
  1915. set constructor ...................  3,4
  1916. set enumeration ...................  3,13
  1917. set range .........................  3,13
  1918. sets ..............................  3,13
  1919. statements ........................ 13,16
  1920. strings ...........................  8
  1921. structs ...........................  8,15
  1922. system commands ...................  2,12
  1923. the operator ......................  4,14
  1924. tl operator  ......................  7,14
  1925. transcript command ................  2,12
  1926. unary operators ...................  2,9
  1927. union operator  ...................  2,14
  1928. universal quantifier ..............  4,14
  1929. void ..............................  9
  1930. while statement ................... 13,16
  1931. writeln statement ................. 13,17
  1932.