Subject: Re: [clisp-list] Question about the compiler

From: [email-masked]
Date: Mon Dec 16 12:08:22 2002

>> Is it possible to get a list of global variables used in a function
>> from the compiler?
>
>if the function is a compiled closure, then yes: look at the
>GETVALUE and SETVALUE instructions in the byte code.
>
>if it is an interpreted closure, the code-walker would need to be
>modified to do this..

What is the difference between a compiled and interpreted closure.

>
>if it is a built-in function written in C, no.
>
>it would be nice to display this information in the disassembly...

It would be helpful if it was in 1 line with a function name,
Somthing like:
funcname uses globals : global1 global2 ...
or
Global usage:
funcname1 : global1 global2 ...
funcname2 : global1 global2 ...
>
>you probably want a CLOSURE-FREE-VARIABLES function, right?
How would I use this function?

Which would be easier, to modify the compiler to produce this,
or to hack together a awk script to do this?

Another thing I would like is a indication of how long the function is,
maybe in terms of symbols, so that I could identify really short functions,
say ones whos length is maybe 5 to 10 symbols.  My goal here is to use the
compiler output as a programming tool.

---

From: Sam Steingold <[email-masked]>
Date: Mon Dec 16 15:10:05 2002

> * In message <[email-masked]>
> * On the subject of "Re: [clisp-list] Question about the compiler"
> * Sent on Mon, 16 Dec 2002 13:08:21 -0700 (MST)
> * Honorable [email-masked] writes:
>

when you compile an interpreted closure, you get a compiled one.

> Which would be easier, to modify the compiler to produce this,

I will change DISASSEMBLE to print this.

> or to hack together a awk script to do this?

huh?

> Another thing I would like is a indication of how long the function
> is, maybe in terms of symbols, so that I could identify really short
> functions, say ones whos length is maybe 5 to 10 symbols.  My goal
> here is to use the compiler output as a programming tool.

see <http://clisp.cons.org/impnotes/bytecode.html>, specifically

# Execution speed of a program can easily be understood by looking at
  the output of the DISASSEMBLE function. A rule of thumb is that every
  elementary instruction costs 1 time unit, whereas a function call
  costs 3 to 4 time units.

I think what you want to do is to to pass :LISTING to COMPILE-FILE (or
-l after -c on the command line) to produce the disassembly.
see <http://clisp.cons.org/impnotes/system.html#compilefile>
and <http://clisp.cons.org/clisp.html#opt-list>.

then you can parse those files, looking for
        "^[0-9]+ byte-code instructions:$"
as the indicator of the function size, and for
        "reads special variables:"
and
        "writes special variables:"

(you will need to apply the appended patch)

On a second thought, you can just grep disassembly for SETVALUE and
GETVALUE and look at the variable name after the ";".

use EXT:SPECIAL-VARIABLE-P to check whether the symbol has been
declared special.

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
Illiterate?  Write today, for free help!

--- compiler.lisp.~1.111.~	2002-11-07 04:14:01.000000000 -0500
+++ compiler.lisp	2002-12-16 18:04:14.000000000 -0500
@@ -10487,7 +10487,21 @@
     (let ((const-string-list
             (mapcar #'(lambda (x) (sys::write-to-short-string x 35))
                     const-list))
+          special-vars-read special-vars-write
           (lap-list (disassemble-LAP byte-list const-list)))
+      (dolist (L lap-list)
+        (when (consp (cdr L))
+          (case (cadr L)        ; instruction
+            ((GETVALUE GETVALUE&PUSH)
+             (pushnew (nth (caddr L) const-list) special-vars-read))
+            ((SETVALUE)
+             (pushnew (nth (caddr L) const-list) special-vars-write)))))
+      (when special-vars-read
+        (format stream (TEXT "~%reads special variable~P: ~S")
+              (length special-vars-read) special-vars-read))
+      (when special-vars-write
+        (format stream (TEXT "~%writes special variable~P : ~S")
+              (length special-vars-write) special-vars-write))
       (format stream (TEXT "~%~S byte-code instruction~:P:") (length lap-list))
       (dolist (L lap-list)
         (let ((PC (car L)) (instr (cdr L)))