From: Francogrex
Subject: How to make the compiler complain?
Date: 
Message-ID: <2b0a1d1d-0747-4e3c-a9cd-0a92aa43e9fd@d19g2000yqb.googlegroups.com>
When one forgets to declare a variable in C, the gcc compiler
complains bitterly; it's annoying but it forces one to declare. The CL
implementations I know (ECL, SBCL) let you get away with undeclare
variable etc..; but is there a way (a workaround) to force CL so that
it wouldn't let you compile unless you make all the appropriate
declarations?

From: Elena
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <0d0ff564-6294-4094-bdd5-5f38355cf8fe@j39g2000yqn.googlegroups.com>
On 26 Mar, 21:31, Francogrex <······@grex.org> wrote:
> When one forgets to declare a variable in C, the gcc compiler
> complains bitterly; it's annoying but it forces one to declare. The CL
> implementations I know (ECL, SBCL) let you get away with undeclare
> variable etc..; but is there a way (a workaround) to force CL so that
> it wouldn't let you compile unless you make all the appropriate
> declarations?

I'm also curious about that. The compiler forcing you to declare all
symbols beforehand has been sold as a solid feature of Clojure over
CL. I see the advantages of such an approach, but I understand the
advantages of the free CL approach as well. Therefore I'm curious
about it. Please, answer ^_^
From: Thomas A. Russ
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <ymivdpwhr1w.fsf@blackcat.isi.edu>
Francogrex <······@grex.org> writes:

> When one forgets to declare a variable in C, the gcc compiler
> complains bitterly; it's annoying but it forces one to declare. The CL
> implementations I know (ECL, SBCL) let you get away with undeclare
> variable etc..; but is there a way (a workaround) to force CL so that
> it wouldn't let you compile unless you make all the appropriate
> declarations?

Gee, my compiler always seems to complain about that.

You just need to make sure you read the warnings that are produced by
the compiler instead of just ignoring them.  I mean, the compiler
produces them for a reason.  At least SBCL does.  I've never used ECL.

For example:
* (defun foo (x y) (+ x y z))

; in: LAMBDA NIL
;     (+ X Y Z)
; ==>
;   (+ (+ X Y) Z)
; 
; caught WARNING:
;   undefined variable: Z

; 
; caught WARNING:
;   This variable is undefined:
;     Z
; 
; compilation unit finished
;   caught 2 WARNING conditions

FOO
* 

It not only warns you about an undeclared Z, but it warns you twice!
Now, granted, I can see how someone using SBCL gets used to not reading
all of the voluminous notes that it issues, but the warnings are there.

If you want it to stop compilation, just do:

  (setq *break-on-signals* t)

and then you will get the warnings to stop your compilation.  Of course,
it will stop it for all warnings, including function redefinition....


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Juanjo
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <f55de4ae-f1ab-47ef-a4d4-bb6fcf03b143@p11g2000yqe.googlegroups.com>
On Mar 26, 11:12 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:
> You just need to make sure you read the warnings that are produced by
> the compiler instead of just ignoring them.  I mean, the compiler
> produces them for a reason.  At least SBCL does.  I've never usedECL.

In ECL

> (compile 'foo '(lambda (x y) (+ x y z)))

;;; OPTIMIZE levels: Safety=2, Space=0, Speed=3, Debug=0
;;; Variable Z was undefined. Compiler assumes it is a global.
;;; End of Pass 1.
From: Francogrex
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <8bfa20b8-723f-4442-905a-dd91cd77e4c2@n33g2000vba.googlegroups.com>
On Mar 26, 11:12 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:
> Gee, my compiler always seems to complain about that.
>
> You just need to make sure you read the warnings that are produced by
> the compiler instead of just ignoring them.  I mean, the compiler
> produces them for a reason.  At least SBCL does.  I've never used ECL.
>
> For example:
> * (defun foo (x y) (+ x y z))

That's not the same thing I was talking about; what you presented is
an undefined variable; I'm talking about declarations in the sense of
those two examples below (in none of those the compiler complains
however the difference is noticeable):

(defun foo (x y)
  (declare (optimize (safety 0)))
  (+ x y))

(disassemble 'foo)

(defun foo2 (x y)
  (declare (fixnum x) (fixnum y) (optimize (safety 0)))
  (the fixnum (+ x y)))

(disassemble 'foo2)
From: gugamilare
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <9fc0fa03-d955-4923-8cd8-c820fe2121a4@r29g2000vbp.googlegroups.com>
On 27 mar, 14:17, Francogrex <······@grex.org> wrote:
> On Mar 26, 11:12 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:
>
> > Gee, my compiler always seems to complain about that.
>
> > You just need to make sure you read the warnings that are produced by
> > the compiler instead of just ignoring them.  I mean, the compiler
> > produces them for a reason.  At least SBCL does.  I've never used ECL.
>
> > For example:
> > * (defun foo (x y) (+ x y z))
>
> That's not the same thing I was talking about; what you presented is
> an undefined variable; I'm talking about declarations in the sense of
> those two examples below (in none of those the compiler complains
> however the difference is noticeable):
>
> (defun foo (x y)
>   (declare (optimize (safety 0)))
>   (+ x y))
>
> (disassemble 'foo)
>
> (defun foo2 (x y)
>   (declare (fixnum x) (fixnum y) (optimize (safety 0)))
>   (the fixnum (+ x y)))
>
> (disassemble 'foo2)

Then see my first post. I thought I got it wrong, but apparently I
didn't.
From: Francogrex
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <82faad38-805f-4079-810e-9425b270498a@o36g2000yqh.googlegroups.com>
On Mar 27, 6:41 pm, gugamilare <··········@gmail.com> wrote:
> Then see my first post. I thought I got it wrong, but apparently I
> didn't

ok, but for some reason my version of SBCL (1.0.22 on win) doesn't
give any notes or warning with this:
(declaim (optimize speed))
(defun sum (a b)
  (+ a b))
From: Francogrex
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <c88740ea-0f58-44fb-9959-53a395720dd2@j39g2000yqn.googlegroups.com>
On Mar 27, 9:10 pm, Francogrex <······@grex.org> wrote:
> On Mar 27, 6:41 pm, gugamilare <··········@gmail.com> wrote:
>
> > Then see my first post. I thought I got it wrong, but apparently I
> > didn't
>
> ok, but for some reason my version of SBCL (1.0.22 on win) doesn't
> give any notes or warning with this:
> (declaim (optimize speed))
> (defun sum (a b)
>   (+ a b))

I correct myself; I think you meant when you wrote that in a file and
then compiled the file using compile-file; now I understand. Then yes
I get the same warnings/notes you mention. Thanks for the tip.
From: Pillsy
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <dbe78442-7c99-47fd-8348-52ef27318853@k2g2000yql.googlegroups.com>
On Mar 27, 1:17 pm, Francogrex <······@grex.org> wrote:
[...]
> That's not the same thing I was talking about; what you presented is
> an undefined variable; I'm talking about declarations in the sense of
> those two examples below (in none of those the compiler complains
> however the difference is noticeable):

> (defun foo (x y)
>   (declare (optimize (safety 0)))
>   (+ x y))

> (disassemble 'foo)

> (defun foo2 (x y)
>   (declare (fixnum x) (fixnum y) (optimize (safety 0)))
>   (the fixnum (+ x y)))

> (disassemble 'foo2)

Why should the compiler complain when you present it with a correct
program? For all it knows, you might want FOO to take floats and
bignums as arguments. Even if it decided to pay attention to the
(SAFETY 0) declaration (which of course it's free not to), it would
only have good reason to assume that X and Y are numbers you can add,
as opposed to conses or symbols or something.

Now, SBCL and (I believe) CMUCL will emit "notes" when you have the
right optimization declarations telling you that, hey, it could
generate faster code if you'd just tell it what kind of numbers X and
Y are supposed to be. If you use SLIME, it will even annotate those
messages directly into the relevant source buffers.

It's really cool if that's the sort of thing you're into.

Cheers,
Pillsy
From: Pascal J. Bourguignon
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <87ljqsc7ae.fsf@galatea.local>
Francogrex <······@grex.org> writes:

> When one forgets to declare a variable in C, the gcc compiler
> complains bitterly; it's annoying but it forces one to declare. The CL
> implementations I know (ECL, SBCL) let you get away with undeclare
> variable etc..; but is there a way (a workaround) to force CL so that
> it wouldn't let you compile unless you make all the appropriate
> declarations?

No it's not possible. CL is specified explicitely to deal with unbound
variables.  

http://www.lispworks.com/documentation/HyperSpec/Body/03_abaa.htm
(follow the glossary link on /unbound variable/).

Actually, a lot of such silly questions are asked about CL because
people don't understand that CL is specified to be able to explicitely
handle and process errors.  You cannot restrict the language at
compilation time because it doesn't want to be restricted: it is
explicitely specified to do something well defined when errors occur,
and this is something that programs may use to implement their
algorithms.


(defun f (x)
  (if (plusp x)
     (* x (f (- x one)))
     one))

(mapcar (lambda (value-for-one)
            (handler-bind ((unbound-variable
                            (lambda (err)
                              (princ "providing ") (princ value-for-one) (terpri)
                              (invoke-restart 'use-value value-for-one))))
              (f 3)))
        '(1 42))

prints:
providing 1
providing 1
providing 1
providing 1
providing 42
providing 42
--> (6 126)





Now, I can understand that you may want to write some code without any
free variable.  You have the right to choose the programming paradigm
and style you want, and CL will do all it can to help you with it.  In
this occurence, CL helps you a lot, since it is homoiconic.  You can
trivially implement a function to find free variables in your code.



Here is for example, a function that extracts free variables for a
scheme expression:

(defun free-variables (expression &optional (bound-variables '()))
  (cond
    ((symbolp expression) (if (member expression bound-variables)
                             '()
                             (list expression)))
    ((atom expression)   '())
    ((eq 'lambda (car expression))
     (let ((bound-variables (append (cadr expression) bound-variables)))
       (mapcan (lambda (subexpr) (free-variables subexpr bound-variables))
               (cddr expression))))
    (t (mapcan (lambda (subexpr) (free-variables subexpr bound-variables))
               expression))))


If we "translate" the definition of F above into scheme we can see
that it has two occurences of the free variable ONE:

(free-variables '(lambda (f x)
                  (if (plusp x)
                    (* x (f (- x one)))
                    one))
                '(if plusp * -))
--> (ONE ONE)


If you're after free variables, you should also consider undefined
operators, undefined tags, undefined block labels, etc.  It's slightly
more complex than in scheme but it is still easy enough to implement
such a tool.


But this is not something that you can expect from the language, since
it is not in the nature of the language.

-- 
__Pascal Bourguignon__
From: gugamilare
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <892f3429-83d7-4e4b-b4d6-23036cdd45af@s28g2000vbp.googlegroups.com>
On 26 mar, 18:18, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Francogrex <······@grex.org> writes:
> > When one forgets to declare a variable in C, the gcc compiler
> > complains bitterly; it's annoying but it forces one to declare. The CL
> > implementations I know (ECL, SBCL) let you get away with undeclare
> > variable etc..; but is there a way (a workaround) to force CL so that
> > it wouldn't let you compile unless you make all the appropriate
> > declarations?
>
> No it's not possible. CL is specified explicitely to deal with unbound
> variables.  
>
Well, it is not exactly like THAT. The code always compiles, but, in
SBCL, for example, it signals warnings. You declare globally that you
want optimized code. Then you go on and compile things. If there is
any declaration left behind, and if not having that declaration in
fact slows down you code, SBCL will signal a note.

For instance, I wrote this down in a file:


(declaim (optimize speed))

(defun sum (a b)
  (+ a b))

And I got several notes. These are some of them:

; compiling file "/home/gugamilare/Lisp/test.lisp" (written 26 MAR
2009 06:36:37 PM):

; file: /home/gugamilare/Lisp/test.lisp
; in: defun sum
;     (+ A B)
;
; note: unable to
;   optimize
; due to type uncertainty:
;   The first argument is a number, not a rational.
;   The second argument is a number, not a float.
;
; note: unable to
;   optimize
; due to type uncertainty:
;   The first argument is a number, not a float.
;   The second argument is a number, not a rational.

If you declare both a and b to be, say, fixnums, no more notes are
given. The problem it, if you declare them as integer:

; compiling file "/home/gugamilare/Lisp/test.lisp" (written 26 MAR
2009 06:41:55 PM):

; file: /home/gugamilare/Lisp/test.lisp
; in: defun sum
;     (+ A B)
;
; note: forced to do generic-+ (cost 10)
;       unable to do inline fixnum arithmetic (cost 2) because:
;       The first argument is a integer, not a fixnum.
;       The second argument is a integer, not a fixnum.
;       The result is a (values integer &optional), not a (values
fixnum &rest t).
;       unable to do inline (signed-byte 64) arithmetic (cost 5)
because:
;       The first argument is a integer, not a (signed-byte 64).
;       The second argument is a integer, not a (signed-byte 64).
;       The result is a (values integer &optional), not a (values
;                                                          (signed-
byte 64) &rest
;                                                          t).
;       etc.
;
; compilation unit finished
;   printed 1 note

The problem is that optimizing sum of integers in general is not
possible, it always will need to check if arguments are bignums and,
in that case, it needs to call the proper function for that purpose.

You can make you compilation abort by specifying a handler around the
compile-file call:

cl-user> (handler-case (compile-file "/home/gugamilare/Lisp/
test.lisp")
	   (sb-int:simple-compiler-note (c) c))
; compiling file "/home/gugamilare/Lisp/test.lisp" (written 26 MAR
2009 06:41:55 PM):
; compiling (declaim (optimize speed))
; compiling (defun sum ...);
                           ; compilation unit aborted
                           ;   caught 1 fatal ERROR condition
; compilation aborted after 0:00:00.005
#<sb-int:simple-compiler-note {10056B6701}>

In this case, compilation is aborted and the condition is returned.
From: Kaz Kylheku
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <20090404121016.258@gmail.com>
On 2009-03-26, Pascal J. Bourguignon <···@informatimago.com> wrote:
> Francogrex <······@grex.org> writes:
>
>> When one forgets to declare a variable in C, the gcc compiler
>> complains bitterly; it's annoying but it forces one to declare. The CL
>> implementations I know (ECL, SBCL) let you get away with undeclare
>> variable etc..; but is there a way (a workaround) to force CL so that
>> it wouldn't let you compile unless you make all the appropriate
>> declarations?
>
> No it's not possible. CL is specified explicitely to deal with unbound
> variables.  

It is useful to receive compiler diagnostics for calls to apparently undefined
functions, and free symbol references. These situations are often errors.

It is also not true that CL is fully specified with respect to unbound
variables. Counterexample:

  ;; x is unbound: undefined behavior:
  (setf x 42) 
From: Matthias Buelow
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <7344vdFt5khnU1@mid.dfncis.de>
Kaz Kylheku <········@gmail.com> wrote:

>  ;; x is unbound: undefined behavior:
>  (setf x 42) 

Why is this undefined?
From: gugamilare
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <013ac36e-c14c-49fb-be88-05671ab3c30c@e2g2000vbe.googlegroups.com>
On 27 mar, 11:08, Matthias Buelow <····@incubus.de> wrote:
> Kaz Kylheku <········@gmail.com> wrote:
> >  ;; x is unbound: undefined behavior:
> >  (setf x 42)
>
> Why is this undefined?

Because the spec says so. It is not defined is x is undeclared. In
this situations implementations can declare the variable globally
dynamic (like an implicit defvar) or even signal an error. OTOH, no
error should be signaled, for instance, here:

(defun foo (a)
  (setf x a))

until you actually run foo and x is still unbound. But if you declare
x after the definition of the function, then calling the function foo
signals no errors or warnings.

On 26 mar, 19:12, ····@sevak.isi.edu (Thomas A. Russ) wrote:
> Now, granted, I can see how someone using SBCL gets used to not reading
> all of the voluminous notes that it issues, but the warnings are there.

I'm used to write code in such a way that SBCL does not signal any
warning at all. This way, I will know if I put a bug inside my code by
mistake.
From: Thomas A. Russ
Subject: Re: How to make the compiler complain?
Date: 
Message-ID: <ymir60iixhf.fsf@blackcat.isi.edu>
gugamilare <··········@gmail.com> writes:

> On 26 mar, 19:12, ····@sevak.isi.edu (Thomas A. Russ) wrote:
> > Now, granted, I can see how someone using SBCL gets used to not reading
> > all of the voluminous notes that it issues, but the warnings are there.
> 
> I'm used to write code in such a way that SBCL does not signal any
> warning at all. This way, I will know if I put a bug inside my code by
> mistake.

Yes.  It is a good practice to follow.

It is just that with all of the compiler notes that SBCL tends to emit,
picking the warnings out of the results is a bit tedious, since unlike
some other lisp implementations, it isn't immediately obvious.

So, I actually think that muffling the style warnings and suppressing
compiler notes can be handy for highlighting where the real problems
lie.

Compiler notes are relatively easy to muffle:

  (declaim (sb-ext:muffle-conditions sb-ext:compiler-note))

Style warnings notes are a bit more tedious, since you have to explicitly wrap
a handler around the calls to the compiler, since apparently the
following DOES NOT WORK:

 (declaim (sb-ext:muffle-conditions sb-ext:compiler-note))

so instead you need something more like:

(defmacro with-style-warnings-suppressed (&rest body)
   `(handler-bind ((style-warning #'muffle-warning))
        ,@body))

and then use it to wrap the code.

(See http://www.math.utexas.edu/pipermail/maxima/2008/011455.html for
more discussion)
-- 
Thomas A. Russ,  USC/Information Sciences Institute