File PPLV53.TX (text file)

Directory of image this file is from
This file as a plain text file


Eric Roberts September 15, 1974 PPL Version 53 - Editing Summary During the past summer, major revisions have been undertaken in the PPL system, and considerable improvements have been made in several aspects of the language. As such, version 53 differs substantially from version 51 which preceded it at Harvard. This paper describes the changes that have been made since the last editing summary was produced for Version 51. These changes have been reflected in the preparation of revised texts for the PPL User's Manual by Ed Taft and Tim ___ ______ ______ Standish and Standish's Introduction to PPL Programming ____________ __ ___ ___________ primer. New editions of each of these texts are currently being printed and will be available at the beginning of the fall term. These manuals are updated to include the features of Version 53, as well as documentation for some features not yet implemented in this version, particularly the new editing system. These incompatibilities are noted in section VII of this summary. Over the past year, Chuck Prenner and Alfred Spector have implemented a new version of PPL on the PDP-11 for use with the new HRSTS (Harvard-Radcliffe Student Timesharing System) under the Unix operating system supplied by Bell Labs. The two versions are designed to be fully compatible within the limits of the architectural differences of the machines, although the two languages are currently in slightly different states of development. Some of the new system functions and capabilities described in this summary currently apply to the PDP-10 implementations only, although most of the important language changes have already been incorporated into both systems. Documentation will be available describing the current state of the Unix version.
PPL Version 53 - Editing Summary Page 2 I. Introduction of operator precedence The most substantial change that has been made in this version of PPL is the introduction of a new precedence scheme for dealing with operators in the language. Initially, PPL was designed to use Iversonian precedence as in APL. While the mechanism is simpler in some respects, experience with the language indicated that standard arithmetic precedence had several advantages. Ed Taft described the motivation for the change in his thesis: The principal reason for the inclusion of Iversonian precedence in PPL was to eliminate the need for the user to specify precedence when defining new operators, and then to have to remember the precedence of all operators he has defined. We have now come to believe, however, that this consideration is relatively unimportant. Experience with PPL has shown that a major proportion of operator definitions that programmers issue in practice are either extensions to existing operators (in which case existing precedence rules would still be adequate) or definitions of new operators to be used in contexts where no ambiguity could arise. The new approach to operator precedence in PPL is similar to the operator definition facility of ECL, in that it allows the user to specify the order of evaluation of unparenthesized expressions with complete freedom, while providing default assumptions that conform to standard mathematical conventions for the built-in operators. Each of the operators in the language has an associated integral value as its precedence. In the absence of parentheses, __________ this value is used to determine the order in which operators are to be performed, with the operator of highest precedence being chosen whenever two operators compete for the operand between them. For example, the expression: X ^ 2 + 2 * Y = 0 would be evaluated as if it had been written: ((X ^ 2) + (2 * Y)) = 0 because '^' and '*' are both of higher precedence than '+', which is in turn of higher precedence than '='. If two operators have the same precedence, the conflict is resolved by an additional property called associativity _____________ which applies to binary operators only. The associativity of an operator is either "LEFT" or "RIGHT" and this determines which of the two operators of equal precedence is to be performed first. The associativity is always taken from the second operator of the conflicting operators to
PPL Version 53 - Editing Summary Page 3 resolve cases of conflicting associativity. As an example, the two expressions: 2+2+2 and 2^2^2 are evaluated as if they had been written (2+2)+2 and 2^(2^2) because the default associativity for '+' is "LEFT" while that of '^' is "RIGHT" as in standard arithmetic usage. The initial operator table is designed to take account of the standard mathematical conventions for order of operations. The initial operator table is given below, with the associated precedence and associativity values. Operator Precedence Associativity Function ________ __________ _____________ ________ + a 100 PLUS(a) - a 100 MINUS(a) a ^ b 90 RIGHT POWER(a,b) a * b 80 LEFT MUL(a,b) a / b 80 LEFT DIV(a,b) a + b 70 LEFT ADD(a,b) a - b 70 LEFT SUB(a,b) a == b 60 LEFT INSTANCE(a,b) a < b 50 LEFT LESS(a,b) a <= b 50 LEFT LESSEQ(a,b) a > b 50 LEFT GR(a,b) a >= b 50 LEFT GREQ(a,b) a = b 50 LEFT EQ(a,b) a # b 50 LEFT NEQ(a,b) a & b 40 LEFT AND(a,b) a ! b 30 LEFT OR(a,b) a <- b 20 RIGHT ASSIGN(a,b) a <-<- b 20 RIGHT NONCOPY(a,b) --> b 10 UGOTO(b) a --> b 10 LEFT CGOTO(a,b) In order to define new operators or extend existing ones in light of the precedence scheme, the functions UNARY and BINARY have been extended to allow extra arguments specifying the precedence and associativity values for operators. The UNARY function allows an optional third argument as the unary precedence of the operator, and BINARY allows two additional arguments, the precedence and the asociativity respectively. If these arguments are supplied, their values are taken as the appropriate attributes of the new operator definition. If these arguments are omitted from the call, they are defaulted in one of the following two ways:
PPL Version 53 - Editing Summary Page 4 (a) If the operator previously existed as an operator of the type indicated by the call on UNARY or BINARY, then the values from the existing definition remain unchanged. This is particularly useful in extending existing operators in that the new definitions will automatically retain the characteristics of the old operators. (b) If this is a new operator (or if it has not been used in this sense before, such as giving an existing binary operator a unary definition) then the values for the precedence and the associativity are taken from the appropriate global bindings of the identifiers DEF.UNARY.PREC, DEF.BINARY.PREC, and DEF.ASSOC, which have initial settings of 100, 25 and "LEFT" respectively. Operators may now be erased from the environment by calling the UNARY or BINARY function with NULL or "" (the empty string) in place of the function name. Currently, the operator continues to function lexically even after it is erased, although this will be changed in a later version. In order to make the operator structure more accessible to the user, a variety of functions have been provided to allow the user convenient access to the properties of operators. These functions are summarized below: UNARY.DEF(o) Returns as a STRING the name of the function associated with the unary operator o, or "" if o is not defined as a unary operator UNARY.PREC(o) Returns as an INT the unary prcedence of the operator o, or zero if o is not defined as a unary operator. BINARY.DEF(o) Returns as a STRING the name of the function associated with the binary operator o, or "" if o is not defined as a binary operator. BINARY.PREC(o) Returns as an INT the binary precedence of the operator o, or zero if o is not defined as a binary operator. ASSOCIATIVITY(o) Returns the STRING "LEFT" or "RIGHT" denoting the associativity of the binary operator o, or "" if o is not defined as a binary operator.
PPL Version 53 - Editing Summary Page 5 OPERATORS Returns a TUPLE of STRINGs enumerating all currently defined operators (both unary and binary as well as both user-defined and built-in). In addition, there are two user functions (currently initialized through the NEWS file at Harvard) that provide user convenience routines for dealing with operators. RENUMBER(n) recalculates new precedence values for all of the existing operators, maintaining the same relative precedence of the operators, but changing the spacing between each subset of operators sharing a common precedence to be the integer n. IVERSONIAN changes the precedence of all operators to be that required to duplicate the function of the Iversonian precedence scheme of earlier versions of PPL. It also resets the values of DEF.UNARY.PREC, DEF.BINARY.PREC and DEF.ASSOC so that each new operator is also defined in accordance with the old scheme. II. Changes to the arithmetic routines The other change most likely to affect existing PPL programs is a change in the action of the standard system division function DIV. Formerly, if two integral arguments were supplied to DIV, the result would be an integer with the remainder ignored, similar to the FORTRAN or ECL interpretation. This has been changed so that in the case of division of two integers the result is an INT if there is no remainder from the division, and is a REAL otherwise, therefore yielding a mathematically correct result. The old interpretation of division is retained in the system function IDIV, although it is not initially invoked by any operator. Thus, to restore the traditional meaning of the division operator, the command BINARY("/",IDIV) may be given. The POWER function has been extended so that it now will accept REALs as exponents. If the exponent is a REAL or a DBL, the computation is accomplished through calls on the system functions LN and EXP, and the result is always a REAL. If a REAL exponent is used, the base must be non-negative.
PPL Version 53 - Editing Summary Page 6 III. New language forms Version 53 of PPL runs with a slightly revised grammar, which has been modified both to take account of the new precedence scheme and to provide a variety of new language forms. The new grammar is included in the appendix to this summary. The changes dealing with precedence are the rules for the formation of expressions, which are now written ambiguously with conflicts resolved by the actual precedences of the operators at parse time. Note that the rules dealing with the GOTO operator --> have been removed from the grammar since this operator may be handled as an ordinary operator under the new precedence scheme. Two of the new forms provide alternative iteration forms and are useful for programs structured along the line proposed by Dijkstra as a solution to the GOTO controversy. These two forms are defined in the grammar as: WHILE <exp> DO <form> REPEAT <form> UNTIL <exp> The semantics of the WHILE form is that the condition specified by <exp> is evaluated before each iteration, and <form> is executed as long as <exp> evaluates to TRUE. The REPEAT form is similar except that the condition is tested after the evaluation of the form, and that the evaluation is_____ repeated until the condition specified by <exp> becomes TRUE. All three of the iteration forms (FOR, WHILE and REPEAT) have been changed slightly from the interpretation given the old FOR form. Each of these statement forms is always NULL valued, and printing is performed on each iteration of the loop, unless the last operation was an assignment or a NULL-valued function. Thus the statement: FOR I <- 1:4 DO I prints 1 2 3 4 (The old version had the confusing effect of printing 5). An additional new statement form is the RETURN statement, which comes in two flavors. The RETURN statement alone is used to return from functions and is intended as a
PPL Version 53 - Editing Summary Page 7 sematically more palatable form of the equivalent statement GOTO %0. If the RETURN statement is given an argument, using the statement RETURN <exp>, the value of the expression is returned as the value of the function. This also has a semantic function in that it allows many functions to be written more compactly, although RETURN <exp> has the additional characteristic of returning values by reference in a manner analogous to passing parameters by__ _________ reference. This allows the user to write functions which can return values which can be assigned to or manipulated as true objects, as well as allowing the return of such system objects as functions, predicates, selector names and so on. In order that the user can access the capability provided by the RETURN statement through an operator, the action of RETURN is also provided by the SRETURN system function, which may be called directly or invoked through the use of an operator which has been assigned to that routine. In order to allow the user to define functions that take an indefinite number of arguments in the manner of many system functions, a new argument specification has been introduced. If the last dummy argument in the function header is prefixed with a left square bracket, the function becomes a variadic function. When the function is called, the corresponding actual argument (if any) and any remaining arguments are collected together into a TUPLE and passed as the value of the final argument. For example, the function FOO below illustrates the basic operation of the tupled argument feature: $FOO([X) [1] X $ FOO(1) [1] FOO(1,3,5,7) [1,3,5,7] FOO() []
PPL Version 53 - Editing Summary Page 8 IV. Additional system functions Several additional system functions have been added to the new version of PPL that further extend the language capability. Several of these functions are designed to allow the user to work more effectively with non-assignable system objects, such as function names and data definitions, or to return information about the current environment. The new system contains four routines allowing enumeration of subsets of the current environment: FUNCTIONS, VARIABLES, DATA.DEFINITIONS and the previously mentioned OPERATORS routine. Each of these enumeration routines returns a TUPLE of STRINGs consisting of the names of all of the existing user functions, global variables, user defined data type names and operators respectively. These values returned may be used simply to list parts of the environment, but may also be manipulated by selection and through the use of the EXECUTE function (described later in this section) or the string/symbol feature (section V). In order to allow the user to determine the sort of object that has been passed to or from a routine, a set of predicates functions have been added for each of the classes of objects available in the system. Each of the following functions take an argument which must be a global identifier *, and returns TRUE if the object fits the predicate class under test. The functions return FALSE in all other cases. In particular, the functions return FALSE even if their argument is not an identifier, such as in the call UNASSIGNED(2). These predicate functions are: ----------------- * In the discussion of these predicates and the CLASS function, the argument must be a global identifier or a parameter which has been passed by reference that was an explicit global identifier at the highest level in the chain of calls. Locals defined in a function, or the names of parameters passed by value are not considered to be identifiers for use with these function. Thus it is currently not possible, for example, to determine if a local variable L has not yet been given a value by the use of the function call UNASSIGNED(L). On such values, the predicate functions will always return FALSE, and CLASS will return the empty string (see the description of the CLASS function).
PPL Version 53 - Editing Summary Page 9 UNASSIGNED VARIABLE (with an assigned value) SYSTEM.FN USER.FN ATOMIC.TYPE COMPOSITE.TYPE ALTERNATE.TYPE (includes GENERAL, ATOMIC, etc.) SELECTOR.NAME The eight predicate classes listed above are mutually exclusive classes of objects, and these class names are also used by the system function CLASS(x), which returns one of the above class names as a STRING. The function returns the null string if its argument is not an identifier. One of the deficiencies in earlier versions of PPL was the inability of the user to invoke the interpreter on program-generated STRINGs. In order to allow this capability, a new system function EXECUTE has been introduced, which takes a STRING, and evaluates the string in the current environment, exactly as if this string had been typed in by the user. For example: EXECUTE("1+2") 3 The EXECUTE function is capable of returning any sort of object, and it always returns its result by reference, making it possible to assign values to the result of EXECUTE or to use the result in several other ways, such as: EXECUTE("A") <- 2 A 2 EXECUTE(CONCAT("SQ","RT")) (4) 2. Note that the second function assembles the string SQRT which is then used as a function on the argument 4. As an example of one of the uses of EXECUTE, consider the INTUPLE routine which is designed to provide a more convenient input convention, in which the user may enter several values separated by commas on a single line, to be returned as a TUPLE by the the routine below: $INTUPLE [1] RETURN EXECUTE(CONCAT("[",CONCAT(?", "]"))) [2] $
PPL Version 53 - Editing Summary Page 10 INTUPLE ? 2, 16+4, TRUE, "A STRING" [2,20,TRUE,A STRING] Note that the INTUPLE function takes in a STRING (using ?"), pads it with brackets, and evaluates the result. The text evaluated by EXECUTE may also contain function and data definitions, which may be generated at execution time. When defining a new function with EXECUTE, the terminating dollar sign must be followed by a carriage-return before the STRING is closed. Statement numbers in the function are optional. For example, the following function creates a function F(X) by requesting a formula in X from the user by building up an appropriate function definition. Note that the function also ERASEs any previous definition of F so that it may be used repeatedly. $INPUT.FUNCTION [1] ERASE($F) ... line-feed used for continuation [2] EXECUTE(CONCAT("$F(X) F <- ", CONCAT(?"," $ "))) [3] $ INPUT.FUNCTION ? 2*X - 4 ?F $F(X) [1] F <- 2*X - 4 $ If an error occurs during the operation of EXECUTE, an error message is printed and a new line is requested from the user. The use of STRINGs within the language have also been expanded through the string/symbol facility described in the following section. An additional deficiency in the old system that prevented some attempts to extend the language was the inability to give a new name to a system routine so that its old name could be used for some other purpose. To accomplish this, a new function COPYSF has been added which takes two arguments, the first of which must be some currently unassigned identifier, and the second must be a system function. COPYSF has the effect of copying the
PPL Version 53 - Editing Summary Page 11 meaning of the system function into the new name supplied. For example, this feature may be used to allow the SIN routine to take its argument in degrees rather than radians. COPYSF(OLDSIN,SIN) ERASE($SIN) $SIN(X) [1] RETURN OLDSIN(X*3.1415926/180) [2] $ SIN(30) .5 To provide a somewhat more useful feature than the function DAYTIME, the function DATE has been added which returns both the date and the time as an 18-character STRING formatted as dd-mmm-yy hh:mm:ss, with a <tab> character separating the two figures. For example, "14-SEP-74 14:23:48". Two additional input/output functions have been defined in the Harvard version of PPL (under the control of the CHARIO conditional) which provide for single character input/output to the teletype. GETCHAR takes no arguments and requests a single character from the user, without requiring a carriage-return at the end of the string. SENDCHAR takes an argument, which may be either a CHAR or an INT, and transmits that character to the terminal as an image character, without any special processing by the monitor. V. Symbols In order to make it possible to conveniently use STRINGs to refer to identifiers without having to use the EXECUTE function, a rudimentary form of a symbol has been ______ introduced in the language. Whenever the language requires an identifier in a particular context, the new version of PPL will also accept any form which evaluates to a STRING which is the name of some identifier. For example, since the system function MAKE requires an identifier as its first argument it is now possible to use the construction: MAKE(TYPE(X),100,X[1])
PPL Version 53 - Editing Summary Page 12 to construct a sequence of the same type as X with 100 components. Similarly, STRINGs can be used in place of the function name position in calls to functions. For example: "SIN" (0) 0 This facility makes it possible to achieve the effect of having a sequence of functions, similar to the ECL construct ROW(ROUTINE). For instance, the following construct could be used to print a table of values for any list of functions, such as that specified by the variable RR. RR <- ["SIN","COS","ATAN"] FOR I<-0:.01:1 DO PRINT(I); (FOR J<-1:LENGTH(RR) DO PRINT(" ",RR[J](I)));"" Strings may be used for symbols only in those cases where identifiers are required by the language. Those cases are: function name position * selector for a structure * arguments to the following system functions MAKE (first argument only) INSTANCE (second argument only) ERASE STOP, TRACE, UNSTOP, etc. (function name only) UNARY and BINARY (function name only) CLASS and its associated predicate functions COPYSF INPUT and OUTPUT (mode only) Strings may never be used as symbols in editing commands or the construction of new definitions. ------------------ * These two uses of the string/symbol feature may not be supported under the Unix version.
PPL Version 53 - Editing Summary Page 13 VI. Other changes Two minor changes have been made in PPL which do not fall into the above categories. The identifier NEWLINE is now a built-in value and is initially set to the two-character string of a carriage-return/line-feed combination. This is useful for generating a new line when using the PRINT function. The built-in alternate types (GENERAL, STRUCTURE, SEQUENCE, V.SEQUENCE, and ATOMIC) have been made non-erasable definitions. Now that TUPLE has been so firmly integrated into the system in the enumerators and the new variadic function convention, it was necessary to protect GENERAL from erasing, in that this would cause system errors in certain cases. Two bugs in the garbage collector were discovered and fixed during the revision. In particular, erasing the currently running function formerly caused errors in some cases. VII. Proposed changes yet to be made The major outstanding revision that will be undertaken in PPL is the construction of the new editor system which is described in the new primer and manual, but is not yet implemented on either system. The Unix system will not conveniently support single character input modes, so that the current control-character oriented editor is infeasible for use with the PDP-11 version. Furthermore, the addition of the many statement forms and compound expressions in PPL since its earliest days have made it necessary to design a more powerful editor with global editing capabilities. Documentation on the editor is available in either the new manual or primer. The projected completion date for the new editor is January, 1975. Currently, operators continue to participate lexically even after they are erased, and the lexical analyzer accepts binary operators in unary contexts and vice-versa. This will hopefully be repaired in a subsequent version. Some mechanism for handling pseudo-files for STRINGs is under consideration, but no firm outline of the operation has been devised.
PPL Version 53 - Editing Summary Page 14 In light of the magnitude and scope of the new changes to PPL, it is likely that the system is not yet perfectly stable, and that some bugs will appear. If any bugs are encountered, please contact either: Eric Roberts @ HARV-10 or Ed Taft @ PARC-MAXC Aiken Computation Lab 212 XEROX Palo Alto Research Center Harvard University 3180 Porter Drive Cambridge, MA 02138 Palo Alto, CA 94304
PPL Version 53 - Editing Summary Page 15 Appendix - The Syntax of PPL (taken from the PPL User's Manual) The following is the BNF (Backus Normal Form) grammar of PPL, which was used to generate its parse tables. <atom> stands for any identifier or constant, and <op> stands for any unary or binary operator. <rpad> is an end-of-line marker analagous to Return. The character '|' is the metasymbol used to separate alternatives. The lexical analyzer determines the decomposition of operator strings into operators and special symbols, and also processes labels; thus, that mechanism does not appear here. The redundancy of <form> and <form-1> is necessary to make the grammar unambiguous (by avoiding the 'dangling ELSE' problem) and has no other significance. The ambiguity in the rules defining <expression> is resolved through application of the precedence of the operators involved. <statement> ::= <form> <rpad> | <rpad> | <for-prefix> <dothru> <expression> <rpad> <form> ::= <s-form> ; <form> | <s-form> | <if-prefix> <form> | <if-prefix> <form-1> <els> <form> | <for-prefix> <do> <form> | WHILE <expression> <do> <form> <form-1> ::= <s-form> ; <form-1> | <s-form> | <if-prefix> <form-1> <els> <form-1> | <for-prefix> <do> <form-1> | WHILE <expression> <do> <form-1> <s-form> ::= <expression> | GOTO <expression> | RETURN | RETURN <expression> | REPEAT <form> UNTIL <expression> <expression> ::= <op> <expression> | <term> | <expression> <op> <expression> <term> ::= <atom> | <term> ( <list> ) | <term> ( ) | <term> [ <list> ] | [ <list> ] | [ ] | ( <form> ) <list> ::= <form> | <list> , <form> <if-prefix> ::= IF <expression> THEN | <expression> => <for-prefix> ::= FOR <for-list> | <for-list> <for-list> ::= <expression> : <expression> | <expression> : <expression> : <expression> <do> ::= DO | ; <dothru> ::= DOTHRU | ;; <els> ::= ELSE | ::
PPL Version 53 - Editing Summary Page 16 Index additional system functions . 8 alternate types . . . . . . . 13 ALTERNATE.TYPE . . . . . . . . 9 ASSOCIATIVITY . . . . . . . . 4 associativity . . . . . . . . 2 ATOMIC.TYPE . . . . . . . . . 9 BINARY . . . . . . . . . . . . 3, 12 BINARY.DEF . . . . . . . . . . 4 BINARY.PREC . . . . . . . . . 4 bugs . . . . . . . . . . . . . 14 changes to arithmetic routines 5 CLASS . . . . . . . . . . . . 9 COMPOSITE.TYPE . . . . . . . . 9 COPYSF . . . . . . . . . . . . 10 DATA.DEFINITIONS . . . . . . . 8 DATE . . . . . . . . . . . . . 11 DEF.ASSOC . . . . . . . . . . 4 DEF.BINARY.PREC . . . . . . . 4 DEF.UNARY.PREC . . . . . . . . 4 DIV . . . . . . . . . . . . . 5 editor . . . . . . . . . . . . 13 enumeration routines . . . . . 8 erasing operators . . . . . . 4, 13 errors during EXECUTE . . . . 10 EXECUTE . . . . . . . . . . . 9 FOR . . . . . . . . . . . . . 6 FUNCTIONS . . . . . . . . . . 8 garbage collector . . . . . . 13 GETCHAR . . . . . . . . . . . 11 global identifier . . . . . . 8 GOTO operator . . . . . . . . 6 IDIV . . . . . . . . . . . . . 5 initial operator table . . . . 3 INPUT.FUNCTION . . . . . . . . 10 INTUPLE . . . . . . . . . . . 9 iteration forms . . . . . . . 6 IVERSONIAN . . . . . . . . . . 5 Iversonian precedence . . . . 2, 5 lexical analysis . . . . . . . 13 local variables . . . . . . . 8 MAKE . . . . . . . . . . . . . 11
PPL Version 53 - Editing Summary Page 17 new language forms . . . . . . 6 NEWLINE . . . . . . . . . . . 13 operator precedence . . . . . 2 OPERATORS . . . . . . . . . . 5, 8 other changes . . . . . . . . 13 POWER . . . . . . . . . . . . 5 PPL syntax . . . . . . . . . . 15 precedence . . . . . . . . . . 2 predicate functions . . . . . 8 proposed changes . . . . . . . 13 psuedo-files . . . . . . . . . 13 RENUMBER . . . . . . . . . . . 5 REPEAT . . . . . . . . . . . . 6 RETURN . . . . . . . . . . . . 6 returning values by reference 7 ROW(ROUTINE) . . . . . . . . . 12 SELECTOR.NAME . . . . . . . . 9 SENDCHAR . . . . . . . . . . . 11 SRETURN . . . . . . . . . . . 7 STRING handling . . . . . . . 9, 11, 13 string/symbol feature . . . . 11 symbols . . . . . . . . . . . 11 SYSTEM.FN . . . . . . . . . . 9 tupled argument feature . . . 7 UNARY . . . . . . . . . . . . 3, 12 UNARY.DEF . . . . . . . . . . 4 UNARY.PREC . . . . . . . . . . 4 UNASSIGNED . . . . . . . . . . 9 Unix . . . . . . . . . . . . . 1, 12, 13 USER.FN . . . . . . . . . . . 9 VARIABLE . . . . . . . . . . . 9 VARIABLES . . . . . . . . . . 8 variadic functions . . . . . . 7 WHILE . . . . . . . . . . . . 6



Feel free to contact me, David Gesswein djg@pdp8online.com with any questions, comments on the web site, or if you have related equipment, documentation, software etc. you are willing to part with.  I am interested in anything PDP-8 related, computers, peripherals used with them, DEC or third party, or documentation. 

PDP-8 Home Page   PDP-8 Site Map   PDP-8 Site Search