home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / MISC / REC.ZIP / RECB.DOC < prev    next >
Encoding:
Text File  |  1986-12-01  |  40.6 KB  |  933 lines

  1.  
  2.  
  3.         Chapter 3.  The Pushdown List
  4.  
  5.     The pushdown list (PDL) in REC is the principal medium for 
  6. argument transmission among subroutines and operators.  Three pointers, 
  7. called px, py and pz are associated with it.  Px always points to the 
  8. address on the PDL where the last argument to come in starts, py points to 
  9. the next free location in the PDL (and thus py-px is the length of the top 
  10. argument) and pz points to the current end of the PDL.  In addition, there 
  11. are markers on both ends to prevent the excess removal of operands on 
  12. either end.
  13.  
  14.     Programming operations on the PDL requires becoming familiar
  15. with reverse Polish, or postfix notation, since all operands needed by
  16. a given operation must be present on the PDL before the operation can
  17. be performed and since operations are performed from left to right.  It is 
  18. well known that arithmetic expressions written in either prefix or postfix 
  19. notation require no parentheses.  Consider the following simple example:
  20.  
  21.             ('hello' T L;)
  22.  
  23.     This is a complete REC program which places the five-character
  24. string hello on the PDL, types it on the console and lifts it (erases it)
  25. from the PDL.  These operations are accomplished by the operators 'hello',
  26. T and L, respectively.  Next consider the program
  27.  
  28.         (3.5 pG * 2.5 pG * - 3.1415926 * # T L;)
  29.  
  30. This one computes the area of a circular ring of inner radius 2.5 units 
  31. and outer radius 3.5 units by squaring 3.5 [3.5 pG *], squaring 2.5 [2.5 
  32. pG *] and subtracting and multiplying by pi [- 3.1415926 *].  The result 
  33. is converted into an ASCII string by #, typed on the console by T and 
  34. erased from the PDL by L.  The combined operator pG places on the PDL a 
  35. new copy of the current top argument and the characters * and - are the 
  36. multiplication and subtraction operators, respectively.  Notice that at 
  37. least one blank or comma must separate the minus sign from the number that 
  38. follows in order for it to be considered the binary subtraction operator 
  39. rather than a unary minus sign affecting the number.
  40.  
  41.     Before proceeding to consider more examples of REC 
  42. programming, we introduce in detail a few operators and predicates 
  43. dealing only with the PDL:
  44.  
  45. Operator/Predicate        Function performed
  46.  
  47.     L        Operator, removes the last entry from the 
  48.             PDL. If it's    already empty, the error is 
  49.             noted and execution continues.
  50.  
  51.     =        Predicate, true if the last two entries on the
  52.             PDL have the same length and are composed of
  53.             the same sequence of bytes.  The last entry is
  54.             lifted regardless of the outcome of the 
  55.             comparison, the next-to-last entry will be 
  56.             lifted only if equality is established.  Note 
  57.             that since length is important, pure numerical 
  58.             equality doesn't yield a true result if the 
  59.             arguments are numerical data of different 
  60.             types (e.g. integer/floating point, 
  61.             single/double precision, short/long integer, 
  62.             etc.)
  63.  
  64.       number        Operator, enters the number in its binary form
  65.             into the PDL.  "number"  may be an instance of 
  66.             any of the following expressions, where [, ], 
  67.             * and | are the    same metasymbols used in 
  68.             Chapter 1, d is any decimal digit (0-9), n is 
  69.             a nonzero decimal digit (1-9) and e stands for 
  70.             the null string:
  71.  
  72.             Two-byte integers:
  73.                     [-n|d]
  74.                     [-|e]n[d]*
  75.  
  76.             Four-byte integers:
  77.                     [-0|0d][d]*
  78.  
  79.             Single precision floating point numbers:
  80.                     [-|e][d]*.[d]*
  81.                     [-|e][d]*.[d]*E[-|+|e][d]*
  82.                     [-|e]d[d]*E[-|+|e][d]*
  83.  
  84.             Double precision floating point numbers:
  85.                     [-|e][d]*.[d]*D[+|-|e][d]*
  86.                     [-|e]d[d]*D[+|-|e][d]*
  87.  
  88.             The terms "two-byte", "four-byte", "single" 
  89.             and "double precision" refer to the internal 
  90.             representation of the numbers, which require 
  91.             2, 4, 5 and 8 bytes, respectively. Note that 
  92.             all forms may be preceded by an optional 
  93.             minus sign, but not by a plus sign, which 
  94.             would be interpreted as the addition 
  95.             operator.  Expressed in words, the above 
  96.             forms mean the following, apart from the 
  97.             optional sign:  A two-byte integer is any 
  98.             single digit, a string of digits whose first 
  99.             digit is not zero or a minus sign followed by 
  100.             a string of digits the first of which is not 
  101.             0; a four byte integer is -0 or a string of 
  102.             two or more digits the first of which is 
  103.             always zero.  A single precision (SP) 
  104.             floating point number is signaled by the 
  105.             presence of a period (indicating the decimal 
  106.             point), the letter E followed by an 
  107.             optionally signed digit string, or both, 
  108.             except that if the decimal point is not 
  109.             present, at least one digit must appear for 
  110.             the E to be interpreted as part of a number.  
  111.             A double precision (DP) floating point number 
  112.             always has the letter D followed by an 
  113.             optionally signed and possibly empty digit 
  114.             string; again, in the absence of a period at 
  115.             least one digit to the left of the D is 
  116.             required for the presence of a numeric 
  117.             constant to be recognized.  The number on 
  118.             the right of the E or D (whose value is zero 
  119.             if the digit string is empty) is interpreted 
  120.             as a power of ten which multiplies the number 
  121.             represented by the digit string on its left. 
  122.             Examples:
  123.  
  124.                 0        Two-byte integer zero.
  125.                 00        Four-byte integer zero.
  126.                 -127        Two-byte number.
  127.                 01000001    Four-byte number.
  128.                 .        Single precision 0.
  129.                 .1E-15        Single precision number.
  130.                 4D200        Double precision number.
  131.                 3.14159265358D    Double precision number.
  132.                 -E3        Not a number, but three
  133.                         operators: -,  E and the
  134.                         two-byte integer 3.
  135.  
  136.             The syntax of floating point numbers is mostly
  137.             identical to that of FORTRAN's REAL and DOUBLE
  138.             PRECISION constants, the exceptions being that 
  139.             an initial + is not part of the number, that 
  140.             the period by itself yields a valid number (0) 
  141.             and that the digit string in the exponent may 
  142.             be empty.  Finally, the syntax allows no blanks 
  143.             or other characters within the string defining 
  144.             a constant; any character not allowed by the 
  145.             above possibilities terminates the conversion 
  146.             and compilation of the number and is preserved 
  147.             and compiled as the next operator or predicate 
  148.             in the program.
  149.  
  150.     %        Operator, converts the top argument to the next
  151.             lower type, where the order, from greater on 
  152.             down is double precision/single precision/four-
  153.             byte integer/two-byte integer/one-byte argument
  154.             /null string.  Arguments whose size is not 0, 
  155.             1, 2, 4, 5 or 8 remain unchanged and cause an 
  156.             error to be noted.  DP to SP and SP to 4-byte 
  157.             integer conversions may cause overflow, 
  158.             indicated by the largest number representable 
  159.             in the corresponding format.  Integer to 
  160.             integer conversions are always done by removal
  161.             of the appropriate number of high-order bytes.
  162.             Null strings are left unchanged.  This operator 
  163.             is often used to generate single ASCII control 
  164.             characters.  For instance, a single carriage 
  165.             return may be generated by the two-operator 
  166.             sequence 13%.
  167.  
  168.     \        Operator, converts the top argument to the next
  169.             higher type; see the above description of % for
  170.             the ordering of operand types.  \ is also 
  171.             restricted to numeric types.  Conversion of an
  172.             integer type to another integer type is 
  173.             accomplished by appending the appropriate 
  174.             number of zeros on the left, with no sign 
  175.             extension (one and two-byte numbers are 
  176.             treated as unsigned integers); conversion of 
  177.             long integer to single precision floating 
  178.             point does take the sign of the integer into 
  179.             account.  Double precision operands are left 
  180.             unchanged.
  181.  
  182.     |        Operator, concatenates the next-to-last 
  183.             argument with the last argument, forming a 
  184.             new argument which replaces both.  
  185.  
  186.     R        Operator, reads a character from the keyboard 
  187.             into the top of the PDL.  It also provides a 
  188.             convenient way to introduce a pause into a 
  189.             program by use of the combination RL, as R 
  190.             will wait until a key is pressed if a character 
  191.             is not already waiting to be read.  Notice 
  192.             that R does not echo to the console the 
  193.             character which it reads.
  194.  
  195.     T        Operator, types on the console the contents of 
  196.             the top of the PDL, leftmost (lowest-addressed) 
  197.             byte first; its argument would normally be an 
  198.             ASCII character string.  It leaves its argument 
  199.             unchanged.
  200.  
  201.     'x' or "x"    Operator, places the string x of ASCII 
  202.             characters on the PDL.  x may contain nests of 
  203.             quoted strings such that the delimiting quotes 
  204.             alternate between " and '.  The null string 
  205.             may be entered into the PDL with '' or "".  
  206.             Other examples follow:
  207.  
  208.                 "quoted string"
  209.                 'another quoted string'
  210.                 'nested "quoted 'string'"'
  211.                 "another 'nested "quoted" string'"
  212.  
  213.             The nesting feature prevents the characters ' 
  214.             and " to be quoted singly; a single instance 
  215.             of them may be placed on the pushdown list by 
  216.             "''"% and '""'%, respectively.  Control 
  217.             characters such as carriage returns and line 
  218.             feeds are included in quoted strings if the 
  219.             opening quote appears on one line and the 
  220.             closing quote on another; other control 
  221.             characters are best introduced by stating
  222.             their numeric value and restricting to one 
  223.             byte if necessary.  For example, 26% leaves 
  224.             a single control-Z character on the PDL; 2573 
  225.             leaves a two-character string consisting of 
  226.             the control characters for carriage return 
  227.             and line feed.
  228.  
  229.     m        Operator, moves the argument at the top of 
  230.             the PDL to the high end of the memory space 
  231.             defined for the PDL (which constitutes thus 
  232.             a complementary PDL) and writes the size (in 
  233.             bytes) of the argument moved in the two bytes 
  234.             just below its new location; pz is updated to 
  235.             reflect the new high limit of available PDL 
  236.             space.  The error flag is set and a null 
  237.             string is moved if the normal end of the PDL
  238.             is empty.
  239.  
  240.     n        Operator, retrieves the last argument moved to 
  241.             the complementary PDL, making it the new top 
  242.             argument on the low or normal end of the PDL.  
  243.             An error is indicated in the error flag if the 
  244.             complementary PDL is empty, but a null string 
  245.             is nevertheless placed on top of the normal PDL.
  246.  
  247.     @x        Predicate which causes execution of the 
  248.             subroutine whose name is the ASCII character 
  249.             x.  If x is the character @, this predicate 
  250.             uses the top PDL argument, which should be one
  251.             or two bytes long, corresponding to the name
  252.             or address, respectively, of the subroutine 
  253.             whose execution is desired.  If the subroutine 
  254.             called by this predicate has NOT been defined 
  255.             in REC, it will return as though it were a
  256.             false predicate, so that (@@) should be used
  257.             in this case.  @@ lifts its argument from the
  258.             PDL before starting execution of the 
  259.             subroutine it invokes.
  260.         
  261.     With the foregoing operators and predicates, we may now write 
  262. a few programs which put together a line typed in at the keyboard, 
  263. with various editing options.  The simplest one is the following:
  264.  
  265.         [read string iteratively]
  266.         {(R13%=;T|:) J
  267.          (''@J 2573TLTL;)}
  268.  
  269. The main program places a null string on the PDL and calls subroutine 
  270. J (which is done by the predicate @J, as described in the previous 
  271. chapter) which reads, types and concatenates each incoming character 
  272. to the previous top of the PDL, until it reads a carriage return 
  273. character, which causes a return to the main program.  The main 
  274. program then types a carriage return, a line feed and the string of 
  275. characters collected by subroutine J; arguments are lifted after 
  276. being typed and the program terminates.
  277.  
  278.     The above procedure may also be stated recursively:
  279.  
  280.         [read string recursively]
  281.         {(R13%=;T@J|;) J
  282.          (''@J 2573 TLTL;)}
  283.  
  284.         [read string recursively - another version]
  285.         {(R13%='';T@J|;) J
  286.          (@J 2573 TLTL;)}
  287.  
  288. The two versions differ in that subroutine J in the second one is 
  289. entirely self contained in that it provides the null string necessary 
  290. to have n+1 operands available for the n concatenations | which will 
  291. occur when n characters followed by a carriage return are read; the 
  292. subroutine in the first version relies on the calling program to 
  293. provide this null string.
  294.  
  295.     The recursive version is more appropriate for the addition of 
  296. line editing features.  Consider for example a program that allows 
  297. for erasure of the rightmost exposed character by using the backspace:
  298.  
  299.     [BACKSPACE to erase character and reposition cursor]
  300.     {(R8%=8%; 13%=''; T@J8%=L8%T' 'TLTL: |;) J
  301.      (@J 8%=: 2573TLTL;)}
  302.  
  303. When a backspace is typed, subroutine J will lift the rightmost 
  304. character from the PDL and backspace, overwrite with a blank and 
  305. backspace again on its copy on the screen (performed by the sequence 
  306. 8%=L8%T' 'TLTL); it will return a backspace if a backspace is given 
  307. as the first character or if more backspaces are given in succession 
  308. than the number of characters collected so far on the PDL.  The main 
  309. program repeats the attempt to read a line if it receives a backspace 
  310. on return from J.
  311.  
  312.     The following program is a variant of the above, except that 
  313. it uses the rubout character "del" and echoes the rubbed out 
  314. characters in reverse.  This version would be useful on a hardcopy 
  315. terminal, where backspacing and overprinting is impractical.
  316.  
  317.     [DEL to erase a character with echo]
  318.     {(R127%=127%;13%='';T@J127%=TL:|;) J
  319.      (@J 127%=: 2573TLTL;)}
  320.  
  321.     The following two programs allow for canceling any characters 
  322. gathered so far by use of the ASCII control characters NAK 
  323. (control-U) and CAN (control-X) which we denote by ^U and ^X.  The 
  324. first program, on detection of ^U, lifts one by one all characters 
  325. gathered, types the character #, repositions the cursor or print 
  326. mechanism of the console to the beginning of the next line and 
  327. resumes the reading of a line from the beginning.  The second program 
  328. blanks out the characters written so far, returning the cursor or 
  329. print mechanism to the beginning of the same line, lifting characters 
  330. from the PDL as it backspaces.  This second program will of course be 
  331. better suited to a screen-type console, whereas the first one will be 
  332. more appropriate for use with a hard-copy terminal.  In both programs 
  333. the line-gathering process terminates when a carriage return is typed 
  334. at the console; the resulting line is then typed out on a new line.
  335.  
  336.     [^U to redo a line from the beginning]
  337.     {(R21%=21%;13%='';T@J21%=L21%;|;) J
  338.      (@J 21%='#'TL2573TL: 2573TLTL;)}
  339.  
  340.     [^X to cancel a line - with rubouts]
  341.     {(R24%=24%;13%='';T@J24%=8%T' 'TLTL24%;|;) J
  342.      (@J 24%=: 2573TLTL;)}
  343.  
  344.     Another editing option is the capability to retype the 
  345. characters gathered so far.  The next two programs accomplish this, 
  346. in iterative and recursive fashions, respectively.  Both type a 
  347. number sign # on detection of control-R (whose decimal value is 18) 
  348. and move all characters gathered so far to the complementary PDL, in 
  349. order to type them out from the earliest character typed in to the 
  350. latest, returning them to the low PDL in the process.  In the 
  351. recursive version this is done by the sequence m@RnT in subroutine R; 
  352. in the iterative version it is done by ''m(''=;m:) ''(n''=;T:).  Both 
  353. programs require an initial null string on the PDL which is used as a 
  354. marker to signal the end of the iteration of (''=;m:) in the first 
  355. program and of the recursion in the second program; this null string 
  356. is removed from the PDL by the last L in the main program.
  357.  
  358.     [^R to retype a line - iterative version]
  359.     {(R18%=18%;13%='';T
  360.       (@J18%='#'TL2573TL''m(''=;m:)''(n''=;T:):;)
  361.        |;) J
  362.      (''(@J 18%=: 2573TLTLL;);)}
  363.  
  364.     [^R to retype a line - recursive version]
  365.     {(''='#'TL2573TL'';m@RnT;) R
  366.      (R18%=18%;13%='';T(@J18%=@R:;)|;) J
  367.      (''(@J 18%=: 2573TLTLL;);)}
  368.  
  369.     As a final example of line editing, we present a program 
  370. which incorporates the backspace, control-X and control-R editing 
  371. options:
  372.  
  373.     [combine backspace, ^X and ^R]
  374.     {(''='#'TL2573TL'';m@RnT;) R
  375.      (R18%=18%;24%=24%;8%=8%;13%='';
  376.         T(@J18%=@R:;)
  377.             8%=L8%T' 'TLTL:
  378.             24%=L8%T' 'TLTL24%;|;) J
  379.      (''(@J 18%=:24%=:8%=: 2573TLTLL;);)}
  380.  
  381.     We continue now our discussion of operators which take their 
  382. arguments from the PDL with a description of the arithmetic/logical 
  383. operators.  A feature common to the operators +, - and * is that they 
  384. require two arguments and return one result in place of the original 
  385. two. The operator / returns two values if both arguments are of 
  386. numeric types whose size doesn't exceed 4 and one if at least one of 
  387. them is of floating point type (size 5 or 8).  If arguments of 
  388. different sizes are given to +, -, *, / or the predicate N, 
  389. conversions of the argument of smaller size to larger sizes will 
  390. occur until the sizes match, and then the operation will be 
  391. performed.  If the top argument is not a numeric type (size 0, 1, 2, 
  392. 4, 5 or 8), the error flag is set, the operation is abandoned and the 
  393. PDL remains unchanged.  If the top argument is of numeric type but 
  394. the next is not, the operation will be abandoned after setting the 
  395. error flag and the top argument is lost, as it is removed from the 
  396. PDL before testing the next argument and is not replaced in case of 
  397. error.
  398.  
  399. Operator/Predicate        Function performed
  400.  
  401.     +        Operator.  If either argument is the null 
  402.             string, the result is the other argument; a 
  403.             null remains if both are null.  If both 
  404.             arguments are one byte long, + returns the 
  405.             logical sum (or) of its arguments (i.e., a 
  406.             bit of the result is 1 if either of the 
  407.             corresponding bits in the arguments is 1, 0
  408.             if both are 0). If either argument is of size 
  409.             2 or greater, the result will be the 
  410.             arithmetic sum of the two arguments expressed 
  411.             in the type of the larger of the two arguments.
  412.  
  413.     -        Operator.  If the top argument is the null 
  414.             string, the result is the other argument; if 
  415.             the lower argument is null, the top argument 
  416.             is returned if its size is 1 and its negative 
  417.             otherwise.  If both arguments are 1 byte 
  418.             items the result will be their logical 
  419.             exclusive or (in which a given bit of the 
  420.             result is 1 if the corresponding bits of the
  421.             arguments are different, 0 otherwise); for 
  422.             arguments of larger sizes this operator 
  423.             returns the result of subtracting the top 
  424.             argument from the next (e.g., 3,5- yields -2).
  425.  
  426.     *        Operator.  Returns a zero of the size of the 
  427.             longer argument if the other argument is the 
  428.             null string, a null string if both are null.  
  429.             If the size of both arguments is 1, the result 
  430.             is the logical product (and) of the operands.  
  431.             All other cases result in the arithmetic 
  432.             product of the operands performed and 
  433.             expressed in the type of the longer operand.
  434.  
  435.     /        Operator.  Returns two zeros of the size of 
  436.             the top argument if the lower one is the null 
  437.             string; in all other cases it attempts to 
  438.             divide the lower argument by the top.  Two one- 
  439.             byte arguments always yield two-byte results; 
  440.             integer divisions leave two results, the 
  441.             remainder and the quotient (with the quotient 
  442.             as top argument) whereas floating point
  443.             divisions leave only the quotient.  Two-byte
  444.             operand divisions are unsigned, results of 
  445.             four byte integer divisions reflect the signs 
  446.             of the operands.  Integer division by zero 
  447.             leaves the arguments unchanged (except for 
  448.             one-byte operands which will have been 
  449.             converted to two-byte integers); floating-point 
  450.             division by zero returns the largest 
  451.             representable number of the corresponding type.
  452.  
  453.     N        Predicate. It requires two arguments, both of 
  454.             which are lifted regardless of the logical 
  455.             outcome.  If both arguments are null, N is 
  456.             true.  Otherwise, conversions are performed on 
  457.             the smaller argument if the sizes are 
  458.             different; size one operands make N true if 
  459.             their logical product is nonzero and false 
  460.             otherwise; N is true for other sizes if the
  461.             lower argument is less than or equal to the 
  462.             top argument and false otherwise.  (Note that 
  463.             two-byte integers are treated as unsigned 
  464.             operands in the comparison.)
  465.  
  466.     ~        Operator, requires one numeric argument.  
  467.             Leaves null strings unchanged, complements or 
  468.             negates its argument if its size is one or 
  469.             greater than one, respectively.  The error 
  470.             flag is set and the operation is abandoned if 
  471.             the argument is non numeric.
  472.  
  473.     ^        Operator.  Mostly used to increment the top
  474.             argument by one.  The top argument must be of
  475.             a valid numeric operand size; null strings are
  476.             left unchanged.  ^ places a 1 of the size of 
  477.             its operand on the PDL and uses the + operator 
  478.             to complete its operation.
  479.  
  480.     d        Predicate.  Requires one numeric argument.  If 
  481.             d's argument is the null string or a zero of 
  482.             any size, it gets lifted and the truth value 
  483.             of the predicate is false.  Otherwise d 
  484.             subtracts the value 1 of the appropriate size 
  485.             from its operand and returns with the value 
  486.             true.
  487.  
  488.     O        Predicate.  True if the argument on the PDL is 
  489.             an ASCII string satisfying the syntax of 
  490.             numbers given above; the result is the same 
  491.             number converted to the corresponding binary 
  492.             representation.  Both the null string and a 
  493.             single minus sign are accepted and convert to 
  494.             a two-byte zero.  O is false if termination of 
  495.             the number conversion algorithm doesn't occur 
  496.             at the end of the argument, in which case the 
  497.             argument is left unchanged.
  498.  
  499.     #        Operator.  Converts a numeric argument to a 
  500.             decimal ASCII string representation of the 
  501.             argument's value.  The null string always 
  502.             yields a single ASCII 0, results from 
  503.             four-byte integers always contain an extra 
  504.             leading 0, single-precision floating point 
  505.             operands always produce a string containing a 
  506.             decimal point and double-precision arguments 
  507.             always produce a decimal point and a D-prefixed 
  508.             exponent of ten in their result.  Nonnumeric 
  509.             arguments cause the error flag to be set and 
  510.             the operation to be abandoned with no changes 
  511.             to the PDL.
  512.  
  513.     &        Operator, exchanges the top two arguments, 
  514.             regardless of their sizes.
  515.  
  516.     pG        A combination of the operators p and G (to be 
  517.             described in detail later on) whose effect is 
  518.             to place on the PDL a duplicate of the top 
  519.             argument.
  520.  
  521.     Two examples will illustrate the use of the operators and 
  522. predicates just described.  In the first example a recursive 
  523. factorial subroutine is driven by its main program to produce 
  524. factorials for the integers 0 to 12 in four-byte arithmetic; in the 
  525. second, Newton's method for roots of equations is applied to the 
  526. problem of extracting the square root of a non-negative number.
  527.  
  528.  
  529.     [4-byte factorial of an integer, defined as follows:
  530.         n! = n*(n-1)! for n>0
  531.         0! = 1            ]
  532.     {(pG-01N'Error'TL;00=01;pGd@F*;) F
  533.      (00 (013=;pG#TO'!='TL@F#TL2573TL^:);)}
  534.  
  535.  
  536.     [Square root by Newton's method]
  537.     {
  538.      [collect a string from the console, with editing options]
  539.      (''='#'TL@c'';m@RnT;) R
  540.      (R18%=18%; 24%=24%; 8%=8%; 13%='';
  541.       T(@J18%=@R:;) 8%=L8%T' 'TLTL: 24%=L8%T' 'TLTL24%; |;) J
  542.  
  543.      [prompt for input, deliver the input string]
  544.      ('>'TL''(@J 18%=: 24%=: 8%=: @c&L;);) L
  545.  
  546.      [type carriage return and line feed]
  547.      (2573TL;) c
  548.  
  549.      [Newton iteration routine: requires the number C whose 
  550.       root is sought to be on the complementary PDL and an 
  551.       approximation X to the root on the PDL]
  552.      (pGpGnpGm & / + 0.5 *          [yields new approx. (X+(C/X))/2.]
  553.       pGm -        [save approx. and compute difference with previous]
  554.       (pG0.N~;;)        [make absolute value of the difference]
  555.       npGm/             [compute error relative to new approx]
  556.       1.E-8Nn;           [exit if rel. err. below this threshold]
  557.       npG#TL@c:) N        [type current approximation and repeat]
  558.  
  559.      [Main program: get input, check validity, get root]
  560.      (@L (O)L 'Not a number'TL@c:
  561.       0.+                 [force argument to floating point]
  562.       pG0.NL;               [exit if input is 0 or negative]
  563.       pGm@N                     [set up arguments, call N]
  564.       'sqrt('TLn#TL')='TL#TL@c:) }          [type result, repeat]
  565.  
  566.  
  567.     Items to be noted about the factorial subroutine are that it 
  568. only gives valid results for input values between 0 and 12 (since 13! 
  569. is greater than 2 147 483 647, the largest positive integer 
  570. representable in the four-byte format), and that it rejects negative 
  571. values of its argument. The square root program illustrates the use 
  572. of parenthesis to negate a predicate [(O) in the first line of the 
  573. main program], in this case used to reject input strings that don't 
  574. translate to a numeric value.
  575.  
  576.     Subroutine N of the square root program shows how reverse 
  577. Polish notation is used to express arithmetic operations.  Given that
  578. the approximation X to the root is on the PDL and that the number C 
  579. whose root is sought is on the PDL complement, the sequence pGpGnpGm& 
  580. leaves the set of operands [X, X, C, X] on the PDL (listed from 
  581. deepest to topmost) and C on the PDL complement; the operators /, +,
  582. 0.5 and * leave successively the operands [X, X, C/X], [X, X+(C/X)],
  583. [X, X+(C/X), 0.5] and [X, 0.5*(X+(C/X))] on the PDL.  The last result
  584. is the new approximation obtained by application of Newton's formula.
  585.  
  586.     The last set of PDL operators and predicates concerns mostly 
  587. the movement of data and the manipulation of addresses.  These 
  588. operators and predicates are the following:
  589.  
  590. Operator/Predicate        Function performed
  591.  
  592.     H        Predicate.  True if the top argument is a 
  593.             hexadecimal string in ASCII (containing only 
  594.             the decimal digits 0-9 and the letters A-F), 
  595.             in which case it is converted to binary.  
  596.             Conversion of an n-digit string produces an 
  597.             |_(n+1)/2_|-byte value stored in Intel 
  598.             convention (least significant byte in the 
  599.             lowest-addressed location); |_x_| is the 
  600.             greatest integer not exceeding x.  Notice 
  601.             that leading zeros in the string affect the 
  602.             size of the result.  Arguments causing H to 
  603.             become false are left unchanged.  The null 
  604.             string causes H to be true, but is left 
  605.             unchanged.
  606.  
  607.     !        Operator.  Performs the conversion inverse to 
  608.             H.  Given an n byte value on the PDL (assumed 
  609.             to be stored following Intel convention) it 
  610.             produces the corresponding 2n character 
  611.             hexadecimal string in ASCII (with leading 
  612.             zeros if necessary).
  613.  
  614.     p        Operator, places the two 2-byte values px and
  615.             py-px on the PDL; that is, the origin and the
  616.             size of the top argument.
  617.  
  618.     l        Operator. Places on the PDL the value of pz,
  619.             which is the current high limit of the PDL as
  620.             well as the address of the cell containing the
  621.             size of the last argument entered by the 
  622.             operator m on the complementary PDL.
  623.  
  624.     c        Operator.  Given a 2-byte integer n on the 
  625.             PDL, c creates in its place a block of n 
  626.             bytes and leaves as top argument a pointer 
  627.             to the beginning of this block (a two-byte 
  628.             address).  If n is 2 or larger, the value 
  629.             n-2 is stored in the first two bytes of the 
  630.             block, an arrangement useful if the block is 
  631.             to be used as a buffer; no other initialization 
  632.             is made.
  633.  
  634.     G        Operator.  Requires two 2-byte values on the 
  635.             PDL, an origin (lower) and a value n 
  636.             representing a size (top).  It replaces both 
  637.             with an argument of n bytes copied from the n 
  638.             locations starting at the given origin.  Thus 
  639.             pG duplicates the top argument and '080'HpGG 
  640.             gets the 128 bytes starting at address 128 
  641.             (absolute on the 8085; data segment relative 
  642.             on the 8086).  On the 8086 the origin may be a 
  643.             four-byte value, in which case the lower bytes 
  644.              contain the address of the block to move and
  645.             the higher two bytes contain the segment base 
  646.             of the block, allowing thus access to the 
  647.             entire address space of the 8086.
  648.  
  649.     g        Operator.  Given an address as the top 
  650.             argument, it fetches the byte stored at that 
  651.             address and places it on the PDL.  The 
  652.             address is not removed, but remains as the 
  653.             lower argument.  Four-byte addresses are 
  654.             allowed in the 8086 version, as described 
  655.             above in connection with G.
  656.  
  657.     u        Operator.  Identical to g except that it 
  658.             increments by one the address operand after 
  659.             fetching the byte stored at the given address.
  660.             Only the address in the lower two bytes is 
  661.             incremented when a 4-byte address is given 
  662.             in the 8086 version.
  663.  
  664.     y        Operator.  Similar to u, but a word (two 
  665.             bytes) is fetched and the address is 
  666.             incremented by two.  The same provisions 
  667.             apply regarding 4-byte arguments in the 8086 
  668.             version.
  669.  
  670.     S        Operator. Expects two arguments on the PDL, a 
  671.             datum (lower) and an address (top).  It stores 
  672.             the datum forward from the designated memory 
  673.             location and erases both arguments from the 
  674.             PDL when done.  The address argument may be a 
  675.             4-byte item in the 8086 version, as described 
  676.             above under G.
  677.  
  678.     v        Operator.  Given two arguments on the PDL, an 
  679.             address (lower) and a datum (top), it stores 
  680.             the datum forward from the designated memory 
  681.             location, erases it, and adds the size of the 
  682.             datum to the address, which remains on the 
  683.             PDL.  Four-byte items are allowed as addresses 
  684.             in the 8086 version.
  685.  
  686.     s        Operator, stores into an area of limited size.
  687.             Requires two arguments, a datum (lower) and an
  688.             address (top).  If the address is 'org', s 
  689.             will store the datum beginning at org+2 if its 
  690.             size does not exceed the value stored at the 
  691.             word pointed to by org (notice the connection 
  692.             with operator c above); no data is stored at 
  693.             all if all will not fit and the error flag 
  694.             will be set in this case.  In either event 
  695.             both arguments are lifted.  As with the 
  696.             preceding operators, the address may be a 
  697.             four-byte item in the 8086 version of REC.
  698.  
  699.     P        Operator, stores into a buffer and notes 
  700.             length.  Similar in arguments and operation to 
  701.             s.  The size of the datum will be stored at 
  702.             the word whose address is org+2 and the datum 
  703.             itself will be stored starting at org+4 if it 
  704.             will fit, that is, if its size plus 2 doesn't 
  705.             exceed the buffer size stored at the word 
  706.             pointed to by org.  Both arguments are lifted 
  707.             if the data fits, but only the address will be 
  708.             lifted if it does not.  The error flag is set 
  709.             in the latter case.  Four-byte addresses are 
  710.             also allowed in the 8086 version.
  711.  
  712.     r        Operator.  Given an address as top argument, r
  713.             replaces it by the two-byte value at which it
  714.             points.  Four-byte addresses composed of an
  715.             address in the lower two bytes and a segment
  716.             base in the upper two bytes are allowed by the
  717.             8086 version.
  718.  
  719.     h        Operator.  Stores, restores or eliminates 
  720.             stored machine registers.  It requires a 
  721.             single null argument, an argument consisting 
  722.             of a pointer to the machine stack or two 
  723.             arguments, the lower one a pointer to the 
  724.             stack an the top one a two-byte zero.  The 
  725.             first use of h must provide a single null 
  726.             string, whereby h pushes onto the stack of the 
  727.             8085 the registers PSW, HL, DE and  BC,
  728.             leaving the value of the machine's stack 
  729.             pointer SP (which points to the last of the
  730.             stacked values) in place of the null argument.
  731.             If h is given a non-zero two-byte argument, it
  732.             assumes it is the value of SP pointing to the
  733.             location on the machine stack at which it 
  734.             stored previously the machine registers, which 
  735.             it then proceeds to unstack, leaving out of 
  736.             reach anything else which may have been 
  737.             stacked after the corresponding ''h call; it 
  738.             lifts also the SP value given on the PDL.  If 
  739.             the top argument is a two-byte zero, h will 
  740.             assume that an SP value is the next argument, 
  741.             and uses it to restore SP to the value prior 
  742.             to the first use of ''h, that is, it lifts 
  743.             the stacked register values from the machine 
  744.             stack without restoring them; it also lifts 
  745.             both given arguments from REC's PDL.  On the 
  746.             8086, the stack pointer argument is a 4-byte 
  747.             value consisting of the SP value in the lower 
  748.             two bytes and the Stack Segment base in the 
  749.             upper two bytes.  The registers saved are the 
  750.             flags, AX, BX, CX, DX, BP, SI, DI, DS and ES.
  751.  
  752.     ?        Predicate.  False if no error has been 
  753.             recorded in the error flag, true if a notation
  754.             exists.  In the latter case, the two-byte 
  755.             value of the flag is placed on the PDL.  This
  756.             value is the address of the last location from
  757.             which the error notation routine was called.
  758.             No indication is given as to how many errors
  759.             have occurred if this predicate is true.  The
  760.             error flag is reset after being consulted.
  761.  
  762.     Before proceeding to show examples of this last group of 
  763. operators and predicates, a few facts will be mentioned with regard 
  764. to the CP/M operating system.
  765.  
  766.     In CP/M, a program residing on a disk is called into 
  767. execution by means of a "command line", consisting of the program 
  768. name followed by a space and any parameters that the program is to 
  769. receive.  This parameter string or "command line tail" is passed on 
  770. to the program in the buffer starting at address 080H (hexadecimal); 
  771. address 080H contains the character count of the string and the 
  772. string is stored forward from address 081H.  If the first two 
  773. parameters of the command line tail are files, they are parsed and 
  774. placed forward from locations 05CH and 06CH.  A file name consists of 
  775. a disk identifier, a name of up to 8 characters and an extension of 
  776. up to 3 characters; omission of the disk designator causes a default 
  777. of @ (which indicates the currently logged disk unit) before 
  778. conversion to the internal disk-numbering scheme, the other two parts 
  779. are blank filled on the right.  When no filenames are identified, the 
  780. file name buffer at 5CH is certain to contain eleven blanks starting 
  781. at 05DH.
  782.  
  783.     When REC is called into execution and finds a file name at 
  784. 05CH, it will attempt to open it, and read, compile and execute 
  785. a program from it.  Any parameters following this file name are 
  786. treated as a command line tail to be received by the REC program at 
  787. the beginning of its execution.  For example, the command line
  788.  
  789.     rec80 sample file.one b:file.two
  790.  
  791. causes the program from file SAMPLE.REC to be compiled and executed;
  792. this compiled program will have available to it the file name FILE.ONE
  793. expanded and stored in the buffer at 5CH, the file name B:FILE.TWO 
  794. expanded and stored in the buffer at 6CH and the command line tail
  795. "FILE.ONE B:FILE.TWO" starting at 81H with the character count (19) in
  796. location 80H.  The program from file SAMPLE may access this 
  797. information through the operators given above, as illustrated in the 
  798. following examples.
  799.  
  800.     [make a buffer in which to save the second file name
  801.      and save it; type and return the buffer's address]
  802.     (33 c pG '05D'H 12G & S ! T H;) M
  803.  
  804. In this example, 33c creates a 33-byte buffer and its address; the pG 
  805. which follows makes a copy of the address to be used later by the 
  806. operator S; '05D'H12G copies the 12-byte expanded file name to the 
  807. PDL, & exchanges data and address for S and S stores the 12 data bytes
  808. starting at the beginning of the 33-byte buffer. !TH converts the 
  809. address to ASCII, types it and restores is to binary.  The reason 
  810. behind making a longer buffer is that CP/M requires a "file control 
  811. block" (FCB) for its operation on disk files; prior to opening a file 
  812. the last 21 bytes of the FCB should be 0.  One way of initializing 
  813. the rest of an FCB is illustrated by the next subroutine:
  814.  
  815.     [clear the upper 21 bytes of an FCB, given its
  816.      address; leave the original address]
  817.     (pG 12 + 7m (n d m '000000'H v:;)L;) C
  818.  
  819.     This subroutine uses pG to ensure a copy of the original 
  820. address is left on the PDL upon completion.  12+ adds 12 to the 
  821. address, which is the location forward from which we want to store 
  822. zeros.  7m sets up a counter in the PDL, and a loop starts.  The 
  823. sequence n d m fetches the counter, decrements it and returns it to
  824. the PDL complement (if not zero), '000000'H makes a three-byte binary 
  825. zero and v stores it forward from the current address, which it 
  826. updates (adding three to it in this case) after storing.  Notice that 
  827. d in the inner loop will be true 7 times so that v will store the 21 
  828. required zeros.  The final L erases the address left over from the 
  829. last execution of v.
  830.  
  831.     As an example of how the operators g and u may be used, 
  832. consider the following subroutines.
  833.  
  834.     [Returns the address of the first nonblank character between
  835.      two addresses, searching from highest to lowest]
  836.     (& m (g (" "=) nL; (d) n; pG n & =; m:) ;) <
  837.  
  838.     [Similar to the previous routine, searching from lowest to
  839.      highest]
  840.     (m (u (" "=) dnL; pG n & =; m:) ;) >
  841.  
  842. In both subroutines the top PDL argument is assumed to be the higher 
  843. address; the argument next to the top should be the lower address.  
  844. In the first subroutine the address left by g is explicitly 
  845. decremented, whereas in the second the operator d is used only when a 
  846. nonblank character is found.  Operator & is used before predicate = in
  847. both subroutines to retain the limiting address of the search (the 
  848. lowest address in the first case and the highest in the second); 
  849. recall that predicate = always erases at least the top argument.
  850.  
  851.     Finally we exhibit an example in which l, y, s, P and r are 
  852. used:
  853.  
  854.     [Execution of s and P, with diagnostics]
  855.     {(N n s;) s
  856.      (2- N n P;) P
  857.      (&mm p&L n lyGr & @@; n "Datum too big" TL)} Q
  858.  
  859. Subroutine Q must receive three arguments:  the two required by s or 
  860. P and the letter s or the letter P as the top argument.  The first 
  861. action taken is to exchange the letter and the buffer address and send
  862. both to the PDL complement [&mm].  The length of the datum to be 
  863. stored is next placed on the PDL and the name of the subroutine to be 
  864. called is retrieved [p&Ln].  The combination lyG puts on the normal 
  865. end of the PDL a copy of the last argument sent to the PDL complement,
  866. which in this case is the buffer address; r replaces this address with
  867. its contents, i.e., leaves on the PDL the length of the buffer 
  868. (assuming it was created by operator c).  & exchanges this value with 
  869. the given letter and @@ calls the subroutine whose name is that 
  870. letter.  If the letter is s, the length of the datum is tested 
  871. against the buffer size, and if the former is less than or equal to 
  872. the latter, the buffer address is retrieved and the datum is stored
  873. [Nns]; if the letter is P, 2 is subtracted from the buffer size (since
  874. P requires two bytes from the buffer to store the datum's length) and
  875. a comparison is performed before retrieving the address and executing
  876. operator P.  If in either s or P the comparison turns out to be false,
  877. predicate @@ becomes false, the address is retrieved and an error 
  878. message is sent to the console; both datum and buffer address remain 
  879. on the PDL, but subroutine Q terminates logically false.
  880.  
  881.     One more item worth noting in the above subroutine is the use 
  882. of lyG, which although it produces results identical to the 
  883. combination npGm, it generates less movement of bytes on the PDL, 
  884. especially when the argument being copied is several bytes long.
  885.  
  886.     The last group of operators which take their arguments from 
  887. the PDL is composed of input and output operators.
  888.  
  889.      Operator            Function performed
  890.  
  891.     t        Operator.  Given an address "org" (as top 
  892.             argument) and a length "l" (as lower 
  893.             argument), t displays on the console the 
  894.             string of l characters stored in memory 
  895.             starting at address org.  Both arguments are 
  896.             lifted from the PDL.  Notice that T is 
  897.             equivalent to the operator pair pt; t is more 
  898.             often used in combination with q, an operator
  899.             described in the next chapter.
  900.  
  901.     W        Operator whose arguments are identical to 
  902.             those required by t, but which sends the 
  903.             character string described by the argument to 
  904.             the device logged in the operating system as 
  905.             the list device (the LST: device of CP/M; 
  906.             usually a printer).  W also removes both of its
  907.             arguments from the PDL after using them.
  908.  
  909.     i        Operator.  Given an argument on the PDL whose 
  910.             least significant byte represents the number 
  911.             of one of the computer's communication ports,
  912.             i reads in a byte from that port, which it 
  913.             leaves on the PDL as top argument.  The 
  914.             original argument stays on the PDL so that it
  915.             may be reused after disposing of the byte read 
  916.             by i.
  917.  
  918.     o        Operator requiring two arguments, the lower 
  919.             one such that its least significant byte is 
  920.             the number of a port and the top a byte to 
  921.             be written to that port.  o outputs the given 
  922.             byte to the indicated port and lifts the byte 
  923.             from the PDL.  The port number stays on the 
  924.             PDL, facilitating multiple outputs to the same
  925.             port.
  926.  
  927.     It should be clear that operators i and o afford the user 
  928. detailed control of the peripheral resources of the computer, but for 
  929. the same reason its use results in REC programs which are extremely 
  930. dependent on the specific configuration of the computer for which 
  931. they are written; consequently these two operators have not been
  932. used very frequently.
  933.