#lang racket/base (require "unsafe.ss" racket/unsafe/ops (for-syntax racket/base)) (define-syntax define* (syntax-rules () [(_ (name . args) body ...) (begin (provide name) (define (name . args) body ...))] [(_ name expr) (begin (provide name) (define name expr))])) (define-syntax (srfi-4-define/provide stx) (syntax-case stx () [(_ TAG type) (identifier? #'TAG) (let ([name (format "~avector" (syntax->datum #'TAG))]) (define (id prefix suffix) (let* ([name (if prefix (string-append prefix name) name)] [name (if suffix (string-append name suffix) name)]) (datum->syntax #'TAG (string->symbol name) #'TAG))) (with-syntax ([TAG? (id "" "?")] [TAG (id "" "")] [s:TAG (id "s:" "")] [make-TAG (id "make-" "")] [TAG-ptr (id "" "-ptr")] [TAG-length (id "" "-length")] [allocate-TAG (id "allocate-" "")] [TAG* (id "" "*")] [list->TAG (id "list->" "")] [TAG->list (id "" "->list")] [TAG-ref (id "" "-ref")] [TAG-set! (id "" "-set!")] [TAG->cpointer (id "" "->cpointer")] [_TAG (id "_" "")] [_TAG* (id "_" "*")] [TAGname name] [f64? (if (eq? (syntax-e #'TAG) 'f64) #'#t #'#f)]) #'(begin (define-struct TAG (ptr length)) (provide TAG? TAG-length (rename-out [TAG s:TAG])) (provide (rename-out [allocate-TAG make-TAG])) (define (allocate-TAG n . init) (let* ([p (if (eq? n 0) #f (malloc n type))] [v (make-TAG p n)]) (when (and p (pair? init)) (let ([init (car init)]) (let loop ([i (sub1 n)]) (unless (< i 0) (ptr-set! p type i init) (loop (sub1 i)))))) v)) (provide (rename-out [TAG* TAG])) (define (TAG* . vals) (list->TAG vals)) (define* (TAG-ref v i) (if (TAG? v) (if (and (exact-nonnegative-integer? i) (< i (TAG-length v))) (if f64? ;; use JIT-inlined operation (unsafe-f64vector-ref v i) (ptr-ref (TAG-ptr v) type i)) (error 'TAG-ref "bad index ~e for ~a bounds of 0..~e" i 'TAG (sub1 (TAG-length v)))) (raise-type-error 'TAG-ref TAGname v))) (define* (TAG-set! v i x) (if (TAG? v) (if (and (exact-nonnegative-integer? i) (< i (TAG-length v))) (if (and f64? ;; use JIT-inlined operation (inexact-real? x)) (unsafe-f64vector-set! v i x) (ptr-set! (TAG-ptr v) type i x)) (error 'TAG-set! "bad index ~e for ~a bounds of 0..~e" i 'TAG (sub1 (TAG-length v)))) (raise-type-error 'TAG-set! TAGname v))) (define* (TAG->list v) (if (TAG? v) (cblock->list (TAG-ptr v) type (TAG-length v)) (raise-type-error 'TAG->list TAGname v))) (define* (list->TAG l) (make-TAG (list->cblock l type) (length l))) (define* (TAG->cpointer v) (if (TAG? v) (TAG-ptr v) (raise-type-error 'TAG->cpointer TAGname v))) ;; same as the _cvector implementation (provide _TAG) (define _TAG* (make-ctype _pointer TAG-ptr (lambda (x) (error '_TAG "cannot automatically convert a C pointer to a ~a" TAGname)))) (define-fun-syntax _TAG (syntax-id-rules (i o io) [(_ i ) _TAG*] [(_ o n) (type: _pointer pre: (malloc n type) post: (x => (make-TAG x n)))] [(_ io ) (type: _cvector* bind: tmp pre: (x => (TAG-ptr x)) post: (x => tmp))] [(_ . xs) (_TAG* . xs)] [_ _TAG*])))))] [(_ TAG type) (identifier? #'TAG)])) ;; check that the types that were used above have the proper sizes (unless (= 4 (ctype-sizeof _float)) (error 'foreign "internal error: float has a bad size (~s)" (ctype-sizeof _float))) (unless (= 8 (ctype-sizeof _double*)) (error 'foreign "internal error: double has a bad size (~s)" (ctype-sizeof _double*))) (srfi-4-define/provide s8 _int8) (srfi-4-define/provide s16 _int16) (srfi-4-define/provide u16 _uint16) (srfi-4-define/provide s32 _int32) (srfi-4-define/provide u32 _uint32) (srfi-4-define/provide s64 _int64) (srfi-4-define/provide u64 _uint64) (srfi-4-define/provide f32 _float) (srfi-4-define/provide f64 _double*) ;; simply rename bytes* to implement the u8vector type (provide (rename-out [bytes? u8vector? ] [bytes-length u8vector-length] [make-bytes make-u8vector ] [bytes u8vector ] [bytes-ref u8vector-ref ] [bytes-set! u8vector-set! ] [bytes->list u8vector->list ] [list->bytes list->u8vector ] [_bytes _u8vector ])) ;; additional `u8vector' bindings for srfi-66 (provide (rename-out [bytes-copy u8vector-copy] [bytes=? u8vector=?])) (define* (u8vector-compare v1 v2) (cond [(bytes? v1 v2) 1] [else 0])) (define* (u8vector-copy! src src-start dest dest-start n) (bytes-copy! dest dest-start src src-start (+ src-start n)))