original commit: d6ea00635da8c31a227f43f0712263984b70bf67
This commit is contained in:
Robby Findler 2002-12-03 03:01:47 +00:00
parent 4ef9706872
commit 77896eab3f

View File

@ -22,6 +22,25 @@
(require (lib "contract-helpers.scm" "mzlib" "private"))
(require-for-syntax (prefix a: (lib "contract-helpers.scm" "mzlib" "private")))
;
;
;
; ; ;;; ; ;
; ; ; ;
; ; ; ; ; ;
; ;; ; ;;; ;;;; ; ; ;; ;;; ; ;;; ;;; ; ;; ;;;; ; ; ;;; ;;; ;;;;
; ; ;; ; ; ; ; ;; ; ; ; ; ; ; ; ; ;; ; ; ;; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ;;;;;; ; ; ; ; ;;;;;; ; ; ; ; ; ; ; ; ;;;; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ;; ; ;;;; ; ; ; ; ;;;; ; ;;; ;;; ; ; ;; ; ;;;;; ;;; ;;
; ;
; ;
;
;; (define/contract id contract expr)
;; defines `id' with `contract'; initially binding
;; it to the result of `expr'. These variables may not be set!'d.
@ -97,6 +116,25 @@
define-stx
(syntax name))]))
;
;
;
; ; ; ;
; ; ;
; ; ; ; ;
; ; ;; ; ; ;;; ; ; ; ;; ; ;;; ; ;;; ;;; ; ;; ;;;; ; ; ;;; ;;; ;;;;
; ;; ; ;; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ;; ; ; ;; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ;;;;;; ; ; ; ; ; ; ; ; ;;;; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ;; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ;; ; ;;; ; ; ;; ; ;;;; ; ;;; ;;; ; ; ;; ; ;;;;; ;;; ;;
; ; ;
; ; ;
; ;
;; (provide/contract p/c-ele ...)
;; p/c-ele = (id expr) | (struct (id expr) ...)
;; provides each `id' with the contract `expr'.
@ -344,7 +382,7 @@
(string-append
prefix
(format
"-~a~a-ACK-DONT_USE_ME"
"-~a~a-ACK-PLEASE_DONT_GUESS_THIS_ID"
(syntax-object->datum id)
(apply
string-append
@ -359,50 +397,24 @@
(require (lib "contract-helpers.scm" "mzlib" "private"))
bodies ...))))]))
;; raise-contract-error : (union syntax #f) symbol symbol string args ... -> alpha
;; doesn't return
(define (raise-contract-error src-info to-blame other-party fmt . args)
(let ([blame-src (if (syntax? src-info)
(string-append (build-src-loc-string src-info) ": ")
"")]
[specific-blame
(let ([datum (syntax-object->datum src-info)])
(if (symbol? datum)
(format "broke ~a's contract" datum)
"failed contract"))])
(raise
(make-exn
(string->immutable-string
(string-append (format "~a~a: ~a ~a: "
blame-src
other-party
to-blame
specific-blame)
(apply format fmt args)))
(current-continuation-marks)))))
;; contract = (make-contract (alpha sym sym sym -> alpha))
;; generic contract container
(define-struct contract (f))
;
;
;
;
;
; ; ;
; ;;; ;;; ; ;; ;;;; ; ; ;;; ;;; ;;;;
; ; ; ; ; ;; ; ; ;; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ;;;; ; ;
; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ;;; ;;; ; ; ;; ; ;;;;; ;;; ;;
;
;
;
;; flat-named-contract = (make-flat-named-contract string (any -> boolean))
;; this holds flat contracts that have names for error reporting
(define-struct flat-named-contract (type-name predicate))
(provide (rename build-flat-named-contract flat-named-contract)
flat-named-contract-type-name
flat-named-contract-predicate)
(define build-flat-named-contract
(let ([flat-named-contract
(lambda (name contract)
(unless (and (string? name)
(procedure? contract)
(procedure-arity-includes? contract 1))
(error 'flat-named-contract "expected string and procedure of one argument as arguments, given: ~e and ~e"
name contract))
(make-flat-named-contract name contract))])
flat-named-contract))
(define-syntax -contract
(lambda (stx)
@ -447,6 +459,137 @@
name))
(check-contract a-contract name pos-blame neg-blame src-info #f)))))])))
;; check-contract : contract any symbol symbol syntax (union false? string?)
(define (check-contract contract val pos neg src-info extra-message)
(cond
[(contract? contract)
((contract-f contract) val pos neg src-info)]
[(flat-named-contract? contract)
(if ((flat-named-contract-predicate contract) val)
val
(raise-contract-error
src-info
pos
neg
"expected type <~a>, given: ~e"
(flat-named-contract-type-name contract)
val))]
[else
(if (contract val)
val
(raise-contract-error
src-info
pos
neg
"~agiven: ~e~a"
(predicate->expected-msg contract)
val
(if extra-message
extra-message
"")))]))
;; raise-contract-error : (union syntax #f) symbol symbol string args ... -> alpha
;; doesn't return
(define (raise-contract-error src-info to-blame other-party fmt . args)
(let ([blame-src (if (syntax? src-info)
(string-append (build-src-loc-string src-info) ": ")
"")]
[specific-blame
(let ([datum (syntax-object->datum src-info)])
(if (symbol? datum)
(format "broke ~a's contract" datum)
"failed contract"))])
(raise
(make-exn
(string->immutable-string
(string-append (format "~a~a: ~a ~a: "
blame-src
other-party
to-blame
specific-blame)
(apply format fmt args)))
(current-continuation-marks)))))
;; contract = (make-contract (alpha sym sym (union syntax #f) -> alpha))
;; generic contract container;
;; the first argument to f is the value to test the contract.
;; the second to f is a symbol representing the name of the positive blame
;; the third to f is the symbol representing the name of the negative blame
;; the final argument is the src-info.
(define-struct contract (f))
;; flat-named-contract = (make-flat-named-contract string (any -> boolean))
;; this holds flat contracts that have names for error reporting
(define-struct flat-named-contract (type-name predicate))
(provide (rename build-flat-named-contract flat-named-contract)
flat-named-contract-type-name
flat-named-contract-predicate)
(define build-flat-named-contract
(let ([flat-named-contract
(lambda (name contract)
(unless (and (string? name)
(procedure? contract)
(procedure-arity-includes? contract 1))
(error 'flat-named-contract "expected string and procedure of one argument as arguments, given: ~e and ~e"
name contract))
(make-flat-named-contract name contract))])
flat-named-contract))
(define -contract?
(let ([contract?
(lambda (val)
(or (contract? val) ;; refers to struct predicate
(flat-named-contract? val)
(and (procedure? val)
(procedure-arity-includes? val 1))))])
contract?))
;; predicate->expected-msg : function -> string
;; if the function has a name and the name ends
;; with a question mark, turn it into a mzscheme
;; style type name
(define (predicate->expected-msg pred)
(let ([name (predicate->type-name pred)])
(if name
(format "expected type <~a>, " name)
"")))
;; predicate->type-name : pred -> (union #f string)
(define (predicate->type-name pred)
(let* ([name (object-name pred)])
(and name
(let ([m (regexp-match "(.*)\\?" (symbol->string name))])
(and m
(cadr m))))))
;; flat-contract->type-name : flat-contract -> string
(define (flat-contract->type-name fc)
(cond
[(flat-named-contract? fc) (flat-named-contract-type-name fc)]
[else (or (predicate->type-name fc)
"unknown type")]))
;
;
;
;
;
; ; ; ;
; ;; ;;; ;;; ; ;; ;;;; ; ; ;;; ;;; ;;;; ;;;
; ;; ; ; ; ; ;; ; ; ;; ; ; ; ; ; ;
; ;; ; ; ; ; ; ; ; ; ; ; ;;
; ;;;;;; ;; ; ; ; ; ; ; ; ;;;; ; ; ;;
; ;; ; ; ; ; ; ; ; ; ; ; ; ;
; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ;;; ;;; ; ; ;; ; ;;;;; ;;; ;; ;;;
;
;
;
(define-syntaxes (-> ->* ->d ->d* case->)
(let ()
;; Each of the /h functions builds three pieces of syntax:
@ -908,68 +1051,76 @@
[opt-vs opts] ...)
(case-> (->* (case-doms ...) (double-res-vs ...)) ...)))))]))
(define -contract?
(let ([contract?
(lambda (val)
(or (contract? val) ;; refers to struct predicate
(flat-named-contract? val)
(and (procedure? val)
(procedure-arity-includes? val 1))))])
contract?))
;; check-contract : contract any symbol symbol syntax (union false? string?)
(define (check-contract contract val pos neg src-info extra-message)
(cond
[(contract? contract)
((contract-f contract) val pos neg src-info)]
[(flat-named-contract? contract)
(if ((flat-named-contract-predicate contract) val)
val
(raise-contract-error
src-info
pos
neg
"expected type <~a>, given: ~e"
(flat-named-contract-type-name contract)
val))]
[else
(if (contract val)
val
(raise-contract-error
src-info
pos
neg
"~agiven: ~e~a"
(predicate->expected-msg contract)
val
(if extra-message
extra-message
"")))]))
;
;
;
; ;
; ;
; ; ; ;
; ;;; ; ;;; ;;; ;;; ;;; ;;; ; ;; ;;;; ; ; ;;; ;;; ;;;; ;;;
; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ;; ; ; ; ; ; ;
; ; ; ; ;; ;; ; ; ; ; ; ; ; ; ; ; ;;
; ; ; ;;;; ;; ;; ; ; ; ; ; ; ; ;;;; ; ; ;;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ;;; ; ;;;;; ;;; ;;; ;;; ;;; ; ; ;; ; ;;;;; ;;; ;; ;;;
;
;
;;
;
; (define-syntax (class-contract stx)
; (syntax-case stx ()
; [(_ (meth-name meth-contract) ...)
; (andmap identifier? (syntax->list (syntax (meth-name ...))))
; (let ()
; (define (expand-contract x y)
; (syntax 1))
; (with-syntax ([(((doms ...) (rngs ...)) ...)
; (map expand-contract
; (syntax->list (syntax (meth-name ...)))
; (syntax->list (syntax (meth-contract ...))))])
; (syntax
; (make-contract
; (lambda (val pos neg src-info)
; (unless (class? val)
; (raise-contract-error src-info pos neg "expected a class, got: ~e" val))
; (let ([class-i (class->interface val)])
; (void)
; (unless (method-in-interface? 'meth-name class-i)
; (raise-contract-error src-info
; pos neg
; "expected class to have method ~a, got: ~e"
; 'meth-name
; val))
; ...)
; (class val
; (define/override (meth-name
; val)))))]
; [(_ (meth-name meth-contract) ...)
; (for-each (lambda (name)
; (unless (identifier? name)
; (raise-syntax-error 'class-contract "expected name" stx name)))
; (syntax->list (syntax (meth-name ...))))]))
;; predicate->expected-msg : function -> string
;; if the function has a name and the name ends
;; with a question mark, turn it into a mzscheme
;; style type name
(define (predicate->expected-msg pred)
(let ([name (predicate->type-name pred)])
(if name
(format "expected type <~a>, " name)
"")))
;
;
;
; ;
;
; ; ;
; ; ;; ;; ; ;;; ;;; ;;; ;;; ; ;; ;;;; ; ; ;;; ;;; ;;;; ;;;
; ;; ;; ; ; ; ; ; ; ; ; ; ;; ; ; ;; ; ; ; ; ; ;
; ; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ;;
; ; ; ; ; ;; ; ; ; ; ; ; ; ; ;;;; ; ; ;;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
; ; ; ; ; ;;; ;;; ; ;;; ;;; ; ; ;; ; ;;;;; ;;; ;; ;;;
;
;
;
;; predicate->type-name : pred -> (union #f string)
(define (predicate->type-name pred)
(let* ([name (object-name pred)])
(and name
(let ([m (regexp-match "(.*)\\?" (symbol->string name))])
(and m
(cadr m))))))
;; flat-contract->type-name : flat-contract -> string
(define (flat-contract->type-name fc)
(cond
[(flat-named-contract? fc) (flat-named-contract-type-name fc)]
[else (or (predicate->type-name fc)
"unknown type")]))
(provide union)
(define (union . args)