Inspector

$Revision: 5.0.2.5 $

The document introduction.htm provides an overview of the Allegro CL documentation with links to all major documents. The document index.htm is an index with pointers to every documented object (operators, variables, etc.) The revision number of this document is below the title. These documents may be revised from time to time between releases.

1.0 The inspector introduction
2.0 Inspect commands
3.0 An example of inspect

1.0 The inspector introduction

The inspector allows the user to examine the internal structure of Allegro CL objects. The commands that control inspecting objects are part of the Allegro CL top level command structure.

Except on Windows when running the Integrated Development Environment, the cl:inspect function invokes a recursive top-level command interpreter. (In the IDE cl:inspect brings up an Inspector window. The top-level command :inspect does not work when the IDE is running since all interaction with the inspector is through the Inspector window. The IDE inspector is not further discussed in this document. Allegro Composer also provides a window inspector but its interface is different. See the Allegro Composer printed manual.)

Once the inspector is started, the :inspect top-level command can be used, as documented here, to further inspect objects, to set values, and so on. All the normal Allegro CL commands are available while inspecting objects. You know inspector commands are available (and an object is being inspected) when the prompt contains an i, like [1i] USER(3):.

The inspector maintains a stack of objects whose components are being inspected. The top object on that stack is called the current object, and can be displayed at any time. When the current object has components, these are displayed with prefixes of the form

index -> name

where index is a numeric index associated with the component and name is a symbolic name for the component. The user can select a component of the current object by name or index, and add it to the stack, making the selected component the new current object. The user can also pop the current object off the stack, making its parent object the current object again. In this way the user can explore the structure of compound objects to any depth.

To begin inspecting an object, call the cl:inspect function with the object as an argument. A break loop is entered when the function is called and exited when inspecting is stopped with the command

:inspect q

The break-level portion of the prompt has an appended `i' to indicate that Lisp is in an inspection break loop (see the example in 3.0 An example of inspect).

Inspection can be started with the :inspect command and a break loop is not entered in that case. However, it is not always possible to initiate an inspection with the command :inspect since that command may confound what you want to inspect with one of its options. For that reason, we recommend starting an inspection with the function inspect.

When inspection is initiated with a call to the inspect function, all the inspect commands except :inspect q set the variable common-lisp:* to the current object being inspected.

On Unix, a windowized inspector is provided with Allegro Composer, an add-on product which provides a programming environment for Allegro CL. See the Allegro Composer User Guide for more information.

On Windows, the Integrated Development Environment has a windowized inspector. See the help file for the IDE for more information.

2.0 Inspect commands

The function cl:inspect and the :inspect top-level command control the inspector.

[Function]
cl:inspect

Arguments: object

Perform special bindings of the inspector's state variables, including the inspect stack. Then initialize the (new) inspect stack to contain only object; display object's structure, and then invoke a top-level read-eval-print loop. The read-eval-print loop is terminated when the user enters the command :inspect q and inspect then returns object. (:pop will also exit the break loop, of course.) This is a standard Common Lisp function.

When entered with no arguments, :inspect redisplays the structure of the current object or prints an error message if there is no current object. When entered with an option, performs as described in the table:

Inspect option Arguments Notes
=
nil
<no arg>
  Redisplay the inspection of the current object.
?   :inspect called with this option prints a message describing the inspector commands
*   :inspect called with this option initializes the inspect stack to hold only the value of *, that is, the first result from the last top-level evaluation. This object becomes the inspector's current object and its structure is displayed.

(inspect *)

is like an

:inspect *

invoked within a recursive read-eval-print loop that sets up its own inspect stack.

+ x Do (inspect (eval x)).
index   :inspect called with this option, where index is an integer, selects the indexth component of the current object. The selection is made according to the component indices displayed by inspect, which may not be the same as the element numbers used by other Allegro CL functions. Some object components cannot be selected. Elements of a specialized vector, for example, are displayed as components but cannot be made the current object. Attempting to select such a component will elicit an explanatory message but will not signal an error.
name   :inspect called with this option, where name is a symbol that is not one of the special inspector command options (such as *, q, and set), selects the named component of the current object. The component names are those displayed by inspect. They are compared using string-equal, so case and package are not significant. If a component's name is shadowed by another component's name or by one of the inspector command symbols, then the numeric index can be used to select the shadowed component. The inspector considers the tail of a dotted list to be a component with no numeric index but with the component name tail. The tail of a proper list can also be designated by name, even though no tail component is displayed for such an object. In addition, the component names car, cdr, caar, cadr, cdar, cddr, caaar, ... cdddr, caaaar, ... cddddr, are recognized for selecting the named components of list structures.

As with selection by index, attempting to select an unselectable component by name results in an explanation but no error.

form   Evaluate form and initialize inspector to inspect the result. form cannot be a number or a symbol.
-
^
  :inspect called with either of these options removes the current object from the inspect stack and displays the new current object. The new current object will be the parent of the old current object. If the inspect stack is empty or has only one entry, then the current object is not changed and an explanatory message is displayed.
<
>
  Inspect the previous (<) or next (>) indexed component of the current object.
q   :inspect called with this option clears the inspect stack, so that there is no current object. If there is an active invocation of inspect, then the inner-most invocation returns to its caller. (This is important if you are looking at a large object which you want to be garbage collected. No object on the inspect stack will be reclaimed by the garbage collector.)
set index-or-name form When :inspect is called with this option, form is evaluated for a single value. If index-or-name is an index (i.e. an integer) and if the current object has a settable component indexed by it, then the value of form is stored in that component. If index-or-name is a name (i.e. a symbol which is not one of the inspect options) and if the current object has a settable component with that name, then the value of form is stored in that component.

If there is no current object, or it has no settable component identified by index-or-name, or if the type of that component does not admit assignment of form's value, then an explanatory message is displayed and the component is not changed. Many components that are not selectable are settable. Elements of specialized vectors, for example, are settable.

print max :inspect called with this option limits the number of components that it displays. The maximum number defaults to 10, but can be changed by using this command. max must be a positive integer. The value starts at 10 for each invocation of the inspector (that is, each entry into an inspector break loop).

If there are more components that the maximum specified, that many are printed, then suspension points (`...') then the final component (whatever its index). If there is exactly one more component than the maximum, all components are printed without suspension points.

raw t-or-nil :inspect called with raw t puts the inspector into raw mode while nil returns it to regular mode. In raw mode, standard-instances are viewed with no special interpretation, instead of having its slots walked in standard CLOS manner. Raw mode is remembered in deeper recursions of inspect.
skip n :inspect called with this option redisplays the current object, omitting the first n components. This allows the display of any section of a large structure or array without filling the screen with unwanted information.
tree   When called with this option, :inspect displays the elements of the inspect stack so the user can see the genealogy of the current object relative to the object specified by :inspect * or (inspect *).

3.0 An example of inspect

The following example shows how the inspect commands are used.

;; Please note that this manual is generic over several
;; implementations of Allegro CL. The exact representation
;; of the objects displayed here may differ in your version.
;;
;; Please also note: 
;;
;; 1. After the initial call to INSPECT, the prompt changes
;; to [1i] USER(<num>):. The `i' indicates an inspect 
;; break loop
;;
;; 2. Some lines wrapped when printed and we have added
;; carriage returns to prettify things.

USER(3): (inspect #(car x 12 #\a #*100 (1/2 0.5 0.5d0)))
A simple T vector (6) @ #x304e6a9a
   0-> The symbol CAR
   1-> The symbol X
   2-> fixnum 12 [#x00000030]
   3-> character #\a [#x0000030e] char-code #x61
   4-> A simple-bit-vector (3) #*100
   5-> (1/2 0.5 0.5d0), a proper list with 3 elements
[1i] USER(4): :i 0
The symbol CAR @ #x30399787
  which is an EXTERNAL symbol in the COMMON-LISP package
   0 type ---------> Bit field: #x02
   1 flags --------> Bit field: #x24
   2 hash ---------> Bit field: #x61d8
   3 value --------> ..unbound..
   4 package ------> The COMMON-LISP package
   5 function -----> #<Function CAR>
   6 name ---------> A simple-string (3) "CAR"
   7 plist --------> (EXCL::.ARGS. (1 . 1) ...), a proper list with 10 elements
[1i] USER(5): :i 7
A proper list @ #x305c3c59 with 10 elements
   0-> The symbol EXCL::.ARGS.
   1-> (1 . 1), a dotted list with 1 element
   2-> The symbol COMP::.COMP-ARGS.
   3-> (1 . 1), a dotted list with 1 element
   4-> The symbol COMP::.QC-CALL-HANDLER.
   5-> #<Closure (:INTERNAL (FLET (:TOP-LEVEL-FORM "qbif.cl" 16575) COMP::QC-CAR-CDR-CLOSURE) 0) [CAR] @
         #x3005a0ea>
   6-> The symbol COMP::.SIDE-EFFECT-FREE-FCN.
   7-> The symbol T
   8-> The symbol EXCL::SETF-INVERSE
   9-> The symbol EXCL::.INV-CAR
[1i] USER(6): :i tree
In first recursive call to inspect.
The current object is:
(EXCL::.ARGS. (1 . 1) ...), a proper list with 10 elements, which is component number 7 of
The symbol CAR, which is component number 0 of
simple T vector (6) = #(CAR X 12 ...), which was selected by "(inspect ...)"
[1i] USER(7): :i -
The symbol CAR @ #x30399787
  which is an EXTERNAL symbol in the COMMON-LISP package
   0 type ---------> Bit field: #x02
   1 flags --------> Bit field: #x24
   2 hash ---------> Bit field: #x61d8
   3 value --------> ..unbound..
   4 package ------> The COMMON-LISP package
   5 function -----> #<Function CAR>
   6 name ---------> A simple-string (3) "CAR"
   7 plist --------> (EXCL::.ARGS. (1 . 1) ...), a proper list with 10 elements
[1i] USER(8): :i 2
Cannot select the element indexed by 2
[1i] USER(9): :i -
A simple T vector (6) @ #x304e6a9a
   0-> The symbol CAR
   1-> The symbol X
   2-> fixnum 12 [#x00000030]
   3-> character #\a [#x0000030e] char-code #x61
   4-> A simple-bit-vector (3) #*100
   5-> (1/2 0.5 0.5d0), a proper list with 3 elements
[1i] USER(10): :i 1
The symbol X @ #x305ca457
  which is an INTERNAL symbol in the COMMON-LISP-USER package
   0 type ---------> Bit field: #x02
   1 flags --------> Bit field: #x00
   2 hash ---------> Bit field: #x0079
   3 value --------> ..unbound..
   4 package ------> The COMMON-LISP-USER package
   5 function -----> #<Function (unnamed) @ #x3000141a>
   6 name ---------> A simple-string (1) "X"
   7 plist --------> The symbol NIL
[1i] USER(11): :i set value 0
The symbol X @ #x305ca457
  which is an INTERNAL symbol in the COMMON-LISP-USER package
   0 type ---------> Bit field: #x02
   1 flags --------> Bit field: #x00
   2 hash ---------> Bit field: #x0079
   3 value --------> fixnum 0 [#x00000000]
   4 package ------> The COMMON-LISP-USER package
   5 function -----> #<Function (unnamed) @ #x3000141a>
   6 name ---------> A simple-string (1) "X"
   7 plist --------> The symbol NIL
[1i] USER(12): :i -
A simple T vector (6) @ #x304e6a9a
   0-> The symbol CAR
   1-> The symbol X
   2-> fixnum 12 [#x00000030]
   3-> character #\a [#x0000030e] char-code #x61
   4-> A simple-bit-vector (3) #*100
   5-> (1/2 0.5 0.5d0), a proper list with 3 elements
[1i] USER(13): :i 5
A proper list @ #x305aa1d9 with 3 elements
   0-> RATIO object = 1/2
   1-> single-float = 0.5 [#x3f000000]
   2-> double-float = 0.5d0 [#x3fe00000 00000000]
[1i] USER(14): :i set tail (cdr *)
A closed list @ #x305aa1d9 with 1-element header and 2-element cycle
   0-> RATIO object = 1/2
   1-> single-float = 0.5 [#x3f000000]
   2-> double-float = 0.5d0 [#x3fe00000 00000000]
   3 == 1
[1i] USER(15): :i tail
Object has no selectable component named TAIL
[1i] USER(16): :i q
#(CAR X 12 #\a #*100 (1/2 0.5 0.5d0 0.5 0.5d0 0.5 0.5d0 0.5 0.5d0 0.5 ...))
USER(17): 
;; Inspection of hashtables starting in release 5.0.1.
;; Inspection of hash tables now shows a nice listing of key/value
;; pairs. Warning: you can't inspect individual keys or values from
;; this display; use ":i raw" to look into keys or values.

USER(1): (setq x (make-hash-table :size 5))
#<EQL hash-table with 0 entries @ #x304cd2e2>
USER(2): (setf (gethash 'a x) 'a1 (gethash 'b x) 'b1 (gethash 'c x) 'c1)
C1
USER(3): (inspect x)
#<EQL hash-table with 3 entries @ #x304cd2e2>
   0 KEY ----------> The symbol A
   1 VALUE --------> The symbol A1
   2 KEY ----------> The symbol B
   3 VALUE --------> The symbol B1
   4 KEY ----------> The symbol C
   5 VALUE --------> The symbol C1
[1i] USER(4): :i raw
#<EQL hash-table with 3 entries @ #x304cd2e2>
   0 excl-type ----> Bit field: #x0a
   1 flags --------> Bit field: #x00
   2 keys ---------> simple T vector (7) = #(A B C ...)
   3 spcl-hash-fn -> The symbol NIL
   4 rehash-size --> single-float = 1.2 [#x3f99999a]
   5 threshold ----> fixnum 4 [#x00000010]
   6 entries ------> fixnum 3 [#x0000000c]
   7 table --------> simple T vector (7) = #(A1 B1 C1 NIL NIL NIL NIL)
   8 hash-tick ----> fixnum 37 [#x00000094]
[1i] USER(5): 

Copyright (C) 1998-1999, Franz Inc., Berkeley, CA. All Rights Reserved.