added a first attempt at define-relation
svn: r15171
This commit is contained in:
parent
c5fdb9c8cc
commit
ddc5d91e24
|
@ -983,20 +983,26 @@
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
(define-syntax-set (define-metafunction define-metafunction/extension)
|
(define-syntax-set (define-metafunction define-metafunction/extension define-relation)
|
||||||
|
|
||||||
(define (define-metafunction/proc stx)
|
(define (define-metafunction/proc stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ . rest)
|
[(_ . rest)
|
||||||
(internal-define-metafunction stx #f #'rest)]))
|
(internal-define-metafunction stx #f #'rest #f)]))
|
||||||
|
|
||||||
|
(define (define-relation/proc stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ . rest)
|
||||||
|
;; need to rule out the contracts for this one
|
||||||
|
(internal-define-metafunction stx #f #'rest #t)]))
|
||||||
|
|
||||||
(define (define-metafunction/extension/proc stx)
|
(define (define-metafunction/extension/proc stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ prev . rest)
|
[(_ prev . rest)
|
||||||
(identifier? #'prev)
|
(identifier? #'prev)
|
||||||
(internal-define-metafunction stx #'prev #'rest)]))
|
(internal-define-metafunction stx #'prev #'rest #f)]))
|
||||||
|
|
||||||
(define (internal-define-metafunction orig-stx prev-metafunction stx)
|
(define (internal-define-metafunction orig-stx prev-metafunction stx relation?)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(lang . rest)
|
[(lang . rest)
|
||||||
(let ([syn-error-name (if prev-metafunction
|
(let ([syn-error-name (if prev-metafunction
|
||||||
|
@ -1140,7 +1146,8 @@
|
||||||
sc))
|
sc))
|
||||||
dsc
|
dsc
|
||||||
`codom-side-conditions-rewritten
|
`codom-side-conditions-rewritten
|
||||||
'name)))
|
'name
|
||||||
|
#,relation?)))
|
||||||
(term-define-fn name name2))
|
(term-define-fn name name2))
|
||||||
'disappeared-use
|
'disappeared-use
|
||||||
(map syntax-local-introduce (syntax->list #'(original-names ...))))))))))))))]
|
(map syntax-local-introduce (syntax->list #'(original-names ...))))))))))))))]
|
||||||
|
@ -1260,7 +1267,7 @@
|
||||||
"expected a side-condition or where clause"
|
"expected a side-condition or where clause"
|
||||||
(car stuff))])]))]))))
|
(car stuff))])]))]))))
|
||||||
|
|
||||||
(define (build-metafunction lang patterns rhss old-cps old-rhss wrap dom-contract-pat codom-contract-pat name)
|
(define (build-metafunction lang patterns rhss old-cps old-rhss wrap dom-contract-pat codom-contract-pat name relation?)
|
||||||
(let ([compiled-patterns (append old-cps
|
(let ([compiled-patterns (append old-cps
|
||||||
(map (λ (pat) (compile-pattern lang pat #t)) patterns))]
|
(map (λ (pat) (compile-pattern lang pat #t)) patterns))]
|
||||||
[dom-compiled-pattern (and dom-contract-pat (compile-pattern lang dom-contract-pat #f))]
|
[dom-compiled-pattern (and dom-contract-pat (compile-pattern lang dom-contract-pat #f))]
|
||||||
|
@ -1284,7 +1291,11 @@
|
||||||
[num (- (length old-cps))])
|
[num (- (length old-cps))])
|
||||||
(cond
|
(cond
|
||||||
[(null? patterns)
|
[(null? patterns)
|
||||||
(redex-error name "no clauses matched for ~s" `(,name . ,exp))]
|
(if relation?
|
||||||
|
(begin
|
||||||
|
(hash-set! cache exp #f)
|
||||||
|
#f)
|
||||||
|
(redex-error name "no clauses matched for ~s" `(,name . ,exp)))]
|
||||||
[else
|
[else
|
||||||
(let ([pattern (car patterns)]
|
(let ([pattern (car patterns)]
|
||||||
[rhs (car rhss)])
|
[rhs (car rhss)])
|
||||||
|
@ -1293,6 +1304,19 @@
|
||||||
[(not mtchs) (loop (cdr patterns)
|
[(not mtchs) (loop (cdr patterns)
|
||||||
(cdr rhss)
|
(cdr rhss)
|
||||||
(+ num 1))]
|
(+ num 1))]
|
||||||
|
[relation?
|
||||||
|
(let ([ans (ormap (λ (mtch) (rhs traced-metafunc (mtch-bindings mtch)))
|
||||||
|
mtchs)])
|
||||||
|
(unless (match-pattern codom-compiled-pattern ans)
|
||||||
|
(redex-error name "codomain test failed for ~s, call was ~s" ans `(,name ,@exp)))
|
||||||
|
(cond
|
||||||
|
[ans
|
||||||
|
(hash-set! cache exp #t)
|
||||||
|
#t]
|
||||||
|
[else
|
||||||
|
(loop (cdr patterns)
|
||||||
|
(cdr rhss)
|
||||||
|
(+ num 1))]))]
|
||||||
[(not (null? (cdr mtchs)))
|
[(not (null? (cdr mtchs)))
|
||||||
(redex-error name "~a matched ~s ~a different ways"
|
(redex-error name "~a matched ~s ~a different ways"
|
||||||
(if (< num 0)
|
(if (< num 0)
|
||||||
|
@ -1974,6 +1998,7 @@
|
||||||
|
|
||||||
define-metafunction
|
define-metafunction
|
||||||
define-metafunction/extension
|
define-metafunction/extension
|
||||||
|
define-relation
|
||||||
|
|
||||||
(rename-out [metafunction-form metafunction])
|
(rename-out [metafunction-form metafunction])
|
||||||
metafunction? metafunction-proc
|
metafunction? metafunction-proc
|
||||||
|
|
|
@ -611,9 +611,52 @@
|
||||||
(term (f 1)))
|
(term (f 1)))
|
||||||
(test (get-output-string sp) "|(f 1)\n|0\n")))
|
(test (get-output-string sp) "|(f 1)\n|0\n")))
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; ;; ;;; ;; ;; ;; ;;
|
||||||
|
; ;; ;;; ;; ;; ;;; ;;
|
||||||
|
; ;;;;; ;;;; ;;;;; ;; ;; ;;; ;;;; ;;;; ;;;; ;; ;;;; ;;;;; ;; ;;;; ;; ;;;
|
||||||
|
; ;;;;;; ;; ;; ;;;; ;; ;;;;;; ;; ;; ;;;; ;; ;; ;; ;; ;; ;;;; ;; ;;;;;; ;;;;;;
|
||||||
|
; ;;; ;; ;;;;;;;; ;; ;; ;; ;; ;;;;;;;;;;;; ;; ;;;;;;;; ;; ;;;; ;;; ;; ;;; ;;; ;; ;;
|
||||||
|
; ;;; ;; ;;; ;; ;; ;; ;; ;;; ;;;; ;; ;;; ;; ;;; ;; ;;; ;; ;;; ;;; ;; ;;
|
||||||
|
; ;;;;;; ;;; ;; ;; ;; ;; ;; ;;; ;; ;; ;;; ;; ;; ;;; ;; ;;;; ;; ;;;;;; ;; ;;
|
||||||
|
; ;;;;; ;;;; ;; ;; ;; ;; ;;;; ;; ;;;; ;; ;;;;;; ;;; ;; ;;;; ;; ;;
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;
|
||||||
|
|
||||||
;
|
|
||||||
;
|
(let ()
|
||||||
|
(define-relation empty-language
|
||||||
|
[(<: any any) #t])
|
||||||
|
|
||||||
|
(test (term (<: 1 1)) #t)
|
||||||
|
(test (term (<: 1 2)) #f))
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-relation empty-language
|
||||||
|
[(<: number_1 number_2) ,(< (term number_1) (term number_2))]
|
||||||
|
[(<: number_1 number_1) #t])
|
||||||
|
|
||||||
|
(test (term (<: 1 2)) #t)
|
||||||
|
(test (term (<: 1 1)) #t)
|
||||||
|
(test (term (<: 2 1)) #f))
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-relation empty-language
|
||||||
|
[(<: number_1 ... number_2 number_3 ... number_2 number_4 ...) #t])
|
||||||
|
|
||||||
|
(test (term (<: 1 2 3 4)) #f)
|
||||||
|
(test (term (<: 1 1 2 3 4)) #t)
|
||||||
|
(test (term (<: 1 2 1 3 4)) #t)
|
||||||
|
(test (term (<: 1 2 3 1 4)) #t)
|
||||||
|
(test (term (<: 1 2 3 4 1)) #t))
|
||||||
|
|
||||||
; ;; ; ;; ;
|
; ;; ; ;; ;
|
||||||
; ; ; ; ;
|
; ; ; ; ;
|
||||||
; ;; ;; ;;; ;; ; ;; ;; ;;;; ;;;;; ;;; ;;; ;; ;; ;; ;; ;;; ; ;;; ;;;;; ;;; ;;; ;; ;;
|
; ;; ;; ;;; ;; ; ;; ;; ;;;; ;;;;; ;;; ;;; ;; ;; ;; ;; ;;; ; ;;; ;;;;; ;;; ;;; ;; ;;
|
||||||
|
|
|
@ -871,7 +871,7 @@ terminate (it does terminate if the only infinite reduction paths are cyclic).
|
||||||
@scheme[reduction-relation]. A @scheme[with] form is an
|
@scheme[reduction-relation]. A @scheme[with] form is an
|
||||||
error elsewhere. }
|
error elsewhere. }
|
||||||
|
|
||||||
@section{Metafunctions}
|
@section{Metafunctions and Relations}
|
||||||
|
|
||||||
All of the exports in this section are provided both by
|
All of the exports in this section are provided both by
|
||||||
@schememodname[redex/reduction-semantics] (which includes
|
@schememodname[redex/reduction-semantics] (which includes
|
||||||
|
@ -980,6 +980,38 @@ legtimate inputs according to @scheme[metafunction-name]'s contract,
|
||||||
and @scheme[#f] otherwise.
|
and @scheme[#f] otherwise.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defform/subs[#:literals ()
|
||||||
|
(define-relation language-exp
|
||||||
|
[(name @#,ttpattern ...) @#,tttterm extras ...]
|
||||||
|
...)
|
||||||
|
([extras (side-condition scheme-expression)
|
||||||
|
(where tl-pat @#,tttterm)]
|
||||||
|
[tl-pat identifier (tl-pat-ele ...)]
|
||||||
|
[tl-pat-ele tl-pat (code:line tl-pat ... (code:comment "a literal ellipsis"))])]{
|
||||||
|
|
||||||
|
The @scheme[define-relation] form builds a relation on
|
||||||
|
sexpressions according to the pattern and right-hand-side
|
||||||
|
expressions. The first argument indicates the language used
|
||||||
|
to resolve non-terminals in the pattern expressions. Each of
|
||||||
|
the rhs-expressions is implicitly wrapped in @|tttterm|.
|
||||||
|
|
||||||
|
If specified, the side-conditions are collected with
|
||||||
|
@scheme[and] and used as guards on the case being matched. The
|
||||||
|
argument to each side-condition should be a Scheme
|
||||||
|
expression, and the pattern variables in the @|ttpattern| are
|
||||||
|
bound in that expression.
|
||||||
|
|
||||||
|
Unlike metafunctions, relations check all possible ways to match each
|
||||||
|
case, looking for a true result and if none of the clauses match, then
|
||||||
|
the result is @scheme[#f].
|
||||||
|
|
||||||
|
Note that relations are assumed to always return the same results
|
||||||
|
for the same inputs, and their results are cached, unless
|
||||||
|
@scheme[caching-enable?] is set to @scheme[#f]. Accordingly, if a
|
||||||
|
metafunction is called with the same inputs twice, then its body is
|
||||||
|
only evaluated a single time.
|
||||||
|
}
|
||||||
|
|
||||||
@defparam[current-traced-metafunctions traced-metafunctions (or/c 'all (listof symbol?))]{
|
@defparam[current-traced-metafunctions traced-metafunctions (or/c 'all (listof symbol?))]{
|
||||||
|
|
||||||
Controls which metafunctions are currently being traced. If it is
|
Controls which metafunctions are currently being traced. If it is
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
none?
|
none?
|
||||||
define-metafunction
|
define-metafunction
|
||||||
define-metafunction/extension
|
define-metafunction/extension
|
||||||
|
define-relation
|
||||||
metafunction
|
metafunction
|
||||||
in-domain?
|
in-domain?
|
||||||
caching-enabled?)
|
caching-enabled?)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user