From: Bob Krovetz
Subject: Allegro debugger question
Date: 
Message-ID: <6nsrj6$r4e$1@news.nj.nec.com>
I have a question about the behavior of the debugger on the following code:

    (defun baz ()
       (let ((foo 2))
          (print 2)
          (break)))


When I run baz I get the following behavior:

    USER(1): (defun baz ()
                (let ((foo 2))
                  (print 2)
                  (break)))
    BAZ
    USER(2): (baz)

    2 
    Break: call to the `break' function.

    Restart actions (select using :continue):
     0: return from break.
    [1c] USER(5): :loc foo
    [1c] USER(6): :evalmode :context t
    [1c] USER(7): foo
    2

I don't understand why ":loc foo" does not return a value.  I then
tried compiling baz:

   USER(8): (compile 'baz)
   BAZ
   NIL
   NIL
   USER(9): (baz)

   2 
   Break: call to the `break' function.

   Restart actions (select using :continue):
    0: return from break.
   [1c] USER(10): :loc foo
   [1c] USER(11): :evalmode :context t
   [1c] USER(12): foo
   Error: Attempt to take the value of the unbound variable `FOO'.
     [condition type: UNBOUND-VARIABLE]

   Restart actions (select using :continue):
    0: Try evaluating FOO again.
    1: Set the symbol-value of FOO and use its value.
    2: Use a value without setting FOO.
    3: return from break.


The command ":evalmode :context t" causes evaluation to be done with respect 
to the current debugger frame rather than the top-level.  I think this should 
be the default, so I also tried advising 'break' to always issue that command:

   USER(1): (defun baz ()
              (let ((foo 2))
                 (print 2)
                 (break)))
   BAZ
   USER(2): (excl::defadvice tpl::break :around
               (tpl:do-command "evalmode" :context t)
                :do-it)
   BREAK
   USER(3): (baz)

   2 
   Break: call to the `break' function.

   Restart actions (select using :continue):
    0: return from break.
   [1c] USER(4): :loc foo
   [1c] USER(5): foo
   Error: Attempt to take the value of the unbound variable `FOO'.
     [condition type: UNBOUND-VARIABLE]

   Restart actions (select using :continue):
    0: Try evaluating FOO again.
    1: Set the symbol-value of FOO and use its value.
    2: Use a value without setting FOO.
    3: return from break.


I have tried this with Allegro Version 4.3 and Version 5.0 (beta), but I get
the same results.  I am running it on Redhat Linux Version 4.2 on a Pentium.  
I am using optimization settings: safety 3, space 3, speed 0, debug 3.  Can 
someone tell me why I get this behavior and how to advise "break" so that 
":evalmode :context t" is always set?

Thanks,
Bob

--
·······@research.nj.nec.com

From: Chuck Fry
Subject: Re: Allegro debugger question
Date: 
Message-ID: <6ntik3$r79$1@shell5.ba.best.com>
In article <············@news.nj.nec.com>,
Bob Krovetz <·······@ira.nj.nec.com> wrote:
>When I run baz I get the following behavior:
>
>    USER(1): (defun baz ()
>                (let ((foo 2))
>                  (print 2)
>                  (break)))
>    BAZ
>    USER(2): (baz)
>
>    2 
>    Break: call to the `break' function.
>
>    Restart actions (select using :continue):
>     0: return from break.
>    [1c] USER(5): :loc foo
>    [1c] USER(6): :evalmode :context t
>    [1c] USER(7): foo
>    2
>
>I don't understand why ":loc foo" does not return a value.  

Because the Allegro debugger doesn't do interpreted code, at least that
I'm aware of.

>							     I then
>tried compiling baz:
>
>   USER(8): (compile 'baz)
>   BAZ
>   NIL
>   NIL
>   USER(9): (baz)
>
>   2 
>   Break: call to the `break' function.
>
>   Restart actions (select using :continue):
>    0: return from break.
>   [1c] USER(10): :loc foo
>   [1c] USER(11): :evalmode :context t
>   [1c] USER(12): foo
>   Error: Attempt to take the value of the unbound variable `FOO'.
>     [condition type: UNBOUND-VARIABLE]
>
>   Restart actions (select using :continue):
>    0: Try evaluating FOO again.
>    1: Set the symbol-value of FOO and use its value.
>    2: Use a value without setting FOO.
>    3: return from break.
>
>
>The command ":evalmode :context t" causes evaluation to be done with respect 
>to the current debugger frame rather than the top-level.  

I don't think it matters.

I believe what has happened is that the compiler has optimized the
unreferenced local variable FOO out of existence.  Allegro's compiler
does aggressive optimization.

Simply referring to FOO in the call to PRINT might not let you see its
value either!  This is because by the time you get to the BREAK call,
the variable FOO is no longer used, and so the compiler will often
optimize it out of existence here too.

If you want to see the value of a local variable, your BREAK call (or
debugger entry, for whatever reason) must come before the last
reference to the variable.

I've had lots of practice debugging code produced by the Allegro
compiler.  I find it one of the better optimizing Common Lisp compilers
around.  However, about the only downside of truly efficient compiled
code is the loss of some debugging information.  I find the performance
of the resulting code is worth this small inconvenience.

 -- Chuck
-- 
	    Chuck Fry -- Jack of all trades, master of none
 ······@chucko.com (text only please), ········@home.com (MIME enabled),
		  ······@gateway.idiom.com (SPAM ONLY)
From: Tim Bradshaw
Subject: Re: Allegro debugger question
Date: 
Message-ID: <ey3af6lbmj1.fsf@todday.aiai.ed.ac.uk>
* Chuck Fry wrote:

> I've had lots of practice debugging code produced by the Allegro
> compiler.  I find it one of the better optimizing Common Lisp compilers
> around.  However, about the only downside of truly efficient compiled
> code is the loss of some debugging information.  I find the performance
> of the resulting code is worth this small inconvenience.

I think if you declare lots of debug then it gets better too (at least
it seems to in my allegro 4.3 on Suns)

--tim
From: Bob Krovetz
Subject: Re: Allegro debugger question
Date: 
Message-ID: <6nuhdp$k5h$1@news.nj.nec.com>
Larry Kramer <······@stsci.edu> wrote:
>The problem is that you are at a different stack level than you think you
>are. You are at the levelof the "let", not inside it.
>Note below that I had to issue an ":up" directive to get to the correct
>stack frame

Ah.  But then why does the ":evalmode :context t" allow me to print out
the value of the local when I am at the level of the "let"?  I *thought*
that issuing that command was the same as omitting the ":local" before the
name of the variable.

Chuck Fry wrote:

: > I've had lots of practice debugging code produced by the Allegro
: > compiler.  I find it one of the better optimizing Common Lisp compilers
: > around.  However, about the only downside of truly efficient compiled
: > code is the loss of some debugging information.  I find the performance
: > of the resulting code is worth this small inconvenience.

: I think if you declare lots of debug then it gets better too (at least
: it seems to in my allegro 4.3 on Suns)

: --tim

Yes, but I had "debug" set to 3 (as high as it will go).  Also, at first
I didn't compile the code - it was just typed into the interpreter.
It looks like the compiler optimized away the "let" once the code was
compiled, so that there no longer was a binding for "foo".  I'm glad
that the compiler produces optimized code, but I want to leave out the
optimizations until I've gotten further in the development.  I already
had "safety" and "debug" set to 3, so I don't know what else to do
to minimize the degree of optimization.  I guess I need to develop code
with the interpreter...

Bob

--
·······@research.nj.nec.com
From: Larry Kramer
Subject: Re: Allegro debugger question
Date: 
Message-ID: <35A36E23.AF3DB055@stsci.edu>
Bob Krovetz wrote:
> 
> Larry Kramer <······@stsci.edu> wrote:
> >The problem is that you are at a different stack level than you think you
> >are. You are at the levelof the "let", not inside it.
> >Note below that I had to issue an ":up" directive to get to the correct
> >stack frame
> 
> Ah.  But then why does the ":evalmode :context t" allow me to print out
> the value of the local when I am at the level of the "let"?  I *thought*
> that issuing that command was the same as omitting the ":local" before the
> name of the variable.
> 

It doesn't.  An ":evalmode :context t" directive tells the debugger to
eval
any Lisp forms in the current stack frame context.  Note from the dump
below
that there are initially no local values printed out. After issuing an
:up command local values are available.

USER(23): (baz)

2 
Break: call to the `break' function.

Restart actions (select using :continue):
 0: return from break.
[1c] USER(24): :evalmode :context t
[1c] USER(25): :local
[1c] USER(26): :up 1
Evaluation stack:

 ->(BREAK)
   (LET ((FOO 2)) (PRINT 2) (BREAK))
   (BAZ)
   (EVAL (BAZ))
   (TPL:TOP-LEVEL-READ-EVAL-PRINT-LOOP)
   (TPL:START-INTERACTIVE-TOP-LEVEL
      #<BIDIRECTIONAL-TERMINAL-STREAM [initial terminal io] fd 0/1 @
#x10d412>
      #<Function TOP-LEVEL-READ-EVAL-PRINT-LOOP> NIL)
[1c] USER(27): :local
Interpreted lexical environment:
FOO: 2
Compiled lexical environment:
0(OPTIONAL): EXCL::DATUM: "call to the `break' function."
1(REST): EXCL::ARGUMENTS: NIL
2(LOCAL): FOO: 2
3(LOCAL): :UNKNOWN: NIL
4(LOCAL): :UNKNOWN: -67113742
5(LOCAL): :UNKNOWN: #<SIMPLE-BREAK @ #x195e482>
6(LOCAL): :UNKNOWN: :REPORT-FUNCTION
7(LOCAL): :UNKNOWN: #<non-lisp object @ #x111>
8(LOCAL): :UNKNOWN: #<BIDIRECTIONAL-TERMINAL-STREAM [initial terminal
io] fd 0/1 @ #x10d412>
9(LOCAL): :UNKNOWN: 0
10(LOCAL): :UNKNOWN: 0
[1c] USER(28): 
======

From the 4.3 documentation for :evalmode --

"If called with :context specified non-nil, evaluation is done with
respect
to the current frame rather than the top level.  All known local
variables
(those printed by the :local command) can be referenced by name in
ordinary Lisp forms..."

BTW, I'd like to apologize for my previous HTML post -- I'm posting with
a newer version of Netscape in which the default is to post HTML.

Larry
From: Chuck Fry
Subject: Re: Allegro debugger question
Date: 
Message-ID: <6o09jh$692$1@shell5.ba.best.com>
In article <············@news.nj.nec.com>,
Bob Krovetz <·······@ira.nj.nec.com> wrote:
> [...]  I'm glad
>that the compiler produces optimized code, but I want to leave out the
>optimizations until I've gotten further in the development.  I already
>had "safety" and "debug" set to 3, so I don't know what else to do
>to minimize the degree of optimization.  I guess I need to develop code
>with the interpreter...

No, you need to stop using contrived examples.  Have you tried to debug
the actual code you're developing on Allegro?

And you need to develop an understanding of how compilers deal with
variables that are no longer needed.

Allegro's debugger, while not as good as the old Symbolics debugger
IMHO, is representative of modern Common Lisp debuggers.  But it doesn't
do interpreted code to my knowledge.

The idea that anyone should test with interpreted code in this day and
age is absolutely ludicrous.  Compiled Lisp code is just as safe as
interpreted code, and at least 2 orders of magnitude faster.  And the
debuggers are designed for compiled code, and aren't as informative when
using interpreted code.  Incremental compilation of modified functions
takes only a few seconds.

Now should you give all that up just because you're confused about what
the compiler is doing with your code?  I sure don't think so.

I'm sorry if this sounds harsh.  But I think you're giving Allegro's
compiler and debugger a bum rap, when it's your example that's buggy.
 -- Chuck
-- 
	    Chuck Fry -- Jack of all trades, master of none
 ······@chucko.com (text only please), ········@home.com (MIME enabled),
		  ······@gateway.idiom.com (SPAM ONLY)
From: Steve Gonedes
Subject: Re: Allegro debugger question
Date: 
Message-ID: <6nv9s5$orl@bgtnsc03.worldnet.att.net>
·······@ira.nj.nec.com (Bob Krovetz) writes:


< When I run baz I get the following behavior:
<
<     USER(1): (defun baz ()
<                 (let ((foo 2))
<                   (print 2)
<                   (break)))
<     BAZ
<     USER(2): (baz)
<
<     2
<     Break: call to the `break' function.
<
<     Restart actions (select using :continue):
<      0: return from break.
<     [1c] USER(5): :loc foo
<     [1c] USER(6): :evalmode :context t
<     [1c] USER(7): foo
<     2
<
< I don't understand why ":loc foo" does not return a value.  I then
< tried compiling baz:

I think you have to use the :i or :c option.

USER(24): (baz)

2
Break: call to the `break' function.

Restart actions (select using :continue):
 0: return from break.
[1c] USER(25): :loc foo
[1c] USER(26): :loc :c foo
2
[1c] USER(27):

<    USER(8): (compile 'baz)
<    BAZ
<    NIL
<    NIL
<    USER(9): (baz)
<
<    2
<    Break: call to the `break' function.
<
<    Restart actions (select using :continue):
<     0: return from break.
<    [1c] USER(10): :loc foo
<    [1c] USER(11): :evalmode :context t
<    [1c] USER(12): foo
<    Error: Attempt to take the value of the unbound variable `FOO'.
<      [condition type: UNBOUND-VARIABLE]


This is because the compiler is discarding the names of lexical variables
(namely FOO). If you place the break statement inside the lexcial
environment (i.e., you must use foo).

USER(38): (disassemble 'baz)
;; disassembly of #<Function BAZ>
;; formals: 
;; constant vector:
0:	PRINT
1:	BREAK

;; code start: #x204fddec:
   0: 55          pushl	ebp
   1: 8b ec       movl	ebp,esp
   3: 56          pushl	esi
   4: 83 ec 24    subl	esp,$36
   7: e3 02       jcxz	11
   9: cd 61       int	$97             ; trap-argerr
  11: d0 7f a3    sarb	[edi-93],$1     ; C_INTERRUPT
  14: 74 02       jz	18
  16: cd 64       int	$100            ; trap-signal-hit
  18: 8b 5e 32    movl	ebx,[esi+50]    ; PRINT
  21: 33 c0       xorl	eax,eax
  23: b0 08       movb	al,$8
  25: b1 01       movb	cl,$1
  27: ff d7       call	*edi
  29: 8b 5e 36    movl	ebx,[esi+54]    ; BREAK
  32: b1 00       movb	cl,$0
  34: ff d7       call	*edi
  36: c9          leave
  37: 8b 75 fc    movl	esi,[ebp-4]
  40: c3          ret
  41: 90          nop
USER(39): 

No more foo (this is probably a good thing though).

(defun baz ()
  (declare (optimize (debug 3)))
  (let ((foo 2))
    (break "foo")
    (print foo)
    ))


USER(48): (setq comp:save-local-scopes-switch t
                comp:save-local-names-switch t)


This should make the compiler try it's heart out to save the names of
local variables. The manual states that it will toss local names in
compiled code unless you set the proper variables. I really can't look
those up because I'm being eaten alive by mosquitos (the screen in my
window doesn't work very well - and they just took my fan so take this
into account if there are any errors in what I'm saying :).

< I am using optimization settings: safety 3, space 3, speed 0, debug 3.  Can
< someone tell me why I get this behavior and how to advise "break" so that
< ":evalmode :context t" is always set?

You're right, setting debug to 3 doesn't help when compiling `baz'.
This is probably strange, although it isn't really useful to have all
those symbols in the code just for debugging (as the lisp already gave
an error message that `foo' wasn't used).

With functions that are a tad bit more complex you can coerce the
compiler to leave the names just by setting debug to 3 (or 2 usually).

Also inspect can be useful as well (but to a lesser degree in compiled code).

USER(1): (defun baz (arg)
           (declare (optimize (debug 3)))
           (let ((foo (1+ arg)))
             (break "time!")
             (print foo)))
BAZ
USER(2): (baz 3)
Break: time!

Restart actions (select using :continue):
 0: return from break.
[1c] USER(3): :cur
(LET ((FOO (1+ ARG))) (BREAK "time!") (PRINT FOO))
[1c] USER(4): :loc
Interpreted lexical environment:
ARG: 3
[1c] USER(5): :i #'baz
#<Interpreted Function BAZ>
  lambda-list: (ARG)
   0 excl-type ----> Bit field: #x08
   1 flags --------> Bit field: #x48
   2 start --------> Bit field: #x20000cf9
   3 hash ---------> Bit field: #x00004c1b
   4 symdef -------> The symbol BAZ
   5 code ---------> (LAMBDA (ARG) ...), a proper list with 4 elements
   6 formals ------> (ARG), a proper list with 1 element
   7 cframe-size --> fixnum 0 [#x00000000]
   8 immed-args ---> fixnum 0 [#x00000000]
   9 locals -------> fixnum 0 [#x00000000]
[1c] USER(6): :i 5
A proper list @ #x2058ef11 with 4 elements
   0-> The symbol LAMBDA
   1-> (ARG), a proper list with 1 element
   2-> (DECLARE ...), a proper list with 2 elements
   3-> (BLOCK BAZ ...), a proper list with 3 elements
[1c] USER(7): :i 3
A proper list @ #x2058eee9 with 3 elements
   0-> The symbol BLOCK
   1-> The symbol BAZ
   2-> (LET ((FOO (1+ ARG))) ...), a proper list with 4 elements
[1c] USER(8): :i 2
A proper list @ #x20591889 with 4 elements
   0-> The symbol LET
   1-> ((FOO (1+ ARG))), a proper list with 1 element
   2-> (BREAK "time!"), a proper list with 2 elements
   3-> (PRINT FOO), a proper list with 2 elements
[1c] USER(9): :pop
USER(10): (compile 'baz)
BAZ
NIL
NIL
USER(11): (baz 3)
Break: time!

Restart actions (select using :continue):
 0: return from break.
[1c] USER(12): :cur
(BAZ 3)
[1c] USER(13): :loc
Compiled lexical environment:
0(REQUIRED): ARG: 3
1(LOCAL): FOO: 4
[1c] USER(14):

< Thanks,
< Bob

Happy debugging? Just kidding - have fun.