From: Liam Healy
Subject: CMUCL, declaration avoids recursive call?
Date: 
Message-ID: <3qni5j$pl9@ra.nrl.navy.mil>
I am trying to debug a load foreign in CMUCL 17f.
In tracking things down, I come across this perplexing
function alien-funcall (alieneval.lisp).  It appears to me
that it should recurse infinitely through stub, because
stub gets applied to the original arguments, but is just
a lambda enclosing an call to alien-funcall.
In fact, if the declaration in the lambda is removed,
it *does* recurse infinitely.  But if the declaration is 
present,  the function returns normally.

My questions:
-- what is the mechanism by which the recursive call is avoided?
-- what/where is the actual source of the return value from stub
   and thus from alien-funcall?

Thanks for any insight.

(defun alien-funcall (alien &rest args)
  "Call the foreign function ALIEN with the specified arguments.  ALIEN's
   type specifies the argument and result types."
  (declare (type alien-value alien))
  (let ((type (alien-value-type alien)))
    (typecase type
      (alien-pointer-type
       (apply #'alien-funcall (deref alien) args))
      (alien-function-type
       (unless (= (length (alien-function-type-arg-types type))
                  (length args))
         (error "Wrong number of arguments for ~S~%Expected ~D, got ~D."
                type
                (length (alien-function-type-arg-types type))
                (length args)))
       (let ((stub (alien-function-type-stub type)))
         (unless stub
           (setf stub
                 (let ((fun (gensym))
                       (parms (loop repeat (length args) collect (gensym))))
                   (compile nil
                            `(lambda (,fun ,@parms)
                               (declare (type (alien ,type) ,fun))
                               (alien-funcall ,fun ,@parms)))))
           (setf (alien-function-type-stub type) stub))
         (apply stub alien args)))
      (t
       (error "~S is not an alien function." alien)))))

-- 
Liam Healy
··········@nrl.navy.mil
From: Barry Margolin
Subject: Re: CMUCL, declaration avoids recursive call?
Date: 
Message-ID: <3qp5ru$370@tools.near.net>
In article <··········@ra.nrl.navy.mil> Liam Healy <··········@nrl.navy.mil> writes:
]I am trying to debug a load foreign in CMUCL 17f.
]In tracking things down, I come across this perplexing
]function alien-funcall (alieneval.lisp).  It appears to me
]that it should recurse infinitely through stub, because
]stub gets applied to the original arguments, but is just
]a lambda enclosing an call to alien-funcall.
]In fact, if the declaration in the lambda is removed,
]it *does* recurse infinitely.  But if the declaration is 
]present,  the function returns normally.
]
]My questions:
]-- what is the mechanism by which the recursive call is avoided?

The compiler presumably recognizes (alien-funcall <alien> ...) specially
and open-codes it into the internal mechanism used to call aliens.  But it
can only do this is if knows that the first argument is of type ALIEN.
That's why the type declaration in the lambda is necessary -- without it,
it is forced to generate a call to the generic function, resulting in
infinite recursion. 

]-- what/where is the actual source of the return value from stub
]   and thus from alien-funcall?

It's coed into the compiler, in its code generator for ALIEN-FUNCALL calls.
-- 
Barry Margolin
BBN Planet Corporation, Cambridge, MA
······@{bbnplanet.com,near.net,nic.near.net,netcom.com}
Phone (617) 873-3126 - Fax (617) 873-5124