From: Albert Reiner
Subject: compiled local function in non-null lexical environment?
Date: 
Message-ID: <m1fzc62o33.fsf@reiner.chello.at>
Hi,

is there a way to have something like LABELS with function definitions that

- depend on information available only at run time

- can access the surrounding lexical environement, and

- are compiled.


Basically, I would like to use something like

(let (var1 var2 ...)
  (labels 
     ((f1 (...) <definition using the VARs and Fs>)
      (f2 (...) <definition using the VARs and Fs>))
    (let ((info-available-at-run-time (<whatever, using the VARs and Fs>)))
      (with-compiled-local-function (foo info-available-at-run-time)
        <call the compiled local function FOO *many* times>))))

(defmacro with-compiled-local-function ((fun info) &body body)
  `(labels
      ((,fun ()
         ,@(<complicated code using INFO to generate the body of a function
             using the Fs and calling the VARs>)))
     (COMPILE ,fun)
     ,@body))

but this does not seem to work as COMPILE won't use the LABELS definition.

Likewise, I thought about using something like (setf (symbol-function 'foo)
(compile nil `(lambda () ,@<complicated code using INFO ...>))) and go
a-FUNCALL-ing FOO, but this still cannot work as the function needs to access
the lexical environment, which COMPILE doesn't allow.

I assume there should be no problem with the LABELS approach I sketched if I
simply forget about compiling, but this is likely to be slow and I assume that
the type annotations in the body of FOO won't help interpreted code all that
much.

One way out I can see is to replace the lexical bindings with global ones,
i.e., to have

    (defvar *VAR1* ...)
    (defvar *VAR2* ...)
    (defun F1 ...)
    (defun F2 ...)
    (defun foo () (error ""))
    (declaim (notinline foo))
    (defmacro define-and-compile-foo (info)
      `(progn
        (defun foo () ,@<complicated code, as above>)
        (compile foo)))
    ...
    (fmakunbound foo)

, in which case I would probably need to replace the *VARs* and Fs with
gensyms if I want to switch between two different such sets of functions. (Do
I need to repeat the (declaim (notinline foo)) after every re-definition? Do I
really need an initial definition of foo?)

Another option is to use the macros that set up the VARs and Fs also inside
the body of FOO, with initializations passed to the macro just like INFO.

My current working solution basically goes through all of INFO at each and
every step, which is quite slow despite compilation: CMUCL gives me a lot of
warnings about missing type annotations, but this types are part of the
information only available once INFO has been obtained.

I would be grateful for any hints and opinions. - Thanks in advance,

Albert.


P.S.: The problem comes from the need to read data encoded in a file, where
      the information on how to decode the real data, and what data is
      available, is only encoded at the beginning of the file.

From: Raymond Wiker
Subject: Re: compiled local function in non-null lexical environment?
Date: 
Message-ID: <86lllych87.fsf@raw.grenland.fast.no>
Albert Reiner <······@chello.at> writes:

> Hi,
>
> is there a way to have something like LABELS with function definitions that
>
> - depend on information available only at run time
>
> - can access the surrounding lexical environement, and
>
> - are compiled.
>
>
> Basically, I would like to use something like
>
> (let (var1 var2 ...)
>   (labels 
>      ((f1 (...) <definition using the VARs and Fs>)
>       (f2 (...) <definition using the VARs and Fs>))
>     (let ((info-available-at-run-time (<whatever, using the VARs and Fs>)))
>       (with-compiled-local-function (foo info-available-at-run-time)
>         <call the compiled local function FOO *many* times>))))
>
> (defmacro with-compiled-local-function ((fun info) &body body)
>   `(labels
>       ((,fun ()
>          ,@(<complicated code using INFO to generate the body of a function
>              using the Fs and calling the VARs>)))
>      (COMPILE ,fun)
>      ,@body))
>
> but this does not seem to work as COMPILE won't use the LABELS definition.

        Have you tried removing the call to compile, and just
compiling the source code? A compiled macro definition should generate
compiled code...

-- 
Raymond Wiker                        Mail:  ·············@fast.no
Senior Software Engineer             Web:   http://www.fast.no/
Fast Search & Transfer ASA           Phone: +47 23 01 11 60
P.O. Box 1677 Vika                   Fax:   +47 35 54 87 99
NO-0120 Oslo, NORWAY                 Mob:   +47 48 01 11 60

Try FAST Search: http://alltheweb.com/
From: Bruno Haible
Subject: Re: compiled local function in non-null lexical environment?
Date: 
Message-ID: <c4f4sh$hni$1@laposte.ilog.fr>
> Basically, I would like to use something like
>
> (let (var1 var2 ...)
>   (labels 
>      ((f1 (...) <definition using the VARs and Fs>)
>       (f2 (...) <definition using the VARs and Fs>))
>     (let ((info-available-at-run-time (<whatever, using the VARs and Fs>)))
>       (with-compiled-local-function (foo info-available-at-run-time)
>         <call the compiled local function FOO *many* times>))))

I think there is no portable way to do this, because in some implementations
the COMPILE function barfs when you give it an interpreted function which was
created in a non-null lexical environment.

In some implementations you can write

  (let (var1 var2 ...)
    (labels
       ((f1 (...) <definition using the VARs and Fs>)
        (f2 (...) <definition using the VARs and Fs>))
      (flet ((foo (<parameters>) <whatever, using the VARs and Fs>))
        (let ((compiled-foo (compile nil #'foo)))
          ...

In GNU CLISP you can also write this as

  (let (var1 var2 ...)
    (labels
       ((f1 (...) <definition using the VARs and Fs>)
        (f2 (...) <definition using the VARs and Fs>))
      (flet ((foo (<parameters>)
               (declare (compile))
               <whatever, using the VARs and Fs>))
        ...

Bruno
From: Albert Reiner
Subject: Re: compiled local function in non-null lexical environment?
Date: 
Message-ID: <86ptas3pod.fsf@chello.at>
·····@clisp.org (Bruno Haible) writes:

> > Basically, I would like to use something like
> >
> > (let (var1 var2 ...)
> >   (labels 
> >      ((f1 (...) <definition using the VARs and Fs>)
> >       (f2 (...) <definition using the VARs and Fs>))
> >     (let ((info-available-at-run-time (<whatever, using the VARs and Fs>)))
> >       (with-compiled-local-function (foo info-available-at-run-time)
> >         <call the compiled local function FOO *many* times>))))
> 
> I think there is no portable way to do this, because in some implementations
> the COMPILE function barfs when you give it an interpreted function which was
> created in a non-null lexical environment.
> 
> In some implementations you can write
...

Thanks for your reply.

In the meantime I re-written my code by replacing the LABELS and LET
bindings needed by FOO by DEFUNs and DEFVAR / DEFPARAMETER so that FOO
can access them without COMPILE complaining about the non-null
environment.  With FOO specialized to take into account the
information this results in roughly a three-fold speedup, which makes
it only about 50 per cent slower than the corresponding Fortran-90 and
is more or less fast enough for my application.

Albert.