~ chicken-core (chicken-5) 57641c946030cc387f8194f72c298f4487e4e934
commit 57641c946030cc387f8194f72c298f4487e4e934
Author: megane <meganeka@gmail.com>
AuthorDate: Sun Dec 1 12:59:26 2019 +0200
Commit: Evan Hanson <evhan@foldling.org>
CommitDate: Fri Dec 27 10:45:39 2019 -0600
Let scrutinizer infer types for foreign types with retconv/argconv given
Not doing any annotation gives the scrutinizer a change to infer the
reconverted arguments. Which it in many cases can do.
For example this:
(define-foreign-type retconverted-foreign-int int identity ->string)
(foreign-lambda retconverted-foreign-int "rand")
Gets converted to something like this:
(set! g14 chicken.string#->string)
(lambda () (g14 (##core#inline stub23 (##core#undefined))
Which the scrutinizer can handle.
* chicken-ffi-syntax.scm (annotate-foreign-procedure): Don't annotate
if scrutinizer can infer types
Ideally we could drop the annotation here completely if
create-foreign-stub just annotated the return type of the stub call:
(##core#inline stub25 (##core#undefined))
=>
(the fixnum (##core#inline stub25 (##core#undefined)))
Generally the scrutinizer can infer the argument types if they are
converted by enforcing functions like this:
(lambda (int2730)
(##core#inline
stub28
(##core#undefined)
(##sys#foreign-fixnum-argument int2730)))
=>
(fixnum -> *)
* tests/typematch-tests.scm: Expect more specific type now
Signed-off-by: Evan Hanson <evhan@foldling.org>
diff --git a/chicken-ffi-syntax.scm b/chicken-ffi-syntax.scm
index b6ec4d5b..c78d0934 100644
--- a/chicken-ffi-syntax.scm
+++ b/chicken-ffi-syntax.scm
@@ -214,16 +214,32 @@
;;; Aliases for internal forms
(define (annotate-foreign-procedure e argtypes rtype)
- `(##core#the
- (procedure ,(map (cut chicken.compiler.support#foreign-type->scrutiny-type <> 'arg)
- (chicken.syntax#strip-syntax argtypes))
- ,@(if rtype
- (list (chicken.compiler.support#foreign-type->scrutiny-type
- (chicken.syntax#strip-syntax rtype) 'result))
- ;; special case for C_values(...). Only triggered by foreign-primitive.
- '*))
- #f
- ,e))
+ (let ((scrut-atypes (map (cut chicken.compiler.support#foreign-type->scrutiny-type <> 'arg)
+ (chicken.syntax#strip-syntax argtypes)))
+ (scrut-rtype (and rtype
+ (chicken.compiler.support#foreign-type->scrutiny-type
+ (chicken.syntax#strip-syntax rtype) 'result))))
+ ;; Don't add type annotation if the scrutinizer can infer the same
+ ;; or better.
+ ;;
+ ;; At least these cases should work:
+ ;;
+ ;; (-> <some-known-type>) => annotate
+ ;; (-> *) => no annotation
+ ;; (* ... -> *) => no annotation
+ ;;
+ (if (and (or (not rtype) (eq? scrut-rtype '*))
+ (every (cut eq? '* <>) scrut-atypes))
+ e
+ `(##core#the
+ (procedure ,scrut-atypes
+ ,@(if rtype
+ (list scrut-rtype)
+ ;; Special case for C_values(...). Only
+ ;; triggered by foreign-primitive.
+ '*))
+ #f
+ ,e))))
(##sys#extend-macro-environment
'define-foreign-type
diff --git a/tests/typematch-tests.scm b/tests/typematch-tests.scm
index 59ba506c..42a97ac9 100644
--- a/tests/typematch-tests.scm
+++ b/tests/typematch-tests.scm
@@ -438,8 +438,7 @@
;; when the return type should be whatever the retconvert argument
;; to define-foreign-type returns (string in this case)
(let ((retconverted (foreign-lambda retconverted-foreign-int "rand")))
- (infer-not fixnum (retconverted))
- (infer-not integer (retconverted)) )
+ (infer string (retconverted)))
(let ((argconverted (foreign-lambda argconverted-foreign-int "rand")))
;; Currently types with only argconvert get a retconvert as well,
Trap