From: Ari Johnson
Subject: Python internals - any pointers on poking around?
Date: 
Message-ID: <871w6zcuzg.fsf@bender.theari.com>
I am trying to wrap my head around the internals of the Python
compiler, or at least the version of it in SBCL since I've found it to
be much easier to track the SBCL sources and they seem to be more
cleanly organized than CMUCL's.

What I'd really like to do is get into the compiler and take a look at
the internal data structures, such as with SLIME, to interactively see
what happens at each step of the way.

I've tried reading :trace-file output, but it leaves a lot out of the
process and in particular does not make clear where the initial
source-to-IR1 transformations come from.  Reading the compiler sources
themselves makes it hard to find the connections between data
structures and translations, mostly because there is just so much
code.

Ideally, I'd like to be able to step through a call to the compiler,
watching which functions get called along the way and inspecting local
variables at each point.

Does anyone have pointers on getting an interactive handle on the
compiler internals?  Thanks.

From: gavino
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <68a23635-3f50-4618-b4bd-afd3c598d55a@i7g2000prf.googlegroups.com>
On Feb 26, 12:40 pm, Ari Johnson <·········@gmail.com> wrote:
> I am trying to wrap my head around the internals of the Python
> compiler, or at least the version of it in SBCL since I've found it to
> be much easier to track the SBCL sources and they seem to be more
> cleanly organized than CMUCL's.
>
> What I'd really like to do is get into the compiler and take a look at
> the internal data structures, such as with SLIME, to interactively see
> what happens at each step of the way.
>
> I've tried reading :trace-file output, but it leaves a lot out of the
> process and in particular does not make clear where the initial
> source-to-IR1 transformations come from.  Reading the compiler sources
> themselves makes it hard to find the connections between data
> structures and translations, mostly because there is just so much
> code.
>
> Ideally, I'd like to be able to step through a call to the compiler,
> watching which functions get called along the way and inspecting local
> variables at each point.
>
> Does anyone have pointers on getting an interactive handle on the
> compiler internals?  Thanks.

python is not quite lisp yet, give it a decade.....
From: Ari Johnson
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <m28x17i43j.fsf@hermes.theari.com>
gavino <·········@gmail.com> writes:

>> On Feb 26, 12:40 pm, Ari Johnson <·········@gmail.com> wrote:
>> I am trying to wrap my head around the internals of the Python
>> compiler, or at least the version of it in SBCL since I've found it to
>> be much easier to track the SBCL sources and they seem to be more
>> cleanly organized than CMUCL's.
>>
>> What I'd really like to do is get into the compiler and take a look at
>> the internal data structures, such as with SLIME, to interactively see
>> what happens at each step of the way.
>>
>> I've tried reading :trace-file output, but it leaves a lot out of the
>> process and in particular does not make clear where the initial
>> source-to-IR1 transformations come from.  Reading the compiler sources
>> themselves makes it hard to find the connections between data
>> structures and translations, mostly because there is just so much
>> code.
>>
>> Ideally, I'd like to be able to step through a call to the compiler,
>> watching which functions get called along the way and inspecting local
>> variables at each point.
>>
>> Does anyone have pointers on getting an interactive handle on the
>> compiler internals?  Thanks.
>
> python is not quite lisp yet, give it a decade.....

You've got the wrong Python.  A basic knowledge of English would have
allowed you to understand that from what I wrote.  What's
disappointing, though, is that nobody but gavino has responded so
far. :P
From: gavino
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <25c69b28-50e9-4526-9954-ad3aff03604f@62g2000hsn.googlegroups.com>
On Feb 26, 5:24 pm, Ari Johnson <·········@gmail.com> wrote:
> gavino <·········@gmail.com> writes:
> >> On Feb 26, 12:40 pm, Ari Johnson <·········@gmail.com> wrote:
> >> I am trying to wrap my head around the internals of the Python
> >> compiler, or at least the version of it in SBCL since I've found it to
> >> be much easier to track the SBCL sources and they seem to be more
> >> cleanly organized than CMUCL's.
>
> >> What I'd really like to do is get into the compiler and take a look at
> >> the internal data structures, such as with SLIME, to interactively see
> >> what happens at each step of the way.
>
> >> I've tried reading :trace-file output, but it leaves a lot out of the
> >> process and in particular does not make clear where the initial
> >> source-to-IR1 transformations come from.  Reading the compiler sources
> >> themselves makes it hard to find the connections between data
> >> structures and translations, mostly because there is just so much
> >> code.
>
> >> Ideally, I'd like to be able to step through a call to the compiler,
> >> watching which functions get called along the way and inspecting local
> >> variables at each point.
>
> >> Does anyone have pointers on getting an interactive handle on the
> >> compiler internals?  Thanks.
>
> > python is not quite lisp yet, give it a decade.....
>
> You've got the wrong Python.  A basic knowledge of English would have
> allowed you to understand that from what I wrote.  What's
> disappointing, though, is that nobody but gavino has responded so
> far. :P

Oh really? What exact part of english am I missing?
From: jc
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <0389908d-2e13-4c66-9fc5-4a8d9fb4e6a5@e10g2000prf.googlegroups.com>
On Feb 26, 5:32 pm, gavino <·········@gmail.com> wrote:
> On Feb 26, 5:24 pm, Ari Johnson <·········@gmail.com> wrote:
>
>
>
> > gavino <·········@gmail.com> writes:
> > >> On Feb 26, 12:40 pm, Ari Johnson <·········@gmail.com> wrote:
> > >> I am trying to wrap my head around the internals of the Python
> > >> compiler, or at least the version of it in SBCL since I've found it to
> > >> be much easier to track the SBCL sources and they seem to be more
> > >> cleanly organized than CMUCL's.
>
> > >> What I'd really like to do is get into the compiler and take a look at
> > >> the internal data structures, such as with SLIME, to interactively see
> > >> what happens at each step of the way.
>
> > >> I've tried reading :trace-file output, but it leaves a lot out of the
> > >> process and in particular does not make clear where the initial
> > >> source-to-IR1 transformations come from.  Reading the compiler sources
> > >> themselves makes it hard to find the connections between data
> > >> structures and translations, mostly because there is just so much
> > >> code.
>
> > >> Ideally, I'd like to be able to step through a call to the compiler,
> > >> watching which functions get called along the way and inspecting local
> > >> variables at each point.
>
> > >> Does anyone have pointers on getting an interactive handle on the
> > >> compiler internals?  Thanks.
>
> > > python is not quite lisp yet, give it a decade.....
>
> > You've got the wrong Python.  A basic knowledge of English would have
> > allowed you to understand that from what I wrote.  What's
> > disappointing, though, is that nobody but gavino has responded so
> > far. :P
>
> Oh really? What exact part of english am I missing?

The part that allows you to recognize that in the fragment, "Python
compiler," the word "compiler" modifies the word "Python," making it
clear that the post was not about the python language, but about a
python compiler implemented in lisp (of which I know nothing about,
sorry).
From: gavino
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <40dd6d24-e006-49b4-aff0-f7bdc51f580b@8g2000hse.googlegroups.com>
On Feb 26, 5:42 pm, jc <··········@gmail.com> wrote:
> On Feb 26, 5:32 pm, gavino <·········@gmail.com> wrote:
>
>
>
> > On Feb 26, 5:24 pm, Ari Johnson <·········@gmail.com> wrote:
>
> > > gavino <·········@gmail.com> writes:
> > > >> On Feb 26, 12:40 pm, Ari Johnson <·········@gmail.com> wrote:
> > > >> I am trying to wrap my head around the internals of the Python
> > > >> compiler, or at least the version of it in SBCL since I've found it to
> > > >> be much easier to track the SBCL sources and they seem to be more
> > > >> cleanly organized than CMUCL's.
>
> > > >> What I'd really like to do is get into the compiler and take a look at
> > > >> the internal data structures, such as with SLIME, to interactively see
> > > >> what happens at each step of the way.
>
> > > >> I've tried reading :trace-file output, but it leaves a lot out of the
> > > >> process and in particular does not make clear where the initial
> > > >> source-to-IR1 transformations come from.  Reading the compiler sources
> > > >> themselves makes it hard to find the connections between data
> > > >> structures and translations, mostly because there is just so much
> > > >> code.
>
> > > >> Ideally, I'd like to be able to step through a call to the compiler,
> > > >> watching which functions get called along the way and inspecting local
> > > >> variables at each point.
>
> > > >> Does anyone have pointers on getting an interactive handle on the
> > > >> compiler internals?  Thanks.
>
> > > > python is not quite lisp yet, give it a decade.....
>
> > > You've got the wrong Python.  A basic knowledge of English would have
> > > allowed you to understand that from what I wrote.  What's
> > > disappointing, though, is that nobody but gavino has responded so
> > > far. :P
>
> > Oh really? What exact part of english am I missing?
>
> The part that allows you to recognize that in the fragment, "Python
> compiler," the word "compiler" modifies the word "Python," making it
> clear that the post was not about the python language, but about a
> python compiler implemented in lisp (of which I know nothing about,
> sorry).

LOL
bullsheep it makes it clear
that is a complete construction!
python has compilers you tool!!
From: ···············@gmail.com
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <51aca0a0-825e-420f-9645-aa7dfe22875d@60g2000hsy.googlegroups.com>
On Feb 26, 8:44 pm, gavino <·········@gmail.com> wrote:

> LOL
> bullsheep it makes it clear
> that is a complete construction!
> python has compilers you tool!!

"Python" was the name used for the Common Lisp compiler developed at
CMU, resulting in CMUCL, which was forked to create SBCL.
Unfortunately, it was also the name Guido later chose for his
language.
From: John Thingstad
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <op.t65vb5e8ut4oq5@pandora.alfanett.no>
P� Wed, 27 Feb 2008 02:44:30 +0100, skrev gavino <·········@gmail.com>:

>
> LOL
> bullsheep it makes it clear
> that is a complete construction!
> python has compilers you tool!!

Python is the Lisp compiler found in SBCL and CMUCL Common Lisp systems.
It predates the language Python with quite a few years.

--------------
John Thingstad
From: Ari Johnson
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <m2r6ezgndo.fsf@hermes.theari.com>
jc <··········@gmail.com> writes:

> On Feb 26, 5:32 pm, gavino <·········@gmail.com> wrote:
>> On Feb 26, 5:24 pm, Ari Johnson <·········@gmail.com> wrote:
>>
>>
>>
>> > gavino <·········@gmail.com> writes:
>> > >> On Feb 26, 12:40 pm, Ari Johnson <·········@gmail.com> wrote:
>> > >> I am trying to wrap my head around the internals of the Python
>> > >> compiler, or at least the version of it in SBCL since I've found it to
>> > >> be much easier to track the SBCL sources and they seem to be more
>> > >> cleanly organized than CMUCL's.
>>
>> > >> What I'd really like to do is get into the compiler and take a look at
>> > >> the internal data structures, such as with SLIME, to interactively see
>> > >> what happens at each step of the way.
>>
>> > >> I've tried reading :trace-file output, but it leaves a lot out of the
>> > >> process and in particular does not make clear where the initial
>> > >> source-to-IR1 transformations come from.  Reading the compiler sources
>> > >> themselves makes it hard to find the connections between data
>> > >> structures and translations, mostly because there is just so much
>> > >> code.
>>
>> > >> Ideally, I'd like to be able to step through a call to the compiler,
>> > >> watching which functions get called along the way and inspecting local
>> > >> variables at each point.
>>
>> > >> Does anyone have pointers on getting an interactive handle on the
>> > >> compiler internals?  Thanks.
>>
>> > > python is not quite lisp yet, give it a decade.....
>>
>> > You've got the wrong Python.  A basic knowledge of English would have
>> > allowed you to understand that from what I wrote.  What's
>> > disappointing, though, is that nobody but gavino has responded so
>> > far. :P
>>
>> Oh really? What exact part of english am I missing?
>
> The part that allows you to recognize that in the fragment, "Python
> compiler," the word "compiler" modifies the word "Python," making it
> clear that the post was not about the python language, but about a
> python compiler implemented in lisp (of which I know nothing about,
> sorry).

How about this part (I will put ^'s beneath the relevant words):

I am trying to wrap my head around the internals of the Python
                                                        ^^^^^^
compiler, or at least the version of it in SBCL since I've found it to
^^^^^^^^                                ^^^^^^^
be much easier to track the SBCL sources and they seem to be more
                            ^^^^^^^^^^^^
cleanly organized than CMUCL's.
                       ^^^^^

Python is the name of the compiler in CMUCL, inherited by SBCL when it
forked from CMUCL.  The CMUCL compiler has been named Python since, I
believe, 1987.

According to Wikipedia, Python the programming language first appeared
in 1991.

Fortunately, most people who will have answers to my question need
only see two things to know what I'm talking about: "comp.lang.lisp"
and "Python internals." =)
From: gavino
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <b5b078b3-d8ea-4bdc-9937-81404599f6bc@p73g2000hsd.googlegroups.com>
On Feb 26, 6:10 pm, Ari Johnson <·········@gmail.com> wrote:
> jc <··········@gmail.com> writes:
> > On Feb 26, 5:32 pm, gavino <·········@gmail.com> wrote:
> >> On Feb 26, 5:24 pm, Ari Johnson <·········@gmail.com> wrote:
>
> >> > gavino <·········@gmail.com> writes:
> >> > >> On Feb 26, 12:40 pm, Ari Johnson <·········@gmail.com> wrote:
> >> > >> I am trying to wrap my head around the internals of the Python
> >> > >> compiler, or at least the version of it in SBCL since I've found it to
> >> > >> be much easier to track the SBCL sources and they seem to be more
> >> > >> cleanly organized than CMUCL's.
>
> >> > >> What I'd really like to do is get into the compiler and take a look at
> >> > >> the internal data structures, such as with SLIME, to interactively see
> >> > >> what happens at each step of the way.
>
> >> > >> I've tried reading :trace-file output, but it leaves a lot out of the
> >> > >> process and in particular does not make clear where the initial
> >> > >> source-to-IR1 transformations come from.  Reading the compiler sources
> >> > >> themselves makes it hard to find the connections between data
> >> > >> structures and translations, mostly because there is just so much
> >> > >> code.
>
> >> > >> Ideally, I'd like to be able to step through a call to the compiler,
> >> > >> watching which functions get called along the way and inspecting local
> >> > >> variables at each point.
>
> >> > >> Does anyone have pointers on getting an interactive handle on the
> >> > >> compiler internals?  Thanks.
>
> >> > > python is not quite lisp yet, give it a decade.....
>
> >> > You've got the wrong Python.  A basic knowledge of English would have
> >> > allowed you to understand that from what I wrote.  What's
> >> > disappointing, though, is that nobody but gavino has responded so
> >> > far. :P
>
> >> Oh really? What exact part of english am I missing?
>
> > The part that allows you to recognize that in the fragment, "Python
> > compiler," the word "compiler" modifies the word "Python," making it
> > clear that the post was not about the python language, but about a
> > python compiler implemented in lisp (of which I know nothing about,
> > sorry).
>
> How about this part (I will put ^'s beneath the relevant words):
>
> I am trying to wrap my head around the internals of the Python
>                                                         ^^^^^^
> compiler, or at least the version of it in SBCL since I've found it to
> ^^^^^^^^                                ^^^^^^^
> be much easier to track the SBCL sources and they seem to be more
>                             ^^^^^^^^^^^^
> cleanly organized than CMUCL's.
>                        ^^^^^
>
> Python is the name of the compiler in CMUCL, inherited by SBCL when it
> forked from CMUCL.  The CMUCL compiler has been named Python since, I
> believe, 1987.
>
> According to Wikipedia, Python the programming language first appeared
> in 1991.
>
> Fortunately, most people who will have answers to my question need
> only see two things to know what I'm talking about: "comp.lang.lisp"
> and "Python internals." =)

Ok you may have won the argument, but that doesn't mean I have to be
happy about it...
From: ···@telent.net
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <47c4d0a2$0$2447$fa0fcedb@news.zen.co.uk>
Ari Johnson wrote:
> You've got the wrong Python.  A basic knowledge of English would have
> allowed you to understand that from what I wrote.  What's
> disappointing, though, is that nobody but gavino has responded so
> far. :P

I think most people likely to know the answers are more often found on 
the sbcl-devel list than here on c.l.l

https://lists.sourceforge.net/lists/listinfo/sbcl-devel ;; start here


-dan
From: D Herring
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <B8ydnQiNn9OOSFnanZ2dnUVZ_tSknZ2d@comcast.com>
Ari Johnson wrote:
> I am trying to wrap my head around the internals of the Python
> compiler, or at least the version of it in SBCL since I've found it to
> be much easier to track the SBCL sources and they seem to be more
> cleanly organized than CMUCL's.
> 
> What I'd really like to do is get into the compiler and take a look at
> the internal data structures, such as with SLIME, to interactively see
> what happens at each step of the way.
> 
> I've tried reading :trace-file output, but it leaves a lot out of the
> process and in particular does not make clear where the initial
> source-to-IR1 transformations come from.  Reading the compiler sources
> themselves makes it hard to find the connections between data
> structures and translations, mostly because there is just so much
> code.
> 
> Ideally, I'd like to be able to step through a call to the compiler,
> watching which functions get called along the way and inspecting local
> variables at each point.
> 
> Does anyone have pointers on getting an interactive handle on the
> compiler internals?  Thanks.

Not interactive, but have you found
http://sbcl-internals.cliki.net/index
and
http://sbcl.sourceforge.net/sbcl-internals/
?

- Daniel
From: Ari Johnson
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <m2oda32c64.fsf@hermes.theari.com>
D Herring <········@at.tentpost.dot.com> writes:

> Ari Johnson wrote:
>> I am trying to wrap my head around the internals of the Python
>> compiler, or at least the version of it in SBCL since I've found it to
>> be much easier to track the SBCL sources and they seem to be more
>> cleanly organized than CMUCL's.
>>
>> What I'd really like to do is get into the compiler and take a look at
>> the internal data structures, such as with SLIME, to interactively see
>> what happens at each step of the way.
>>
>> I've tried reading :trace-file output, but it leaves a lot out of the
>> process and in particular does not make clear where the initial
>> source-to-IR1 transformations come from.  Reading the compiler sources
>> themselves makes it hard to find the connections between data
>> structures and translations, mostly because there is just so much
>> code.
>>
>> Ideally, I'd like to be able to step through a call to the compiler,
>> watching which functions get called along the way and inspecting local
>> variables at each point.
>>
>> Does anyone have pointers on getting an interactive handle on the
>> compiler internals?  Thanks.
>
> Not interactive, but have you found
> http://sbcl-internals.cliki.net/index
> and
> http://sbcl.sourceforge.net/sbcl-internals/

Yeah - fairly limited as to the details of how the process works.  I
want to see the structures in the inspector.  The internals manual and
wiki are too high-level and not descriptive enough (not to mention
riddled with ambiguities and unexplained acronyms).  On the other
hand, the source code itself is too low-level and verbose - you have
to read too much of it to understand how it fits together.

With live IR1 data and INSPECT, I'd be more able to poke and prod and
see snapshots of what actually goes on.  That's what I think I am
missing to grok what's going on with blocks and nodes.
From: Marco Antoniotti
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <a90fc4a1-e627-4826-81cd-0f11e06731f0@q78g2000hsh.googlegroups.com>
On Feb 26, 10:40 pm, Ari Johnson <·········@gmail.com> wrote:
> I am trying to wrap my head around the internals of the Python
> compiler, or at least the version of it in SBCL since I've found it to
> be much easier to track the SBCL sources and they seem to be more
> cleanly organized than CMUCL's.
>
> What I'd really like to do is get into the compiler and take a look at
> the internal data structures, such as with SLIME, to interactively see
> what happens at each step of the way.
>
> I've tried reading :trace-file output, but it leaves a lot out of the
> process and in particular does not make clear where the initial
> source-to-IR1 transformations come from.  Reading the compiler sources
> themselves makes it hard to find the connections between data
> structures and translations, mostly because there is just so much
> code.
>
> Ideally, I'd like to be able to step through a call to the compiler,
> watching which functions get called along the way and inspecting local
> variables at each point.
>
> Does anyone have pointers on getting an interactive handle on the
> compiler internals?  Thanks.

There is a document available online in the CMUCL web site at
http://www.cons.org/cmucl/doc/index.html (look for "internals").

Cheers
--
Marco
From: Ari Johnson
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <87ejayrv1w.fsf@bender.theari.com>
Marco Antoniotti <·······@gmail.com> writes:

> On Feb 26, 10:40�pm, Ari Johnson <·········@gmail.com> wrote:
> > I am trying to wrap my head around the internals of the Python
> > compiler, or at least the version of it in SBCL since I've found it to
> > be much easier to track the SBCL sources and they seem to be more
> > cleanly organized than CMUCL's.
> >
> > What I'd really like to do is get into the compiler and take a look at
> > the internal data structures, such as with SLIME, to interactively see
> > what happens at each step of the way.
> >
> > I've tried reading :trace-file output, but it leaves a lot out of the
> > process and in particular does not make clear where the initial
> > source-to-IR1 transformations come from. �Reading the compiler sources
> > themselves makes it hard to find the connections between data
> > structures and translations, mostly because there is just so much
> > code.
> >
> > Ideally, I'd like to be able to step through a call to the compiler,
> > watching which functions get called along the way and inspecting local
> > variables at each point.
> >
> > Does anyone have pointers on getting an interactive handle on the
> > compiler internals? �Thanks.
> 
> There is a document available online in the CMUCL web site at
> http://www.cons.org/cmucl/doc/index.html (look for "internals").

The CMUCL-design.pdf section regarding the compiler is helpful, but
still too high-level and sometimes ambiguous regarding exactly what is
going on.  I'm really looking for forms I can throw at SLIME to end up
in an inspector looking at the ICR/IR1 data structures that represent
my code.

The closest I've come so far goes like this:

(let* ((form '(lambda (n) (list n)))
       (sb-c::*lexenv* (sb-c::make-null-lexenv))
       (sb-c::*source-info* (sb-c::make-lisp-source-info form)))
  (sb-c::with-ir1-namespace
    (sb-c::ir1-toplevel form '(original-source-start 0 0) t)))

This code returns a SB-C::CLAMBDA structure that feels somewhat opaque
but is at least a starting point.  Part of the problem is that it's so
hard to get at the intermediate functions between calling IR1-TOPLEVEL
and getting the CLAMBDA structure back.
From: Nathan Froyd
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <ee02a3c0-467a-4b15-ad4a-35fcdae02598@x30g2000hsd.googlegroups.com>
On Feb 27, 3:41 pm, Ari Johnson <·········@gmail.com> wrote:
> The CMUCL-design.pdf section regarding the compiler is helpful, but
> still too high-level and sometimes ambiguous regarding exactly what is
> going on.  I'm really looking for forms I can throw at SLIME to end up
> in an inspector looking at the ICR/IR1 data structures that represent
> my code.

Juho Snellman's cl-dot package comes with an example file describing
how to generate a graph for IR1.  I hacked on it a year or two ago and
got it to generate decent looking graphs.  My code for doing so is
below; I haven't tested it recently and I might have left it in a half-
working state, soo..

Find %COMPILE-COMPONENT in src/compiler/main.lisp and add these bits
prior to the function:

(defvar *generating-dot* nil)
(defvar *draw-graphs* t)

Then, in the body of %COMPILE-COMPONENT, add:

    (when (and (not *generating-dot*) *draw-graphs*)
      (let ((*generating-dot* t))
        (with-open-file (stream #p"/Users/froydnj/Documents/frob.dot"
                                :direction :output :if-
exists :supersede)
          (cl-dot:print-graph (cl-dot:generate-graph component)
stream))))

Pick a suitable output file.  Note that I did this work on a Mac,
where there's a super-convenient interface to graphviz that
automagically redisplays a file if it notices that it's changed.  So
one can just load up that file and toggle back and forth between your
SLIME window and the graphviz output.

Of course, you'll want to have the appropriate cl-dot bits loaded,
which you can find below.

I usually stuck the function I wanted to look at into a file, and then
ran COMPILE-FILE on that, so I could get the dot output and the trace
file all at the same time.  You could extend this to generate
successive dumps after each round of optimization or type propagation,
too.

Hope this helps,
-Nathan

(in-package :cl-dot)

(defun list-no-nil (&rest args)
  (remove nil args))

(defun boldify-edge (object)
  (make-instance 'attributed :object object
                 :attributes '(:style :bold)))

(defun attributify-edge (object &rest attribute-plist)
  (make-instance 'attributed :object object
                 :attributes attribute-plist))

(defmethod object-node ((object null))
  nil)

(defmethod object-node :around ((object sb-c::node))
  (let ((node (call-next-method)))
    (values node (sb-c::block-number (sb-c::block-or-lose object)))))

(defmethod object-node :around ((object sb-c::ctran))
  (let ((node (call-next-method)))
    (values node (sb-c::block-number (sb-c::block-or-lose object)))))

(defmethod object-node :around ((object sb-c::cblock))
  (let ((node (call-next-method)))
    (values node (sb-c::block-number (sb-c::block-or-lose object)))))

;; COMPONENT
(defmethod object-node ((object sb-c:component))
  nil)

(defmethod object-knows-of ((c sb-c:component))
  (list* (sb-c::component-head c)
         (sb-c::component-lambdas c)))


;; CBLOCK
(defmethod object-node ((c sb-c::cblock))
  (make-instance 'cluster-node
                 :attributes `(:label ,(format nil "Block ~A" (sb-
c::block-number c)))))

(defmethod object-points-to ((c sb-c::cblock))
  nil #+nil (sb-c::block-succ c))

(defmethod object-knows-of ((c sb-c::cblock))
  (append (sb-c::block-pred c) (sb-c::block-succ c)))

;; CLAMBDA
(defmethod object-node ((c sb-c::clambda))
  (make-instance 'node
                 :attributes `(:label ,(format nil "Lambda ~A"
                                               (sb-c::lambda-%source-
name c)))))

(defmethod object-points-to ((c sb-c::clambda))
  (sb-c::lambda-vars c))

;; LAMBDA-VAR
(defmethod object-node ((c sb-c::lambda-var))
  (make-instance 'node
                 :attributes `(:label ,(format nil "Var ~A"
                                               (sb-c::lambda-var-
%source-name c)))))

(defmethod object-knows-of ((c sb-c::lambda-var))
  (sb-c::lambda-var-refs c))

;; REF
(defmethod object-node ((c sb-c::ref))
  (make-instance 'node
                 :attributes (list :label "REF"
                                   :fillcolor "#ddffbb"
                                   :style :filled
                                   :shape :diamond)))

(defmethod object-points-to ((c sb-c::ref))
  (list-no-nil (sb-c::ref-leaf c)
               (boldify-edge (sb-c::ref-next c))))

(defmethod object-knows-of ((c sb-c::ref))
  (list-no-nil (sb-c::ref-prev c)
               (sb-c::ref-lvar c)))

;; CTRAN
(defmethod object-node ((c sb-c::ctran))
  (make-instance 'node
                 :attributes `(:label ,(format nil "CTRAN ~D ~A"
                                               (sb-c::cont-num c)
                                               (sb-c::ctran-kind
c)))))

(defmethod object-points-to ((c sb-c::ctran))
  (list-no-nil (boldify-edge (sb-c::ctran-next c))
               (sb-c::ctran-use c)))

;; BIND
(defmethod object-node ((c sb-c::bind))
  (make-instance 'node
                 :attributes `(:label ,(format nil "BIND"))))

(defmethod object-points-to ((c sb-c::bind))
  (list-no-nil (sb-c::bind-next c)))

(defmethod object-knows-of ((c sb-c::bind))
  (list-no-nil (sb-c::bind-prev c)))

;; GLOBAL-VAR
(defmethod object-node ((c sb-c::global-var))
  (make-instance 'node
                 :attributes (list :label (format nil "GLOBAL-VAR\\n~A\
\n~A"
                                                  (sb-c::global-var-
%source-name c)
                                                  (sb-c::global-var-
kind c))
                                   :shape :box)))

(defmethod object-knows-of ((c sb-c::global-var))
  (sb-c::global-var-refs c))

;; CONSTANT
(defmethod object-node ((c sb-c::constant))
  (make-instance 'node
                 :attributes (list :label (format nil "CONSTANT"
                                                  #+nil (sb-c::lvar-
source c)
                                                  #+nil (sb-
c::constant-value c))
                                   :style :filled
                                   :fillcolor "#ffffee"
                                   :shape :box)))

(defmethod object-knows-of ((c sb-c::constant))
  (sb-c::constant-refs c))

;; ENTRY
(defmethod object-node ((c sb-c::entry))
  (make-instance 'node
                 :attributes `(:label ,(format nil "ENTRY"))))

(defmethod object-points-to ((c sb-c::entry))
  ;; cleanup
  (list-no-nil (sb-c::entry-next c)))

(defmethod object-knows-of ((c sb-c::entry))
  (list-no-nil (sb-c::entry-prev c)))

;; COMBINATION
(defmethod object-node ((c sb-c::basic-combination))
  (make-instance 'node
                 :attributes (list :label (format nil "~(~A~A ~A\
\n~A~)"
                                                  (if (sb-c::node-tail-
p c) "tail " "")
                                                  (sb-c::basic-
combination-kind c)
                                                  (type-of c)
                                                  (sb-c::lvar-fun-name
(sb-c::basic-combination-fun c)))
                                   :shape :octagon
                                   :style :filled
                                   :fillcolor "#ccffff")))

(defmethod object-points-to ((c sb-c::basic-combination))
  (apply #'list-no-nil
         (boldify-edge (sb-c::basic-combination-next c))
         (attributify-edge (sb-c::basic-combination-lvar
c) :style :bold :color "#9999ff")
         (attributify-edge (sb-c::basic-combination-fun
c) :style :bold :color "#0000ff")
         (sb-c::basic-combination-args c)))

(defmethod object-knows-of ((c sb-c::basic-combination))
  (list* (sb-c::basic-combination-prev c)
         (sb-c::basic-combination-args c)))

;; LVAR
(defmethod object-node ((c sb-c::lvar))
  (let ((combination-result-p (let ((use (sb-c::principal-lvar-use
c)))
                                (typep use 'sb-c::basic-combination)))
        (combination-fun-p (let ((dest (sb-c::lvar-dest c)))
                             (and (typep dest 'sb-c::basic-
combination)
                                  (eq (sb-c::basic-combination-fun
dest) c))))
        (leaf (let ((ref (sb-c::lvar-uses c)))
                (when (sb-c::ref-p ref)
                  (let ((leaf (sb-c::ref-leaf ref)))
                    (when (sb-c::leaf-has-source-name-p leaf)
                      (sb-c::leaf-source-name leaf)))))))
    (make-instance 'node
                   :attributes (list :label (format nil "~A ~A"
                                                    (cond
                                                      (combination-fun-
p "FUN LVAR")
                                                      (t "LVAR"))
                                                    leaf)
                                     :style :filled
                                     :fillcolor "#ffcc99"
                                     :shape :hexagon))))

(defmethod object-points-to ((c sb-c::lvar))
  (let ((dest (sb-c::lvar-dest c)))
    (list-no-nil dest))
    #+nil
    (cond
      ((typep dest 'sb-c::basic-combination)
       (if (member c (sb-c::basic-combination-args dest))
           nil
           (list-no-nil (sb-c::lvar-dest c))))
      (t (list-no-nil (sb-c::lvar-dest c))))))

(defmethod object-pointed-to-by ((c sb-c::lvar))
  (let ((uses (sb-c::lvar-uses c)))
    (remove-if #'(lambda (x) (typep x 'sb-c::basic-combination))
               (if (listp uses)
                   uses
                   (list-no-nil uses)))))

;; CIF
(defmethod object-node ((c sb-c::cif))
  (make-instance 'node
                 :attributes `(:label ,(format nil "CIF"))))

(defmethod object-points-to ((c sb-c::cif))
  (list-no-nil (sb-c::if-next c)
               (sb-c::if-test c)
               (sb-c::if-consequent c)
               (sb-c::if-alternative c)))

(defmethod object-knows-of ((c sb-c::cif))
  (list-no-nil (sb-c::if-prev c)))

;; CRETURN
(defmethod object-node ((c sb-c::creturn))
  (make-instance 'node
                 :attributes `(:label ,(format nil "CRETURN"))))

(defmethod object-points-to ((c sb-c::creturn))
  (list-no-nil (sb-c::return-next c)))

(defmethod object-knows-of ((c sb-c::creturn))
  (list-no-nil (sb-c::return-prev c)
               (sb-c::return-result c)))

;; CAST
(defmethod object-node ((c sb-c::cast))
  (make-instance 'node
                 :attributes (list :label "CAST"
                                   :style :filled
                                   :fillcolor "#ffccff")))

;; CSET
(defmethod object-node ((c sb-c::cset))
  (make-instance 'node
                 :attributes '(:label "CSET")))

(defmethod object-points-to ((c sb-c::cset))
  (list (sb-c::set-value c)))
From: Ari Johnson
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <m2pruivu20.fsf@hermes.theari.com>
Nathan Froyd <·······@gmail.com> writes:

> On Feb 27, 3:41 pm, Ari Johnson <·········@gmail.com> wrote:
>> The CMUCL-design.pdf section regarding the compiler is helpful, but
>> still too high-level and sometimes ambiguous regarding exactly what is
>> going on.  I'm really looking for forms I can throw at SLIME to end up
>> in an inspector looking at the ICR/IR1 data structures that represent
>> my code.
>
> Juho Snellman's cl-dot package comes with an example file describing
> how to generate a graph for IR1.  I hacked on it a year or two ago and
> got it to generate decent looking graphs.  My code for doing so is
> below; I haven't tested it recently and I might have left it in a half-
> working state, soo..
>
> Find %COMPILE-COMPONENT in src/compiler/main.lisp and add these bits
> prior to the function:
>
> (defvar *generating-dot* nil)
> (defvar *draw-graphs* t)
>
> Then, in the body of %COMPILE-COMPONENT, add:
>
>     (when (and (not *generating-dot*) *draw-graphs*)
>       (let ((*generating-dot* t))
>         (with-open-file (stream #p"/Users/froydnj/Documents/frob.dot"
>                                 :direction :output :if-
> exists :supersede)
>           (cl-dot:print-graph (cl-dot:generate-graph component)
> stream))))
>
> Pick a suitable output file.  Note that I did this work on a Mac,
> where there's a super-convenient interface to graphviz that
> automagically redisplays a file if it notices that it's changed.  So
> one can just load up that file and toggle back and forth between your
> SLIME window and the graphviz output.
>
> Of course, you'll want to have the appropriate cl-dot bits loaded,
> which you can find below.
>
> I usually stuck the function I wanted to look at into a file, and then
> ran COMPILE-FILE on that, so I could get the dot output and the trace
> file all at the same time.  You could extend this to generate
> successive dumps after each round of optimization or type propagation,
> too.
>
> Hope this helps,
> -Nathan

I don't suppose you remember the procedure to get these things loaded
into SBCL?  I thought about hacking it into the source around genesis
time, but cl-dot uses CLOS, which I don't believe to be available in
SB!C-land.

I really like this idea and am excited to get it up and running.
Thanks!
From: Nathan Froyd
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <00eb6ca2-11fc-4e9f-b261-07a8112b2de6@p73g2000hsd.googlegroups.com>
On Feb 27, 6:49 pm, Ari Johnson <·········@gmail.com> wrote:
> I don't suppose you remember the procedure to get these things loaded
> into SBCL?  I thought about hacking it into the source around genesis
> time, but cl-dot uses CLOS, which I don't believe to be available in
> SB!C-land.

This is Lisp: it's OK to incrementally redefine bits of the compiler.
You just load the code into the image via C-M-x or what have you.

-Nathan
From: Ari Johnson
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <m2myplnatf.fsf@hermes.theari.com>
Nathan Froyd <·······@gmail.com> writes:

> On Feb 27, 6:49 pm, Ari Johnson <·········@gmail.com> wrote:
>> I don't suppose you remember the procedure to get these things loaded
>> into SBCL?  I thought about hacking it into the source around genesis
>> time, but cl-dot uses CLOS, which I don't believe to be available in
>> SB!C-land.
>
> This is Lisp: it's OK to incrementally redefine bits of the compiler.
> You just load the code into the image via C-M-x or what have you.

src/compiler/main.lisp is defined in terms of (in-package "SB!C"), so
I was hoping for a way to avoid (load "src/cold/chill.lisp")
From: Juho Snellman
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <87ve49g8c8.fsf@vasara.proghammer.com>
Ari Johnson <·········@gmail.com> writes:
> Nathan Froyd <·······@gmail.com> writes:
> > On Feb 27, 6:49 pm, Ari Johnson <·········@gmail.com> wrote:
> >> I don't suppose you remember the procedure to get these things loaded
> >> into SBCL?  I thought about hacking it into the source around genesis
> >> time, but cl-dot uses CLOS, which I don't believe to be available in
> >> SB!C-land.
> >
> > This is Lisp: it's OK to incrementally redefine bits of the compiler.
> > You just load the code into the image via C-M-x or what have you.
> 
> src/compiler/main.lisp is defined in terms of (in-package "SB!C"), so
> I was hoping for a way to avoid (load "src/cold/chill.lisp")

You do not need to do anything special, just C-c C-c the
function. Slime has magic to automatically install the SBCL bootstrap
packages and readtables for the duration of a compilation of a SBCL
source file.

-- 
Juho Snellman
From: Nathan Froyd
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <83ab97c0-e24c-413e-a560-0738b0a8d136@n58g2000hsf.googlegroups.com>
On Feb 27, 8:47 pm, Juho Snellman <······@iki.fi> wrote:
> Ari Johnson <·········@gmail.com> writes:
> > src/compiler/main.lisp is defined in terms of (in-package "SB!C"), so
> > I was hoping for a way to avoid (load "src/cold/chill.lisp")
>
> You do not need to do anything special, just C-c C-c the
> function. Slime has magic to automatically install the SBCL bootstrap
> packages and readtables for the duration of a compilation of a SBCL
> source file.

If you didn't have slime available, you could create a new source file
that's (in-package :sb-c) and put the DEFVAR forms in there, along
with a cut-paste-and-modified version of %COMPILE-COMPONENT and load
that, too.

-Nathan
From: Ari Johnson
Subject: Re: Python internals - any pointers on poking around?
Date: 
Message-ID: <m2pruhwud1.fsf@hermes.theari.com>
Nathan Froyd <·······@gmail.com> writes:

> On Feb 27, 8:47 pm, Juho Snellman <······@iki.fi> wrote:
>> Ari Johnson <·········@gmail.com> writes:
>> > src/compiler/main.lisp is defined in terms of (in-package "SB!C"), so
>> > I was hoping for a way to avoid (load "src/cold/chill.lisp")
>>
>> You do not need to do anything special, just C-c C-c the
>> function. Slime has magic to automatically install the SBCL bootstrap
>> packages and readtables for the duration of a compilation of a SBCL
>> source file.
>
> If you didn't have slime available, you could create a new source file
> that's (in-package :sb-c) and put the DEFVAR forms in there, along
> with a cut-paste-and-modified version of %COMPILE-COMPONENT and load
> that, too.
>
> -Nathan

I'm not sure if this went through or not the first time.  The below is
a file that can be loaded into SBCL, assuming that ASDF can find and
load CL-DOT.  The effect is a replacement COMPILE-FILE with a new
argument, DOT-FILE, which works much like TRACE-FILE (takes T or a
pathname).

I am not sure that I have it all set up perfectly.  I had to add a few
functions to what you posted earlier, at the bottom of the file, to
get sb-c-dot.lisp to graph itself.

Of course, actually reading the massive graph that you get from this
is another project altogether.  But I hope that this can be useful to
others in my situation.

----[ sb-c-dot.lisp ]----
(in-package "CL-USER")

(require :asdf)
(asdf:operate 'asdf:load-op :cl-dot)

(in-package "SB-C")

(defvar *dot-file-pathname* nil)
(defvar *generating-dot* nil)

(without-package-locks
  (defun %compile-component (component)
    (let ((*code-segment* nil)
          (*elsewhere* nil))
      (maybe-mumble "GTN ")
      (gtn-analyze component)
      (maybe-mumble "LTN ")
      (ltn-analyze component)
      (dfo-as-needed component)
      (maybe-mumble "control ")
      (control-analyze component #'make-ir2-block)

      (when (and (not *generating-dot*) *dot-file-pathname*)
        (let ((*generating-dot* t))
          (with-open-file (stream *dot-file-pathname*
                                  :direction :output :if-exists :supersede)
            (cl-dot:print-graph (cl-dot:generate-graph component) stream))))

      (when (or (ir2-component-values-receivers (component-info component))
                (component-dx-lvars component))
        (maybe-mumble "stack ")
        (stack-analyze component)
        (dfo-as-needed component))

      (unwind-protect
           (progn
             (maybe-mumble "IR2tran ")
             (init-assembler)
             (entry-analyze component)
             (ir2-convert component)

             (when (policy *lexenv* (>= speed compilation-speed))
               (maybe-mumble "copy ")
               (copy-propagate component))

             (select-representations component)

             (when *check-consistency*
               (maybe-mumble "check2 ")
               (check-ir2-consistency component))

             (delete-unreferenced-tns component)

             (maybe-mumble "life ")
             (lifetime-analyze component)

             (when *compile-progress*
               (compiler-mumble "")
               (pre-pack-tn-stats component *standard-output*))

             (when *check-consistency*
               (maybe-mumble "check-life ")
               (check-life-consistency component))

             (maybe-mumble "pack ")
             (pack component)

             (when *check-consistency*
               (maybe-mumble "check-pack ")
               (check-pack-consistency component))

             (when *compiler-trace-output*
               (describe-component component *compiler-trace-output*)
               (describe-ir2-component component *compiler-trace-output*))

             (maybe-mumble "code ")
             (multiple-value-bind (code-length trace-table fixup-notes)
                 (generate-code component)

               (when *compiler-trace-output*
                 (format *compiler-trace-output*
                         "~|~%disassembly of code for ~S~2%" component)
                 (sb-disassem:disassemble-assem-segment
                  *code-segment* *compiler-trace-output*))

               (etypecase *compile-object*
                 (fasl-output
                  (maybe-mumble "fasl")
                  (fasl-dump-component component
                                       *code-segment*
                                       code-length
                                       trace-table
                                       fixup-notes
                                       *compile-object*))
                 (core-object
                  (maybe-mumble "core")
                  (make-core-component component
                                       *code-segment*
                                       code-length
                                       trace-table
                                       fixup-notes
                                       *compile-object*))
                 (null))))))

    (setf (component-info component) :dead)

    (values))

  (defun compile-file
      (input-file
       &key
       (output-file (cfp-output-file-default input-file))
       (external-format :default)
       (trace-file nil)
       (dot-file nil)
       ((:block-compile *block-compile-arg*) nil))
    (let* ((fasl-output nil)
           (output-file-name nil)
           (abort-p nil)
           (warnings-p nil)
           (failure-p t)
           (input-pathname (verify-source-file input-file))
           (source-info (make-file-source-info input-pathname external-format))
           (*dot-file-pathname* nil)
           (*compiler-trace-output* nil))

      (unwind-protect
           (progn
             (when output-file
               (setq output-file-name
                     (cl:compile-file-pathname input-file
                                               :output-file output-file))
               (setq fasl-output
                     (open-fasl-output output-file-name
                                       (namestring input-pathname))))
             (when trace-file
               (let* ((default-trace-file-pathname
                       (make-pathname :type "trace" :defaults input-pathname))
                      (trace-file-pathname
                       (if (eql trace-file t)
                           default-trace-file-pathname
                           (merge-pathnames trace-file
                                            default-trace-file-pathname))))
                 (setf *compiler-trace-output*
                       (open trace-file-pathname
                             :if-exists :supersede
                             :direction :output))))

             (when dot-file
               (let* ((default-dot-file-pathname
                       (make-pathname :type "dot" :defaults input-pathname))
                      (dot-file-pathname
                       (if (eql dot-file t)
                           default-dot-file-pathname
                           (merge-pathnames dot-file
                                            default-dot-file-pathname))))
                 (setf *dot-file-pathname* dot-file-pathname)))

             (when cl:*compile-verbose*
               (print-compile-start-note source-info))

             (let ((*compile-object* fasl-output))
               (setf (values abort-p warnings-p failure-p)
                     (sub-compile-file source-info))))

        (close-source-info source-info)

        (when fasl-output
          (close-fasl-output fasl-output abort-p)
          (setq output-file-name
                (pathname (fasl-output-stream fasl-output)))
          (when (and (not abort-p) cl:*compile-verbose*)
            (compiler-mumble "~2&; ~A written~%"
                             (namestring output-file-name))))

        (when cl:*compile-verbose*
          (print-compile-end-note source-info (not abort-p)))

        (when *compiler-trace-output*
          (close *compiler-trace-output*)))

      (values (when (and (not abort-p) output-file)
                (or (probe-file output-file-name) output-file-name))
              warnings-p
              failure-p))))

(in-package "CL-DOT")

(defun list-no-nil (&rest args)
  (remove nil args))

(defun boldify-edge (object)
  (make-instance 'attributed :object object
                 :attributes '(:style :bold)))

(defun attributify-edge (object &rest attribute-plist)
  (make-instance 'attributed :object object
                 :attributes attribute-plist))

(defmethod object-node ((object null))
  nil)

(defmethod object-node :around ((object sb-c::node))
  (let ((node (call-next-method)))
    (values node (sb-c::block-number (sb-c::block-or-lose object)))))

(defmethod object-node :around ((object sb-c::ctran))
  (let ((node (call-next-method)))
    (values node (sb-c::block-number (sb-c::block-or-lose object)))))

(defmethod object-node :around ((object sb-c::cblock))
  (let ((node (call-next-method)))
    (values node (sb-c::block-number (sb-c::block-or-lose object)))))

;; COMPONENT
(defmethod object-node ((object sb-c:component))
  nil)

(defmethod object-knows-of ((c sb-c:component))
  (list* (sb-c::component-head c)
         (sb-c::component-lambdas c)))


;; CBLOCK
(defmethod object-node ((c sb-c::cblock))
  (make-instance 'node
                 :attributes
                 `(:label ,(format nil "Block ~A" (sb-c::block-number c)))))

(defmethod object-points-to ((c sb-c::cblock))
  nil #+nil (sb-c::block-succ c))

(defmethod object-knows-of ((c sb-c::cblock))
  (append (sb-c::block-pred c) (sb-c::block-succ c)))

;; CLAMBDA
(defmethod object-node ((c sb-c::clambda))
  (make-instance 'node
                 :attributes `(:label ,(format nil "Lambda ~A"
                                               (sb-c::lambda-%source-name c)))))

(defmethod object-points-to ((c sb-c::clambda))
  (sb-c::lambda-vars c))

;; LAMBDA-VAR
(defmethod object-node ((c sb-c::lambda-var))
  (make-instance 'node
                 :attributes
                 `(:label ,(format nil "Var ~A"
                                   (sb-c::lambda-var-%source-name c)))))

(defmethod object-knows-of ((c sb-c::lambda-var))
  (sb-c::lambda-var-refs c))

;; REF
(defmethod object-node ((c sb-c::ref))
  (make-instance 'node
                 :attributes (list :label "REF"
                                   :fillcolor "#ddffbb"
                                   :style :filled
                                   :shape :diamond)))

(defmethod object-points-to ((c sb-c::ref))
  (list-no-nil (sb-c::ref-leaf c)
               (boldify-edge (sb-c::ref-next c))))

(defmethod object-knows-of ((c sb-c::ref))
  (list-no-nil (sb-c::ref-prev c)
               (sb-c::ref-lvar c)))

;; CTRAN
(defmethod object-node ((c sb-c::ctran))
  (make-instance 'node
                 :attributes `(:label ,(format nil "CTRAN ~D ~A"
                                               (sb-c::cont-num c)
                                               (sb-c::ctran-kind c)))))

(defmethod object-points-to ((c sb-c::ctran))
  (list-no-nil (boldify-edge (sb-c::ctran-next c))
               (sb-c::ctran-use c)))

;; BIND
(defmethod object-node ((c sb-c::bind))
  (make-instance 'node
                 :attributes `(:label ,(format nil "BIND"))))

(defmethod object-points-to ((c sb-c::bind))
  (list-no-nil (sb-c::bind-next c)))

(defmethod object-knows-of ((c sb-c::bind))
  (list-no-nil (sb-c::bind-prev c)))

;; GLOBAL-VAR
(defmethod object-node ((c sb-c::global-var))
  (make-instance 'node
                 :attributes
                 (list :label (format nil "GLOBAL-VAR\\n~A\\n~A"
                                      (sb-c::global-var-%source-name c)
                                      (sb-c::global-var-kind c))
                       :shape :box)))

(defmethod object-knows-of ((c sb-c::global-var))
  (sb-c::global-var-refs c))

;; CONSTANT
(defmethod object-node ((c sb-c::constant))
  (make-instance 'node
                 :attributes
                 (list :label (format nil "CONSTANT"
                                      #+nil (sb-c::lvar-source c)
                                      #+nil (sb-c::constant-value c))
                       :style :filled
                       :fillcolor "#ffffee"
                       :shape :box)))

(defmethod object-knows-of ((c sb-c::constant))
  (sb-c::constant-refs c))

;; ENTRY
(defmethod object-node ((c sb-c::entry))
  (make-instance 'node
                 :attributes `(:label ,(format nil "ENTRY"))))

(defmethod object-points-to ((c sb-c::entry))
  ;; cleanup
  (list-no-nil (sb-c::entry-next c)))

(defmethod object-knows-of ((c sb-c::entry))
  (list-no-nil (sb-c::entry-prev c)))

;; COMBINATION
(defmethod object-node ((c sb-c::basic-combination))
  (make-instance 'node
                 :attributes
                 (list :label (format nil "~(~A~A ~A\\n~A~)"
                                      (if (sb-c::node-tail-p c) "tail " "")
                                      (sb-c::basic-combination-kind c)
                                      (type-of c)
                                      (sb-c::lvar-fun-name
                                       (sb-c::basic-combination-fun c)))
                       :shape :octagon
                       :style :filled
                       :fillcolor "#ccffff")))

(defmethod object-points-to ((c sb-c::basic-combination))
  (apply #'list-no-nil
         (boldify-edge (sb-c::basic-combination-next c))
         (attributify-edge (sb-c::basic-combination-lvar c)
                           :style :bold :color "#9999ff")
         (attributify-edge (sb-c::basic-combination-fun c)
                           :style :bold :color "#0000ff")
         (sb-c::basic-combination-args c)))

(defmethod object-knows-of ((c sb-c::basic-combination))
  (list* (sb-c::basic-combination-prev c)
         (sb-c::basic-combination-args c)))

;; LVAR
(defmethod object-node ((c sb-c::lvar))
  (let ((combination-result-p (let ((use (sb-c::principal-lvar-use c)))
                                (typep use 'sb-c::basic-combination)))
        (combination-fun-p (let ((dest (sb-c::lvar-dest c)))
                             (and (typep dest 'sb-c::basic-combination)
                                  (eq (sb-c::basic-combination-fun dest) c))))
        (leaf (let ((ref (sb-c::lvar-uses c)))
                (when (sb-c::ref-p ref)
                  (let ((leaf (sb-c::ref-leaf ref)))
                    (when (sb-c::leaf-has-source-name-p leaf)
                      (sb-c::leaf-source-name leaf)))))))
    (make-instance 'node
                   :attributes
                   (list :label (format nil "~A ~A"
                                        (cond
                                          (combination-fun-p "FUN LVAR")
                                          (t "LVAR"))
                                        leaf)
                         :style :filled
                         :fillcolor "#ffcc99"
                         :shape :hexagon))))

(defmethod object-points-to ((c sb-c::lvar))
  (let ((dest (sb-c::lvar-dest c)))
    (list-no-nil dest))
    #+nil
    (cond
      ((typep dest 'sb-c::basic-combination)
       (if (member c (sb-c::basic-combination-args dest))
           nil
           (list-no-nil (sb-c::lvar-dest c))))
      (t (list-no-nil (sb-c::lvar-dest c)))))

(defmethod object-pointed-to-by ((c sb-c::lvar))
  (let ((uses (sb-c::lvar-uses c)))
    (remove-if #'(lambda (x) (typep x 'sb-c::basic-combination))
               (if (listp uses)
                   uses
                   (list-no-nil uses)))))

;; CIF
(defmethod object-node ((c sb-c::cif))
  (make-instance 'node
                 :attributes `(:label ,(format nil "CIF"))))

(defmethod object-points-to ((c sb-c::cif))
  (list-no-nil (sb-c::if-next c)
               (sb-c::if-test c)
               (sb-c::if-consequent c)
               (sb-c::if-alternative c)))

(defmethod object-knows-of ((c sb-c::cif))
  (list-no-nil (sb-c::if-prev c)))

;; CRETURN
(defmethod object-node ((c sb-c::creturn))
  (make-instance 'node
                 :attributes `(:label ,(format nil "CRETURN"))))

(defmethod object-points-to ((c sb-c::creturn))
  (list-no-nil (sb-c::return-next c)))

(defmethod object-knows-of ((c sb-c::creturn))
  (list-no-nil (sb-c::return-prev c)
               (sb-c::return-result c)))

;; CAST
(defmethod object-node ((c sb-c::cast))
  (make-instance 'node
                 :attributes (list :label "CAST"
                                   :style :filled
                                   :fillcolor "#ffccff")))

;; CSET
(defmethod object-node ((c sb-c::cset))
  (make-instance 'node
                 :attributes '(:label "CSET")))

(defmethod object-points-to ((c sb-c::cset))
  (list (sb-c::set-value c)))

;; EXIT
(defmethod object-node ((c sb-c::exit))
  (make-instance 'node
                 :attributes `(:label ,(format nil "EXIT"))))

(defmethod object-points-to ((c sb-c::exit))
  ;; cleanup
  (list-no-nil (sb-c::exit-next c)))

(defmethod object-knows-of ((c sb-c::exit))
  (list-no-nil (sb-c::exit-prev c)))

;; FUNCTIONAL
(defmethod object-node ((c sb-c::functional))
  (make-instance 'node
                 :attributes `(:label ,(format nil "FUNCTIONAL"))))

(defmethod object-points-to ((c sb-c::functional))
  nil)

(defmethod object-knows-of ((c sb-c::functional))
  nil)