[cffi-devel] %expand-type-to-foreign-dyn vs *runtime-translator-form*

Stephen Compall s11 at member.fsf.org
Mon Mar 13 18:48:50 UTC 2006


On Mon, 2006-03-13 at 17:11 +0000, Luís Oliveira wrote:
> I think this isn't a good idea. Here's an example:
> 
> (defmethod expand-to-foreign-dyn (value var body (name (eql :string)))
>    (if <string's size is appropriate for stack allocation>
>        `(with-foreign-string (,var ,value)
>           , at body)
>        *runtime-translator-form*))
> 
> Surely we want free-translated-object to be called in this case.

It will be.  The problem appears in the current rules for providing a
fallback when expand-to-foreign-dyn is not provided.  This is
exemplified in the new tests: one answers T and the other answers NIL,
when both should answer T or NIL.

According to node "Optimizing Type Translators", several forms are
guaranteed to use `expand-type-to-foreign' even when they want the
semantics of foreign-dyn expansion, when such an explicit expansion is
unavailable.

I ran into this problem while eliminating *runtime-translator-form* from
the interface.  I have a patch that implements option 1; it can be
trivially changed to implement either other option, however.

1) Remove the guarantee; fall back on the translate-* gfs when no
foreign-dyn expansion is available.  This is currently implemented by
answering *runtime-translator-form* from a foreign-dyn expansion.

2) Specify that the form answered by expand-type-to-foreign must have
the exact same semantics as those evaluated by calling
translate-type-to-foreign, thereby meeting a congruence with CL
compiler-macros.  This means that it returns an ALLOC-PARAM as its
second value, which is then passed to the gf free-type-translated-object
in an unwind-protect.

3) Specify that the form answered by expand-type-to-foreign, when
evaluated, answers a value that does not need to be freed.  This is
currently implemented by not providing a foreign-dyn expansion method,
in the case of foreign-typedefs anyway.

I prefer 1 to 2 because the point of the expand-* interface is to avoid
gf calls and stuff.  If you let users expect optimization in all cases
without providing foreign-dyn expansions, they may not expect that the
result may still contain an unwind-protect whose cleanup form calls a
gf.  I would rather say that the user can only expect perfect
optimization by providing explicit to-foreign, from-foreign, and
to-foreign-dyn expansions.

This does not preclude providing a function to trivialize overriding the
default behavior in favor of option 3, if the type-defining user so
chooses.

(defun simple-foreign-dyn-expansion (value var body typename)
  "Answer a form to be answered from `expand-to-foreign-dyn',
where VALUE, VAR, BODY, and TYPENAME are the respective args to
the aforementioned GF.  The result will not be freed."
  `(let ((,var ,(expand-type-to-foreign value (parse-type typename))))
     , at body))

-- 
Stephen Compall
http://scompall.nocandysw.com/blog




More information about the cffi-devel mailing list