Re: how to compute
Steve Haflich <[email protected]> Tue, 16 May 2006 18:51:57 -0700
| Newsgroups | gmane.lisp.allegro |
|---|---|
| Message-ID | <7668.1147830717@gemini> |
From: "Pierpaolo BERNARDI" <[email protected]> BTW, I think the following is a small bug in acl: CL-USER(153): 6042715942219502152353483497843569525253244555916134.0 Error: This integer is too large to be converted to single float: 343488630960564478300511837005615234375 [condition type: SIMPLE-ERROR] (there's no integer in my code, and the value printed is bogus) I'm curious why you think this is a bug, whether small or otherwise. What did you expect to be the result of executing this form? What do you find wrong about the result? That execution signaled error? Or that the error wasn't what you expected? First, why do you think the integer value in the error message is bogus? It look likes the printed representation of a perfectly reasonable integer. (If that integer were truly bogus, then we would be in danger of the sun stopping to shine and cracks appearing in the sky. :-) Rather, you should have said that you don't understand where that integer comes from. When lisp execution signals an error and enters the debugger, the intention is that you can use the debugger to find out that happened and why. It would be straightforward to wrap an error handler around the read-eval-print loop such that any error signaled during evaluation of a form would cause a straightforward "An error has occurred." message with no further information. But surely this would not be useful. This is what I did after duplicating your error. I've deleted some binary characters from the stream input buffer to avoid confusing some mail reading software. cl-user(12): 6042715942219502152353483497843569525253244555916134.0 Error: This integer is too large to be converted to single float: 343488630960564478300511837005615234375 [condition type: simple-error] Restart actions (select using :continue): 0: Return to Top Level (an "abort" restart). 1: Abort entirely from this (lisp) process. [1] cl-user(13): :zo :all t Evaluation stack: ... 4 more newer frames ... (excl::make-float #("6042715942219502152353483497843569525253244555916134.0 <binary text suppressed here>" 512 54 ...)) (excl::read-token #<terminal-simple-stream [initial terminal io] fd 0/1 @ #x71120c6a> #\6) (excl::read2 #<terminal-simple-stream [initial terminal io] fd 0/1 @ #x71120c6a> t ...) (excl::read1 #<terminal-simple-stream [initial terminal io] fd 0/1 @ #x71120c6a> t ...) ->(read-preserving-whitespace #<terminal-simple-stream [initial terminal io] fd 0/1 @ #x71120c6a>) (tpl::read-top-level-command #<terminal-simple-stream [initial terminal io] fd 0/1 @ #x71120c6a>) (tpl::read-eval-print-one-command nil nil) (excl::read-eval-print-loop :level 0) (tpl::top-level-read-eval-print-loop1) ... more older frames ... [1] cl-user(14): :up 4 Evaluation stack: (excl::internal-invoke-debugger "Error" #<simple-error @ #x71cc407a> ...) (error simple-error :format-control ...) (excl::.error "This integer is too large to be converted ~ to single float: ~s" 343488630960564478300511837005615234375) (excl::integer-to-single-float 343488630960564478300511837005615234375) ->(excl::make-float #("6042715942219502152353483497843569525253244555916134.0 <binary text suppressed here>" 512 54 ...)) (excl::read-token #<terminal-simple-stream [initial terminal io] fd 0/1 @ #x71120c6a> #\6) (excl::read2 #<terminal-simple-stream [initial terminal io] fd 0/1 @ #x71120c6a> t ...) (excl::read1 #<terminal-simple-stream [initial terminal io] fd 0/1 @ #x71120c6a> t ...) (read-preserving-whitespace #<terminal-simple-stream [initial terminal io] fd 0/1 @ #x71120c6a>) ... more older frames ... [1] cl-user(15): As you can see, the execution of make-float is indeed trying to coerce that integer you found "bogus" into a float. That is the immediate error the code encountered, so that is what it is reporting to you. It would be impossible to try find _all_ the places in the implementation where an error might be encountered -- it is provably impossible -- and wrap a restart around each point there user code might call implementation code in order to report the error at the point that user code called the implementation code. This would hide from the developer's delicate eyes the internal working of the code, but it would also make debugging impossible in many cases. For example, suppose compile-file did the same thing, and when an error occurs during compilation all the compiler tells you is would be "An error occurred during the compilation of file foo.cl." In addition, wrapping these error handlers around every entry from user code to to system code would impose significant overhead. Lisp culture makes a debugger available so you, a code developer, can use it. The implementation was indeed trying to convert that "bogus" integer to a float because that was what it needed to do in the reader' algorithm for translating character sequences into floats. You should be able to figure that out from the backtrace, including the functions named read-token and make-float. The debugger is there because having it available (instead of "An error has occurred" or "Core dumped") makes it easier and efficient for you to determine the cause of an error. As both a developer and user of ACL, I would not want to wrap an error handler around make-float (or whatever) in order to be able to produce a more explicit error message for an out-of-range float because I want the reader to operate as fast as possible. There is essentially nothing gained by trying to create an error-signaling boundary at the point user code calls implementation code, and a lot is lost if developers and users cannot see the details of what the implementation is trying to do.