ffi/unsafe: match i, o, or io as symbols

Changes `_ptr`, `_list`, and `_vector` syntax to be more permissive.
Matching by symbol rather than binding is usually the wrong choice,
but the position where `i`, `o`, or `io` is recognized in `_ptr` and
company is not an expression position. Also, `i`, `o`, and `io` are
not otherwise bound. So, it's difficult to justify the current
behavior. If `_ptr` and company were defined today, we'd use keywords
like `#:i` instead of symbols like `i`.

A potential drawback of this change is that a `i`, `o`, or `io` might
be written with the intent of referring to a binding, and this change
makes such a reference silently allwowed instead of an errror. That
seems relatively unlikely, however, while having to avoid `i`, `o`, or
`io` as a binding is occassionally a pain --- something I've run into
once or maybe twice.

Closes #887
This commit is contained in:
Matthew Flatt 2020-05-19 07:32:28 -06:00
parent 6d06086dad
commit 1655b6e2bb
3 changed files with 39 additions and 7 deletions

View File

@ -1016,7 +1016,7 @@ Examples:
Creates a C pointer type, where @racket[mode] indicates input or
output pointers (or both). The @racket[mode] can be one of the
following:
following (matched as a symbol independent of binding):
@itemize[
@ -1058,7 +1058,11 @@ following type:
creates a function that calls the foreign function with a fresh
integer pointer, and use the value that is placed there as a second
return value.}
return value.
@history[#:changed "7.7.0.6" @elem{The modes @racket[i], @racket[o],
and @racket[io] match as symbols
instead of free identifiers.}]}
@defform[(_box type)]{
@ -1124,7 +1128,10 @@ return two values, the vector and the boolean.
-> (values vec res))
]
@history[#:changed "7.7.0.2" @elem{Added @racket[maybe-mode].}]}
@history[#:changed "7.7.0.2" @elem{Added @racket[maybe-mode].}]
#:changed "7.7.0.6" @elem{The modes @racket[i], @racket[o],
and @racket[io] match as symbols
instead of free identifiers.}]}
@defform[(_vector mode type maybe-len maybe-mode)]{
@ -1145,7 +1152,10 @@ Examples:
See @racket[_list] for more explanation about the examples.
@history[#:changed "7.7.0.2" @elem{Added @racket[maybe-mode].}]}
@history[#:changed "7.7.0.2" @elem{Added @racket[maybe-mode].}
#:changed "7.7.0.6" @elem{The modes @racket[i], @racket[o],
and @racket[io] match as symbols
instead of free identifiers.}]}
@defform*[#:id _bytes

View File

@ -1145,6 +1145,22 @@
(define-serializable-cstruct _serializable-example-1 ([a _int]))
(test 17 serializable-example-1-a (deserialize (serialize (make-serializable-example-1 17))))
;; ----------------------------------------
;; Check that `i`, `o`, and `io` are matched as symbols, not by binding:
(let ([i 'no]
[o 'no]
[io 'no])
(test #t ctype? (_ptr i _int))
(test #t ctype? (_ptr o _int))
(test #t ctype? (_ptr io _int))
(test #t ctype? (_list i _int))
(test #t ctype? (_list o _int 10))
(test #t ctype? (_list io _int 10))
(test #t ctype? (_vector i _int))
(test #t ctype? (_vector o _int 10))
(test #t ctype? (_vector io _int 10)))
;; ----------------------------------------
(define-cpointer-type _foo)

View File

@ -1054,13 +1054,19 @@
(define-fun-syntax _?
(syntax-id-rules () [(_ . xs) ((type: #f) . xs)] [_ (type: #f)]))
(begin-for-syntax
(define-syntax-rule (syntax-rules/symbol-literals (lit ...) [pat tmpl] ...)
(lambda (stx)
(syntax-case* stx (lit ...) (lambda (a b) (eq? (syntax-e a) (syntax-e b)))
[pat (syntax-protect (syntax/loc stx tmpl))] ...))))
;; (_ptr <mode> <type>)
;; This is for pointers, where mode indicates input or output pointers (or
;; both). If the mode is `o' (output), then the wrapper will not get an
;; argument for it, instead it generates the matching argument.
(provide _ptr)
(define-fun-syntax _ptr
(syntax-rules (i o io)
(syntax-rules/symbol-literals (i o io)
[(_ i t) (type: _pointer
pre: (x => (let ([p (malloc t)]) (ptr-set! p t x) p)))]
[(_ o t) (type: _pointer
@ -1090,7 +1096,7 @@
;; the C function will most likely require.
(provide _list)
(define-fun-syntax _list
(syntax-rules (i o io)
(syntax-rules/symbol-literals (i o io)
[(_ i t ) (type: _pointer
pre: (x => (list->cblock x t)))]
[(_ i t mode) (type: _pointer
@ -1112,7 +1118,7 @@
;; Same as _list, except that it uses Scheme vectors.
(provide _vector)
(define-fun-syntax _vector
(syntax-rules (i o io)
(syntax-rules/symbol-literals (i o io)
[(_ i t ) (type: _pointer
pre: (x => (vector->cblock x t)))]
[(_ i t mode) (type: _pointer