ToCDocOverviewCGDocRelNotesFAQIndexPermutedIndex
Allegro CL version 8.2
Moderately revised from 8.1.
8.1 version

Inspector

This document contains the following sections:

1.0 The inspector introduction
   1.1 Inspector commands
   1.2 The inspector and the right margin
2.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 when using the IDE (where inspection goes on in an Inspect window), you can inspect objects at any time with the :istep top-level command. Outside an inspector command interpreter (described just below), :istep displays an inspection of its argument but does not enter an inspector command interpreter (its behavior is different inside an inspector command interpreter.)

Except when running the Integrated Development Environment, the inspect function invokes a recursive top-level command interpreter as does the :inspect top-level command. (In the IDE inspect brings up an Inspect dialog. 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 (see cgide.htm for information on the IDE). Allegro Composer also provides a window inspector but its interface is different. See composer.htm.)


1.1 Inspector commands

Once the inspector is started, the :istep, whose minimal abbreviation is :i, 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 inspect function or the :inspect top-level command 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

:istep 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 Section 2.0 An example of inspect).

When inspection is initiated with a call to the inspect function, all the inspect commands except :istep 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.

When entered with no arguments, :istep 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 below.

Multiple options can be placed in a single :istep command. Each is processed serially, except intermediate information is not printed. But the pprint option causes the current obejct to be pretty printed, so pprint's interspersed with other commands cause intermediate printing. See the end of the example section for some examples.

Thus :istep commands can look like the following (:i is the abreviation for :istep:

:i    ;; causes the redisplay of the current object

;;  Here are the forms of a single option (x) with
;;  one argument (y) or with two arguments (y and z):
:i <x> 
  OR 
:i <x> <y> 
  OR 
:i <x> <y> <z>

;;  As many options (along with arguments) can appear 
;;  in a single :i command, so in BNF notation:

:i {<x> [<y> [<z>]]}* 

Here is the table of options:

Istep option Arguments Notes
= or nil (i.e. <no arg>) Redisplay the inspection of the current object.
? :istep called with this option prints a message describing the inspector commands
*

:istep 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

:istep *

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

+ x Do (inspect (eval x)).
index :istep 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

:istep 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.
- ^ :istep 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 :istep 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 :istep 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

:istep 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 than 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.

pprint :istep called with this option pretty prints the current object. When you have multiple options in the same command, interspersing pprint's where desired cause the intermediate objects to be printed. Thus :i 7 pprint < tells the system to inspect the component at index 7, pretty print it, and go back to the previous (at index 6) component. :i 7 < would only print the component at index 6.
raw t-or-nil :istep 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 :istep 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, :istep displays the elements of the inspect stack so the user can see the genealogy of the current object relative to the object specified by :istep * or (inspect *).

1.2 The inspector and the right margin

The inspector uses the right margin (the value of *print-right-margin*) to determine when to abbreviate data displayed. The following example shows that making *print-right-margin* causes more data to be displayed.

;; We are inspecting an internal variable, excl::*shared-cons-table*,
;; which has largish but not unreasonably sized data elements:

cl-user(1): :inspect excl::*shared-cons-table*
A tenured #<equal hash-table (sans values) with weak keys, 16882 entries @
            #x4016bfba>
   0 key ----------> ((:internal) ...), a proper list with 3 elements
   1 key ----------> (# . excl::generate-eql-match-tree), a dotted list with 1 element
   2 key ----------> (ff::value ff::pointer ff::extra ...), a proper list with 5 elements
   3 key ----------> (comp::con comp::cycle), a proper list with 2 elements
   4 key ----------> (comp::syms), a proper list with 1 element
   5 key ----------> (&optional comp::nocommit), a proper list with 2 elements
   6 key ----------> (((method) . mp:process-name) ...), a proper list with 2 elements
   7 key ----------> (# . excl.yacc::grammar-defaults), a dotted list with 1 element
   8 key ----------> (# . :modeless-end-anchor-no-newline), a dotted list with 1 element
   9 key ----------> (# ...), a proper list with 3 elements
  10 key ----------> (regexp::end regexp::back-end), a proper list with 2 elements
  11 key ----------> (#:class #:kids #:type ...), a proper list with 19 elements
  [...]

;; remaining printed entries deleted

;; Next, with a larger right margin set:

[1i] cl-user(2): :i q
cl-user(3): (setq *print-right-margin* 150)
150
cl-user(4): :in excl::*shared-cons-table*
A tenured #<equal hash-table (sans values) with weak keys, 16882 entries @ #x4016bfba>
   0 key ----------> ((:internal) ((method) . lep::compute-reply) lep::tpl-command-session), a proper list with 3 elements
   1 key ----------> ((labels) . excl::generate-eql-match-tree), a dotted list with 1 element
   2 key ----------> (ff::value ff::pointer ff::extra ff::offset ff::width), a proper list with 5 elements
   3 key ----------> (comp::con comp::cycle), a proper list with 2 elements
   4 key ----------> (comp::syms), a proper list with 1 element
   5 key ----------> (&optional comp::nocommit), a proper list with 2 elements
   6 key ----------> (((method) . mp:process-name) mp:process), a proper list with 2 elements
   7 key ----------> ((setf) . excl.yacc::grammar-defaults), a dotted list with 1 element
   8 key ----------> ((:property) . :modeless-end-anchor-no-newline), a dotted list with 1 element
   9 key ----------> (((method) . regexp::fe-compile-pass3-rec) regexp::ast-greedy-optional-repetition t), a proper list with 3 elements
  10 key ----------> (regexp::end regexp::back-end), a proper list with 2 elements
  11 key ----------> (#:class #:kids #:type #:bits #:env #:inline-info #:source #:vars #:vals #:srcs ...), a proper list with 19 elements


2.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.

cl-user(1): (inspect #(car x 12 #\a #*100 (1/2 0.5 0.5d0)))
A simple t vector (6) @ #x4566d32
   0-> The symbol car
   1-> The symbol x
   2-> fixnum 12 [#x00000030]
   3-> character #\a [#x0000030e] char-code #x0061
   4-> A simple-bit-vector (3) #*100
   5-> (1/2 0.5 0.5d0), a proper list with 3 elements
[1i] cl-user(2): :i 0
The symbol car @ #x400a1d7
  which is an external symbol in the common-lisp package
   0 type ---------> Bit field: #x07
   1 flags --------> Bit field: #x24
   2 hash ---------> Bit field: #x2c85
   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 12 elements
[1i] cl-user(3): :i 7
A proper list @ #x4614b49 with 12 elements
   0-> The symbol excl::.args.
   1-> (1 . 1), a dotted list with 1 element
   2-> The symbol comp::.side-effect-free-fcn.
   3-> The symbol t
   4-> The symbol comp::.comp-args.
   5-> (1 . 1), a dotted list with 1 element
   6-> The symbol comp::.qc-call-handler.
   7-> #<Closure (:internal
                  (flet (:top-level-form "qbif.cl" 8473)
                    comp::qc-car-cdr-closure)
                  0) [car]
         @ #x40c5b7a>
   8-> The symbol excl::setf-inverse
   9-> The symbol excl::.inv-car
  10-> The symbol excl::dynamic-extent-arg-template
  11-> The symbol nil
[1i] cl-user(4): :i tree
In first recursive call to inspect.
The current object is:
(excl::.args. (1 . 1) ...), a proper list with 12 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] cl-user(5): :i -
The symbol car @ #x400a1d7
  which is an external symbol in the common-lisp package
   0 type ---------> Bit field: #x07
   1 flags --------> Bit field: #x24
   2 hash ---------> Bit field: #x2c85
   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 12 elements
[1i] cl-user(6): :i 2
Cannot select the element indexed by 2
[1i] cl-user(7): :i -
A simple t vector (6) @ #x4566d32
   0-> The symbol car
   1-> The symbol x
   2-> fixnum 12 [#x00000030]
   3-> character #\a [#x0000030e] char-code #x0061
   4-> A simple-bit-vector (3) #*100
   5-> (1/2 0.5 0.5d0), a proper list with 3 elements
[1i] cl-user(8): :i 1
The symbol x @ #x456693f
  which is an internal symbol in the common-lisp-user package
   0 type ---------> Bit field: #x07
   1 flags --------> Bit field: #x00
   2 hash ---------> Bit field: #x207a
   3 value --------> ..unbound..
   4 package ------> The common-lisp-user package
   5 function -----> #<Function (unnamed) @ #x4002532>
   6 name ---------> A simple-string (1) "x"
   7 plist --------> The symbol nil
[1i] cl-user(9): :i set value 0
The symbol x @ #x456693f
  which is an internal symbol in the common-lisp-user package
   0 type ---------> Bit field: #x07
   1 flags --------> Bit field: #x00
   2 hash ---------> Bit field: #x207a
   3 value --------> fixnum 0 [#x00000000]
   4 package ------> The common-lisp-user package
   5 function -----> #<Function (unnamed) @ #x4002532>
   6 name ---------> A simple-string (1) "x"
   7 plist --------> The symbol nil
[1i] cl-user(10): :i -
A simple t vector (6) @ #x4566d32
   0-> The symbol car
   1-> The symbol x
   2-> fixnum 12 [#x00000030]
   3-> character #\a [#x0000030e] char-code #x0061
   4-> A simple-bit-vector (3) #*100
   5-> (1/2 0.5 0.5d0), a proper list with 3 elements
[1i] cl-user(11): :i 5
A proper list @ #x45fe489 with 3 elements
   0-> ratio object = 1/2
   1-> single-float = 0.5 [#x3f000000]
   2-> double-float = 0.5d0 [#x3fe00000 00000000]
[1i] cl-user(12): :i set tail (cdr *)
A closed list @ #x45fe489 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] cl-user(13): :i tail
Object has no selectable component named tail
[1i] cl-user(14): :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 ...))
cl-user(15): 

;; Inspection of hashtables starting in release 5.0.1.
;; Inspection of hash tables now shows a nice listing of key/value
;; pairs. In the initial implementation, you could't inspect individual 
;; keys or values without using raw mode but now you can.
;; Further, values (but not keys) can be set, as we show.

cl-user(15): (setq x (make-hash-table :size 5))
#<eql hash-table with 0 entries @ #x4572aca>
cl-user(16): (setf (gethash 'a x) 'a1 
                   (gethash 'b x) 'b1 (gethash 'c x) 'c1)
c1
cl-user(17): (inspect x)
#<eql hash-table with 3 entries @ #x4572aca>
   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(18): :i set 3 'b1new
#<eql hash-table with 3 entries @ #x54c6ba2>
   0 key ----------> The symbol a
   1 value --------> The symbol a1
   2 key ----------> The symbol b
   3 value --------> The symbol b1new
   4 key ----------> The symbol c
   5 value --------> The symbol c1
[1i] user(19): :i 3
The symbol b1new @ #x580c457
  which is an internal symbol in the common-lisp-user package
   0 type ---------> Bit field: #x01
   1 flags --------> Bit field: #x00
   2 hash ---------> Bit field: #x41d4
   3 value --------> ..unbound..
   4 package ------> The common-lisp-user package
   5 function -----> #<Function (unnamed) @ #x4001872>
   6 name ---------> A simple-string (5) "b1new"
   7 plist --------> The symbol nil
[1i] user(20): :i q
#<eql hash-table with 3 entries @ #x4572aca>
cl-user(21): 

;;  Here are some examples using multiple options in the
;;  same command, showing also the use of pprint to display
;;  intermediate information:
cl-user(1): :i 'car
The symbol car @ #x7100c337
  which is an external symbol in the common-lisp package
   0 type ---------> Bit field: #x07
   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 --------> <...>, a proper list with 8 elements
cl-user(2): :i 7 pprint <

(compiler::.side-effect-free-fcn. t compiler::.comp-args. (1 . 1)
 compiler::.qc-call-handler.
 #<Closure (:internal
            (flet (:top-level-form "qbif.cl" 8593)
              compiler::qc-car-cdr-closure)
            0) [car]
   @ #x71353c8a>
 excl::setf-inverse excl::.inv-car)
A simple-string (3) "car" @ #x7101a1ca
   0-> The character #\c [#x63]
   1-> The character #\a [#x61]
   2-> The character #\r [#x72]
cl-user(3): 


;;  Here several objects can be printed at once:

cl-user(10): (inspect *print-pprint-dispatch*)
pprint-dispatch struct @ #x7126301a = #S(pprint-dispatch ...)
   0 Class --------> #<structure-class pprint-dispatch>
   1 conses-with-cars -> #<eq hash-table with 70 entries @ #x71278eca>
   2 structures ---> #<equal hash-table with 0 entries @ #x71278eea>
   3 others -------> (#S(excl::entry ...) ...), a proper list with 3 elements
[1i] cl-user(11): :i 3
A proper list @ #x71954281 with 3 elements
   0-> excl::entry struct = #S(excl::entry ...)
   1-> excl::entry struct = #S(excl::entry ...)
   2-> excl::entry struct = #S(excl::entry ...)
[1i] cl-user(12): :i 0 pprint > pprint > pprint -

#S(excl::entry :test #<Function function-call-p>
               :fn #<Function alternative-fn-call>
               :full-spec ((-5) (satisfies excl::function-call-p)))

#S(excl::entry :test #<Function consp>
               :fn #<Function pprint-fill-no-annotation>
               :full-spec ((-10) cons))

#S(excl::entry :test #<Function always-true>
               :fn #<Function default-use-print-object>
               :full-spec ((-10) t))
A proper list @ #x71954281 with 3 elements
   0-> excl::entry struct = #S(excl::entry ...)
   1-> excl::entry struct = #S(excl::entry ...)
   2-> excl::entry struct = #S(excl::entry ...)
[1i] cl-user(13): 


Copyright (c) 1998-2012, Franz Inc. Oakland, CA., USA. All rights reserved.
This page has had moderate revisions compared to the 8.1 page.
Created 2010.1.21.

ToCDocOverviewCGDocRelNotesFAQIndexPermutedIndex
Allegro CL version 8.2
Moderately revised from 8.1.
8.1 version