Artifact db8843aa04feef4b0cc25ae89446ac55d4ed39e3e6afce35e0dea9d2018d18cf:
- File
psl-1983/3-1/lpt/20-syslisp.lpt
— part of check-in
[eb17ceb7f6]
at
2020-04-21 19:40:01
on branch master
— Add Reduce 3.0 to the historical section of the archive, and some more
files relating to version sof PSL from the early 1980s. Thanks are due to
Paul McJones and Nelson Beebe for these, as well as to all the original
authors.git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/historical@5328 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 26710) [annotate] [blame] [check-ins using] [more...]
- File
psl-1983/lpt/20-syslisp.lpt
— part of check-in
[eb17ceb7f6]
at
2020-04-21 19:40:01
on branch master
— Add Reduce 3.0 to the historical section of the archive, and some more
files relating to version sof PSL from the early 1980s. Thanks are due to
Paul McJones and Nelson Beebe for these, as well as to all the original
authors.git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/historical@5328 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 26710) [annotate] [blame] [check-ins using]
PSL Manual 7 February 1983 SYSLISP section 20.0 page 20.1 CHAPTER 20 CHAPTER 20 CHAPTER 20 SYSLISP SYSLISP SYSLISP 20.1. Introduction to the SYSLISP level of PSL. . . . . . 20.1 20.2. The Relationship of SYSLISP to RLISP . . . . . . . 20.2 20.2.1. SYSLISP Declarations . . . . . . . . . . 20.2 20.2.2. SYSLISP Mode Analysis. . . . . . . . . . 20.3 20.2.3. Defining Special Functions for Mode Analysis . . 20.4 20.2.4. Modified FOR Loop . . . . . . . . . . . 20.4 20.2.5. Char and IDLOC Macros. . . . . . . . . . 20.5 20.2.6. The Case Statement. . . . . . . . . . . 20.6 20.2.7. Memory Access and Address Operations. . . . . 20.7 20.2.8. Bit-Field Operation . . . . . . . . . . 20.8 20.3. Using SYSLISP. . . . . . . . . . . . . . . 20.9 20.3.1. To Compile SYSLISP Code . . . . . . . . . 20.9 20.4. SYSLISP Functions . . . . . . . . . . . . . 20.10 20.4.1. W-Arrays . . . . . . . . . . . . . . 20.11 20.5. Remaining SYSLISP Issues . . . . . . . . . . . 20.12 20.5.1. Stand Alone SYSLISP Programs . . . . . . . 20.12 20.5.2. Need for Two Stacks . . . . . . . . . . 20.12 20.5.3. New Mode System. . . . . . . . . . . . 20.13 20.5.4. Extend CREF for SYSLISP . . . . . . . . . 20.13 This chapter is very out of date and will be replaced as soon as possible. 20.1. Introduction to the SYSLISP level of PSL 20.1. Introduction to the SYSLISP level of PSL 20.1. Introduction to the SYSLISP level of PSL SYSLISP [Benson 81] is a BCPL-like language, couched in LISP form, providing operations on machine words, machine bytes and LISP ITEMs (tagged objects, packed into one or more words). We actually think of SYSLISP as a lower level of PSL, dealing with words, bytes, bit-fields, machine operations, and compile-time storage allocation, enabling us to write essentially all of the kernel in PSL. The control structures and definition language are those of LISP, but the Plus2 Times2 WPlus2 WTimes2 Plus2 Times2 WPlus2 WTimes2 familiar Plus2, Times2, etc. are mapped to word operations WPlus2, WTimes2, etc. SYSLISP handles static allocation of SYSLISP variables and arrays and initial LISP symbols, permitting the easy definition of higher level Standard LISP functions and storage areas. SYSLISP provides convenient ______ compile-time constants for handling strings, LISP symbols, etc. The SYSLISP compiler is based on the PORTABLE STANDARD LISP Compiler, with extensions to handle word level objects and efficient, open-coded, word-level operations. The SYSLISP mode of the compiler does efficient compile-time folding of constants and more comprehensive register allocation than in the distributed version of the PLC. Currently, SYSLISP handles bytes through the explicit packing and unpacking operations SYSLISP 7 February 1983 PSL Manual page 20.2 section 20.1 GetByte GetByte GetByte(word-address,byte-number) / PutByte PutByte PutByte(word-address,byte-number,byte-value) without the notion of byte- pointer; it is planned to extend SYSLISP to a C-like language by adding the appropriate declarations and analysis of word/byte/structure operations. SYSLISP is a collection of functions and their corresponding data types which are used to implement low level primitives in PSL, such as storage allocation, garbage collection and input and output. The basic data object ____ in SYSLISP is the "word", a unit of storage large enough to contain a LISP ____ ____ ____ item. On the PDP-10, a SYSLISP word is just a 36-bit PDP-10 word. On the ____ VAX and most other byte addressed machines, a word is 4 bytes, or 32 bits. Conceptually, SYSLISP functions manipulate the actual bit patterns found in words, unlike normal LISP functions which manipulate higher-level objects, ____ ______ _____ ______ such as pairs, vectors, and floats or arbitrary-precision numbers. Arithmetic in SYSLISP is comparable to the corresponding operations in FORTRAN or PASCAL. In fact, SYSLISP is most closely modeled after BCPL, in that operations are essentially "typeless". 20.2. The Relationship of SYSLISP to RLISP 20.2. The Relationship of SYSLISP to RLISP 20.2. The Relationship of SYSLISP to RLISP ______ ______ ______ smacro smacro RLISP was extended with a CASE statement, SYSLISP declarations, smacros _____ _____ _____ macro macro and macros to provide convenient infix syntax (+, *, / etc.) for calling the SYSLISP primitives. Even though SYSLISP is semantically somewhat different from LISP (RLISP), we have tried to keep the syntax as similar as possible so that SYSLISP code is "familiar" to RLISP users, and easy to use. RLISP functions can be easily converted and interfaced to functions at the SYSLISP level, gaining considerable efficiency by declaring and directly using words and bytes instead of tagged LISP objects. 20.2.1. SYSLISP Declarations 20.2.1. SYSLISP Declarations 20.2.1. SYSLISP Declarations SYSLISP variables are either GLOBAL, memory locations (allocated by the compiler), or local stack locations. Locals are declared by SCALAR, as usual. Globals come in the following flavors: WCONST id = wconstexp {,id = wconstexp} ; Wconstexp is an expression involving constants and wconsts. WVAR wvardecl {, wvardecl} ; wvardecl ::= id | id = wconstexp WARRAY warraydecl {, warraydecl} ; warraydecl ::= id[wconstexp] | id[] = [ wconstexp {,wconstexp} ] | id[] = string PSL Manual 7 February 1983 SYSLISP section 20.2 page 20.3 WSTRING warraydecl {, warraydecl} ; Each of these declarations can also be prefixed with the keywords: INTERNAL or EXTERNAL. If nothing appears, then a DEFAULT is used. (Notice there are no metasyntactic square brackets here, only curly brackets.) For example, the following GLOBAL-DATA is used in PSL: on SysLisp; exported WConst MaxSymbols = 8000, MaxConstants = 500, HeapSize = 100000; external WArray SymNam, SymVal, SymFnc, SymPrp, ConstantVector; external WVar NextSymbol, NextConstant; exported WConst MaxRealRegs = 5, MaxArgs = 15; external WArray ArgumentBlock; off SysLisp; END; 20.2.2. SYSLISP Mode Analysis 20.2.2. SYSLISP Mode Analysis 20.2.2. SYSLISP Mode Analysis ____ In SYSLISP mode, the basic operators +, *, -, /, etc., are bound to word WPlus2 WTimes2 WMinus WPlus2 WTimes2 WMinus operators (WPlus2, WTimes2, WMinus, etc.), which compile OPEN as ____ conventional machine operations on machine words. Thus most SYSLISP expressions, loops, etc. look exactly like their RLISP equivalents. 20.2.3. Defining Special Functions for Mode Analysis 20.2.3. Defining Special Functions for Mode Analysis 20.2.3. Defining Special Functions for Mode Analysis To have the Mode analyzer (currently a REFORM function) replace LISP function names by SYSLISP ones, do: PUT('LispName,'SYSNAME,'SysLispName); SYSLISP 7 February 1983 PSL Manual page 20.4 section 20.2 The Following have been done: DefList('((Plus WPlus2) (Plus2 WPlus2) (Minus WMinus) (Difference WDifference) (Times WTimes2) (Times2 WTimes2) (Quotient WQuotient) (Remainder WRemainder) (Mod WRemainder) (Land WAnd) (Lor WOr) (Lxor WXor) (Lnot WNot) (LShift WShift) (LSH WShift)), 'SysName); DefList('((Neq WNeq) (Equal WEq) (Eqn WEq) (Eq WEq) (Greaterp WGreaterp) (Lessp WLessp) (Geq WGeq) (Leq WLeq) (Getv WGetv) (Indx WGetv) (Putv WPutv) (SetIndx WPutv)), 'SysName); 20.2.4. Modified FOR Loop 20.2.4. Modified FOR Loop 20.2.4. Modified FOR Loop Wxxxx Wxxxx The FOR loop is modified in SYSLISP mode to use the Wxxxx functions to do loop incrementation and testing. [??? Should pick up via SysReform ???] [??? Should pick up via SysReform ???] [??? Should pick up via SysReform ???] 20.2.5. Char and IDLOC Macros 20.2.5. Char and IDLOC Macros 20.2.5. Char and IDLOC Macros ____ In SYSLISP mode, '<id> refers to the tagged item, just as in LISP mode, IdLoc LispVar IdLoc __ LispVar IdLoc <id> refers to the id space offset of the <id>, and LispVar <id> ____ refers to the GLOBAL value cell of a GLOBAL or FLUID variable. Note: LispVar LispVar LispVar can be used on the left hand side of an argument sentence. For __ example, to store a NIL in the value cell of id FOO, we do any one of the following. PSL Manual 7 February 1983 SYSLISP section 20.2 page 20.5 SYMVAL IDLOC FOO := 'NIL; LISPVAR FOO := MKITEM(ID,IDLOC NIL); Char Char _ __ _______ _____ (Char U:id): integer macro Char Char The Char macro returns the ASCII code corresponding to its single character-id argument. CHAR also can handle alias's for certain special characters, remove QUOTE marks that may be needed to pass special characters through the parser, and can accept a prefixes to compute LOWER case, <Ctrl> characters, and <Meta> characters. For example: Little_a:= Char LOWER A; % In case we think RAISE will occur Little_a:= Char '!a; % !a should not be raised Meta_X := Char META X; Weird := Char META Lower X; Dinger := Char <Ctrl-G>; Dinger := Char BELL; PUT PUT The following Aliases are defined by PUTing the association under the indicator 'CharConst: DefList('((NULL 8#0) (BELL 8#7) (BACKSPACE 8#10) (TAB 8#11) (LF 8#12) (EOL 8#12) (FF 8#14) (CR 8#15) (EOF 26) (ESC 27) (ESCAPE 27) (BLANK 32) (RUB 8#177) (RUBOUT 8#177) (DEL 8#177) (DELETE 8#177)), 'CharConst); 20.2.6. The Case Statement 20.2.6. The Case Statement 20.2.6. The Case Statement RLISP in SYSLISP mode provides a Numeric case statement, that is implemented quite efficiently; some effort is made to examine special cases (compact vs. non compact sets of cases, short vs. long sets of cases, etc.). [??? Note, CASE can also be used from LISP mode, provided tags are [??? Note, CASE can also be used from LISP mode, provided tags are [??? Note, CASE can also be used from LISP mode, provided tags are numeric. There is also an FEXPR, CASE ???] numeric. There is also an FEXPR, CASE ???] numeric. There is also an FEXPR, CASE ???] The syntax is: SYSLISP 7 February 1983 PSL Manual page 20.6 section 20.2 Case-Statement ::= CASE expr OF case-list END Case-list ::= Case-expr [; Case-list ] Case-expr ::= Tag-expr : expr tag-expr ::= DEFAULT | OTHERWISE | tag | tag, tag ... tag | tag TO tag Tag ::= Integer | Wconst-Integer % This is a piece of code from the Token Scanner, % in file "PI:token-Scanner.red" ..... case ChTokenType of 0 to 9: % digit << TokSign := 1; goto InsideNumber >>; 10: % Start of ID << if null LispVar !*Raise then goto InsideID else << RaiseLastChar(); goto InsideRaisedID >> >>; 11: % Delimiter, but not beginning of diphthong << LispVar TokType!* := '3; return MkID TokCh >>; 12: % Start of comment goto InsideComment; 13: % Diphthong start-Lisp function uses P-list of starting char return ScanPossibleDipthong(TokChannel, MkID TokCh); 14: % ID escape character << if null LispVar !*Raise then goto GotEscape else goto GotEscapeInRaisedID >>; 15: % string quote << BackupBuf(); goto InsideString >>; 16: % Package indicator - % at start of token means use global package << ResetBuf(); ChangedPackages := 1; Package 'Global; if null LispVar !*Raise then goto GotPackageMustGetID else goto GotPackageMustGetIDRaised >>; 17: % Ignore - can't ever happen ScannerError("Internal error - consult a wizard"); 18: % Minus sign << TokSign := -1; PSL Manual 7 February 1983 SYSLISP section 20.2 page 20.7 goto GotSign >>; 19: % Plus sign << TokSign := 1; goto GotSign >>; 20: % decimal point << ResetBuf(); ReadInBuf(); if ChTokenType >= 10 then << UnReadLastChar(); return ScanPossibleDipthong(TokChannel, '!.) >> else << TokSign := 1; TokFloatFractionLength := 1; goto InsideFloatFraction >> >>; default: return ScannerError("Unknown token type") end; ..... 20.2.7. Memory Access and Address Operations 20.2.7. Memory Access and Address Operations 20.2.7. Memory Access and Address Operations The operators @ and & (corresponding to GetMem and Loc) may be used to do direct memory operations, similar to * and & in C. @ may also be used on the LHS of an assignment. Example: WARRAY FOO[10]; WVAR FEE=&FOO[0]; ... @(fee+2) := @(fee+4) + & foo(5); ... 20.2.8. Bit-Field Operation 20.2.8. Bit-Field Operation 20.2.8. Bit-Field Operation The Field and PutField operations are used for accessing fields smaller than whole words: PUTFIELD(LOC, BITOFFSET, BITLENGTH, VALUE); and GETFIELD(LOC,BITOFFSET, BITLENGTH); Special cases such as bytes, halfwords, single bits are optimized if possible. For example, the following definitions on the DEC-20 are used to define SYSLISP 7 February 1983 PSL Manual page 20.8 section 20.2 the fields of an item (in file p20c:data-machine.red): % Divide up the 36 bit DEC-20 word: WConst TagStartingBit = 0, TagBitLength = 18, StrictTagStartingBit = 9, StrictTagBitLength = 9, InfStartingBit = 18, InfBitLength = 18, GCStartingBit = 0, GCBitLength = 9; % Access to tag (type indicator) of Lisp item in ordinary code syslsp macro procedure Tag U; list('Field, cadr U, '(wconst TagStartingBit), '(wconst TagBitLe syslsp macro procedure PutTag U; list('PutField, cadr U, '(wconst TagStartingBit), '(wconst TagBitLength), caddr U); % Access to tag of Lisp item in garbage collector, % if GC bits may be in use syslsp macro procedure StrictTag U; list('Field, cadr U, '(wconst StrictTagStartingBit), '(wconst StrictTagBitLength)); syslsp macro procedure PutStrictTag U; list('PutField, cadr U, '(wconst StrictTagStartingBit), '(wconst StrictTagBitLength), caddr U); % Access to info field of item (pointer or immediate operand) syslsp macro procedure Inf U; list('Field, cadr U, '(wconst InfStartingBit), '(wconst InfBitLe syslsp macro procedure PutInf U; list('PutField, cadr U, '(wconst InfStartingBit), '(wconst InfBitLength), caddr U); PSL Manual 7 February 1983 SYSLISP section 20.3 page 20.9 20.3. Using SYSLISP 20.3. Using SYSLISP 20.3. Using SYSLISP ___________ Restriction: SYSLISP code is currently ONLY compiled, since it is converted into machine level operations, most of which are dangerous or tricky to use in an interpreted environment. Note: In SYSLISP mode, we currently execute some commands in the above PARSE/EVAL/PRINT mode, either to load files or select options, but most SYSLISP code is compiled to a file, rather than being immediately interpreted or compiled in-core. 20.3.1. To Compile SYSLISP Code 20.3.1. To Compile SYSLISP Code 20.3.1. To Compile SYSLISP Code Use PSL:RLISP, which usually has the Compiler, with SYSLISP extensions, loaded. Alternatively, one may use <psl>syscmp.exe. This is a version of RLISP built upon <PSL>psl.exe with the SYSLISP compiler and data-machine macros loaded. % Turn on SYSLISP mode: ON SYSLISP; % This is causes the "mode-analysis" to be done % Converting some LISP names to SYSLISP names. % Use SYSLSP as the procedure type. Example: % Small file to access BPS origin and end. % Starts in LISP mode Fluid '(NextBP0 LastBP0); NextBP0:=NIL; LastBP0:=NIL; On SYSLISP,COMP; % Switch to SYSLISP mode syslsp procedure BPSize(); Begin scalar N1,L1; If Null LispVar NextBP0 then LispVar NextBP0:=GtBPS 0; If Null LispVar LastBP0 then LispVar LastBP0:=GtWarray 0; N1 :=GtBPS(0); L1:= GtWarray(0); PrintF('" NextBPS=8#%o, used %d, LastBPS=8#%o, used %d%n", N1, N1-LispVar(NextBP0), L1,LispVar(LastBP0)-L1) LispVar NextBP0:=N1; LispVar LastBP0:=L1; End; BPSize(); % Call the function SYSLISP 7 February 1983 PSL Manual page 20.10 section 20.4 20.4. SYSLISP Functions 20.4. SYSLISP Functions 20.4. SYSLISP Functions [??? What about overflow in Syslisp arithmetic? ???] [??? What about overflow in Syslisp arithmetic? ???] [??? What about overflow in Syslisp arithmetic? ???] WPlus2 WPlus2 _ ____ _ ____ ____ ____ ________ ____ (WPlus2 U:word, V:word): word open-compiled, expr WDifference WDifference _ ____ _ ____ ____ ____ ________ ____ (WDifference U:word, V:word): word open-compiled, expr WTimes2 WTimes2 _ ____ _ ____ ____ ____ ________ ____ (WTimes2 U:word, V:word): word open-compiled, expr WQuotient WQuotient _ ____ _ ____ ____ ____ ________ ____ (WQuotient U:word, V:word): word open-compiled, expr WRemainder WRemainder _ ____ _ ____ ____ ____ ________ ____ (WRemainder U:word, V:word): word open-compiled, expr WShift WShift _ ____ _ ____ ____ ____ ________ ____ (WShift U:word, V:word): word open-compiled, expr WAnd WAnd _ ____ _ ____ ____ ____ ________ ____ (WAnd U:word, V:word): word open-compiled, expr WOr WOr _ ____ _ ____ ____ ____ ________ ____ (WOr U:word, V:word): word open-compiled, expr WXor WXor _ ____ _ ____ ____ ____ ________ ____ (WXor U:word, V:word): word open-compiled, expr WNot WNot _ ____ ____ ____ ________ ____ (WNot U:word): word open-compiled, expr WEQ WEQ _ ____ _ ____ _______ ____ ________ ____ (WEQ U:word, V:word): boolean open-compiled, expr WNEQ WNEQ _ ____ _ ____ _______ ____ ________ ____ (WNEQ U:word, V:word): boolean open-compiled, expr WGreaterP WGreaterP _ ____ _ ____ _______ ____ ________ ____ (WGreaterP U:word, V:word): boolean open-compiled, expr WLessP WLessP _ ____ _ ____ _______ ____ ________ ____ (WLessP U:word, V:word): boolean open-compiled, expr WGEQ WGEQ _ ____ _ ____ _______ ____ ________ ____ (WGEQ U:word, V:word): boolean open-compiled, expr PSL Manual 7 February 1983 SYSLISP section 20.4 page 20.11 WLEQ WLEQ _ ____ _ ____ _______ ____ ________ ____ (WLEQ U:word, V:word): boolean open-compiled, expr WGetV WGetV _ ____ _ ____ ____ ____ ________ _____ (WGetV U:word, V:word): word open-compiled, macro WPutV WPutV _ ____ _ ____ _ ____ ____ ____ ________ _____ (WPutV U:word, V:word, W:word): word open-compiled, macro Byte Byte _ ____ _ ____ ____ ____ ________ ____ (Byte U:word, V:word): word open-compiled, expr PutByte PutByte _ ____ _ ____ _ ____ ____ ____ ________ ____ (PutByte U:word, V:word, W:word): word open-compiled, expr 20.4.1. W-Arrays 20.4.1. W-Arrays 20.4.1. W-Arrays CopyWArray CopyWArray ___ _ ______ ___ _ ______ _____ ___ ___ _ ______ ____ (CopyWArray NEW:w-vector, OLD:w-vector, UPLIM:any): NEW:w-vector expr _____ Copy UPLIM + 1 words. CopyWRDSToFrom CopyWRDSToFrom ___ _ ______ ___ ___ ___ ____ (CopyWRDSToFrom NEW:w-vector, OLD:any): any expr CopyWArray CopyWArray Like CopyWArray in heap. CopyWRDS CopyWRDS _ ___ ___ ____ (CopyWRDS S:any): any expr Allocate new WRDS array in heap. 20.5. Remaining SYSLISP Issues 20.5. Remaining SYSLISP Issues 20.5. Remaining SYSLISP Issues The system should be made less dependent on the assemblers, compilers and loaders of the particular machine it is implemented on. One way to do this is to bring up a very small kernel including a fast loader to load in the rest. 20.5.1. Stand Alone SYSLISP Programs 20.5.1. Stand Alone SYSLISP Programs 20.5.1. Stand Alone SYSLISP Programs In principle it works, but we need to clearly define a small set of support functions. Also, need to implement EXTERNAL properly, so that a normal LINKING loader can be used. In PSL, we currently produce a single kernel module, with resident LAP (or later FAP), and it serves as dynamic linking loader for SYSLISP (ala MAIN SAIL). SYSLISP 7 February 1983 PSL Manual page 20.12 section 20.5 20.5.2. Need for Two Stacks 20.5.2. Need for Two Stacks 20.5.2. Need for Two Stacks We must distinguish between true LISP items and untagged SYSLISP items on the stack for the garbage collector to work properly. Two of the options for this are 1. Put a mark on the stack indicating a region containing untagged items. 2. Use a separate stack for untagged items. Either of these involves a change in the compiler, since it currently only allocates one frame for temporaries on the stack and does not distinguish where they get put. The garbage collector should probably be recoded more modularly and at a higher level, short of redesigning the entire storage management scheme. This in itself would probably require the existence of a separate stack which is not traced through for return addresses and SYSLISP temporaries. 20.5.3. New Mode System 20.5.3. New Mode System 20.5.3. New Mode System A better scheme for intermixing SYSLISP and LISP within a package is needed. Mode Reduce will probably take care of this. 20.5.4. Extend CREF for SYSLISP 20.5.4. Extend CREF for SYSLISP 20.5.4. Extend CREF for SYSLISP The usual range of LISP tools should be available, such as profiling, a break package, tracing, etc.