~ chicken-core (chicken-5) f912e5647a7a410908e0cfbbf5200ae980920364
commit f912e5647a7a410908e0cfbbf5200ae980920364 Author: felix <felix@call-with-current-continuation.org> AuthorDate: Fri Jun 24 17:09:28 2011 +0200 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Fri Jun 24 17:09:28 2011 +0200 local specializations; added badass define-specialization diff --git a/chicken-syntax.scm b/chicken-syntax.scm index 08346d58..a1200aa6 100644 --- a/chicken-syntax.scm +++ b/chicken-syntax.scm @@ -1202,6 +1202,59 @@ ((_ ((var type) ...) body ...) (let ((var (##core#the type var)) ...) body ...))))) +(##sys#extend-macro-environment + 'define-specialization '() + (##sys#er-transformer + (lambda (x r c) + (cond ((memq #:csi ##sys#features) '(##core#undefined)) + (else + (##sys#check-syntax 'define-specialization x '(_ (symbol . #(_ 0)) _ . #(_ 0 1))) + (let* ((head (cadr x)) + (name (car head)) + (args (cdr head)) + (alias (gensym name)) + (rtypes (and (pair? (cdddr x)) (caddr x))) + (%define (r 'define)) + (body (if rtypes (cadddr x) (caddr x)))) + (let loop ((args args) (anames '()) (atypes '())) + (cond ((null? args) + (let ((anames (reverse anames)) + (atypes (reverse atypes)) + (spec + `(,alias ,@(let loop2 ((anames anames) (i 1)) + (if (null? anames) + '() + (cons (vector i) + (loop2 (cdr anames) (fx+ i 1)))))))) + (##sys#put! + name '##compiler#local-specializations + (##sys#append + (list + (cons atypes + (if rtypes + (list rtypes spec) + (list spec)))) + (or (##compiler#variable-mark + name '##compiler#local-specializations) + '()))) + `(##core#begin + (##core#declare (inline ,alias) (hide ,alias)) + (,%define (,alias ,@anames) + (##core#let ,(map (lambda (an at) + (list an `(##core#the ,at ,an))) + anames atypes) + ,body))))) + (else + (let ((arg (car args))) + (cond ((symbol? arg) + (loop (cdr args) (cons arg anames) (cons '* atypes))) + ((and (list? arg) (fx= 2 (length arg)) (symbol? (car arg))) + (loop (cdr args) (cons (car arg) anames) + (cons (cadr arg) atypes))) + (else (##sys#syntax-error + 'define-specialization + "invalid argument syntax" arg head))))))))))))) + ;; capture current macro env diff --git a/manual/Types b/manual/Types index ebddf393..3cd55803 100644 --- a/manual/Types +++ b/manual/Types @@ -182,6 +182,26 @@ in unsafe mode any faster: compilation in unsafe mode will omit most type checks anyway. But specialization can often improve the performance of code compiled in safe (default) mode. +Specializations can also be defined by the user: + +===== define-specialization + +<syntax>(define-specialization (NAME ARGUMENT ...) [RESULTS] BODY)</syntax> + +{{NAME}} should have a declared type (for example by using {{:}}). +Declares the calls to the procedure {{NAME}} with arguments matching +the types given in {{ARGUMENTS}} should be replaced by {{BODY}} (a +single expression). If given, {{RESULTS}} (which follows the syntax +given above under "Type Syntax") narrows the result type(s) if it +differs from the result types previously declared for {{NAME}}. +{{ARGUMENT}} should be an identifier naming the formal parameter or a +list of the form {{(IDENTIFIER TYPE)}}. In the former case, this +argument specializes on the {{*}} type. User-defined specializations +are always local to the compilation unit in which they occur and can +not be exported. When encountered in the interpreter, +{{define-specialization}} does nothing and returns an unspecified +result. + --- Previous: [[Modules]] diff --git a/scrutinizer.scm b/scrutinizer.scm index 6ce2190b..bf0ed22d 100755 --- a/scrutinizer.scm +++ b/scrutinizer.scm @@ -72,6 +72,7 @@ ; ##compiler#declared-type -> BOOL ; ##compiler#predicate -> TYPESPEC ; ##compiler#specializations -> (SPECIALIZATION ...) +; ##compiler#local-specializations -> (SPECIALIZATION ...) ; ##compiler#enforce -> BOOL ; ##compiler#special-result-type -> PROCEDURE ; ##compiler#escape -> #f | 'yes | 'no @@ -471,6 +472,12 @@ (lambda () (pp (fragment x)))))) + (define (get-specializations name) + (let* ((a (variable-mark name '##compiler#specializations)) + (b (variable-mark name '##compiler#local-specializations)) + (c (append (or a '()) (or b '())))) + (and (pair? c) c))) + (define (call-result node args e loc params) (define (pname) (sprintf "~ain procedure call to `~s', " @@ -550,7 +557,7 @@ node `(let ((#(tmp) #(1))) '#f)) (set! op (list pt `(not ,pt)))))))) - ((and specialize (variable-mark pn '##compiler#specializations)) => + ((and specialize (get-specializations pn)) => (lambda (specs) (let loop ((specs specs)) (cond ((null? specs)) @@ -1092,8 +1099,7 @@ (lambda (sym plist) (when (variable-visible? sym) (when (variable-mark sym '##compiler#declared-type) - (let ((specs - (or (variable-mark sym '##compiler#specializations) '())) + (let ((specs (or (variable-mark sym '##compiler#specializations) '())) (type (variable-mark sym '##compiler#type)) (pred (variable-mark sym '##compiler#predicate)) (enforce (variable-mark sym '##compiler#enforce)))Trap