guile-devel
[Top][All Lists]
Advanced

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

Re: Reporting unused local variables


From: Ludovic Courtès
Subject: Re: Reporting unused local variables
Date: Thu, 02 Jul 2009 19:35:47 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1.50 (gnu/linux)

Hello,

address@hidden (Ludovic Courtès) writes:

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

Following Andy's suggestion on IRC, I tried to integrate this feature in
the `analyze-lexicals' procedure of Tree-IL, this time (and with an
imperative style not quite to my taste.)

Unfortunately, source location information appears to be unavailable (or
just difficult to obtain?) at this level for code generated by macros
such as `record-case'.  Well, I probably just need some guidance.  ;-)

Voilà!

Ludo'.

diff --git a/module/language/tree-il/analyze.scm 
b/module/language/tree-il/analyze.scm
index 9768077..d8bdaef 100644
--- a/module/language/tree-il/analyze.scm
+++ b/module/language/tree-il/analyze.scm
@@ -64,6 +64,9 @@
   ;;  allows us to heapify vars in an O(1) fashion
   ;; refcounts: sym -> count
   ;;  allows us to detect the or-expansion an O(1) time
+  ;; variable-origins: gensym -> ((name . SYM) (filename . F) (column . C) ...)
+  ;;  associates the gensym variable symbol with an alist containing its
+  ;;  original name and source location information
 
   (define (find-heap sym parent)
     ;; fixme: check displaced lexicals here?
@@ -71,6 +74,16 @@
         parent
         (find-heap sym (hashq-ref parents parent))))
 
+  (define (tree-il? x)
+    (record? x))
+
+  (define (find-src x parent)
+    ;; Find the closest source location alist available.
+    (if (tree-il? x)
+        (or (tree-il-src x)
+            (find-src parent #f))
+        '()))
+
   (define (analyze! x parent level)
     (define (step y) (analyze! y parent level))
     (define (recur x parent) (analyze! x parent (1+ level)))
@@ -104,7 +117,13 @@
       ((<sequence> exps)
        (for-each step exps))
       
-      ((<lambda> vars meta body)
+      ((<lambda> names vars meta body)
+       ;; FIXME: Handle the case where NAMES and VARS are dotted lists.
+       (if (list? vars)
+           (for-each (lambda (name var)
+                       (hashq-set! variable-origins var
+                                   (cons `(name . ,name) (find-src x parent))))
+                     names vars))
        (hashq-set! parents x parent)
        (hashq-set! bindings x
                    (let rev* ((vars vars) (out '()))
@@ -115,19 +134,31 @@
        (recur body x)
        (hashq-set! bindings x (reverse! (hashq-ref bindings x))))
 
-      ((<let> vars vals body)
+      ((<let> names vars vals body)
+       (for-each (lambda (name var)
+                   (hashq-set! variable-origins var
+                               (cons `(name . ,name) (find-src x parent))))
+                 names vars)
        (for-each step vals)
        (hashq-set! bindings parent
                    (append (reverse vars) (hashq-ref bindings parent)))
        (step body))
       
-      ((<letrec> vars vals body)
+      ((<letrec> names vars vals body)
+       (for-each (lambda (name var)
+                   (hashq-set! variable-origins var
+                               (cons `(name . ,name) (find-src x parent))))
+                 names vars)
        (hashq-set! bindings parent
                    (append (reverse vars) (hashq-ref bindings parent)))
        (for-each step vals)
        (step body))
 
-      ((<let-values> vars exp body)
+      ((<let-values> names vars exp body)
+       (for-each (lambda (name var)
+                   (hashq-set! variable-names var
+                               (cons `(name . ,name) (find-src x parent))))
+                 names vars)
        (hashq-set! bindings parent
                    (let lp ((out (hashq-ref bindings parent)) (in vars))
                      (if (pair? in)
@@ -251,8 +282,30 @@
   (define refcounts (make-hash-table))
   (define allocation (make-hash-table))
   (define heap-indexes (make-hash-table))
+  (define variable-origins (make-hash-table))
 
   (analyze! x #f -1)
   (allocate! x -1 0)
 
+  (hash-for-each (lambda (gensym value)
+                   (if (symbol? gensym)
+                       (let* ((refcount (hashq-ref refcounts gensym 0))
+                              (origins  (hashq-ref variable-origins gensym
+                                                   '()))
+                              (name     (assoc-ref origins 'name))
+                              (location
+                               (if (assoc-ref origins 'line)
+                                   (format #f "~a:~a:~a"
+                                           (or (assoc-ref origins 'filename)
+                                               "<stdin>")
+                                           (1+ (assoc-ref origins 'line))
+                                           (assoc-ref origins 'column))
+                                   "<unknown-location>")))
+                         (if (zero? refcount)
+                             (format (current-error-port)
+                                     "~A: variable `~A' never used~%"
+                                     location
+                                     (or name gensym))))))
+                 allocation)
+
   allocation)

reply via email to

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