Adds define-term form
This commit is contained in:
parent
35a8359c6d
commit
c0625dc30c
|
@ -14,4 +14,4 @@
|
||||||
(thunk)))
|
(thunk)))
|
||||||
|
|
||||||
(define (report-undefined name desc)
|
(define (report-undefined name desc)
|
||||||
(redex-error #f "~a ~s applied before its definition" desc name))
|
(redex-error #f "reference to ~a ~s before its definition" desc name))
|
|
@ -1331,10 +1331,6 @@
|
||||||
(map (λ (x) (to-lw/proc (datum->syntax #f (cdr (syntax-e x)) x)))
|
(map (λ (x) (to-lw/proc (datum->syntax #f (cdr (syntax-e x)) x)))
|
||||||
(syntax->list #'(lhs-for-lw ...)))))
|
(syntax->list #'(lhs-for-lw ...)))))
|
||||||
|
|
||||||
(define-for-syntax (not-expression-context stx)
|
|
||||||
(when (eq? (syntax-local-context) 'expression)
|
|
||||||
(raise-syntax-error #f "not allowed in an expression context" stx)))
|
|
||||||
|
|
||||||
;
|
;
|
||||||
;
|
;
|
||||||
;
|
;
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
(struct-out term-id)
|
(struct-out term-id)
|
||||||
(struct-out judgment-form)
|
(struct-out judgment-form)
|
||||||
judgment-form-id?
|
judgment-form-id?
|
||||||
defined-check)
|
(struct-out defined-term)
|
||||||
|
defined-term-id?
|
||||||
|
defined-check
|
||||||
|
not-expression-context)
|
||||||
|
|
||||||
(define-values (struct-type make-term-fn term-fn? term-fn-get term-fn-set!)
|
(define-values (struct-type make-term-fn term-fn? term-fn-get term-fn-set!)
|
||||||
(make-struct-type 'term-fn #f 1 0))
|
(make-struct-type 'term-fn #f 1 0))
|
||||||
|
@ -15,13 +18,24 @@
|
||||||
|
|
||||||
(define-struct term-id (id depth))
|
(define-struct term-id (id depth))
|
||||||
|
|
||||||
(define-struct judgment-form (name mode proc lang lws))
|
(define ((transformer-predicate p?) stx)
|
||||||
|
|
||||||
(define (judgment-form-id? stx)
|
|
||||||
(and (identifier? stx)
|
(and (identifier? stx)
|
||||||
(judgment-form? (syntax-local-value stx (λ () 'not-a-judgment-form)))))
|
(cond [(syntax-local-value stx (λ () #f)) => p?]
|
||||||
|
[else #f])))
|
||||||
|
|
||||||
|
(define-struct judgment-form (name mode proc lang lws))
|
||||||
|
(define judgment-form-id?
|
||||||
|
(transformer-predicate judgment-form?))
|
||||||
|
|
||||||
|
(define-struct defined-term (value))
|
||||||
|
(define defined-term-id?
|
||||||
|
(transformer-predicate defined-term?))
|
||||||
|
|
||||||
(define (defined-check id desc #:external [external id])
|
(define (defined-check id desc #:external [external id])
|
||||||
(if (eq? (identifier-binding id) 'lexical)
|
(if (eq? (identifier-binding id) 'lexical)
|
||||||
(quasisyntax/loc external (check-defined-lexical #,id '#,external #,desc))
|
(quasisyntax/loc external (check-defined-lexical #,id '#,external #,desc))
|
||||||
(quasisyntax/loc external (check-defined-module (λ () #,id) '#,external #,desc))))
|
(quasisyntax/loc external (check-defined-module (λ () #,id) '#,external #,desc))))
|
||||||
|
|
||||||
|
(define (not-expression-context stx)
|
||||||
|
(when (eq? (syntax-local-context) 'expression)
|
||||||
|
(raise-syntax-error #f "not allowed in an expression context" stx)))
|
|
@ -3,11 +3,14 @@
|
||||||
(require (for-syntax scheme/base
|
(require (for-syntax scheme/base
|
||||||
"term-fn.rkt"
|
"term-fn.rkt"
|
||||||
syntax/boundmap
|
syntax/boundmap
|
||||||
|
syntax/parse
|
||||||
racket/syntax)
|
racket/syntax)
|
||||||
"error.rkt"
|
"error.rkt"
|
||||||
"matcher.rkt")
|
"matcher.rkt")
|
||||||
|
|
||||||
(provide term term-let term-let/error-name term-let-fn term-define-fn hole in-hole)
|
(provide term term-let define-term
|
||||||
|
hole in-hole
|
||||||
|
term-let/error-name term-let-fn term-define-fn)
|
||||||
|
|
||||||
(define-syntax (hole stx) (raise-syntax-error 'hole "used outside of term"))
|
(define-syntax (hole stx) (raise-syntax-error 'hole "used outside of term"))
|
||||||
(define-syntax (in-hole stx) (raise-syntax-error 'in-hole "used outside of term"))
|
(define-syntax (in-hole stx) (raise-syntax-error 'in-hole "used outside of term"))
|
||||||
|
@ -69,6 +72,15 @@
|
||||||
(let ([id (syntax-local-value/record (syntax x) (λ (x) #t))])
|
(let ([id (syntax-local-value/record (syntax x) (λ (x) #t))])
|
||||||
(values (datum->syntax (term-id-id id) (syntax-e (term-id-id id)) (syntax x))
|
(values (datum->syntax (term-id-id id) (syntax-e (term-id-id id)) (syntax x))
|
||||||
(term-id-depth id)))]
|
(term-id-depth id)))]
|
||||||
|
[x
|
||||||
|
(defined-term-id? #'x)
|
||||||
|
(let ([ref (syntax-property
|
||||||
|
(defined-term-value (syntax-local-value #'x))
|
||||||
|
'disappeared-use #'x)])
|
||||||
|
(with-syntax ([v #`(begin
|
||||||
|
#,(defined-check ref "term" #:external #'x)
|
||||||
|
#,ref)])
|
||||||
|
(values #'#,v 0)))]
|
||||||
[(unquote x)
|
[(unquote x)
|
||||||
(values (syntax (unsyntax x)) 0)]
|
(values (syntax (unsyntax x)) 0)]
|
||||||
[(unquote . x)
|
[(unquote . x)
|
||||||
|
@ -208,3 +220,11 @@
|
||||||
(term-let/error-name term-let ((x rhs) ...) body1 body2 ...))]
|
(term-let/error-name term-let ((x rhs) ...) body1 body2 ...))]
|
||||||
[(_ x)
|
[(_ x)
|
||||||
(raise-syntax-error 'term-let "expected at least one body" stx)]))
|
(raise-syntax-error 'term-let "expected at least one body" stx)]))
|
||||||
|
|
||||||
|
(define-syntax (define-term stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ x:id t:expr)
|
||||||
|
(not-expression-context stx)
|
||||||
|
#'(begin
|
||||||
|
(define term-val (term t))
|
||||||
|
(define-syntax x (defined-term #'term-val)))]))
|
|
@ -421,8 +421,8 @@ stands for repetition unless otherwise indicated):
|
||||||
|
|
||||||
@item{A term written @racket[_identifier] is equivalent to the
|
@item{A term written @racket[_identifier] is equivalent to the
|
||||||
corresponding symbol, unless the identifier is bound by
|
corresponding symbol, unless the identifier is bound by
|
||||||
@racket[term-let] (or in a @|pattern| elsewhere) or is
|
@racket[term-let], @racket[define-term], or a @|pattern| variable or
|
||||||
@tt{hole} (as below). }
|
the identifier is @tt{hole} (as below).}
|
||||||
|
|
||||||
@item{A term written @racket[(_term-sequence ...)] constructs a list of
|
@item{A term written @racket[(_term-sequence ...)] constructs a list of
|
||||||
the terms constructed by the sequence elements.}
|
the terms constructed by the sequence elements.}
|
||||||
|
@ -532,6 +532,9 @@ In some contexts, it may be more efficient to use @racket[term-match/single]
|
||||||
The @racket[let*] analog of @racket[redex-let].
|
The @racket[let*] analog of @racket[redex-let].
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defform[(define-term identifier @#,tttterm)]{
|
||||||
|
Defines @racket[identifier] for use in @|tterm| templates.}
|
||||||
|
|
||||||
@defform[(term-match language [@#,ttpattern expression] ...)]{
|
@defform[(term-match language [@#,ttpattern expression] ...)]{
|
||||||
|
|
||||||
This produces a procedure that accepts term (or quoted)
|
This produces a procedure that accepts term (or quoted)
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
term-match/single
|
term-match/single
|
||||||
redex-let
|
redex-let
|
||||||
redex-let*
|
redex-let*
|
||||||
|
define-term
|
||||||
match? match-bindings
|
match? match-bindings
|
||||||
make-bind bind? bind-name bind-exp
|
make-bind bind? bind-name bind-exp
|
||||||
|
|
||||||
|
|
|
@ -153,4 +153,25 @@
|
||||||
(test (send annotations collected-rename-class contract-name)
|
(test (send annotations collected-rename-class contract-name)
|
||||||
(expected-rename-class metafunction-binding)))
|
(expected-rename-class metafunction-binding)))
|
||||||
|
|
||||||
|
;; define-term
|
||||||
|
(let ([annotations (new collector%)])
|
||||||
|
(define-values (add-syntax done)
|
||||||
|
(make-traversal module-namespace #f))
|
||||||
|
|
||||||
|
(define def-name (identifier x))
|
||||||
|
(define use-name (identifier x))
|
||||||
|
|
||||||
|
(parameterize ([current-annotations annotations]
|
||||||
|
[current-namespace module-namespace])
|
||||||
|
(add-syntax
|
||||||
|
(expand #`(let ()
|
||||||
|
(define-term #,def-name a)
|
||||||
|
(term (#,use-name b)))))
|
||||||
|
(done))
|
||||||
|
|
||||||
|
(test (send annotations collected-rename-class def-name)
|
||||||
|
(expected-rename-class (list def-name use-name)))
|
||||||
|
(test (send annotations collected-rename-class def-name)
|
||||||
|
(expected-rename-class (list def-name use-name))))
|
||||||
|
|
||||||
(print-tests-passed 'check-syntax-test.rkt)
|
(print-tests-passed 'check-syntax-test.rkt)
|
|
@ -1,4 +1,4 @@
|
||||||
("judgment form q applied before its definition"
|
("reference to judgment form q before its definition"
|
||||||
([use q]) ([def q])
|
([use q]) ([def q])
|
||||||
(let ()
|
(let ()
|
||||||
(judgment-holds (use 1))
|
(judgment-holds (use 1))
|
||||||
|
|
|
@ -39,4 +39,11 @@
|
||||||
|
|
||||||
(#rx"term .* does not match pattern"
|
(#rx"term .* does not match pattern"
|
||||||
([rhs 'a]) ([ellipsis ...])
|
([rhs 'a]) ([ellipsis ...])
|
||||||
(term-let ([(x ellipsis) rhs]) 3))
|
(term-let ([(x ellipsis) rhs]) 3))
|
||||||
|
|
||||||
|
("reference to term x before its definition"
|
||||||
|
([use x]) ([def x])
|
||||||
|
(let ()
|
||||||
|
(define t (term (use y)))
|
||||||
|
(define-term def z)
|
||||||
|
t))
|
|
@ -989,14 +989,14 @@
|
||||||
(with-handlers ([exn:fail:redex? exn-message])
|
(with-handlers ([exn:fail:redex? exn-message])
|
||||||
(eval '(require 'm))
|
(eval '(require 'm))
|
||||||
#f))
|
#f))
|
||||||
"metafunction q applied before its definition")
|
"reference to metafunction q before its definition")
|
||||||
(test (with-handlers ([exn:fail:redex? exn-message])
|
(test (with-handlers ([exn:fail:redex? exn-message])
|
||||||
(let ()
|
(let ()
|
||||||
(term (q))
|
(term (q))
|
||||||
(define-language L)
|
(define-language L)
|
||||||
(define-metafunction L [(q) ()])
|
(define-metafunction L [(q) ()])
|
||||||
#f))
|
#f))
|
||||||
"metafunction q applied before its definition")
|
"reference to metafunction q before its definition")
|
||||||
|
|
||||||
(exec-syntax-error-tests "syn-err-tests/metafunction-definition.rktd")
|
(exec-syntax-error-tests "syn-err-tests/metafunction-definition.rktd")
|
||||||
;
|
;
|
||||||
|
@ -2131,6 +2131,33 @@
|
||||||
(eval '(require redex/reduction-semantics))
|
(eval '(require redex/reduction-semantics))
|
||||||
(exec-runtime-error-tests "run-err-tests/judgment-form-undefined.rktd"))
|
(exec-runtime-error-tests "run-err-tests/judgment-form-undefined.rktd"))
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; ; ;; ;
|
||||||
|
; ; ; ; ;
|
||||||
|
; ; ; ;
|
||||||
|
; ;;;; ;;; ;;; ; ;;;; ;;; ;;; ;;; ; ;; ;;;;;
|
||||||
|
; ; ; ; ; ; ; ; ; ; ; ;;;;; ; ; ; ;; ; ; ; ;
|
||||||
|
; ; ; ;;;;; ; ; ; ; ;;;;; ; ;;;;; ; ; ; ; ;
|
||||||
|
; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
|
||||||
|
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
|
||||||
|
; ;;;; ;;; ; ; ; ; ;;; ;; ;;; ; ; ; ;
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;
|
||||||
|
|
||||||
|
(test (let ()
|
||||||
|
(define-term x 1)
|
||||||
|
(term (x x)))
|
||||||
|
(term (1 1)))
|
||||||
|
(test (let ()
|
||||||
|
(define-term x 1)
|
||||||
|
(let ([x 'whatever])
|
||||||
|
(term (x x))))
|
||||||
|
(term (x x)))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; examples from doc.txt
|
;; examples from doc.txt
|
||||||
|
|
Loading…
Reference in New Issue
Block a user