~ chicken-core (chicken-5) ff5ec0968e287aa3d8ae65378fbc806a26cc2523
commit ff5ec0968e287aa3d8ae65378fbc806a26cc2523 Merge: 2d9ddc53 c9a081e9 Author: felix <felix@call-with-current-continuation.org> AuthorDate: Mon Mar 28 09:59:46 2011 -0400 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Mon Mar 28 09:59:46 2011 -0400 resolved conflicts diff --cc compiler.scm index efae5b99,34031b56..4d958fa6 --- a/compiler.scm +++ b/compiler.scm @@@ -1472,20 -1463,31 +1463,47 @@@ ((type) (for-each (lambda (spec) - (cond ((and (list? spec) (symbol? (car spec)) (= 2 (length spec))) - (##sys#put! (car spec) '##compiler#type (cadr spec)) - (##sys#put! (car spec) '##compiler#declared-type #t)) - (else - (warning "illegal `type' declaration item" spec)))) - (globalize-all (cdr spec)))) + (if (not (and (list? spec) + (>= (length spec) 2) + (symbol? (car spec)))) + (warning "illegal type declaration" (##sys#strip-syntax spec)) + (let ((name (##sys#globalize (car spec) se)) + (type (##sys#strip-syntax (cadr spec)))) - (cond ((validate-type type name) - ;; HACK: since `:' doesn't have access to the SE, we - ;; fixup the procedure name if type is a named procedure type - ;; (We only have access to the SE for ##sys#globalize in here). - ;; Quote terrible. - (when (and (pair? type) (eq? 'procedure (car type)) (symbol? (cadr type))) - (set-car! (cdr type) name)) - (print "mark: " name " -> " type) - (mark-variable name '##core#type type) - (mark-variable name '##core#declared-type) - (when (pair? (cddr spec)) - (mark-variable - name '##core#specializations - (##sys#strip-syntax (cddr spec))))) - (else - (warning - "illegal type declaration" - (##sys#strip-syntax spec))))))) ++ (cond ((validate-type type name) => ++ (lambda (type) ++ ;; HACK: since `:' doesn't have access to the SE, we ++ ;; fixup the procedure name if type is a named procedure type ++ ;; (We only have access to the SE for ##sys#globalize in here). ++ ;; Quite terrible. ++ (when (and (pair? type) ++ (eq? 'procedure (car type)) ++ (symbol? (cadr type))) ++ (set-car! (cdr type) name)) ++ (mark-variable name '##core#type type) ++ (mark-variable name '##core#declared-type) ++ (when (pair? (cddr spec)) ++ (mark-variable ++ name '##compiler#specializations ++ (##sys#strip-syntax (cddr spec))))) ++ (else ++ (warning ++ "illegal `type' declaration" ++ (##sys#strip-syntax spec)))))))) ++ (cdr spec))) + ((predicate) + (for-each + (lambda (spec) + (cond ((and (list? spec) (symbol? (car spec)) (= 2 (length spec))) - (##sys#put! (car spec) '##compiler#predicate (cadr spec))) ++ (let ((name (##sys#globalize (car spec) se)) ++ (type (##sys#strip-syntax (cadr spec)))) ++ (cond ((validate-type type name) => ++ (lambda (type) ++ (##sys#put! name '##compiler#predicate type))) ++ (else ++ (warning "illegal `predicate' declaration" spec))))) + (else - (warning "illegal `predicate' declaration item" spec)))) - (globalize-all (cdr spec)))) ++ (warning "illegal `predicate' declaration" spec)))) + (cdr spec))) ((unsafe-specialized-arithmetic) (set! unchecked-specialized-arithmetic #t)) (else (warning "illegal declaration specifier" spec)) ) diff --cc csc.scm index f414a02f,b4dda098..16643dd2 --- a/csc.scm +++ b/csc.scm @@@ -138,8 -138,7 +138,9 @@@ -no-symbol-escape -no-parentheses-synonyms -r5rs-syntax -no-argc-checks -no-bound-checks -no-procedure-checks -no-compiler-syntax -emit-all-import-libraries -setup-mode -unboxing -no-elevation -no-module-registration - -no-procedure-checks-for-usual-bindings -module -specialize + -no-procedure-checks-for-usual-bindings -module ++ -specialize + -lambda-lift ; OBSOLETE -no-procedure-checks-for-toplevel-bindings)) (define-constant complex-options diff --cc scrutinizer.scm index df018c19,e70cd013..70015bac --- a/scrutinizer.scm +++ b/scrutinizer.scm @@@ -54,65 -56,73 +56,126 @@@ ; pointer-vector ; RESULTS = * ; | (VAL1 ...) - +; ; global symbol properties: ; - ; ##compiler#type -> <typespec> - ; ##compiler#declared-type -> <bool> - ; ##compiler#predicate -> <typespec> -; ##core#type -> TYPESPEC -; ##core#declared-type -> BOOL -; ##core#specializations -> (SPECIALIZATION ...) ++; ##compiler#type -> TYPESPEC ++; ##compiler#declared-type -> BOOL ++; ##compiler#predicate -> TYPESPEC ++; ##compiler#specializations -> (SPECIALIZATION ...) + ; + ; specialization specifiers: + ; + ; SPECIALIZATION = ((MVAL ... [#!rest MVAL]) TEMPLATE) + ; MVAL = VAL | (not VAL) | (or VAL ...) | (and VAL ...) + ; TEMPLATE = #(INDEX [...]) + ; | INTEGER | SYMBOL | STRING + ; | (quote CONSTANT) + ; | (TEMPLATE . TEMPLATE) + ; + ; - (not number) succeeds for fixnum and flonum + ; - (not list) succeeds for pair and null + (define-constant +fragment-max-length+ 5) (define-constant +fragment-max-depth+ 3) ++ +(define (scrutinize node db) + (let ((blist '())) + (define (constant-result lit) + (cond ((string? lit) 'string) + ((symbol? lit) 'symbol) + ((fixnum? lit) 'fixnum) + ((flonum? lit) 'float) + ((number? lit) 'number) ; in case... + ((boolean? lit) 'boolean) + ((list? lit) 'list) + ((pair? lit) 'pair) + ((eof-object? lit) 'eof) + ((vector? lit) 'vector) + ((and (not (##sys#immediate? lit)) ##sys#generic-structure? lit) + `(struct ,(##sys#slot lit 0))) + ((null? lit) 'null) + ((char? lit) 'char) + (else '*))) + (define (global-result id loc) + (cond ((##sys#get id '##compiler#type) => + (lambda (a) + (cond + #;((and (get db id 'assigned) ; remove assigned global from type db + (not (##sys#get id '##core#declared-type))) + (##sys#put! id '##compiler#type #f) + '*) + ((eq? a 'deprecated) + (report + loc + (sprintf "use of deprecated library procedure `~a'" id) ) + '(*)) + ((and (pair? a) (eq? (car a) 'deprecated)) + (report + loc + (sprintf + "use of deprecated library procedure `~a' - consider using `~a' instead" + id (cadr a))) + '(*)) + (else (list a))))) + (else '(*)))) + (define (variable-result id e loc flow) + (cond ((find (lambda (b) + (and (eq? id (caar b)) + (memq (cdar b) flow)) ) + blist) + => (o list cdr)) + ((and (get db id 'assigned) + (not (##sys#get id '##core#declared-type)) ) + '(*)) ++======= + (define specialization-statistics '()) + + (define (scrutinize node db complain specialize) + (define (constant-result lit) + (cond ((string? lit) 'string) + ((symbol? lit) 'symbol) + ((fixnum? lit) 'fixnum) + ((flonum? lit) 'float) + ((number? lit) + (case number-type + ((fixnum) 'fixnum) + ((flonum) 'flonum) + (else 'number))) ; in case... + ((boolean? lit) 'boolean) + ((null? lit) 'null) + ((pair? lit) 'pair) + ((list? lit) 'list) + ((eof-object? lit) 'eof) + ((vector? lit) 'vector) + ((and (not (##sys#immediate? lit)) ##sys#generic-structure? lit) + `(struct ,(##sys#slot lit 0))) + ((char? lit) 'char) + (else '*))) + (define (global-result id loc) + (cond ((##sys#get id '##core#type) => + (lambda (a) + (cond ((eq? a 'deprecated) + (report + loc + (sprintf "use of deprecated library procedure `~a'" id) ) + '*) + ((and (pair? a) (eq? (car a) 'deprecated)) + (report + loc + (sprintf + "use of deprecated library procedure `~a' - consider using `~a' instead" + id (cadr a))) + '*) + (else (list a))))) + (else '*))) + (define (variable-result id e loc) + (cond ((and (get db id 'assigned) + (not (##sys#get id '##core#declared-type))) + '*) ++>>>>>>> specialization ((assq id e) => (lambda (a) (cond ((eq? 'undefined (cdr a)) @@@ -399,11 -409,12 +462,12 @@@ (report loc (sprintf "expected ~a a single result, but were given ~a result~a" - what n (multiples n))) + what n (multiples n))) (first tv)))))) (define (report loc desc) - (warning - (conc (location-name loc) desc))) + (when complain + (warning + (conc (location-name loc) desc)))) (define (location-name loc) (define (lname loc1) (if loc1 @@@ -431,17 -442,17 +495,17 @@@ (with-output-to-string (lambda () (pp (fragment x)))))) - (define (call-result args e loc x params) + (define (call-result node args e loc params) (define (pname) (sprintf "~ain procedure call to `~s', " - (if (and (pair? params) (pair? (cdr params))) - (let ((n (source-info->line (cadr params)))) - (if n - (sprintf "~a: " n) - "")) - "") - (fragment x))) - (d "call-result: ~a" args) + (if (and (pair? params) (pair? (cdr params))) + (let ((n (source-info->line (cadr params)))) + (if n + (sprintf "~a: " n) + "")) + "") + (fragment (first (node-subexpressions node))))) - (d "call-result: ~a (~a)" args loc) ++ (d "call-result: ~a " args) (let* ((ptype (car args)) (nargs (length (cdr args))) (xptype `(procedure ,(make-list nargs '*) *))) @@@ -471,10 -483,25 +536,25 @@@ (report loc (sprintf - "~aexpected argument #~a of type `~a', but where given an argument of type `~a'" - (pname) i (car atypes) (car args))))) + "~aexpected argument #~a of type `~a', but was given an argument of type `~a'" + (pname) i (car atypes) (car args))))) (let ((r (procedure-result-types ptype values-rest (cdr args)))) (d " result-types: ~a" r) + (when specialize + ;;XXX we should check whether this is a standard- or extended bindng + (and-let* ((pn (procedure-name ptype)) - (specs (##sys#get pn '##core#specializations))) ++ (specs (##sys#get pn '##compiler#specializations))) + (for-each + (lambda (spec) + (when (match-specialization (car spec) (cdr args)) + (let ((op (cons pn (car spec)))) + (cond ((assoc op specialization-statistics) => + (lambda (a) (set-cdr! a (add1 (cdr a))))) + (else + (set! specialization-statistics + (cons (cons op 1) specialization-statistics))))) + (specialize-node! node (cadr spec)))) + specs))) r)))) (define (procedure-type? t) (or (eq? 'procedure t) @@@ -683,7 -669,14 +765,14 @@@ '*)))) (d " -> ~a" results) results))) - (walk (first (node-subexpressions node)) '() '() #f #f (list (tag)) #f))) - (let ((rn (walk (first (node-subexpressions node)) '() '() #f #f))) ++ (let ((rn (walk (first (node-subexpressions node)) '() '() #f #f (list (tag)) #f))) + (when (and (pair? specialization-statistics) + (debugging 'x "specializations:")) + (for-each + (lambda (ss) + (printf " ~a ~s~%" (cdr ss) (car ss))) + specialization-statistics)) + rn)) (define (load-type-database name #!optional (path (repository-path))) (and-let* ((dbfile (file-exists? (make-pathname path name)))) @@@ -691,16 -684,129 +780,132 @@@ (printf "loading type database ~a ...~%" dbfile)) (for-each (lambda (e) - (let* ((name (car e)) - (old (##sys#get name '##core#type)) - (new (cadr e)) - (specs (and (pair? (cddr e)) (cddr e)))) - (when (and old (not (equal? old new))) - (##sys#notice - (sprintf - "type-definition `~a' for toplevel binding `~a' conflicts with previously loaded type `~a'" - name new old))) - (##sys#put! name '##core#type new) - (when specs - (##sys#put! name '##core#specializations specs)))) + (cond ((eq? 'predicate (car e)) + (##sys#put! (cadr e) '##compiler#predicate (caddr e))) + (else + (let* ((name (car e)) + (old (##sys#get name '##compiler#type)) - (new (cadr e))) ++ (new (cadr e)) ++ (specs (and (pair? (cddr e)) (cddr e)))) + (when (and old (not (equal? old new))) + (##sys#notice + (sprintf + "type-definition `~a' for toplevel binding `~a' conflicts with previously loaded type `~a'" + name new old))) - (##sys#put! name '##compiler#type new))))) ++ (##sys#put! name '##compiler#type new) ++ (when specs ++ (##sys#put! name '##compiler#specializations specs)))))) (read-file dbfile)))) + + (define (match-specialization typelist atypes) + (define (match st t) + (cond ((pair? st) + (case (car st) + ((not) + (cond ((and (pair? t) (eq? 'or (car t))) + (not (any (cute match (cadr st) <>) (cdr t)))) + ((eq? '* t) #f) + (else (not (match (cadr st) t))))) + ((or) (any (cut match <> t) (cdr st))) + ((and) (every (cut match <> t) (cdr st))) + (else (equal? st t)))) + ((eq? st '*)) + ((eq? st 'procedure) + (or (eq? t 'procedure) + (and (pair? t) (eq? 'procedure (car t))))) + ;;XXX match number with fixnum and float? + (else (eq? st t)))) + (let loop ((tl typelist) (atypes atypes)) + (cond ((null? tl) (null? atypes)) + ((null? atypes) #f) + ((eq? (car tl) '#!rest) + (every (cute match (cadr tl) <>) atypes)) + ((match (car tl) (car atypes)) (loop (cdr tl) (cdr atypes))) + (else #f)))) + + (define (specialize-node! node template) + (let ((args (cdr (node-subexpressions node)))) + (define (subst x) + (cond ((and (vector? x) + (= 1 (vector-length x)) + (integer? (vector-ref x 0))) + (list-ref args (sub1 (vector-ref x 0)))) + ((and (vector? x) + (= 2 (vector-length x)) + (integer? (vector-ref x 0)) + (eq? '... (vector-ref x 1))) + (list-tail args (sub1 (vector-ref x 0)))) + ((not (pair? x)) x) + ((eq? 'quote (car x)) x) ; to handle numeric constants + (else (cons (subst (car x)) (subst (cdr x)))))) + (let ((spec (subst template))) + (copy-node! (build-node-graph spec) node)))) + + (define (validate-type type name) + ;; - returns converted type or #f + ;; - also converts "(... -> ...)" types + ;; - drops "#!key ..." args by converting to #!rest + (define (upto lst p) + (let loop ((lst lst)) + (cond ((eq? lst p) '()) + (else (cons (car lst) (loop (cdr lst))))))) + (define (validate-llist llist) + (cond ((null? llist) '()) + ((symbol? llist) '(#!rest *)) + ((not (pair? llist)) #f) + ((eq? '#!optional (car llist)) + (cons '#!optional (validate-llist (cdr llist)))) + ((eq? '#!rest (car llist)) + (cond ((null? (cdr llist)) '(#!rest *)) + ((not (pair? (cdr llist))) #f) + ((and (pair? (cddr llist)) + (eq? '#!key (caddr llist))) + `(#!rest ,(validate (cadr llist)))) + (else #f))) + ((eq? '#!key (car llist)) '(#!rest *)) + (else (cons (validate (car llist)) (validate-llist (cdr llist)))))) + (define (validate t) + (cond ((memq t '(* string symbol char number boolean list pair + procedure vector null eof undefined port blob + pointer locative fixnum float pointer-vector + deprecated)) + t) + ((not (pair? t)) t) + ((eq? 'or (car t)) + (and (list? t) + (let ((ts (map validate (cdr t)))) + (and (every identity ts) + `(or ,@ts))))) + ((eq? 'struct (car t)) + (and (= 2 (length t)) + (symbol? (cadr t)) + t)) + ((eq? 'procedure (car t)) + (and (pair? (cdr t)) + (let* ((name (if (symbol? (cadr t)) + (cadr t) + name)) + (t2 (if (symbol? (cadr t)) (cddr t) (cdr t)))) + (and (pair? t2) + (list? (car t2)) + (let ((ts (validate-llist (car t2)))) + (and ts + (every identity ts) + (let* ((rt2 (cdr t2)) + (rt (if (eq? '* rt2) + rt2 + (and (list? rt2) + (let ((rts (map validate rt2))) + (and (every identity rts) + rts)))))) + (and rt + `(procedure + ,@(if name (list name) '()) + ,ts + ,@rt))))))))) + ((and (pair? (cdr t)) (memq '-> (cdr t))) => + (lambda (p) + (validate + `(procedure ,(upto t p) ,@(cdr p))))) + (else #f))) + (validate type)) diff --cc support.scm index d2fde7af,a56dd850..61d10df9 --- a/support.scm +++ b/support.scm @@@ -731,6 -736,24 +736,24 @@@ (loop))))))) + ;;; write declared types to file + + (define (emit-type-file filename db) + (with-output-to-file filename + (lambda () + (print "; GENERATED BY CHICKEN " (chicken-version) " FROM " + source-filename "\n") + (##sys#hash-table-for-each + (lambda (sym plist) + (when (variable-visible? sym) + (when (variable-mark sym '##core#declared-type) + (let ((specs - (or (variable-mark sym '##core#specializations) '()))) ++ (or (variable-mark sym '##compiler#specializations) '()))) + (pp (cons* sym (variable-mark sym '##core#type) specs)))))) + db) + (print "; END OF FILE")))) + + ;;; Match node-structure with pattern: (define (match-node node pat vars)Trap