LISP PROJECTS (20)
most recent version : 7.1.pre-beta |release date : 2005-06-17

1. Basic function call to determine what declarations are available

In cmucl:

  * (pprint (sys::declaration-information 'declaration))
  (SYSTEM::VARIABLE-REBINDING DYNAMIC-EXTENT SPECIAL IGNORABLE IGNORE NOTINLINE
   INLINE FTYPE SYSTEM::DISCRIMINATED-TYPE TYPE DECLARATION OPTIMIZE)
  * 

In Allegro CL:

  CL-USER(1): (pprint (sys::declaration-information 'declaration))
  (:FASLMODE VALUES COMPILER::INSTANCE-VARIABLE :EXPLAIN
   EXCL::DYNAMIC-EXTENT-ARGUMENTS :DISCARD-SOURCE-FILE-INFO
   SYSTEM::VARIABLE-REBINDING DYNAMIC-EXTENT SPECIAL IGNORE-IF-UNUSED IGNORABLE
   IGNORE NOTINLINE INLINE FTYPE SYSTEM::DISCRIMINATED-TYPE TYPE DECLARATION
   OPTIMIZE)
  CL-USER(2): 

2. Some experiments on the optimize declaration:

In CMUCL:

  * (setq e1 (sys::make-compilation-unit-environment))
  Warning:  Declaring E1 special.
  #<Augmentable COMPILER environment {48589D55}>
  * (setq e2 (sys::augment-environment e1 :declare '((optimize speed debug))))
  Warning:  Declaring E2 special.
  #<Augmentable COMPILER environment 1 {4858B675}>
  * (sys::declaration-information 'optimize)
  ((SAFETY 1) (SPACE 1) (SPEED 1) (COMPILATION-SPEED 1) (DEBUG 2))

Note that the information is pushed, above, and does not modify the oiginal data here.

  * (sys::declaration-information 'optimize e2)
  ((SPEED 3) (DEBUG 3) (SAFETY 1) (SPACE 1) (SPEED 1) (COMPILATION-SPEED 1)
   (DEBUG 2))
  * (declaim (optimize (space 0) (safety 0)))
  NIL
  * (sys::declaration-information 'optimize)
  ((SAFETY 1) (SPACE 1) (SPEED 1) (COMPILATION-SPEED 1) (DEBUG 2))
  *

Note that the above did not make any difference, because Environments Access is currently implemented in CMUCL at level 1, and thus declaim does not invoke augment-environment (a level 2 acivity). Contrast with the Allegro CL example below.

  * (sys::augment-environment nil :declare '((optimize (space 0) (safety 0))))
  NIL
  * (sys::declaration-information 'optimize)
  ((SPACE 0) (SAFETY 0) (SPEED 1) (COMPILATION-SPEED 1) (DEBUG 2))

note now that the values have actually changed, but...

  * (sys::declaration-information 'optimize e2)
  ((SPEED 3) (DEBUG 3) (SAFETY 1) (SPACE 1) (SPEED 1) (COMPILATION-SPEED 1)
   (DEBUG 2))
  * 

Note also that the global change did not affect anything in this local environment.

Now in Allegro CL:

  CL-USER(3): (setq e1 (sys::make-compilation-unit-environment))
  #<Augmentable COMPILER environment @ #x40c25152>
  CL-USER(4): (setq e2 (sys::augment-environment e1 :declare '((optimize speed debug))))
  #<Augmentable COMPILER environment 1 @ #x40c25b22>
  CL-USER(5): (sys::declaration-information 'optimize)
  ((SAFETY 1) (SPACE 1) (SPEED 1) (COMPILATION-SPEED 1) (DEBUG 2))
  CL-USER(6): (sys::declaration-information 'optimize e2)
  ((SPEED 3) (DEBUG 3) (SAFETY 1) (SPACE 1) (SPEED 1) (COMPILATION-SPEED 1)
   (DEBUG 2))
  CL-USER(7): (declaim (optimize (space 0) (safety 0)))
  T
  CL-USER(8): (sys::declaration-information 'optimize)
  ((SPACE 0) (SAFETY 0) (SPEED 1) (COMPILATION-SPEED 1) (DEBUG 2))

Note above that the declaim took effect, and affected the global optimize namespace. If we had been in a compile-file, the shadow environment's optimize namespace would have been affected and not the global space.

  CL-USER(9): (sys::declaration-information 'optimize e2)
  ((SPEED 3) (DEBUG 3) (SAFETY 1) (SPACE 1) (SPEED 1) (COMPILATION-SPEED 1)
   (DEBUG 2))
  CL-USER(10): 

3. Peter Seibel complains in his book (Practical Common Lisp, p 441) that there is no way to call eval with an explicit environment, and he develops a workaround. Well, in Allegro CL, and this module, w can do just that:

  CL-USER(2): (compile
   (defun eval-in-env (form sys::*interpreter-environment*)
     (excl::%eval form)))
  EVAL-IN-ENV
  NIL
  NIL
  CL-USER(3): (setq e1
    (sys::augment-environment
     (sys::make-augmentable-environment-boa :interpreter)
     :variable 'x
     :locative (list 10)))
  #<Augmentable INTERPRETER environment 1 @ #x40c27322>
  CL-USER(4): (describe 'x)
  X is a NEW SYMBOL.
    It is unbound.
    It is INTERNAL in the COMMON-LISP-USER package.
  CL-USER(5): (sys:variable-information 'x)
  NIL
  CL-USER(6): (sys:variable-information 'x e1)
  :LEXICAL
  (10)
  NIL
  T
  CL-USER(7): (eval 'x)
  Error: Attempt to take the value of the unbound variable `X'.
    [condition type: UNBOUND-VARIABLE]
  Restart actions (select using :continue):
   0: Try evaluating X again.
   1: Use :X instead.
   2: Set the symbol-value of X and use its value.
   3: Use a value without setting X.
   4: Return to Top Level (an "abort" restart).
   5: Abort entirely from this (lisp) process.
  [1] CL-USER(8): :res
  CL-USER(9): (eval-in-env 'x e1)
  10
  CL-USER(10): (eval-in-env '(setq x 1) e1)
  1
  CL-USER(11): (sys:variable-information 'x e1)
  :LEXICAL
  (1)
  NIL
  T
  CL-USER(12): 

4. During compilation, variable-information and function-information can tell us things about the names being processed. Note that this will only work on a level 4 Implementation (currently only Allegro CL). Note also that the values of variable and function information slots during compilation are implementation-dependent. (vifitest.cl is needed for this next example.)

  CL-USER(1): (shell "cat vifitest.cl")
  (in-package :user)
  ;; Avoid infinite recursion:
  (eval-when (compile)
    (without-package-locks
     comp::(defmethod print-object ((x varrec) s)
	     (print-unreadable-object (x s :type t :identity nil)
	       (format s "~s~@[ ~:_Specialp: ~a~]~@[ ~:_~a~]"
		       (varrec-name x) (varrec-specialp x) (varrec-type x))))))
  (defmacro with-vi-test ((var &optional all) &body body &environment e)
    (format t "variable-information ~:[~;(all)~] of ~s is ~s~%"
	    all var (multiple-value-list (sys:variable-information var e all)))
    `(progn ,@body))
  (defmacro with-fi-test ((var &optional all spec) &body body &environment e)
    (format t "function-information ~:[~;(all)~]~:[~; w/spec~] of ~s is ~s~%"
	    all spec var (multiple-value-list (sys:function-information var e all spec)))
    `(progn ,@body))
  (defconstant seven 7)
  (defvar *framis*)
  (defmacro not-twelve (x)
    `(/= 12 ,x))
  (define-symbol-macro not-eleven (1- seven))
  (let ((x (multiple-value-list (get-universal-time))))
    (declare (special frob))
    (symbol-macrolet ((pie 22/7))
      (flet ((epi (x) (1+ x)))
	(macrolet ((poi (x)
		     `(sqrt ,x)))
	  (defun load-time ()
	    (with-vi-test (x)
	      (with-vi-test (frob)
		(with-vi-test (*print-base*)
		  (with-vi-test (seven)
		    (with-vi-test (not-eleven)
		      (with-vi-test (pi)
			(with-vi-test (pi t)
			  (with-vi-test (*framis*)
			    (let ((*framis* 10.0))
			      (with-vi-test (*framis*)
				(with-vi-test (unknown)
				  (+ seven x)))))))))))))
	  (defun apple-pie (apple)
	    (with-vi-test (apple)
	      (with-vi-test (pie)
		(with-fi-test (or)
		  (with-fi-test (or t)
		    (with-fi-test (or t t)
		      (with-fi-test (poi)
			(with-fi-test (not-twelve)
			  (with-fi-test (car)
			    (with-fi-test (car t)
			      (with-fi-test (epi)
				(print
				 (values pi
					 (* apple pie))))))))))))))))))
  0
  CL-USER(2): :cf vifitest
  ;;; Compiling file vifitest.cl
  variable-information  of X is (:LEXICAL (#<COMPILER::VARREC X UNKNOWN-TYPE>)
				 NIL :OUTER)
  variable-information  of FROB is (:SPECIAL
				    (#<COMPILER::VARREC FROB Specialp: DECLARE
				       UNKNOWN-TYPE>)
				    NIL :OUTER)
  variable-information  of *PRINT-BASE* is (:SPECIAL NIL NIL)
  variable-information  of SEVEN is (:CONSTANT 7 NIL)
  variable-information  of NOT-ELEVEN is (:SYMBOL-MACRO ((1- SEVEN)) NIL)
  variable-information  of PI is (:CONSTANT 3.141592653589793d0 NIL)
  variable-information (all) of PI is (:CONSTANT 3.141592653589793d0
				       ((TYPE
					 (DOUBLE-FLOAT
					  3.141592653589793d0
					  3.141592653589793d0))))
  variable-information  of *FRAMIS* is (:SPECIAL NIL NIL)
  variable-information  of *FRAMIS* is (:SPECIAL
					(#<COMPILER::VARREC
					   *FRAMIS*
					   Specialp: T
					   UNKNOWN-TYPE>)
					NIL :OUTER)
  variable-information  of UNKNOWN is (NIL)
  variable-information  of APPLE is (:LEXICAL
				     (#<COMPILER::VARREC APPLE UNKNOWN-TYPE>)
				     NIL :OUTER)
  variable-information  of PIE is (:SYMBOL-MACRO (22/7) NIL :OUTER)
  function-information  of OR is (:MACRO NIL NIL)
  function-information (all) of OR is (:MACRO
				       (#<Function MACROEXPAND-1-TRANSFORM>) NIL)
  function-information (all) w/spec of OR is (:SPECIAL-OPERATOR NIL NIL)
  function-information  of POI is (:MACRO
				   (#<Interpreted Function POI @ #x10679afa>)
				   NIL T)
  function-information  of NOT-TWELVE is (:MACRO NIL NIL)
  function-information  of CAR is (:FUNCTION NIL NIL)
  function-information (all) of CAR is (:FUNCTION (#<Function CAR>) NIL)
  function-information  of EPI is (:FUNCTION (#:G45) NIL T)
  ;;; Writing fasl file vifitest.fasl
  ;;; Fasl write complete
  CL-USER(3):