diff --git a/collects/tests/typed-scheme/optimizer/generic/in-list.rkt b/collects/tests/typed-scheme/optimizer/generic/in-list.rkt new file mode 100644 index 00000000..6d9dde83 --- /dev/null +++ b/collects/tests/typed-scheme/optimizer/generic/in-list.rkt @@ -0,0 +1,4 @@ +(module in-list typed/scheme #:optimize + (require racket/unsafe/ops) + (for: ((i : Natural '(1 2 3))) + (display i))) diff --git a/collects/typed-scheme/private/for-clauses.rkt b/collects/typed-scheme/private/for-clauses.rkt index 78c04cc8..3d9bea9b 100644 --- a/collects/typed-scheme/private/for-clauses.rkt +++ b/collects/typed-scheme/private/for-clauses.rkt @@ -10,21 +10,15 @@ (define-splicing-syntax-class for-clause ;; single-valued seq-expr (pattern (~and c (var:annotated-name seq-expr:expr)) - #:with (expand ...) (list (quasisyntax/loc + #:with (expand ...) (list (syntax/loc #'c - (var.ann-name - #,(syntax-property #'seq-expr - 'type-ascription - #'(Sequenceof var.ty)))))) + (var.ann-name seq-expr)))) ;; multi-valued seq-expr ;; currently disabled because it triggers an internal error in the typechecker #;(pattern (~and c (((v:annotated-name) ...) seq-expr:expr)) - #:with (expand ...) (list (quasisyntax/loc + #:with (expand ...) (list (syntax/loc #'c - ((v.ann-name ...) - #,(syntax-property #'seq-expr - 'type-ascription - #'(Sequenceof (values v.ty ...))))))) + ((v.ann-name ...) seq-expr)))) ;; when clause (pattern (~seq #:when guard:expr) #:with (expand ...) (list #'#:when #'guard))) @@ -33,22 +27,16 @@ (define-splicing-syntax-class for*-clause ;; single-valued seq-expr (pattern (~and c (var:annotated-name seq-expr:expr)) - #:with (expand ...) (list (quasisyntax/loc + #:with (expand ...) (list (syntax/loc #'c - (var.ann-name - #,(syntax-property #'seq-expr - 'type-ascription - #'(Sequenceof var.ty)))) + (var.ann-name seq-expr)) #'#:when #'#t)) ;; multi-valued seq-expr ;; currently disabled because it triggers an internal error in the typechecker #;(pattern (~and c (((v:annotated-name) ...) seq-expr:expr)) #:with (expand ...) (list (quasisyntax/loc #'c - ((v.ann-name ...) - #,(syntax-property #'seq-expr - 'type-ascription - #'(Sequenceof (values v.ty ...))))) + ((v.ann-name ...) seq-expr)) #'#:when #'#t)) ;; when clause (pattern (~seq #:when guard:expr) diff --git a/collects/typed-scheme/private/optimize.rkt b/collects/typed-scheme/private/optimize.rkt index e998e9b4..fecbaaba 100644 --- a/collects/typed-scheme/private/optimize.rkt +++ b/collects/typed-scheme/private/optimize.rkt @@ -1,7 +1,7 @@ #lang scheme/base -(require syntax/parse (for-template scheme/base scheme/flonum scheme/fixnum scheme/unsafe/ops) - "../utils/utils.rkt" unstable/match scheme/match unstable/syntax +(require syntax/parse (for-template scheme/base scheme/flonum scheme/fixnum scheme/unsafe/ops racket/private/for) + "../utils/utils.rkt" "../utils/tc-utils.rkt" unstable/match scheme/match unstable/syntax (rep type-rep) syntax/id-table racket/dict (types abbrev type-table utils subtype)) (provide optimize) @@ -124,6 +124,15 @@ (pattern (~literal vector-ref) #:with unsafe #'unsafe-vector*-ref) (pattern (~literal vector-set!) #:with unsafe #'unsafe-vector*-set!)) +(define-syntax-class list-opt-expr + (pattern e:opt-expr + #:when (match (type-of #'e) + [(tc-result1: (Listof: _)) #t] + [(tc-result1: (List: _)) #t] + [_ #f]) + #:with opt #'e.opt)) + + (define-syntax-class opt-expr (pattern e:opt-expr* #:with opt (syntax-recertify #'e.opt this-syntax (current-code-inspector) #f))) @@ -227,6 +236,19 @@ (begin (log-optimization "vector" #'op) #'(op.unsafe v.opt i.opt new.opt ...))) + ;; if we're iterating (with the for macros) over something we know is a list, + ;; we can generate code that would be similar to if in-list had been used + (pattern (#%plain-app op:id _ l) + #:when (id-from? #'op 'make-sequence 'racket/private/for) + #:with l*:list-opt-expr #'l + #:with opt + (begin (log-optimization "in-list" #'op) + #'(let ((i l*.opt)) + (values unsafe-car unsafe-cdr i + (lambda (x) (not (null? x))) + (lambda (x) #t) + (lambda (x y) #t))))) + ;; boring cases, just recur down (pattern (#%plain-lambda formals e:opt-expr ...) #:with opt #'(#%plain-lambda formals e.opt ...)) diff --git a/collects/typed-scheme/private/prims.rkt b/collects/typed-scheme/private/prims.rkt index e213f46d..cef82b22 100644 --- a/collects/typed-scheme/private/prims.rkt +++ b/collects/typed-scheme/private/prims.rkt @@ -428,17 +428,11 @@ This file defines two sorts of primitives. All of them are provided into any mod ;; unlike the definitions in for-clauses.rkt, this does not include ;; #:when clauses, which are handled separately here (pattern (var:annotated-name seq-expr:expr) - #:with expand #`(var.ann-name - #,(syntax-property #'seq-expr - 'type-ascription - #'(Sequenceof var.ty)))) + #:with expand #'(var.ann-name seq-expr)) ;; multi-valued seq-expr ;; currently disabled because it triggers an internal error in the typechecker #;(pattern ((v:annotated-name ...) seq-expr:expr) - #:with expand #`((v.ann-name ...) - #,(syntax-property #'seq-expr - 'type-ascription - #'(Sequenceof (values v.ty ...)))))) + #:with expand #'((v.ann-name ...) seq-expr))) (syntax-parse clauses [(head:for-clause next:for-clause ... #:when rest ...) (syntax-property