refactored contract opters so they return structs instead

of (8!) multiple values
This commit is contained in:
Robby Findler 2012-05-08 11:29:14 -05:00
parent 4c59943b0d
commit 7221d01483
8 changed files with 480 additions and 617 deletions

View File

@ -377,154 +377,3 @@
(define-syntax (opt-> stx) (make-opt->/proc #f stx select/h #'case-> #'->))
(define-syntax (opt->* stx) (make-opt->*/proc #f stx stx select/h #'case-> #'->))
;;
;; arrow opter
;;
(define/opter (-> opt/i opt/info stx)
(define (opt/arrow-ctc doms rngs)
(let*-values ([(dom-vars rng-vars) (values (generate-temporaries doms)
(generate-temporaries rngs))]
[(next-doms lifts-doms superlifts-doms partials-doms stronger-ribs-dom doms-chaperone?)
(let loop ([vars dom-vars]
[doms doms]
[next-doms null]
[lifts-doms null]
[superlifts-doms null]
[partials-doms null]
[stronger-ribs null]
[chaperone? #t])
(cond
[(null? doms) (values (reverse next-doms)
lifts-doms
superlifts-doms
partials-doms
stronger-ribs
chaperone?)]
[else
(let-values ([(next lift superlift partial _ __ this-stronger-ribs this-chaperone?)
(opt/i (opt/info-swap-blame opt/info) (car doms))])
(loop (cdr vars)
(cdr doms)
(cons (with-syntax ((next next)
(car-vars (car vars)))
(syntax (let ((val car-vars)) next)))
next-doms)
(append lifts-doms lift)
(append superlifts-doms superlift)
(append partials-doms partial)
(append this-stronger-ribs stronger-ribs)
(and chaperone? this-chaperone?)))]))]
[(next-rngs lifts-rngs superlifts-rngs partials-rngs stronger-ribs-rng rngs-chaperone?)
(let loop ([vars rng-vars]
[rngs rngs]
[next-rngs null]
[lifts-rngs null]
[superlifts-rngs null]
[partials-rngs null]
[stronger-ribs null]
[chaperone? #t])
(cond
[(null? rngs) (values (reverse next-rngs)
lifts-rngs
superlifts-rngs
partials-rngs
stronger-ribs
chaperone?)]
[else
(let-values ([(next lift superlift partial _ __ this-stronger-ribs this-chaperone?)
(opt/i opt/info (car rngs))])
(loop (cdr vars)
(cdr rngs)
(cons (with-syntax ((next next)
(car-vars (car vars)))
(syntax (let ((val car-vars)) next)))
next-rngs)
(append lifts-rngs lift)
(append superlifts-rngs superlift)
(append partials-rngs partial)
(append this-stronger-ribs stronger-ribs)
(and this-chaperone? chaperone?)))]))])
(values
(with-syntax ((blame (opt/info-blame opt/info))
((dom-arg ...) dom-vars)
((rng-arg ...) rng-vars)
((next-dom ...) next-doms)
(dom-len (length dom-vars))
((next-rng ...) next-rngs))
(syntax (begin
(check-procedure val dom-len 0 '() '() #| keywords |# blame)
(λ (dom-arg ...)
(let-values ([(rng-arg ...) (val next-dom ...)])
(values next-rng ...))))))
(append lifts-doms lifts-rngs)
(append superlifts-doms superlifts-rngs)
(append partials-doms partials-rngs)
#f
#f
(append stronger-ribs-dom stronger-ribs-rng)
(and rngs-chaperone? doms-chaperone?))))
(define (opt/arrow-any-ctc doms)
(let*-values ([(dom-vars) (generate-temporaries doms)]
[(next-doms lifts-doms superlifts-doms partials-doms stronger-ribs-dom doms-chaperone?)
(let loop ([vars dom-vars]
[doms doms]
[next-doms null]
[lifts-doms null]
[superlifts-doms null]
[partials-doms null]
[stronger-ribs null]
[chaperone? #t])
(cond
[(null? doms) (values (reverse next-doms)
lifts-doms
superlifts-doms
partials-doms
stronger-ribs
chaperone?)]
[else
(let-values ([(next lift superlift partial flat _ this-stronger-ribs this-chaperone?)
(opt/i (opt/info-swap-blame opt/info) (car doms))])
(loop (cdr vars)
(cdr doms)
(cons (with-syntax ((next next)
(car-vars (car vars)))
(syntax (let ((val car-vars)) next)))
next-doms)
(append lifts-doms lift)
(append superlifts-doms superlift)
(append partials-doms partial)
(append this-stronger-ribs stronger-ribs)
(and chaperone? this-chaperone?)))]))])
(values
(with-syntax ((blame (opt/info-blame opt/info))
((dom-arg ...) dom-vars)
((next-dom ...) next-doms)
(dom-len (length dom-vars)))
(syntax (begin
(check-procedure val dom-len 0 '() '() #|keywords|# blame)
(λ (dom-arg ...)
(val next-dom ...)))))
lifts-doms
superlifts-doms
partials-doms
#f
#f
stronger-ribs-dom
doms-chaperone?)))
(syntax-case* stx (-> values any) module-or-top-identifier=?
[(-> dom ... (values rng ...))
(if (ormap (λ (x) (keyword? (syntax-e x))) (syntax->list #'(dom ...)))
(opt/unknown opt/i opt/info stx) ;; give up if there is a mandatory keyword
(opt/arrow-ctc (syntax->list (syntax (dom ...)))
(syntax->list (syntax (rng ...)))))]
[(-> dom ... any)
(if (ormap (λ (x) (keyword? (syntax-e x))) (syntax->list #'(dom ...)))
(opt/unknown opt/i opt/info stx) ;; give up if there is a mandatory keyword
(opt/arrow-any-ctc (syntax->list (syntax (dom ...)))))]
[(-> dom ... rng)
(if (ormap (λ (x) (keyword? (syntax-e x))) (syntax->list #'(dom ...)))
(opt/unknown opt/i opt/info stx) ;; give up if there is a mandatory keyword
(opt/arrow-ctc (syntax->list (syntax (dom ...)))
(list #'rng)))]))

View File

@ -12,20 +12,21 @@
;;
(define-for-syntax (opt/pred opt/info pred)
(with-syntax ((pred pred))
(values
(build-optres
#:exp
(with-syntax ((val (opt/info-val opt/info))
(ctc (opt/info-contract opt/info))
(blame (opt/info-blame opt/info)))
(syntax (if (pred val)
val
(raise-opt/pred-error blame val 'pred))))
null
null
null
(syntax (pred val))
#f
null
#t)))
#:lifts null
#:superlifts null
#:partials null
#:flat (syntax (pred val))
#:opt #f
#:stronger-ribs null
#:chaperone #t)))
(define (raise-opt/pred-error blame val pred-name)
(raise-blame-error
@ -52,15 +53,15 @@
;;
(define/opter (any/c opt/i opt/info stx)
(syntax-case stx (any/c)
[any/c (values
(opt/info-val opt/info)
null
null
null
#'#t
#f
null
#t)]))
[any/c
(build-optres #:exp (opt/info-val opt/info)
#:lifts null
#:superlifts null
#:partials null
#:flat #'#t
#:opt #f
#:stronger-ribs null
#:chaperone #t)]))
;;
;; false/c
@ -86,8 +87,8 @@
(ctc (opt/info-contract opt/info))
(blame (opt/info-blame opt/info))
(lift-pred lift-pred))
(values
(syntax (if (lift-pred val)
(build-optres
#:exp (syntax (if (lift-pred val)
val
(raise-blame-error
blame
@ -96,16 +97,17 @@
(contract-name ctc)
(given/produced blame)
val)))
#:lifts
(interleave-lifts
lift-vars
(list #'pred (cond [(eq? checker 'check-flat-contract) #'(check-flat-contract lift-pred)]
[(eq? checker 'check-flat-named-contract) #'(check-flat-named-contract lift-pred)])))
null
null
(syntax (lift-pred val))
#f
null
#t)))]))
#:superlifts null
#:partials null
#:flat (syntax (lift-pred val))
#:opt #f
#:stronger-ribs null
#:chaperone #t)))]))
;;
;; flat-contract and friends

View File

@ -147,15 +147,15 @@ which are then called when the contract's fields are explored
(and (identifier? #'f)
(opt/info-recf opt/info)
(free-identifier=? (opt/info-recf opt/info) #'f))
(values
#`(f #,id arg ...)
null
null
null
#f
#f
null
#f)]
(build-optres
#:exp #`(f #,id arg ...)
#:lifts null
#:superlifts null
#:partials null
#:flat #f
#:opt #f
#:stronger-ribs null
#:chaperone #f)]
[else (opt/i (opt/info-change-val id opt/info)
stx)]))
@ -193,8 +193,7 @@ which are then called when the contract's fields are explored
[(id (x ...) ctc-exp)
(and (identifier? (syntax id))
(andmap identifier? (syntax->list (syntax (x ...)))))
(let*-values ([(next lifts superlifts partials _ _2 _3 chaperone?)
(opt/enforcer-clause let-var (syntax ctc-exp))]
(let*-values ([(an-optres) (opt/enforcer-clause let-var (syntax ctc-exp))]
[(maker-arg)
(with-syntax ([val (opt/info-val opt/info)]
[(new-let-bindings ...)
@ -204,11 +203,12 @@ which are then called when the contract's fields are explored
arglist)])
#`(#,let-var
#,(bind-lifts
superlifts
(optres-superlifts an-optres)
#`(let (new-let-bindings ...)
#,(bind-lifts
(append lifts partials)
next)))))])
(append (optres-lifts an-optres)
(optres-partials an-optres))
(optres-exp an-optres))))))])
(loop (cdr clauses)
(cdr let-vars)
(cdr arglists)
@ -227,23 +227,22 @@ which are then called when the contract's fields are explored
(syntax->list (syntax (x ...)))))]
[(id ctc-exp)
(identifier? (syntax id))
(let*-values ([(next lifts superlifts partials _ __ stronger-ribs chaperone?)
(opt/enforcer-clause let-var (syntax ctc-exp))]
(let*-values ([(an-optres) (opt/enforcer-clause let-var (syntax ctc-exp))]
[(maker-arg)
(with-syntax ((val (opt/info-val opt/info)))
#`(#,let-var
#,(bind-lifts
partials
next)))])
(optres-partials an-optres)
(optres-exp an-optres))))])
(loop (cdr clauses)
(cdr let-vars)
(cdr arglists)
(cdr ac-ids)
(cons (car ac-ids) prior-ac-ids)
(cons maker-arg maker-args)
(append lifts-ps lifts)
(append superlifts-ps superlifts)
(append stronger-ribs-ps stronger-ribs)))]
(append lifts-ps (optres-lifts an-optres))
(append superlifts-ps (optres-superlifts an-optres))
(append stronger-ribs-ps (optres-stronger-ribs an-optres))))]
[(id ctc-exp)
(raise-syntax-error name "expected identifier" stx (syntax id))]))]))))

View File

@ -427,7 +427,8 @@ it around flattened out.
(cons contract/info-var
(syntax
(make-opt-contract/info ctc enforcer-id id))))])
(values
(build-optres
#:exp
(syntax
(cond
[(opt-wrap-predicate val)
@ -462,15 +463,13 @@ it around flattened out.
(contract-name ctc)
(given/produced blame)
val)]))
lifts
superlifts
partials
#f
#f
stronger-ribs
;; opt'd struct contracts don't use chaperones yet
#f)))))))]))
)))))
#:lifts lifts
#:superlifts superlifts
#:partials partials
#:flat #f
#:opt #f
#:stronger-ribs stronger-ribs
#:chaperone #f)))))))])))))))
(define-syntax (define-contract-struct stx)
(syntax-case stx ()

View File

@ -23,7 +23,81 @@
opt/info-change-val
opt/unknown
combine-two-chaperone?s)
combine-two-chaperone?s
optres-exp
optres-lifts
optres-superlifts
optres-partials
optres-flat
optres-opt
optres-stronger-ribs
optres-chaperone
build-optres)
;; (define/opter (<contract-combinator> opt/i opt/info stx) body)
;;
;; An opter is to a function with the following signature:
;;
;; opter : (syntax opt/info -> <opter-results>) opt/info list-of-ids -> opt-res
;;
;; The first argument can be used to recursively process sub-contracts
;; It returns what an opter returns and its results should be accumulated
;; into the opter's results.
;;
;; The opt/info struct has a number of identifiers that get used to build
;; contracts; see opt-guts.rkt for the selectors.
;;
;; The last argument is a list of free-variables if the calling context
;; was define/opt, otherwise it is null.
;;
;; The fields of the optres struct are:
;; - the optimized syntax
;; - lifted variables: a list of (id, sexp) pairs
;; - super-lifted variables: functions or the such defined at the toplevel of the
;; calling context of the opt routine.
;; Currently this is only used for struct contracts.
;; - partially applied contracts: a list of (id, sexp) pairs
;; - if the contract being optimized is flat,
;; then an sexp that evals to bool, indicating if the contract passed or not,
;; else #f
;; This is used in conjunction with optimizing flat contracts into one boolean
;; expression when optimizing or/c.
;; - if the contract can be optimized,
;; then #f (that is, it is not unknown)
;; else the symbol of the lifted variable
;; This is used for contracts with subcontracts (like cons) doing checks.
;; - a list of stronger-ribs
;; - a boolean or a syntax object; if it is a boolean,
;; the boolean indicaties if this contract is a chaperone contract
;; if it is a syntax object, then evaluating its contents determines
;; if this is a chaperone contract
(struct optres (exp
lifts
superlifts
partials
flat
opt
stronger-ribs
chaperone))
(define (build-optres #:exp exp
#:lifts lifts
#:superlifts superlifts
#:partials partials
#:flat flat
#:opt opt
#:stronger-ribs stronger-ribs
#:chaperone chaperone)
(optres exp
lifts
superlifts
partials
flat
opt
stronger-ribs
chaperone))
;; a hash table of opters
(define opters-table
@ -169,7 +243,7 @@
[val (opt/info-val opt/info)]
[uctc uctc]
[blame (opt/info-blame opt/info)])
(values
(optres
#'(partial-var val)
(list (cons #'lift-var
#'(coerce-contract 'opt/c uctc)))
@ -200,4 +274,3 @@
(and chaperone-b? chaperone-a?)]
[else
#`(and #,chaperone-a? #,chaperone-b?)]))

View File

@ -11,45 +11,6 @@
opt/direct
begin-lifted)
;; (define/opter (<contract-combinator> opt/i opt/info stx) body)
;;
;; An opter is to a function with the following signature:
;;
;; opter : (syntax opt/info -> <opter-results>) opt/info list-of-ids ->
;; (values syntax syntax-list syntax-list
;; syntax-list (union syntax #f) (union syntax #f) syntax)
;;
;; The first argument can be used to recursively process sub-contracts
;; It returns what an opter returns and its results should be accumulated
;; into the opter's results.
;;
;; The opt/info struct has a number of identifiers that get used to build
;; contracts; see opt-guts.rkt for the selectors.
;;
;; The last argument is a list of free-variables if the calling context
;; was define/opt otherwise it is null.
;;
;; Every opter needs to return:
;; - the optimized syntax
;; - lifted variables: a list of (id, sexp) pairs
;; - super-lifted variables: functions or the such defined at the toplevel of the
;; calling context of the opt routine.
;; Currently this is only used for struct contracts.
;; - partially applied contracts: a list of (id, sexp) pairs
;; - if the contract being optimized is flat,
;; then an sexp that evals to bool,
;; else #f
;; This is used in conjunction with optimizing flat contracts into one boolean
;; expression when optimizing or/c.
;; - if the contract can be optimized,
;; then #f (that is, it is not unknown)
;; else the symbol of the lifted variable
;; This is used for contracts with subcontracts (like cons) doing checks.
;; - a list of stronger-ribs
;; - a boolean or a syntax object; if it is a boolean,
;; the boolean indicaties if this contract is a chaperone contract
;; if it is a syntax object, then evaluating its contents determines
;; if this is a chaperone contract
(define-syntax (define/opter stx)
(syntax-case stx ()
[(_ (for opt/i opt/info stx) expr ...)
@ -66,23 +27,20 @@
;;
;; opt/recursive-call
;;
;; BUG: currently does not try to optimize the arguments, this requires changing
;; every opter to keep track of bound variables.
;;
(define-for-syntax (opt/recursive-call opt/info stx)
(values
(with-syntax ((stx stx)
(build-optres
#:exp (with-syntax ((stx stx)
(val (opt/info-val opt/info))
(blame (opt/info-blame opt/info)))
(syntax (let ((ctc stx))
(((contract-projection ctc) blame) val))))
null
null
null
#f
#f
null
null))
#:lifts null
#:superlifts null
#:partials null
#:flat #f
#:opt #f
#:stronger-ribs null
#:chaperone null))
;; make-stronger : list-of-(union syntax #f) -> syntax
(define-for-syntax (make-stronger strongers)
@ -122,17 +80,18 @@
[(number? konst)
(values #`(and (number? #,v) (= #,konst #,v))
"=")]))
(values
(build-optres
#:exp
#`(if #,predicate
#,v
(opt-constant-contract-failure #,(opt/info-blame opt/info) #,v #,word #,konst))
null
null
null
predicate
#f
null
#t))
#:lifts null
#:superlifts null
#:partials null
#:flat predicate
#:opt #f
#:stronger-ribs null
#:chaperone #t))
(define (opt-constant-contract-failure blame val compare should-be)
(raise-blame-error blame val "expected a value ~a to ~e" compare should-be))
@ -144,7 +103,7 @@
;; opt/i : id opt/info syntax ->
;; syntax syntax-list syntax-list (union syntax #f) (union syntax #f)
(define-for-syntax (opt/i opt/info stx)
;; the case dispatch here must match what top-level-unknown? is doing
;; te case dispatch here must match what top-level-unknown? is doing
(syntax-case stx ()
[(ctc arg ...)
(and (identifier? #'ctc) (opter #'ctc))
@ -155,19 +114,20 @@
[(f arg ...)
(and (identifier? #'f)
(define-opt/recursive-fn? (syntax-local-value #'f (λ () #f))))
(values
(build-optres
#:exp
#`(#,(define-opt/recursive-fn-internal-fn (syntax-local-value #'f))
#,(opt/info-contract opt/info)
#,(opt/info-blame opt/info)
#,(opt/info-val opt/info)
arg ...)
null
null
null
#f
#f
null
#t)]
#:lifts null
#:superlifts null
#:partials null
#:flat #f
#:opt #f
#:stronger-ribs null
#:chaperone #t)]
[konst
(coerecable-constant? #'konst)
(opt-constant-contract (syntax->datum #'konst) opt/info)]
@ -201,32 +161,24 @@
(define-syntax (opt/c stx)
(syntax-case stx ()
[(_ e)
(let*-values ([(info) (make-opt/info #'ctc
#'val
#'blame
#f
'()
#f
#f
#'this
#'that)]
[(next lifts superlifts partials _ __ stronger-ribs chaperone?) (opt/i info #'e)])
(with-syntax ([next next])
(let ()
(define info (make-opt/info #'ctc #'val #'blame #f '() #f #f #'this #'that))
(define an-optres (opt/i info #'e))
(bind-superlifts
superlifts
(optres-superlifts an-optres)
(bind-lifts
lifts
(optres-lifts an-optres)
#`(make-opt-contract
(λ (ctc)
(λ (blame)
#,(bind-superlifts
partials
#`(λ (val) next))))
(optres-partials an-optres)
#`(λ (val) #,(optres-exp an-optres)))))
(λ () e)
(λ (this that) #f)
(vector)
(begin-lifted (box #f))
#,chaperone?)))))]))
#,(optres-chaperone an-optres)))))]))
;; this macro optimizes 'e' as a contract,
;; using otherwise-id if it does not recognize 'e'.
@ -234,28 +186,21 @@
(syntax-case stx ()
[(_ e val-e blame-e otherwise-id)
(identifier? #'otherwise-id)
(if (top-level-unknown? #'e)
#'(otherwise-id e val-e blame-e)
(let*-values ([(info) (make-opt/info #'ctc
#'val
#'blame
#f
'()
#f
#f
#'this
#'that)]
[(next lifts superlifts partials _ __ stronger-ribs) (opt/i info #'e)])
(cond
[(top-level-unknown? #'e) #'(otherwise-id e val-e blame-e)]
[else
(define info (make-opt/info #'ctc #'val #'blame #f '() #f #f #'this #'that))
(define an-optres (opt/i info #'e))
#`(let ([ctc e] ;;; hm... what to do about this?!
[val val-e]
[blame blame-e])
#,(bind-superlifts
superlifts
(optres-superlifts an-optres)
(bind-lifts
lifts
(optres-lifts an-optres)
(bind-superlifts
partials
next))))))]))
(optres-partials an-optres)
(optres-exp an-optres)))))])]))
(define-syntax (begin-lifted stx)
(syntax-case stx ()
@ -285,31 +230,23 @@
(define-syntax (opt/c-helper stx)
(syntax-case stx ()
[(_ f1 f2 (id args ...) e)
(let*-values ([(info) (make-opt/info #'ctc
#'val
#'blame
#f
(syntax->list #'(args ...))
#f
#f
#'this
#'that)]
[(next lifts superlifts partials _ __ stronger-ribs chaperone?) (opt/i info #'e)])
(with-syntax ([next next])
(let ()
(define info (make-opt/info #'ctc #'val #'blame #f (syntax->list #'(args ...)) #f #f #'this #'that))
(define an-optres (opt/i info #'e))
#`(let ()
(define (f2 ctc blame val args ...)
#,(bind-superlifts
superlifts
(optres-superlifts an-optres)
(bind-lifts
lifts
(optres-lifts an-optres)
(bind-superlifts
partials
#'next))))
(optres-partials an-optres)
(optres-exp an-optres)))))
(define (f1 args ...)
#,(bind-superlifts
superlifts
(optres-superlifts an-optres)
(bind-lifts
lifts
(optres-lifts an-optres)
#`(make-opt-contract
(λ (ctc)
(λ (blame)
@ -319,8 +256,8 @@
(λ (this that) #f)
(vector)
(begin-lifted (box #f))
#,chaperone?))))
(values f1 f2))))]))
#,(optres-chaperone an-optres)))))
(values f1 f2)))]))
;; optimized contracts
;;

View File

@ -18,24 +18,18 @@
(partial-var (car (generate-temporaries (syntax (partial))))))
(values
(with-syntax ((partial-var partial-var)
(lift-var lift-var)
(uctc uctc)
(val (opt/info-val opt/info)))
(syntax (partial-var val)))
(list (cons lift-var
;; FIXME needs to get the contract name somehow
(with-syntax ((uctc uctc))
(syntax (coerce-contract 'opt/c uctc)))))
null
'()
(list (cons
partial-var
(with-syntax ((lift-var lift-var)
(blame (opt/info-blame opt/info)))
(syntax ((contract-projection lift-var) blame)))))
#f
lift-var
(list #f)
null)))
(syntax ((contract-projection lift-var) blame))))))))
(define (opt/or-ctc ps)
(let ((lift-from-hos null)
@ -61,28 +55,27 @@
ho-ctc
chaperone?)]
[else
(let-values ([(next lift superlift partial flat _ this-stronger-ribs this-chaperone?)
(opt/i opt/info (car ps))])
(if flat
(define ps-optres (opt/i opt/info (car ps)))
(if (optres-flat ps-optres)
(loop (cdr ps)
(cons flat next-ps)
(append lift-ps lift)
(append superlift-ps superlift)
(append partial-ps partial)
(append this-stronger-ribs stronger-ribs)
(cons (optres-flat ps-optres) next-ps)
(append lift-ps (optres-lifts ps-optres))
(append superlift-ps (optres-superlifts ps-optres))
(append partial-ps (optres-partials ps-optres))
(append (optres-stronger-ribs ps-optres) stronger-ribs)
hos
ho-ctc
(combine-two-chaperone?s chaperone? this-chaperone?))
(combine-two-chaperone?s chaperone? (optres-chaperone ps-optres)))
(if (< (length hos) 1)
(loop (cdr ps)
next-ps
(append lift-ps lift)
(append superlift-ps superlift)
(append partial-ps partial)
(append this-stronger-ribs stronger-ribs)
(append lift-ps (optres-lifts ps-optres))
(append superlift-ps (optres-superlifts ps-optres))
(append partial-ps (optres-partials ps-optres))
(append (optres-stronger-ribs ps-optres) stronger-ribs)
(cons (car ps) hos)
next
(combine-two-chaperone?s chaperone? this-chaperone?))
(optres-exp ps-optres)
(combine-two-chaperone?s chaperone? (optres-chaperone ps-optres)))
(loop (cdr ps)
next-ps
lift-ps
@ -91,11 +84,12 @@
stronger-ribs
(cons (car ps) hos)
ho-ctc
chaperone?))))]))])
chaperone?)))]))])
(with-syntax ((next-ps
(with-syntax (((opt-p ...) (reverse opt-ps)))
(syntax (or opt-p ...)))))
(values
(build-optres
#:exp
(cond
[(null? hos)
(with-syntax ([val (opt/info-val opt/info)]
@ -113,21 +107,22 @@
(if next-ps val ho-ctc)))]
;; FIXME something's not right with this case.
[(> (length hos) 1)
(let-values ([(next-hos lift-hos superlift-hos partial-hos _ __ stronger-hos stronger-vars-hos)
(opt/or-unknown stx)])
(set! lift-from-hos lift-hos)
(set! superlift-from-hos superlift-hos)
(set! partial-from-hos partial-hos)
(with-syntax ((next-hos next-hos))
(syntax
(if next-ps val next-hos))))])
(define-values (exp new-lifts new-superlifts new-partials) (opt/or-unknown stx))
(set! lift-from-hos new-lifts)
(set! superlift-from-hos new-superlifts)
(set! partial-from-hos new-partials)
#`(if next-ps val #,exp)])
#:lifts
(append lift-ps lift-from-hos)
#:superlifts
(append superlift-ps superlift-from-hos)
#:partials
(append partial-ps partial-from-hos)
#:flat
(if (null? hos) (syntax next-ps) #f)
#f
stronger-ribs
chaperone?)))))
#:opt #f
#:stronger-ribs stronger-ribs
#:chaperone chaperone?)))))
(syntax-case stx (or/c)
[(or/c p ...)
@ -152,16 +147,18 @@
(blame (opt/info-blame opt/info))
(this (opt/info-this opt/info))
(that (opt/info-that opt/info)))
(values
(build-optres
#:exp
(syntax (if (and (number? val) (<= n val m))
val
(raise-opt-between/c-error
blame val n m)))
lifts3
null
null
(syntax (and (number? val) (<= n val m)))
#f
#:lifts lifts3
#:superlifts null
#:partials null
#:flat (syntax (and (number? val) (<= n val m)))
#:opt #f
#:stronger-ribs
(list (new-stronger-var
lift-low
(λ (this that)
@ -174,6 +171,7 @@
(with-syntax ([this this]
[that that])
(syntax (<= this that))))))
#:chaperone
#t)))))]))
(define (raise-opt-between/c-error blame val lo hi)
@ -195,23 +193,25 @@
(blame (opt/info-blame opt/info))
(this (opt/info-this opt/info))
(that (opt/info-that opt/info)))
(values
(build-optres
#:exp
(syntax
(if (and (real? val) (comparison val m))
val
(raise-opt-single-comparison-opter-error blame val comparison m)))
lifts3
null
null
(syntax (and (number? val) (comparison val m)))
#f
#:lifts lifts3
#:superlifts null
#:partials null
#:flat (syntax (and (number? val) (comparison val m)))
#:opt #f
#:stronger-ribs
(list (new-stronger-var
lift-low
(λ (this that)
(with-syntax ([this this]
[that that])
(syntax (comparison this that))))))
#t)))))))
#:chaperone #t)))))))
(define (raise-opt-single-comparison-opter-error blame val comparison m)
(raise-blame-error
@ -286,18 +286,17 @@
(define/opter (cons/c opt/i opt/info stx)
(define (opt/cons-ctc hdp tlp)
(let-values ([(next-hdp lifts-hdp superlifts-hdp partials-hdp flat-hdp unknown-hdp stronger-ribs-hd hd-chaperone?)
(opt/i opt/info hdp)]
[(next-tlp lifts-tlp superlifts-tlp partials-tlp flat-tlp unknown-tlp stronger-ribs-tl tl-chaperone?)
(opt/i opt/info tlp)])
(define optres-hd (opt/i opt/info hdp))
(define optres-tl (opt/i opt/info tlp))
(with-syntax ((check (with-syntax ((val (opt/info-val opt/info)))
(syntax (pair? val)))))
(values
(build-optres
#:exp
(with-syntax ((val (opt/info-val opt/info))
(ctc (opt/info-contract opt/info))
(blame (opt/info-blame opt/info))
(next-hdp next-hdp)
(next-tlp next-tlp))
(next-hdp (optres-exp optres-hd))
(next-tlp (optres-exp optres-tl)))
(syntax (if check
(cons (let ((val (car val))) next-hdp)
(let ((val (cdr val))) next-tlp))
@ -308,36 +307,42 @@
(contract-name ctc)
(given/produced blame)
val))))
(append lifts-hdp lifts-tlp)
(append superlifts-hdp superlifts-tlp)
(append partials-hdp partials-tlp)
(if (and flat-hdp flat-tlp)
#:lifts
(append (optres-lifts optres-hd) (optres-lifts optres-tl))
#:superlifts
(append (optres-superlifts optres-hd) (optres-superlifts optres-tl))
#:partials
(append (optres-partials optres-hd) (optres-partials optres-tl))
#:flat
(if (and (optres-flat optres-hd) (optres-flat optres-tl))
(with-syntax ((val (opt/info-val opt/info))
(flat-hdp flat-hdp)
(flat-tlp flat-tlp))
(flat-hdp (optres-flat optres-hd))
(flat-tlp (optres-flat optres-tl)))
(syntax (and check
(let ((val (car val))) flat-hdp)
(let ((val (cdr val))) flat-tlp))))
#f)
#f
(append stronger-ribs-hd stronger-ribs-tl)
(combine-two-chaperone?s hd-chaperone? tl-chaperone?)))))
#:opt #f
#:stronger-ribs
(append (optres-stronger-ribs optres-hd) (optres-stronger-ribs optres-tl))
#:chaperone
(combine-two-chaperone?s (optres-chaperone optres-hd) (optres-chaperone optres-tl)))))
(syntax-case stx (cons/c)
[(_ hdp tlp) (opt/cons-ctc #'hdp #'tlp)]))
(define-for-syntax (opt/listof-ctc content non-empty? opt/i opt/info)
(let-values ([(next lifts superlifts partials flat unknown stronger-ribs chaperone?)
(opt/i opt/info content)])
(define optres-ele (opt/i opt/info content))
(with-syntax ([check (with-syntax ((val (opt/info-val opt/info)))
(if non-empty?
#'(and (list? val) (pair? val))
#'(list? val)))]
[val (opt/info-val opt/info)])
(values
(build-optres
#:exp
(with-syntax ([blame (opt/info-blame opt/info)]
[next next])
[next (optres-exp optres-ele)])
(with-syntax ([(non-empty-check ...) (if non-empty?
(list #'(pair? val))
(list))])
@ -350,12 +355,13 @@
#,(if non-empty?
"expected a non-empty list"
"expected a list")))))
lifts
superlifts
partials
(if flat
#:lifts (optres-lifts optres-ele)
#:superlifts (optres-superlifts optres-ele)
#:partials (optres-partials optres-ele)
#:flat
(if (optres-flat optres-ele)
(with-syntax ((val (opt/info-val opt/info))
(flat flat))
(flat (optres-flat optres-ele)))
#`(and check
#,@(if non-empty? (list #'(pair? val)) '())
(let loop ([lst val])
@ -366,9 +372,9 @@
(and flat
(loop (cdr lst))))]))))
#f)
#f
stronger-ribs
chaperone?))))
#:opt #f
#:stronger-ribs (optres-stronger-ribs optres-ele)
#:chaperone (optres-chaperone optres-ele))))
(define/opter (listof opt/i opt/info stx)
(syntax-case stx ()
@ -403,20 +409,19 @@
stronger-ribs
chaperone?)]
[else
(let-values ([(next lift superlift partial _ __ this-stronger-ribs this-chaperone?)
(opt/i (opt/info-swap-blame opt/info) (car doms))])
(define optres-dom (opt/i (opt/info-swap-blame opt/info) (car doms)))
(loop (cdr vars)
(cdr doms)
(cons (with-syntax ((next next)
(cons (with-syntax ((next (optres-exp optres-dom))
(car-vars (car vars))
(val (opt/info-val opt/info)))
(syntax (let ((val car-vars)) next)))
next-doms)
(append lifts-doms lift)
(append superlifts-doms superlift)
(append partials-doms partial)
(append this-stronger-ribs stronger-ribs)
(combine-two-chaperone?s chaperone? this-chaperone?)))]))]
(append lifts-doms (optres-lifts optres-dom))
(append superlifts-doms (optres-superlifts optres-dom))
(append partials-doms (optres-partials optres-dom))
(append (optres-stronger-ribs optres-dom) stronger-ribs)
(combine-two-chaperone?s chaperone? (optres-chaperone optres-dom)))]))]
[(next-rngs lifts-rngs superlifts-rngs partials-rngs stronger-ribs-rng rng-chaperone?)
(let loop ([vars rng-vars]
[rngs rngs]
@ -434,20 +439,19 @@
stronger-ribs
chaperone?)]
[else
(let-values ([(next lift superlift partial _ __ this-stronger-ribs this-chaperone?)
(opt/i opt/info (car rngs))])
(define optres-rng (opt/i opt/info (car rngs)))
(loop (cdr vars)
(cdr rngs)
(cons (with-syntax ((next next)
(cons (with-syntax ((next (optres-exp optres-rng))
(car-vars (car vars))
(val (opt/info-val opt/info)))
(syntax (let ((val car-vars)) next)))
next-rngs)
(append lifts-rngs lift)
(append superlifts-rngs superlift)
(append partials-rngs partial)
(append this-stronger-ribs stronger-ribs)
(combine-two-chaperone?s chaperone? this-chaperone?)))]))])
(append lifts-rngs (optres-lifts optres-rng))
(append superlifts-rngs (optres-superlifts optres-rng))
(append partials-rngs (optres-partials optres-rng))
(append (optres-stronger-ribs optres-rng) stronger-ribs)
(combine-two-chaperone?s chaperone? (optres-chaperone optres-rng)))]))])
(values
(with-syntax ((val (opt/info-val opt/info))
(blame (opt/info-blame opt/info))
@ -499,19 +503,16 @@
stronger-ribs
chaperone?)]
[else
(let-values ([(next lift superlift partial flat _ this-stronger-ribs this-chaperone?)
(opt/i (opt/info-swap-blame opt/info) (car doms))])
(define optres-dom (opt/i (opt/info-swap-blame opt/info) (car doms)))
(loop (cdr vars)
(cdr doms)
(cons (with-syntax ((next next)
(car-vars (car vars)))
(syntax (let ((val car-vars)) next)))
(cons #`(let ([#,(opt/info-val opt/info) #,(car vars)]) #,(optres-exp optres-dom))
next-doms)
(append lifts-doms lift)
(append superlifts-doms superlift)
(append partials-doms partial)
(append this-stronger-ribs stronger-ribs)
(combine-two-chaperone?s chaperone? this-chaperone?)))]))])
(append lifts-doms (optres-lifts optres-dom))
(append superlifts-doms (optres-superlifts optres-dom))
(append partials-doms (optres-partials optres-dom))
(append (optres-stronger-ribs optres-dom) stronger-ribs)
(combine-two-chaperone?s chaperone? (optres-chaperone optres-dom)))]))])
(values
(with-syntax ((blame (opt/info-blame opt/info))
((dom-arg ...) dom-vars)
@ -536,45 +537,49 @@
(syntax-case* stx (-> values any any/c) module-or-top-identifier=?
[(-> any/c ... any)
(with-syntax ([n (- (length (syntax->list stx)) 2)])
(values
(build-optres
#:exp
(with-syntax ((val (opt/info-val opt/info))
(ctc (opt/info-contract opt/info))
(blame (opt/info-blame opt/info)))
(syntax (if (procedure-arity-includes? val n)
val
(raise-flat-arrow-err blame val n))))
null
null
null
#'(procedure-arity-includes? val n)
#f
null
#t))]
#:lifts null
#:superlifts null
#:partials null
#:flat #'(procedure-arity-includes? val n)
#:opt #f
#:stronger-ribs null
#:chaperone #t))]
[(-> dom ... (values rng ...))
(if (ormap (λ (x) (keyword? (syntax-e x))) (syntax->list #'(dom ...)))
(opt/unknown opt/i opt/info stx) ;; give up if there is a mandatory keyword
(let-values ([(next lift superlift partial flat _ stronger-ribs chaperone?)
(let-values ([(next lift superlift partial flat opt stronger-ribs chaperone?)
(opt/arrow-ctc (syntax->list (syntax (dom ...)))
(syntax->list (syntax (rng ...))))])
(if (eq? chaperone? #t)
(values next lift superlift partial flat _ stronger-ribs chaperone?)
(build-optres #:exp next #:lifts lift #:superlifts superlift #:partials partial
#:flat flat #:opt opt #:stronger-ribs stronger-ribs #:chaperone chaperone?)
(opt/unknown opt/i opt/info stx))))]
[(-> dom ... any)
(if (ormap (λ (x) (keyword? (syntax-e x))) (syntax->list #'(dom ...)))
(opt/unknown opt/i opt/info stx) ;; give up if there is a mandatory keyword
(let-values ([(next lift superlift partial flat _ stronger-ribs chaperone?)
(let-values ([(next lift superlift partial flat opt stronger-ribs chaperone?)
(opt/arrow-any-ctc (syntax->list (syntax (dom ...))))])
(if (eq? chaperone? #t)
(values next lift superlift partial flat _ stronger-ribs chaperone?)
(build-optres #:exp next #:lifts lift #:superlifts superlift #:partials partial
#:flat flat #:opt opt #:stronger-ribs stronger-ribs #:chaperone chaperone?)
(opt/unknown opt/i opt/info stx))))]
[(-> dom ... rng)
(if (ormap (λ (x) (keyword? (syntax-e x))) (syntax->list #'(dom ...)))
(opt/unknown opt/i opt/info stx) ;; give up if there is a mandatory keyword
(let-values ([(next lift superlift partial flat _ stronger-ribs chaperone?)
(let-values ([(next lift superlift partial flat opt stronger-ribs chaperone?)
(opt/arrow-ctc (syntax->list (syntax (dom ...)))
(list #'rng))])
(if (eq? chaperone? #t)
(values next lift superlift partial flat _ stronger-ribs chaperone?)
(build-optres #:exp next #:lifts lift #:superlifts superlift #:partials partial
#:flat flat #:opt opt #:stronger-ribs stronger-ribs #:chaperone chaperone?)
(opt/unknown opt/i opt/info stx))))]))
(define (raise-flat-arrow-err blame val n)

View File

@ -795,17 +795,12 @@
(define sub-val (car (generate-temporaries '(struct/dc))))
(define-values (this-code
this-lifts this-super-lifts this-partially-applied
this-flat? this-can-be-optimized? this-stronger-ribs
this-chaperone?)
(opt/i (opt/info-change-val sub-val opt/info)
exp))
(define this-optres (opt/i (opt/info-change-val sub-val opt/info) exp))
(when dep-vars
(for ([dep-var (in-list (syntax->list dep-vars))])
(free-identifier-mapping-put! depended-on-fields dep-var #t)))
(free-identifier-mapping-put! flat-fields sel-id this-flat?)
(free-identifier-mapping-put! flat-fields sel-id (optres-flat this-optres))
(define this-body-code
(cond
@ -815,17 +810,17 @@
[(dep-var ...) dep-vars])
#`(let ([dep-var (sel #,(opt/info-val opt/info))] ...)
#,(bind-superlifts
this-super-lifts
(optres-superlifts this-optres)
(bind-lifts
this-lifts
(optres-lifts this-optres)
(bind-lifts
this-partially-applied
this-code)))))]
[else this-code]))
(optres-partials this-optres)
(optres-exp this-optres))))))]
[else (optres-exp this-optres)]))
(define this-chap-code
(and (or (not this-flat?)
(and (or (not (optres-flat this-optres))
lazy?)
(with-syntax ([proc-name (string->symbol
(format "~a-~a-chap"
@ -844,7 +839,7 @@
proc-name))))))
(define this-fo-code
(and (and this-flat?
(and (and (optres-flat this-optres)
(not lazy?))
#`(let ([#,sub-val
(#,(id->sel-id #'struct-id sel-id)
@ -857,12 +852,12 @@
(if this-chap-code
(list* this-chap-code (id->sel-id #'struct-id sel-id) s-chap-code)
s-chap-code)
(if dep-vars s-lifts (append this-lifts s-lifts))
(if dep-vars s-super-lifts (append this-super-lifts s-super-lifts))
(if dep-vars s-partially-applied (append this-partially-applied s-partially-applied))
(and this-can-be-optimized? can-be-optimized?)
(if dep-vars stronger-ribs (append this-stronger-ribs stronger-ribs))
(combine-two-chaperone?s chaperone? this-chaperone?))))
(if dep-vars s-lifts (append (optres-lifts this-optres) s-lifts))
(if dep-vars s-super-lifts (append (optres-superlifts this-optres) s-super-lifts))
(if dep-vars s-partially-applied (append (optres-partials this-optres) s-partially-applied))
(and (optres-opt this-optres) can-be-optimized?)
(if dep-vars stronger-ribs (append (optres-stronger-ribs this-optres) stronger-ribs))
(combine-two-chaperone?s chaperone? (optres-chaperone this-optres)))))
;; to avoid having to deal with indy-ness, just give up if any
;; of the fields that are depended on aren't flat
@ -879,7 +874,9 @@
[(free-var ...) (opt/info-free-vars opt/info)]
[(index ...) (build-list (length (opt/info-free-vars opt/info)) values)]
[pred? (list-ref info 2)])
(values (if (null? s-chap-code) ;; if this is #t, when we have to avoid putting the property on here.
(build-optres
#:exp
(if (null? s-chap-code) ;; if this is #t, when we have to avoid putting the property on here.
#`(if (pred? #,(opt/info-val opt/info))
(begin
#,@s-fo-code
@ -898,14 +895,16 @@
stronger-prop-desc
(vector free-var ...)))
(struct/dc-error blame #,(opt/info-val opt/info) 'struct-name))))
#:lifts
s-lifts
#:superlifts
s-super-lifts
#:partials
s-partially-applied
#f ;; flat sexp
can-be-optimized?
stronger-ribs
#t ;;chaperone?
))]))]))
#:flat #f
#:opt can-be-optimized?
#:stronger-ribs stronger-ribs
#:chaperone #t))]))]))
(define (struct/dc-error blame obj what)
(raise-blame-error blame obj