diff --git a/collects/racket/dict.rkt b/collects/racket/dict.rkt index cddceffaef..43ff07b5aa 100644 --- a/collects/racket/dict.rkt +++ b/collects/racket/dict.rkt @@ -1,46 +1,6 @@ #lang racket/base - -(require (for-syntax racket/base)) - -(provide prop:dict - dict? - - dict-mutable? - dict-can-remove-keys? - dict-can-functional-set? - - dict-has-key? - dict-ref - dict-ref! - dict-set! - dict-set*! - dict-set - dict-set* - dict-update! - dict-update - dict-remove! - dict-remove - dict-count - dict-iterate-first - dict-iterate-next - dict-iterate-key - dict-iterate-value - - dict-map - dict-for-each - - in-dict - in-dict-keys - in-dict-values - in-dict-pairs - - dict-keys - dict-values - dict->list - - (rename-out [create-custom-hash make-custom-hash] - [create-immutable-custom-hash make-immutable-custom-hash]) - make-weak-custom-hash) +(require (for-syntax racket/base) + racket/contract/base) (define (dict-property-guard v info) (check-dict-vector 'prop:dict "dictionary property" v) @@ -131,9 +91,23 @@ (apply format fmt args) (current-continuation-marks)))) +(define (dict/c-property-guard v _) + v) + +(define (dict/contracts-property-guard v _) + v) + (define-values (prop:dict dict-struct? dict-struct-ref) (make-struct-type-property 'dict dict-property-guard)) +(define-values (prop:dict/c dict/c-struct? dict/c-struct-ref) + (make-struct-type-property 'dict/c dict/c-property-guard)) + +(define-values (prop:dict/contracts dict/contracts? dict/contracts-ref) + (make-struct-type-property 'dict/contracts dict/contracts-property-guard + (list (cons prop:dict car) + (cons prop:dict/c cadr)))) + (define (get-dict-ref v) (vector-ref v 0)) (define (get-dict-set! v) @@ -155,6 +129,19 @@ (define (get-dict-iterate-value v) (vector-ref v 9)) +(define (get-dict/c-type-key-c v) + (vector-ref v 0)) +(define (get-dict/c-type-value-c v) + (vector-ref v 1)) +(define (get-dict/c-type-iter-c v) + (vector-ref v 2)) +(define (get-dict/c-inst-key-c v) + (vector-ref v 3)) +(define (get-dict/c-inst-value-c v) + (vector-ref v 4)) +(define (get-dict/c-inst-iter-c v) + (vector-ref v 5)) + (define (assoc? v) (and (list? v) (andmap pair? v))) @@ -510,7 +497,34 @@ (for/list ([k*v (in-dict-pairs d)]) k*v)) +;; ---------------------------------------- +(define (dict-key-contract d) + (if (dict/c-struct? d) + (let ([type-key-contract (get-dict/c-type-key-c d)] + [inst-key-contract (get-dict/c-inst-key-c d)]) + (if inst-key-contract + (and/c type-key-contract (inst-key-contract d)) + type-key-contract)) + any/c)) + +(define (dict-value-contract d) + (if (dict/c-struct? d) + (let ([type-value-contract (get-dict/c-type-value-c d)] + [inst-value-contract (get-dict/c-inst-value-c d)]) + (if inst-value-contract + (and/c type-value-contract (inst-value-contract d)) + type-value-contract)) + any/c)) + +(define (dict-iter-contract d) + (if (dict/c-struct? d) + (let ([type-iter-contract (get-dict/c-type-iter-c d)] + [inst-iter-contract (get-dict/c-inst-iter-c d)]) + (if inst-iter-contract + (and/c type-iter-contract (inst-iter-contract d)) + type-iter-contract)) + any/c)) ;; ---------------------------------------- @@ -645,3 +659,95 @@ (values make-custom-hash make-immutable-custom-hash make-weak-custom-hash)))) + +;; -------------------- + +(provide prop:dict + prop:dict/contracts + dict? + + dict-mutable? + dict-can-remove-keys? + dict-can-functional-set?) + +(provide/contract + [dict-has-key? + (-> dict? any/c boolean?)] + [dict-ref + (->i ([d dict?] [k (d) (dict-key-contract d)]) + ([default any/c]) + [_ (d) (dict-value-contract d)])] ;; or == default ? + [dict-ref! + (->i ([d dict-mutable?] [k (d) (dict-key-contract d)] + [default any/c]) ;; refine using if/c + [_ (d) (dict-value-contract d)])] ;; or == default ? + [dict-set! + (->i ([d dict-mutable?] + [k (d) (dict-key-contract d)] + [value (d) (dict-value-contract d)]) + [_ void?])] + [dict-set + (->i ([d dict-can-functional-set?] + [k (d) (dict-key-contract d)] + [value (d) (dict-value-contract d)]) + [_ dict?])] + [dict-set*! any/c] ;; FIXME!!! + [dict-set* any/c] ;; FIXME!!! + [dict-update! + (->i ([d dict-mutable?] + [k (d) (dict-key-contract d)] + [update (d) (-> (dict-value-contract d) (dict-value-contract d))]) + [_ void?])] + [dict-update + (->i ([d dict-can-functional-set?] + [k (d) (dict-key-contract d)] + [update (d) (-> (dict-value-contract d) (dict-value-contract d))]) + [_ dict?])] + [dict-remove! + (->i ([d (and/c dict-mutable? dict-can-remove-keys?)] + [k (d) (dict-key-contract d)]) + [_ void?])] + [dict-remove + (->i ([d (and/c dict-can-functional-set? dict-can-remove-keys?)] + [k (d) (dict-key-contract d)]) + [_ dict?])] + [dict-count + (-> dict? exact-nonnegative-integer?)] + [dict-iterate-first + (->i ([d dict?]) [_ (d) (or/c #f (dict-iter-contract d))])] + [dict-iterate-next + (->i ([d dict?] [iter (d) (dict-iter-contract d)]) + [_ (d) (or/c #f (dict-iter-contract d))])] + [dict-iterate-key + (->i ([d dict?] [iter (d) (dict-iter-contract d)]) + [_ (d) (dict-key-contract d)])] + [dict-iterate-value + (->i ([d dict?] [iter (d) (dict-iter-contract d)]) + [_ (d) (dict-value-contract d)])] + + [dict-map + (->i ([d dict?] [proc (d) (-> (dict-key-contract d) (dict-value-contract d) any)]) + [_ list?])] + [dict-for-each + (->i ([d dict?] [proc (d) (-> (dict-key-contract d) (dict-value-contract d) any)]) + [_ void?])] + + [dict-keys + (->i ([d dict?]) + [_ (d) (listof (dict-key-contract d))])] + [dict-values + (->i ([d dict?]) + [_ (d) (listof (dict-value-contract d))])] + [dict->list + (->i ([d dict?]) + [_ (d) (listof (cons/c (dict-key-contract d) (dict-value-contract d)))])]) + +(provide (rename-out [create-custom-hash make-custom-hash] + [create-immutable-custom-hash make-immutable-custom-hash]) + make-weak-custom-hash + + in-dict + in-dict-keys + in-dict-values + in-dict-pairs) + diff --git a/collects/unstable/dirs.rkt b/collects/unstable/dirs.rkt index 9e984c98f5..2530024b6d 100644 --- a/collects/unstable/dirs.rkt +++ b/collects/unstable/dirs.rkt @@ -3,8 +3,7 @@ ;; Unstable library by: Carl Eastlund ;; intended for use in racket/contract, so don't try to add contracts! -(require racket/dict - setup/path-relativize +(require setup/path-relativize setup/dirs (only-in planet/config [CACHE-DIR find-planet-dir])) @@ -31,19 +30,21 @@ (error 'path->directory-relative-string "expected a path or a string (first argument); got: ~e" path)) - (unless (dict? dirs) + (unless (and (list? dirs) (andmap pair? dirs)) (error 'path->directory-relative-string - "expected a dictionary (#:dirs keyword argument); got: ~e" dirs)) + "expected an association list (#:dirs keyword argument); got: ~e" dirs)) (let/ec return (when (complete-path? path) - (for ([(find-dir dir-name) (in-dict dirs)]) + (for ([dir-entry (in-list dirs)]) + (define find-dir (car dir-entry)) + (define dir-name (cdr dir-entry)) (unless (and (procedure? find-dir) (procedure-arity-includes? find-dir 0)) (error 'path->directory-relative-string - "expected keys in dictionary to be thunks (~a); got: ~e" + "expected keys in association list to be thunks (~a); got: ~e" "#:dirs keyword argument" find-dir))