[Openmcl-devel] Getting inside a compiled-lexical-closure
Gary Byers
gb at clozure.com
Wed May 19 04:18:09 PDT 2004
All memory-allocated lisp objects in OpenMCL that aren't CONS cells
(strings, functions, floats, bignums, processes, classes, instances,
MACPTRs, CL arrays, ...) are called "UVECTORS". A UVECTOR is basically
a typed vector-like sequence of elements; the number of elements in
a UVECTOR is returned by the function CCL:UVSIZE:
? (CCL:UVSIZE "abcd")
4
? (CCL:UVSIZE PI)
3 ; a DOUBLE-FLOAT is 3 32-bit words, at this level
The function CCL:UVREF returns the I'th element of a UVECTOR:
? (CCL:UVREF "abcd" 0)
#\a
? (CCL:UVREF "abcd" 1)
#\b
? (CCL:UVREF "abcd" 4)
-> an error
CCL:UVREF can be used with SETF (and you can get yourself in all kinds of
trouble because of this ...)
It's not too hard to write a function that shows the contents of any
UVECTOR:
? (defun show-uvector (v)
(dotimes (i (uvsize v) (values))
(format t "~&~d: ~s" i (uvref v i))))
? (show-uvector "abcd")
0: #\a
1: #\b
2: #\c
3: #\d
?
A FUNCTION is just a special kind of uvector: the 0th element is a special
type of UVECTOR (a CODE-VECTOR) that contains machine instructions; the
last element is a fixnum that encodes information about the function,
and the intervening elements are constant lisp objects referenced by the
function and/or debugging information.
? (show-uvector #'show-uvector)
0: #<CODE-VECTOR #x536A0AE>
1: "~&~d: ~s"
2: FORMAT
3: (FUNCTION-SYMBOL-MAP (#(I #:G103 V) . #(31 56 140 575 52 140 63 28 140)))
4: SHOW-UVECTOR
5: 8388864
A lexical clozure is just a special kind of function (identified by
certain bit patterns in the fixnum in its last element). The 0th
element is a special CODE-VECTOR, the 1st element is the "real"
function, the last element is a fixnum and the next-to-last is always
NIL, and the intervening elements (starting at element 2) are
values that the real function "inherits" from the lexical environment.
(If any of these values are SETQed, the value will actually be a
1-element UVECTOR of type VALUE-CELL, and the actual value will be
at (UVREF <that VALUE-CELL> 0).)
? (let ((a-list '(1 2 3))) (defun foobar (x) #'(lambda ()
(append x (list-all-packages) a-\
list))))
FOOBAR
? (show-uvector #'foobar)
0: #<CODE-VECTOR #x10104D6>
1: #<Compiled-function FOOBAR (Non-Global) #x536C86E>
2: (1 2 3)
3: NIL
4: 16777216
The number of closed-over/inherited values in a clozure is its UVIZE - 4
(1 in the example above)
On Wed, 19 May 2004, Sven Van Caekenberghe wrote:
> In OpenMCL 0.13.6, I want to see and access some of the variables a
> compiled-lexical-closure is closed over (to get access to the start
> arguments of a process):
>
> In OpenMCL 0.14.1p1 I can do this:
>
> CL-USER> (let ((a-list '(1 2 3))) (defun foobar (x) #'(lambda ()
> (append x (list-all-packages) a-list))))
> Foobar
> CL-USER> (foobar '(100 200))
> #<COMPILED-LEXICAL-CLOSURE #x54807A6>
> CL-USER> (describe *)
> #<COMPILED-LEXICAL-CLOSURE #x53D80D6>
> Name: NIL
> Arglist (analysis): NIL
> Inner lfun: #<Anonymous Function #x53D793E>
> Closed over values
> X: (100 200)
> A-LIST: (1 2 3)
> ; No value
>
> In OpenMCL 0.13.6 this fails:
>
> Welcome to OpenMCL Version (Beta: Darwin) 0.13.6!
> ? (let ((a-list '(1 2 3))) (defun foobar (x) #'(lambda () (append x
> (list-all-packages) a-list))))
> FOOBAR
> ? (setf foo (foobar '(100 200))
> )
> #<COMPILED-LEXICAL-CLOSURE #x52ACCDE>
> ? (describe foo)
> > Error: Slot INSPECTOR::N-CLOSED is unbound in
> #<INSPECTOR::CLOSURE-INSPECTOR #x52ACECE>
> > While executing: #<CCL::STANDARD-KERNEL-METHOD SLOT-UNBOUND (T T T)>
> > Type :POP to abort.
> Type :? for other options.
>
> This is probably an older bug that got fixed.
>
> But anyway I just want the list of closed over values, as a first class
> lisp object...
>
> Is there some way to do this using internal functions ?
>
> Sven
>
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
>
More information about the Openmcl-devel
mailing list