guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Reporting unused local variables


From: Ludovic Courtès
Subject: Reporting unused local variables
Date: Mon, 29 Jun 2009 00:50:21 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1.50 (gnu/linux)

Hello,

The attached patch is an attempt to add unused variable reporting to the
compiler, at the GLIL->assembly step.  It was quite simple to implement
here, and it should work with all front-ends (Scheme, ECMAScript, etc.),
which is nice.

Example:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> (lambda () (let ((x 2)) x))
$1 = #<program 7ffae3f42b40 at <unknown port>:1:0 ()>
scheme@(guile-user)> (lambda () (let ((x 2)) 'something-else))
<stdin>:3:11: variable `x' never referenced
$2 = #<program 7ffae3f36560 at <unknown port>:2:0 ()>
--8<---------------cut here---------------end--------------->8---

It works as well on actual programs such as the compiler itself, but
leads to a stack overflow on files with lots of unused variables, such
as `language/tree-il/compile-glil.scm', although `analyze-program' is
tail-recursive AFAICS (ideas welcome).

Also, it's annoying because it reports unused bindings introduced by
`record-case', and there are lots of them in the compiler.

Is this the right place and the right way to do such things?  Comments?

Thanks,
Ludo'.

diff --git a/module/language/glil/compile-assembly.scm 
b/module/language/glil/compile-assembly.scm
index 0b92a4e..5d3d400 100644
--- a/module/language/glil/compile-assembly.scm
+++ b/module/language/glil/compile-assembly.scm
@@ -26,7 +26,7 @@
   #:use-module (system vm instruction)
   #:use-module ((system vm program) #:select (make-binding))
   #:use-module (ice-9 receive)
-  #:use-module ((srfi srfi-1) #:select (fold))
+  #:use-module (srfi srfi-1)
   #:use-module (rnrs bytevector)
   #:export (compile-assembly))
 
@@ -134,6 +134,54 @@
   (and (not (null? objects))
        (list->vector (cons #f objects))))
 
+(define (analyze-program program)
+  (let loop ((glil       (glil-program-body program))
+             (locals     '())
+             (local-refs '())
+             (location   #f))
+    (if (null? glil)
+        program
+        (record-case (car glil)
+          ((<glil-bind> vars)
+           (loop (cdr glil)
+                 (append (filter-map (lambda (name+type+index)
+                                       (and (eq? (cadr name+type+index)
+                                                 'local)
+                                            (cons (caddr name+type+index)
+                                                  (car name+type+index))))
+                                     vars)
+                         locals)
+                 local-refs
+                 location))
+          ((<glil-local> op index)
+           (loop (cdr glil)
+                 locals
+                 (if (eq? op 'ref)
+                     (cons index local-refs)
+                     local-refs)
+                 location))
+          ((<glil-unbind>)
+           (let ((unused   (lset-difference = (map car locals)
+                                            local-refs))
+                 (location (if (pair? location)
+                               (format #f "~a:~a:~a"
+                                       (or (assoc-ref location 'filename)
+                                           "<stdin>")
+                                       (1+ (assoc-ref location 'line))
+                                       (assoc-ref location 'column))
+                               "<unknown-location>")))
+             (for-each (lambda (var)
+                         (format (current-error-port)
+                                 "~A: variable `~A' never referenced~%"
+                                 location
+                                 (assoc-ref locals var)))
+                       unused)
+             (loop (cdr glil) '() '() location)))
+          ((<glil-source> props)
+           (loop (cdr glil) locals local-refs props))
+          (else
+           (loop (cdr glil) locals local-refs location))))))
+
 (define (glil->assembly glil nexts-stack bindings
                         source-alist label-alist object-alist addr)
   (define (emit-code x)
@@ -143,6 +191,7 @@
 
   (record-case glil
     ((<glil-program> nargs nrest nlocs nexts meta body closure-level)
+     (analyze-program glil)
      (let ((toplevel? (null? nexts-stack)))
        (define (process-body)
          (let ((nexts-stack (cons nexts nexts-stack)))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]