;;;; fast-generic.scm ; ; By Thant Tessman, ported to CHICKEN by felix (module fast-generic ((define-generic build-or-clause) generic-error define-type) (import scheme (chicken base) (chicken format) fast-generic-compile-time) (import-for-syntax matchable (chicken plist) srfi-1 fast-generic-compile-time) (define-syntax define-type (er-macro-transformer (lambda (x r c) (match x ((_ name pred) (register-type name (r pred) 'any)) ((_ name pred base) (register-type name (r pred) 'base))) `(,(r 'void))))) (define-syntax define-generic (er-macro-transformer (lambda (x r c) (let ((%begin (r 'begin)) (%define-compiler-syntax (r 'define-compiler-syntax)) (%let* (r 'let*)) (%let (r 'let)) (%if (r 'if)) (%or (r 'or)) (%and (r 'and)) (%list (r 'list)) (%set! (r 'set!)) (%car (r 'car)) (%cdr (r 'cdr)) (%map (r 'map)) (%null? (r 'null?)) (%lambda (r 'lambda)) (%cons (r 'cons)) (%get (r 'get)) (%cons* (r 'cons*)) (%quote (r 'quote)) (%error (r 'error)) (%eq? (r 'eq?)) (%length (r 'length)) (%gensym (r 'gensym)) (%build-or-clause (r 'build-or-clause)) (%generic-error (r 'generic-error)) (%generic-forms (r 'generic-forms)) (%define (r 'define)) (%er-macro-transformer (r 'er-macro-transformer))) (match x ((_ (name types+bindings ...) body ...) (let* ((types (map (lambda (a) (if (symbol? a) 'any (car a))) types+bindings)) (bindings (map (lambda (a) (if (symbol? a) a (cadr a))) types+bindings)) (full-name (generic-build-name name types)) (dummy (generic-data-add name full-name types)) (params (map (lambda _ (gensym)) bindings)) (unset (gensym)) (len (length bindings)) (fresult (gensym))) `(,%begin (,%define (,full-name ,@bindings) ,@body) (,%define (,name ,@bindings) (,%let* ((,unset '##fast-generic#unset) (,fresult ,unset)) ,(build-or-clause (get name 'generic-trees) bindings bindings fresult r) (,%if (,%eq? ,unset ,fresult) (,%generic-error ',name (,%list ,@bindings) ',(generic-forms name)) ,fresult))) (,%define-compiler-syntax ,name (,%er-macro-transformer (,%lambda (x2 r2 c2) (if (,%eq? ,len (,%length (,%cdr x2))) (,%let* ((arg-list (,%cdr x2)) (result (,%gensym)) (unset (,%gensym)) (args (,%map (lambda _ (,%gensym)) arg-list)) (method-body (,%build-or-clause (,%get ',name 'generic-trees) args args result r2))) (,%list (r2 'let*) (,%cons (,%list unset (,%list (r2 'quote) '##fast-generic#unset)) (,%cons (,%list result unset) (,%map ,%list args arg-list))) method-body (,%list (r2 'if) (,%list (r2 'eq?) result unset) (,%list (r2 'generic-error) (,%list (r2 'quote) ',name) (,%cons (r2 'list) args) (,%list (r2 'quote) ',(generic-forms name))) result))) x2)))))))))) )) (define (generic-error name args expected) (error name (sprintf "argument mismatch - was given `~s' but expected" args) expected)) (define (##fast-generic#any? x) #t) ; must be available, even if renamed )