[Openmcl-devel] two portability issues

Gary Byers gb at clozure.com
Sun Dec 21 13:10:27 PST 2014


On 12/20/2014 02:12:25 PM, Rainer Joswig wrote:
> 
> > Am 20.12.2014 um 21:37 schrieb Gary Byers <gb at clozure.com>:
> >
> > On 12/20/2014 10:53:40 AM, Rainer Joswig wrote:
> >> Hi,
> >> I just looked a small benchmark someone wrote and tried to improve  
> it.
> >> The result is here:
> >> https://gist.github.com/lispm/6066e1eeadf943910c47  
> <https://gist.github.com/lispm/6066e1eeadf943910c47>
> >> The corresponding data file is here:
> >>  
> https://raw.githubusercontent.com/logicchains/LPATHBench/master/agraph
> >> There were two issues I saw with CCL:
> >> ** first issue:  DEFSTRUCT defined type at compile time unknown? **
> >> There is a structure declaration ROUTE via a DEFSTRUCT.
> >> I wanted to use the type ROUTE in a LOOP later in the function
> >> (defun get-longest-path (nodes node-id visited &aux (max 0))
> >>  (declare (optimize (speed 3) (space 0) (debug 0) (safety 0)  
> (compilation-speed 0)
> >>           #+lispworks (fixnum-safety 0))
> >>           (fixnum max))
> >>  (setf (svref visited node-id) t)
> >>  (setf max (loop for neighbour of-type route in (svref nodes  
> node-id)     ; <—  declaration
> >>                  unless (svref visited (route-dest neighbour))
> >>                  maximize (+ (the fixnum (route-cost neighbour))
> >>                              (the fixnum (get-longest-path nodes
> >>                                                             
> (route-dest neighbour)
> >>                                                             
> visited)))
> >>                  #+lispworks fixnum))
> >>  (setf (svref visited node-id) nil)
> >>  max)
> >> The CCL compiler did not know about the type ROUTE, so I had to  
> use EVAL-WHEN around the structure definition. Shouldn’t the compiler  
> recognize the type at compile time? The ANSI CL documentation for  
> DEFSTRUCT indicates that…
> >
> > Please read and try to understand section 3.2.3.1.1, then think  
> about whether your understanding of the issues here is correct.  I  
> strongly suspect that it isn’t.
> 
> Okay, read it...
> 
> How about:  
> http://www.lispworks.com/documentation/HyperSpec/Body/m_defstr.htm#defstruct  
> <http://www.lispworks.com/documentation/HyperSpec/Body/m_defstr.htm#defstruct>
> 
> 
> > If a defstruct form appears as a top level form, the compiler must  
> make the structure type name recognized as a valid type name in  
> subsequent declarations
> 
> My interpretation would be that a type declaration in a LOOP should  
> be able to use a structure type, without compile-time evaluation.

The compiler indeed makes the structure name be recognized as a valid  
type name; you can use the structure name as a type name in subsequent  
declarations in the file that contains the defstruct form.  That means  
that the compiler can't warn that it's never heard of the type if it  
encounters it in a declaration (the type doesn't necessarily exist in  
the global environment at compile-time, but it will exist at runtime  
and at least some information about the type in the compilation  
environment.

Code called by the LOOP macro (the function  
ANSI-LOOP::LOOP-MAKE-VARIABLE) calls TYPEP on the structure name and  
the global environment when processing loop variable with OF-TYPE  
qualifiers, and that's wrong.  I don't think of that code as being part  
of the compiler (and find it confusing when people attribute behavior  
to the compiler that other code is responsible for), but I agree that  
code that's part of the implementation shouldn't be so casual about  
assuming that types that are used in declarations are globally defined.
> 
> The problem seems to appear without optimize declarations...
> 
> (defun get-longest-path (nodes node-id visited &aux (max 0))
>   (setf (svref visited node-id) t)
>   (setf max (loop for neighbour of-type route in (svref nodes node-id)
>                   unless (svref visited (route-dest neighbour))
>                   maximize (+ (the fixnum (route-cost neighbour))
>                               (the fixnum (get-longest-path nodes
>                                                              
> (route-dest neighbour)
>                                                             visited)))
>                             fixnum))
>   (setf (svref visited node-id) nil)
>   max)
> 
> Safety 3 and Speed 0 takes a long time and returns the wrong result:  
> -1152921504606837995


Note that (for instance)

? (logand (1- (ash 1 14)) -1152921504606837995)'
8981

> 
> The expected result would have been 8981.

I haven't looked at your code yet and probably won't have time to do  
that for that for at least a few days, but that's either an amazing  
coincidence or it isn't.


More information about the Openmcl-devel mailing list