#lang scheme/base (require scheme/contract scheme/class (for-syntax scheme/base)) (define class-or-interface/c (or/c class? interface?)) (define (subclass-or-implements/c class-or-iface) (cond [(class? class-or-iface) (subclass?/c class-or-iface)] [(interface? class-or-iface) (implementation?/c class-or-iface)] [else (error 'subclass-or-implements/c "not a class or interface: ~s" class-or-iface)])) (define (object/c . class-or-ifaces) (apply and/c object? (map is-a?/c class-or-ifaces))) (define (class/c . class-or-ifaces) (apply and/c class? (map subclass-or-implements/c class-or-ifaces))) (define-syntax (mixin/c stx) (syntax-case stx () [(form (super-in ...) (other-in ...) (sub-out ...)) (with-syntax ([(super-var ...) (generate-temporaries (syntax (super-in ...)))] [(other-var ...) (generate-temporaries (syntax (other-in ...)))] [(dummy ...) (generate-temporaries (syntax (other-in ...)))] [(sub-var ...) (generate-temporaries (syntax (sub-out ...)))]) (syntax/loc stx (let* ([super-var super-in] ... [other-var other-in] ... [sub-var sub-out] ...) (->d ([super (class/c super-var ...)] [dummy other-var] ...) () [_ (class/c super sub-var ...)]))))])) (define-syntax (send+ stx) (syntax-case stx () [(s+ expr clause ...) (syntax/loc stx (let* ([obj expr]) (send obj . clause) ... obj))])) (define-syntax (send-each stx) (syntax-case stx () [(se objs-expr method arg-expr ...) (with-syntax ([(arg-var ...) (generate-temporaries #'(arg-expr ...))]) (syntax/loc stx (let ([objs-var objs-expr] [arg-var arg-expr] ...) (for-each (lambda (obj) (send obj method arg-var ...)) objs-var))))])) (define (ensure-interface iface<%> mx class%) (if (implementation? class% iface<%>) class% (mx class%))) (provide/contract [class-or-interface/c flat-contract?] [object/c (->* [] [] #:rest (listof class-or-interface/c) flat-contract?)] [class/c (->* [] [] #:rest (listof class-or-interface/c) flat-contract?)] [ensure-interface (->d ([the-interface interface?] [the-mixin (mixin/c [] [] [the-interface])] [the-class class?]) () [_ (class/c the-class the-interface)])]) (provide mixin/c send+ send-each)