2/7/75 - JONL AND GLS - BRIEF SYNOPSIS: [1] THE VALUE OF PRIN1 CONTROLS USE OF PRIN1 BY LISP. [2] NEW COMPLR SWITCHES, AND DECLARATIONS, AND THINGS: [2A] ^^ NOW ENTERS MAKLAP. [2B] COMPILER-STATE TO DETERMINE STATE OF COMPILER. [2C] EXPR-HASH (E SWITCH) FOR FUNCTION HASHING. [2D] THE GLOBAL VARIABLE "SOBARRAY" HOLDS THE ARRAY POINTER TO THE STANDARD LISP OBARRAY. [2E] EOC-EVAL TO EVAL THINGS AFTER COMPILATION IS COMPLETED. [2F] COUTPUT TO OUTPUT THINGS TO THE LAP FILE. [2G] DONT EVER, BUT EVER, USER "QUOTE" AS A LAMBDA OR PROG VARIABLE. [3] VALUE OF DEFUN CONTROLS EXPR-HASH CROCK IN INTERPRETER. [4] USE PLIST AND SETPLIST TO ACCESS AND STORE PROPERTY LISTS [5] "ROMAN" APPEARS ON THE FEATURE LIST [GOTTEN BY (STATUS FEATURES), OR TESTED BY (STATUS FEATURE ROMAN)] IF THAT HACK IS ASSEMBLED IN. [6] ON A DEC-10 MONITOR, (STATUS JNAME) RETURNS "NNNLSP". [7] _ FIXNUM OUTPUT FORMAT EXTENDED TO _22, _11. [8] (STATUS FREE ...), (SSTATUS FREE ...) FLUSHED. [9] MANY CHANGES TO THE BREAK AND *BREAK FUNCTIONS: [4A] BREAK OF THREE ARGUMENTS NO LONGER EXISTS. [4B] BREAK/*BREAK LAMBDA-BIND *, +, -. [4C] ([S]STATUS BREAKLEVEL) IS LIKE ([S]STATUS TOPLEVEL). [4D] BREAK USES A CATCH; (THROW <VALUE> BREAK) EXITS. ALSO, AN ATTEMPT TO EXPLAIN BREAK AND TOPLEVEL IN EXPR CODE ---------------------------------------------------------------- [1] THE VALUE OF THE ATOM "PRIN1" NOW CONTROLS THE ACTION OF PRINTING BY THE TOP-LEVEL AND BREAK ROUTINES. IN SHORT, AN ITEM X RESULTING FROM THE EVALUATION IN THESE LOOPS IS PRINTED LIKE (COND (PRIN1 (FUNCALL PRIN1 X)) (T (PRIN1 X))) THIS FEATURE EXISTS PRIMARILY FOR THE OWL SYSTEM, WHICH HAS CIRCULAR LIST STRUCTURE ABUNDANT, AND DOESN'T NEED TO REWRITE THE ENTIRE TOP-LEVEL ROUTINE MERELY TO ACCOUNT FOR THE PRINTING OF CIRCULAR STRUCTURE. [2] SOME NEW SWITCHES AND DECLARATIONS FOR THE COMPILER: [2A] TYPING ^^ NOW ENTERS MAKLAP [JUST AS IN MACSYMA, WHERE ^^ DOES A (CONTINUE)]. [2B] COMPILER-STATE THIS VARIABLE REVEALS TO THE USER ONE OF THREE STATES THAT THE COMPILER MAY BE IN, AND IS OF INTEREST TO SOMEONE WHO WANTS TO WRITE SOPHISTICATED MACROS WHICH EXPAND IN DIFFERENT WAYS DEPENDING ON THE REASON FOR THE EXPANSION. POSSIBLE VALUES FOR COMPILER-STATE: [2B1] "TOPLEVEL" THE COMPILER IS AT THE TOP LEVEL OF LISP. [2B2] "MAKLAP" THE COMPILER IS SCANNING AN INPUT FILE LOOKING FOR FUNCTION DEFINITIONS TO COMPILE. IN THIS STATE THE COMPILER WILL EXPAND ANY TOP-LEVEL FORM (FOO ...) FOR WHICH FOO HAS A MACRO PROPERTY TO SEE IF A FUNCTION DEFINITION IS PRODUCED [WHICH WOULD THEN BE COMPILED]. [2B3] "COMPILE" THE COMPILER IS ACTUALLY COMPILING A FORM WHICH IS A FUNCTION DEFINITION, PRODUCING LAP CODE. IN THIS STATE ANY SUB-FORM (FOO ...) WHICH IS TO BE COMPILED IS EXPANDED IF FOO HAS A MACRO PROPERTY. RANDOM EXAMPLE: WHEN A FUNCTION IS DEFINED YOU WANT THE FLATSIZE OF THE DEFINITION TO BE PUT ON THE PROPERTY LIST OF THE FUNCTION. IF THE FUNCTION IS COMPILED, YOU WANT TO ARRANGE TO OUTPUT AN APPROPRIATE DEFPROP INTO THE LAP FILE. (DEFUN STRANGE-DEFUN MACRO (FORM) ;DO THE MACRO THING (NOT HAIRY) (RPLACA FORM 'DEFUN) ;NOW HACK THE FLATSIZE THING (COND ((OR (NULL (BOUNDP COMPILER-STATE)) (EQ COMPILER-STATE 'TOPLEVEL)) ;IF INTERPRETING, OR AT COMPILER TOPLEVEL, ; JUST GO AHEAD AND DO THE PUTPROP (PUTPROP (CADR FORM) (FLATSIZE FORM) 'STRANGE-FLATSIZE)) ((EQ COMPILER-STATE 'MAKLAP) ;IF COMPILING A TOP-LEVEL FORM FROM A FILE, ; ARRANGE FOR A DEFPROP IN THE LAP FILE (COUTPUT (LIST 'DEFPROP (CADR FORM) (FLATSIZE FORM) 'STRANGE-FLATSIZE))) ((EQ COMPILER-STATE 'COMPILE) ;WE DON'T WANT A DEFPROP IN THE ; MIDDLE OF ANY LAP CODE! (ERROR 'STRANGE-DEFUN/ IN/ SUBFORM FORM 'FAIL-ACT)))) [2C] EXPR-HASH THIS FEATURE CONTROLS THE AUTOMATIC OUTPUTTING BY THE COMPILER OF A DEFPROP FOR EACH FUNCTION COMPILED WHICH DEFINES AN "EXPR-HASH" PROPERTY FOR THAT FUNCTION. THIS PROPERTY IS A NUMBER, WHICH IS THE SXHASH OF THE LAMBDA-FORM STORED AS THE EXPR PROPERTY OF THE FUNCTION WHEN USED IN EXPRFORM. THE INTENDED USE OF THIS IS TO HAVE A QUICK, AUTOMATIC SCHEME TO DECIDE WHICH FUNCTIONS HAVE BEEN EDITED SINCE COMPILATION, AND TO READ IN THE EXPR VERSIONS OF THOSE CHANGED FUNCTIONS. STORING THE SXHASH OF THE LAMBDA DEFINITION OF THE FUNCTION LENDS ITSELF TO SIMPLE, QUICK, AND NON-SPACE-CONSUMING (IF NOT COMPLETELY FOOLPROOF) METHODS. IT IS SET EITHER BY A DECLARATION (DECLARE (EXPR-HASH <T-OR-NIL>)) OR BY USING THE "E" SWITCH IN THE MAKLAP COMMAND LINE. [SEE ITEM [3] BELOW FOR AN ASSOCIATED CHANGE IN DEFUN.] [2D] SOBARRAY THIS VARIABLE HOLDS A POINTER TO THE STANDARD LISP OBARRAY, IN WHICH THE COMPILER ITSELF IS RESIDENT. "COBARRAY" HOLDS THE ARRAY POINTER TO THE COMPILER'S OBARRAY USED WHILE COMPILING FILES. THESE TWO VARIABLES FACILITATE WRITING OBARRAY-SWITCHING FUNCTIONS. [2E] EOC-EVAL THIS VARIABLE HOLDS A LIST OF FORMS TO BE EVALUATED AFTER COMPILATION OF A FILE HAS BEEN COMPLETED. ONE CAN SET IT FROM A DECLARE, OR USE THE FUNCTION "EOC-EVAL" WHICH CONSES THE ITEMS OF THE CALLING FORM ONTO THE LIST STORED IN EOC-EVAL. AT THE TIME OF COMPLETION OF COMPILATION, (MAPC 'EVAL EOC-EVAL) IS DONE. EOC-EVAL IS RESET BY INITIALIZATION, OR BY THE WHIM OF THE USER. [2F] COUTPUT THIS FUNCTION SHOULD BE USED TO OUTPUT RANDOM FORMS TO THE LAP FILE. THIS IS CURRENTLY DONE BY USING PRINT; THUS ONE USED TO SAY, FOR EXAMPLE (DECLARE (PRINT (LIST 'SETQ 'VERSION (CADR (STATUS UREAD))))) IT IS ANTICIPATED, HOWEVER, THAT EVENTUALLY THE COMPILER MAY NOT WRITE A LAP FILE, BUT WILL BUFFER UP FORMS FOR THE ASSEMBLY PASS. THEREFORE THE FUNCTION COUTPUT SHOULD BE USED INSTEAD: (DECLARE (COUTPUT (LIST 'SETQ 'VERSION (CADR (STATUS UREAD))))) WHICH WILL DO THE CORRECT THING IN THE FUTURE WHEN THE BUFFERING MODE MATERIALIZES. [3] THE VALUE OF THE VARIABLE DEFUN CONTROLS A CROCK IN THE WORKINGS OF THE FUNCTION DEFUN. IF THE VALUE OF DEFUN IS NON-NIL, THEN EVALUATING (DEFUN FOO ...) WILL SUCCEED IN CREATING THE NEW DEFINITION ONLY IF EITHER: [A] FOO HAS NO EXPR-HASH PROPERTY. [B] FOO HAS AN EXPR-HASH PROPERTY, BUT IT IS NOT THE SAME AS SXHASH OF THE LAMBDA FORM FOR THE NEW DEFINITION. THUS A POOR MAN'S WAY TO USE THE COMPILER'S EXPR-HASH FEATURE IS TO COMPILE A FILE WITH THE (E) SWITCH, LOAD IT INTO A LISP, EDIT THE FILE SOME, DO (SETQ DEFUN T), THEN JUST READ IN THE UPDATED SOURCE, AND THE EXPR-HASH SCHEME WILL (PROBABLY) REDEFINE ONLY THOSE FUNCTIONS WHICH HAVE CHANGED, AND LEAVE THE SUBR VERSIONS IN FORCE FOR UNCHANGED FUNCTIONS, PROBABLY. [4] THE NEW SUBR OF ONE ARGUMENT, PLIST, IS USED TO RETRIEVE THE PROPERTY LIST OF A SYMBOL; THIS FUNCTION WORKS ON ALL SYMBOLS INCLUDING NIL, WHEREAS CDR WILL WORK ONLY FOR NON-NULL SYMBOLS IN NON-*RSET MODE. SIMILAR REMARKS HOLD FOR THE NEW SUBR OF TWO ARGUMENTS, SETPLIST. (SETPLIST X (PLIST X)) SHOULD BE A NOOP. [5] IF "ROMAN" IS A FEATURE OF THE LISP YOU ARE USEING, THEN YOU CAN TRY (SETQ IBASE 'ROMAN) OR (SETQ BASE 'ROMAN) FOR FUN AND GAMES; OTHERWISE, NO. [6] IN THE DEC-10 VERSION OF MACLISP, (STATUS JNAME) RETURNS THE ATOMIC SYMBOL "NNNLSP", WHERE NNN IS THE JOB NUMBER IN DECIMAL. THIS IS A STANDARD FIRST FILE NAME FOR TEMPORARY FILES, ETC. [7] TO MAKE THE _ FORMAT OF FIXNUM OUTPUT MORE USEFUL, THE FOLLOWING FORMATS ARE NOW USED [WHEN IBASE IS 8 AND (STATUS _) IS T]: IF THE NUMBER IS SMALLER THAN 2**18., OR IF THE LOW NINE BITS IN THE BINARY REPRESENTATION ARE NOT ALL ZERO, THEN THE _ FORMAT IS NOT USED. IF THE LOW 41 BITS ARE ALL ZERO, THEN N_41 IS USED. IF THE LOW 33 BITS ARE ALL ZERO, THEN N_33 IS USED. IF THE LOW 22 BITS ARE ALL ZERO, THEN N_22 IS USED. OTHERWISE, N_11 IS USED. NOTE THAT THESE CORRESPOND TO QUARTER-WORD BOUNDARIES (EXCEPT N_41); BUT N_11 IS NOT USED IF 6 OR FEWER DIGITS WOULD SUFFICE. [8] (STATUS FREE ...) AND (SSTATUS FREE ...) HAVE BEEN, OR SOON WILL BE, FLUSHED, SINCE THEY ARE OBSOLETE AND MAINLY A PAIN TO MAINTAIN. [9] MANY CHANGES TO THE BREAK FUNCTION: [9A] BREAK OF THREE ARGUMENTS HAS BEEN FLUSHED. (THE THIRD ARGUMENT USED TO BE A FORM TO BE EVALUATED IF P WERE TYPED.) [9B] *BREAK (ERGO ALSO BREAK) NOW LAMBDA-BINDS *, +, AND - TO THEIR OWN CURRENT VALUES SO THAT THEY WILL BE RESTORED ON EXIT FROM THE BREAK. [9C] (STATUS BREAKLEVEL) AND (SSTATUS BREAKLEVEL <FORM>) ARE ANALOGOUS TO (STATUS TOPLEVEL) AND (SSTATUS TOPLEVEL <FORM>). THE DEFAULT BREAKLEVEL, LIKE THE DEFAULT TOPLEVEL, IS A READ-EVAL-PRINT LOOP WHICH UPDATES *, +, AND - PROPERLY. [9D] BREAK HAS BEEN REDEFINED USING CATCH, WITH A CATCH-TAG OF "BREAK". IF AT ANY TIME WITHIN A BREAK THE FORM (THROW <VALUE> BREAK) IS EXECUTED, THE BREAK (OR *BREAK) FUNCTION WILL BE EXITED, RETURNING <VALUE>. THUS, FOR EXAMPLE, IF ONE TIRES OF TYPING (RETURN '(FOO)) TO UNBND-VRBL BREAKS OR WHATEVER, ONE MIGHT DEFINE A MACRO- CHARACTER (SETSYNTAX '/: 'MACRO '(LAMBDA NIL (THROW (LIST (READ)) BREAK))) AND SIMPLY TYPE :FOO AT THE UNBND-VRBL BREAK TO USE THE VARIABLE FOO INSTEAD. BELOW IS A NEW DEFINITION OF THE BREAK AND *BREAK FUNCTIONS W WRITTEN IN LISP, AS WELL AS A HALF-HEARTED ATTEMPT AT EXPLAINING THE TOP LEVEL LOOP. (DEFUN BREAK FEXPR (X) (*BREAK (EVAL (CADR X)) (CAR X)) ;NOTE ARGUMENT REVERSAL ;;; THE FIRST ARGUMENT TO BREAK IS A SWITCH, WHICH IF NIL CAUSES ;;; IMMEDIATE EXIT WITH NOTHING BEING DONE; ;;; OTHERWISE, THE VARIABLES ^Q, ^W, AND EVALHOOK ARE BOUND ;;; TO NIL, AND THE VARIABLES *, +, AND - ARE BOUND TO THEIR ;;; CURRENT VALUES, AND THE MESSAGE ";BKPT <BREAKID>" IS PRINTED. ;;; A READ-EVAL-PRINT LOOP SIMILAR TO THE TOP LEVEL LOOP ;;; IS THEN ENTERED. THIS BREAK LOOP IS SURROUNDED BY AN ;;; ERRSET AND A CATCH. ERRORS MERELY CAUSE THE BREAK ;;; LOOP TO BE RE-ENTERED. ;;; THE VALUE OF (STATUS BREAKLEVEL) SERVES A FUNCTION ;;; SIMILAR TO THAT OF (STATUS TOPLEVEL) IN THE TOP LEVEL ;;; LOOP. ;;; AS EACH FORM IS READ IN THE DEFAULT BREAK LOOP, THERE ARE ;;; FOUR CASES: ;;; [1] END OF FILE. THIS INDICATES OVER-RUBOUT AND ;;; SIMPLY CAUSES A TERPRI. ;;; [2] THE FORM IS THE ATOM P. *BREAK RETURNS NIL. ;;; [3] THE FORM IS (RETURN <VALUE>). THE FORM <VALUE> ;;; IS EVALUATED AND RETURNED. ;;; [4] OTHERWISE, THE FORM IS EVALUATED AND THE RESULT ;;; PRINTED OUT IN A MANNER ANALOGOUS TO THE TOP ;;; LEVEL READ-EVAL-PRINT LOOP. THE VARIABLES +, -, ;;; AND * ARE UPDATED APPROPRIATELY. (RECALL, HOWEVER, ;;; THAT THEY WERE BOUND ON ENTRY TO *BREAK, AND SO ;;; WILL BE RESTORED EVENTUALLY.) ;;; THE WAY TO RETURN FROM A BREAK IS TO DO A THROW WITH ;;; A TAG OF "BREAK"; THIS WILL RETURN FROM THE CATCH WHICH ;;; SURROUNDS THE BREAK LOOP. THIS IS HOW CASES [2] AND [3] ;;; RETURN THEIR VALUES; CASE [4] MAY ALSO CAUSE A RETURN FROM ;;; THE BREAK. (DECLARE (SPECIAL Q ^W EVALHOOK * + -)) (DEFUN *BREAK (BREAKP BREAKID) (AND BREAKP ((LAMBDA (^Q ^W EVALHOOK * + -) (TERPRI) (PRINC '/;BKPT/ ) (PRINC BREAKID) (SETQ + -) (CATCH (DO NIL (NIL) (ERRSET (DO ((EOF (LIST NIL)) (FORM)) (NIL) (COND ((STATUS BREAKLEVEL) (EVAL (STATUS BREAKLEVEL))) (T (SETQ FORM (READ EOF)) (COND ((EQ FORM EOF) (TERPRI)) ((EQ FORM 'P) (THROW NIL BREAK)) ((EQ (CAR FORM) 'RETURN) (THROW (EVAL (CADR FORM)) BREAK)) (T (SETQ - FORM) (SYSPRINT (SETQ * ((LAMBDA (+) (EVAL FORM)) (PROG2 NIL + (SETQ + -))))) (TERPRI)))))))) BREAK) (OR (STATUS LINMODE) (TERPRI))) NIL NIL NIL * + -))) (DEFUN SYSPRINT (X) ;INTERNAL PRINTING FUNCTION (OR (STATUS LINMODE) (TERPRI)) (COND (PRIN1 (FUNCALL PRIN1 X)) (T (PRIN1 X))) (TYO 40)) (DEFUN STANDARD-TOP-LEVEL NIL (PROG (^Q ^W ^R EVALHOOK BASE IBASE ...) ERRS ;ERRORS, UNCAUGHT THROWS, ETC. COME HERE (RESET-BOUND-VARS) ^G ;^G QUITS COME HERE (RESET-INTERNAL-TOP-LEVEL-VARS) (RESTORE-THE-WORLD) (DO-DELAYED-INTERRUPTS) ;RECALL THAT ERRORS DO (SETQ // ERRLIST) SO LAMBDA-BINDING ERRLIST WORKS (MAPC (FUNCTION EVAL) //) (AND (STATUS LINMODE) (TERPRI)) (SETQ * '*) (DO ((EOF (LIST NIL))) (NIL) (RESET-INTERNAL-TOP-LEVEL-VARS) (SETQ * (COND ((STATUS TOPLEVEL) (EVAL (STATUS TOPLEVEL))) (T (SYSPRINT *) (TERPRI) (DO ((FORM (READ EOF) (READ EOF))) ((NOT (EQ FORM EOF)) (SETQ - FORM)) (TERPRI)) ((LAMBDA (+) (EVAL -)) (PROG2 NIL + (SETQ + -))))))))) (DEFUN RESTORE-THE-WORLD NIL (RESET-THE-PDLS) (SETQ ^Q NIL) (SETQ EVALHOOK NIL) (RESTORE-THE-IO-SYSTEM) (ENABLE-SYSTEM-INTERRUPTS) (RESET-INTERNAL-GC-MARK-BITS)) (DEFUN DO-DELAYED-INTERRUPTS NIL (OR INTERNAL-NOINTERRUPT-SWITCH (PROCESS-PENDING-ALARMCLOCK-AND-TTY-INTERRUPTS)))