added in checking that dependent variables are all sensible
This commit is contained in:
parent
8b05829717
commit
9e92a976a7
|
@ -97,6 +97,15 @@ and then operates on it to generate the expanded form
|
||||||
(raise-syntax-error #f "dependent variable not bound"
|
(raise-syntax-error #f "dependent variable not bound"
|
||||||
stx var))))
|
stx var))))
|
||||||
|
|
||||||
|
;; not-range-bound : (listof identifier[used-by-an-arg]) -> void
|
||||||
|
(define (not-range-bound arg-vars)
|
||||||
|
(when (istx-ress istx)
|
||||||
|
(for ([arg-var (in-list arg-vars)])
|
||||||
|
(when (ormap (λ (a-res) (free-identifier=? (res-var a-res) arg-var))
|
||||||
|
(istx-ress istx))
|
||||||
|
(raise-syntax-error #f "an argument cannot depend on a result"
|
||||||
|
stx arg-var)))))
|
||||||
|
|
||||||
;; no dups in the domains
|
;; no dups in the domains
|
||||||
(for ([dom (in-list (istx-args istx))])
|
(for ([dom (in-list (istx-args istx))])
|
||||||
(when (arg-kwd dom)
|
(when (arg-kwd dom)
|
||||||
|
@ -126,10 +135,12 @@ and then operates on it to generate the expanded form
|
||||||
(no-var-dups (rst-var (istx-rst istx))))
|
(no-var-dups (rst-var (istx-rst istx))))
|
||||||
|
|
||||||
|
|
||||||
;; dependent arg variables are all bound.
|
;; dependent arg variables are all bound, but not to a range variable
|
||||||
(for ([an-arg (in-list (istx-args istx))])
|
(for ([an-arg (in-list (istx-args istx))])
|
||||||
(when (arg-vars an-arg)
|
(let ([a-vars (arg-vars an-arg)])
|
||||||
(ensure-bound (arg-vars an-arg))))
|
(when a-vars
|
||||||
|
(ensure-bound a-vars)
|
||||||
|
(not-range-bound a-vars))))
|
||||||
|
|
||||||
;; dependent range variables are all bound.
|
;; dependent range variables are all bound.
|
||||||
(when (istx-ress istx)
|
(when (istx-ress istx)
|
||||||
|
@ -138,39 +149,48 @@ and then operates on it to generate the expanded form
|
||||||
(ensure-bound (res-vars a-res)))))))
|
(ensure-bound (res-vars a-res)))))))
|
||||||
|
|
||||||
(define (ensure-no-cycles stx istx)
|
(define (ensure-no-cycles stx istx)
|
||||||
(let ([neighbors (make-hash)]
|
(let ([neighbors (make-free-identifier-mapping)]
|
||||||
[sp '()]
|
[safe (make-free-identifier-mapping)]
|
||||||
[safe (make-hash)]
|
[sp '()])
|
||||||
[vars->stx (make-hash)])
|
|
||||||
|
|
||||||
(define (link from to)
|
(define (link from to)
|
||||||
(printf "linking ~s => ~s\n" from to)
|
(printf "linking ~s => ~s\n" from to)
|
||||||
(set! sp (cons (syntax-e from) sp))
|
(set! sp (cons from sp))
|
||||||
(hash-set! vars->stx (syntax-e from) from)
|
(free-identifier-mapping-put!
|
||||||
(hash-set! neighbors (syntax-e from)
|
neighbors from
|
||||||
(cons (syntax-e to)
|
(cons to (free-identifier-mapping-get neighbors from (λ () '())))))
|
||||||
(hash-ref neighbors (syntax-e from) '()))))
|
|
||||||
|
(define (no-links from)
|
||||||
|
(printf "no links ~s\n" from)
|
||||||
|
(set! sp (cons from sp))
|
||||||
|
(free-identifier-mapping-put! neighbors from '()))
|
||||||
|
|
||||||
(for ([an-arg (in-list (istx-args istx))])
|
(for ([an-arg (in-list (istx-args istx))])
|
||||||
(when (arg-vars an-arg)
|
(cond
|
||||||
(for ([nvar (in-list (arg-vars an-arg))])
|
[(arg-vars an-arg)
|
||||||
(link (arg-var an-arg) nvar))))
|
(for ([nvar (in-list (arg-vars an-arg))])
|
||||||
|
(link (arg-var an-arg) nvar))]
|
||||||
|
[else
|
||||||
|
(no-links (arg-var an-arg))]))
|
||||||
|
|
||||||
(when (istx-ress istx)
|
(when (istx-ress istx)
|
||||||
(for ([a-res (in-list (istx-ress istx))])
|
(for ([a-res (in-list (istx-ress istx))])
|
||||||
(when (res-vars a-res)
|
(cond
|
||||||
(for ([nvar (in-list (res-vars a-res))])
|
[(res-vars a-res)
|
||||||
(link (res-var a-res) nvar)))))
|
(for ([nvar (in-list (res-vars a-res))])
|
||||||
|
(link (res-var a-res) nvar))]
|
||||||
|
[else
|
||||||
|
(no-links (res-var a-res))])))
|
||||||
|
|
||||||
(for ([var (in-list sp)])
|
(for ([var (in-list sp)])
|
||||||
(let loop ([var var]
|
(let loop ([var var]
|
||||||
[visited '()])
|
[visited '()])
|
||||||
|
(printf "var ~s\n" var)
|
||||||
(cond
|
(cond
|
||||||
[(hash-ref safe var #f)
|
[(free-identifier-mapping-get safe var (λ () #f))
|
||||||
(void)]
|
(void)]
|
||||||
[(member var visited)
|
[(memf (λ (x) (free-identifier=? x var)) visited)
|
||||||
(let ([ids (map (λ (x) (hash-ref vars->stx x))
|
(let ([ids (trim-at var visited)])
|
||||||
(trim-at var visited))])
|
|
||||||
(raise-syntax-error #f
|
(raise-syntax-error #f
|
||||||
"cyclic dependencies are not allowed"
|
"cyclic dependencies are not allowed"
|
||||||
stx
|
stx
|
||||||
|
@ -178,18 +198,18 @@ and then operates on it to generate the expanded form
|
||||||
(cdr ids)))]
|
(cdr ids)))]
|
||||||
[else
|
[else
|
||||||
(let ([new-visited (cons var visited)])
|
(let ([new-visited (cons var visited)])
|
||||||
(for ([neighbor (in-list (hash-ref neighbors var))])
|
(for ([neighbor (in-list (free-identifier-mapping-get neighbors var))])
|
||||||
(loop neighbor new-visited)
|
(loop neighbor new-visited)
|
||||||
(hash-set! safe var #t)))])))))
|
(free-identifier-mapping-put! safe var #t)))])))))
|
||||||
|
|
||||||
;; trim-at : X (listof X) -> (listof X)
|
;; trim-at : identifier? (listof identifier?) -> (listof identifier?)
|
||||||
;; returns the shortest prefix of vars that ends with var
|
;; returns the shortest prefix of vars that ends with var
|
||||||
(define (trim-at var vars)
|
(define (trim-at var vars)
|
||||||
(let loop ([vars vars])
|
(let loop ([vars vars])
|
||||||
(cond
|
(cond
|
||||||
[(null? vars) (error 'trim-at "not found")]
|
[(null? vars) (error 'trim-at "not found")]
|
||||||
[else (let ([fst (car vars)])
|
[else (let ([fst (car vars)])
|
||||||
(if (eq? fst var)
|
(if (free-identifier=? fst var)
|
||||||
(list fst)
|
(list fst)
|
||||||
(cons fst (loop (cdr vars)))))])))
|
(cons fst (loop (cdr vars)))))])))
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require racket/contract)
|
(require racket/contract)
|
||||||
|
|
||||||
(->i ([x (y) number?])
|
|
||||||
[y number?])
|
|
||||||
; => domain cannot depend on a range variable
|
|
||||||
|
|
||||||
#|
|
#|
|
||||||
test cases:
|
test cases:
|
||||||
|
@ -84,6 +81,18 @@ test cases:
|
||||||
|
|
||||||
;; => cyclic depenencies
|
;; => cyclic depenencies
|
||||||
|
|
||||||
|
(->i ([x (y) number?]
|
||||||
|
[y number?])
|
||||||
|
any)
|
||||||
|
; => no syntax error
|
||||||
|
|
||||||
|
(->i ()
|
||||||
|
(values [x (y) number?]
|
||||||
|
[y number?]))
|
||||||
|
; => no syntax error
|
||||||
|
|
||||||
|
(->i ([x (y) number?])
|
||||||
|
[y number?])
|
||||||
|
; => domain cannot depend on a range variable
|
||||||
|
|
||||||
|#
|
|#
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user