rpav / cl-autowrap

(c-include "file.h") => complete FFI wrapper
BSD 2-Clause "Simplified" License
210 stars 41 forks source link

duplicated variable/argument name during C to Lisp translation #124

Closed oldk1331 closed 1 year ago

oldk1331 commented 1 year ago

Take this simple example:

int f(int a, int A);

This is valid C code, but during translation, the argument names will be represented by symbol, then they will be the same.

Some Common Lisp implementations accept this, some don't:

(defun f (a a) a)

(A real life example is FLINT_DLL slong nmod_mat_reduce_row(nmod_mat_t M, slong * P, slong * L, slong m);. P.S. the official SBCL binary complains about "The variable A occurs more than once in the lambda list", but SBCL compiled by me doesn't complain. I'm scratching my head on it...)

rpav commented 1 year ago

Yeah that's probably; silly C. Unfortunately I'm not really set up to dev on this right now and don't have a lot of immediate time, but if you want to submit a PR that corrects it, I can get it merged.

The simple solutions might be generating numbers for arguments, or using gensyms, or interning arguments with case. Slightly more work with probably not a lot of gain would be keeping a map and only generating something different for dupes.

oldk1331 commented 1 year ago

Thanks for confirming this bug.

Here is a quick and dirty fix:

--- a/autowrap/sffi.lisp      2022-09-08 09:30:29.456193402 +0800
+++ b/autowrap/sffi.lisp  2022-09-08 09:38:23.666189669 +0800
@@ -705,10 +705,11 @@
     (with-wrap-attempt ("function ~S" name-or-function) name-or-function
       (with-slots (name type c-symbol fields) fun
         (let* ((fun-name (intern (symbol-name name) package))
                (param-names (mapcar #'foreign-type-name fields))
                (param-syms (mapcar (lambda (x) (gensym (symbol-name x))) param-names))
+               (param-names (mapcar (lambda (x) (gensym (symbol-name x))) param-names))
                (make-function-p (not (foreign-function-variadic-p fun)))
                (maybe-cbv-return
                  (when (cbv-return-p fun)
                    (list 'return-value))))
           (with-gensyms (!fun !fields rest)

I can prepare a proper PR later.

(P.S. the SBCL mystery is caused by ":sb-fasteval", it doesn't check param-names duplication, while the default compiler checks.)