Allow various kinds of statelike processing during pattern analysis
This commit is contained in:
parent
55e5c36725
commit
2124915de2
|
@ -18,6 +18,10 @@
|
|||
|
||||
!dump-registered-preserves-patterns!
|
||||
|
||||
transform-pattern-binding
|
||||
current-pattern-binding-let
|
||||
pattern-binding-let
|
||||
|
||||
(all-from-out "schemas/dataspacePatterns.rkt"))
|
||||
|
||||
(require (for-syntax racket/base))
|
||||
|
@ -32,6 +36,7 @@
|
|||
(require preserves-schema)
|
||||
(require racket/match)
|
||||
(require racket/list)
|
||||
(require racket/stxparam)
|
||||
(require "pattern-expander.rkt")
|
||||
(require "smart-pattern.rkt")
|
||||
(require "schemas/dataspacePatterns.rkt")
|
||||
|
@ -70,6 +75,23 @@
|
|||
(define-for-syntax orig-insp
|
||||
(variable-reference->module-declaration-inspector (#%variable-reference)))
|
||||
|
||||
(define-syntax-parameter transform-pattern-binding (lambda (id-stx expanded-stx) expanded-stx))
|
||||
|
||||
(define-syntax-parameter current-pattern-binding-let
|
||||
(lambda (stx)
|
||||
(syntax-case stx ()
|
||||
[(_ [(binding ...) bindings] body ...)
|
||||
(syntax/loc stx
|
||||
(match-let ([(list binding ...) bindings]) body ...))])))
|
||||
|
||||
(define-syntax pattern-binding-let
|
||||
(lambda (stx)
|
||||
(syntax-case stx ()
|
||||
[(_ [pat bindings] body ...)
|
||||
(with-syntax (((binding ...) (analyse-pattern-bindings #'pat)))
|
||||
(syntax/loc stx
|
||||
(current-pattern-binding-let [(binding ...) bindings] body ...)))])))
|
||||
|
||||
(begin-for-syntax
|
||||
(define (dollar-id? stx)
|
||||
(and (identifier? stx)
|
||||
|
@ -77,7 +99,7 @@
|
|||
|
||||
(define (undollar stx)
|
||||
(and (dollar-id? stx)
|
||||
(datum->syntax stx (string->symbol (substring (symbol->string (syntax-e stx)) 1)))))
|
||||
(datum->syntax stx (string->symbol (substring (symbol->string (syntax-e stx)) 1)) stx)))
|
||||
|
||||
(define (id=? expected stx)
|
||||
(and (identifier? stx)
|
||||
|
@ -112,6 +134,9 @@
|
|||
[(list _) (raise-syntax-error #f "Odd number of elements in hash-like pattern")]
|
||||
[(list* k v more) (append (f k v) (append-map-pairs f more))]))
|
||||
|
||||
(define (transform-binding id-stx expanded-stx)
|
||||
((syntax-parameter-value #'transform-pattern-binding) id-stx expanded-stx))
|
||||
|
||||
(define (analyse-pattern stx
|
||||
#:check-destructuring [check-destructuring (lambda (stx) stx)]
|
||||
#:wrap-literal [wrap-literal (lambda (stx) stx)])
|
||||
|
@ -153,10 +178,10 @@
|
|||
|
||||
[id
|
||||
(dollar-id? #'id)
|
||||
#`(Pattern-DBind (DBind (Pattern-DDiscard (DDiscard))))]
|
||||
(transform-binding (undollar #'id) #`(Pattern-DBind (DBind (Pattern-DDiscard (DDiscard)))))]
|
||||
|
||||
[($ id p)
|
||||
#`(Pattern-DBind (DBind #,(walk #'p)))]
|
||||
(transform-binding #'id #`(Pattern-DBind (DBind #,(walk #'p))))]
|
||||
|
||||
[id
|
||||
(discard-id? #'id)
|
||||
|
@ -357,3 +382,9 @@
|
|||
(for [(k (in-list (free-id-table-keys preserves-pattern-registry)))]
|
||||
(printf " - ~v\n" k))
|
||||
#'(void))]))
|
||||
|
||||
;;---------------------------------------------------------------------------
|
||||
;;; Local Variables:
|
||||
;;; eval: (put 'pattern-binding-let 'racket-indent-function 1)
|
||||
;;; eval: (put 'current-pattern-binding-let 'racket-indent-function 1)
|
||||
;;; End:
|
||||
|
|
|
@ -56,10 +56,10 @@
|
|||
(ref (entity #:name 'field-name
|
||||
#:assert
|
||||
(lambda (bindings handle)
|
||||
(match-define (list #,@(analyse-pattern-bindings #'P)) bindings)
|
||||
(set! assertion-count (+ assertion-count 1))
|
||||
(F expr)
|
||||
on-add.expr)
|
||||
(pattern-binding-let [P bindings]
|
||||
(set! assertion-count (+ assertion-count 1))
|
||||
(F expr)
|
||||
on-add.expr))
|
||||
#:retract
|
||||
(lambda (_handle)
|
||||
(set! assertion-count (- assertion-count 1))
|
||||
|
@ -77,16 +77,16 @@
|
|||
(assert
|
||||
(Observe (:pattern P)
|
||||
(object #:name 'field-name
|
||||
[#:asserted bindings
|
||||
(match-define (list #,@(analyse-pattern-bindings #'P)) bindings)
|
||||
(define v expr)
|
||||
(define-values (bag1 outcome1) (bag-change (F) v 1))
|
||||
(F bag1)
|
||||
(when (eq? outcome1 'absent->present) on-add.expr)
|
||||
#:retracted
|
||||
(define-values (bag2 outcome2) (bag-change (F) v -1))
|
||||
(F bag2)
|
||||
(when (eq? outcome2 'present->absent) on-remove.expr)])))))]))
|
||||
[#:asserted* bindings
|
||||
(pattern-binding-let [P bindings]
|
||||
(define v expr)
|
||||
(define-values (bag1 outcome1) (bag-change (F) v 1))
|
||||
(F bag1)
|
||||
(when (eq? outcome1 'absent->present) on-add.expr)
|
||||
(lambda ()
|
||||
(define-values (bag2 outcome2) (bag-change (F) v -1))
|
||||
(F bag2)
|
||||
(when (eq? outcome2 'present->absent) on-remove.expr)))])))))]))
|
||||
|
||||
(-define-query (query-set field-name args ...) (set) query-set*)
|
||||
|
||||
|
@ -99,16 +99,16 @@
|
|||
(assert
|
||||
(Observe (:pattern P)
|
||||
(object #:name 'field-name
|
||||
[#:asserted bindings
|
||||
(match-define (list #,@(analyse-pattern-bindings #'P)) bindings)
|
||||
(define v expr)
|
||||
(when (eq? (bag-change! b v 1) 'absent->present)
|
||||
(F (set-add (F) v))
|
||||
on-add.expr)
|
||||
#:retracted
|
||||
(when (eq? (bag-change! b v -1) 'present->absent)
|
||||
(F (set-remove (F) v))
|
||||
on-remove.expr)])))))]))
|
||||
[#:asserted* bindings
|
||||
(pattern-binding-let [P bindings]
|
||||
(define v expr)
|
||||
(when (eq? (bag-change! b v 1) 'absent->present)
|
||||
(F (set-add (F) v))
|
||||
on-add.expr)
|
||||
(lambda ()
|
||||
(when (eq? (bag-change! b v -1) 'present->absent)
|
||||
(F (set-remove (F) v))
|
||||
on-remove.expr)))])))))]))
|
||||
|
||||
(-define-query (query-hash field-name args ...) (hash) query-hash*)
|
||||
|
||||
|
@ -120,21 +120,21 @@
|
|||
(assert
|
||||
(Observe (:pattern P)
|
||||
(object #:name 'field-name
|
||||
[#:asserted bindings
|
||||
(match-define (list #,@(analyse-pattern-bindings #'P)) bindings)
|
||||
(define k key-expr)
|
||||
(define v value-expr)
|
||||
(when (hash-has-key? (F) k)
|
||||
(log-warning
|
||||
"query-hash: field ~s with pattern ~s: overwriting existing entry ~s"
|
||||
'field-name
|
||||
'P
|
||||
k))
|
||||
(F (hash-set (F) k v))
|
||||
on-add.expr
|
||||
#:retracted
|
||||
(F (hash-remove (F) k))
|
||||
on-remove.expr])))))]))
|
||||
[#:asserted* bindings
|
||||
(pattern-binding-let [P bindings]
|
||||
(define k key-expr)
|
||||
(define v value-expr)
|
||||
(when (hash-has-key? (F) k)
|
||||
(log-warning
|
||||
"query-hash: field ~s with pattern ~s: overwriting existing entry ~s"
|
||||
'field-name
|
||||
'P
|
||||
k))
|
||||
(F (hash-set (F) k v))
|
||||
on-add.expr
|
||||
(lambda ()
|
||||
(F (hash-remove (F) k))
|
||||
on-remove.expr))])))))]))
|
||||
|
||||
(define-syntax-rule (define/query-value id ae P x ...) (define id (query-value id ae P x ...)))
|
||||
(define-syntax-rule (define/query-count id P x ...) (define id (query-count id P x ...)))
|
||||
|
|
|
@ -141,6 +141,14 @@
|
|||
body+ ... #f] ]
|
||||
[more ...])]
|
||||
|
||||
[(_ name input is-message? [completed ...]
|
||||
[ [#:asserted* pat body ...] more ... ])
|
||||
#`(-object-clauses name
|
||||
input
|
||||
is-message?
|
||||
[ completed ... [(-object-pattern pat) #:when (not is-message?) body ...] ]
|
||||
[more ...])]
|
||||
|
||||
[(_ name input is-message? [completed ...]
|
||||
[ [#:asserted pat body+ ... #:retracted body- ...] more ... ])
|
||||
#`(-object-clauses name
|
||||
|
@ -342,16 +350,16 @@
|
|||
(Observe (:pattern pat)
|
||||
(ref (entity #:message
|
||||
(lambda (bindings)
|
||||
(match-define (list #,@(analyse-pattern-bindings #'pat)) bindings)
|
||||
expr ...)))))))]
|
||||
(pattern-binding-let [pat bindings]
|
||||
expr ...))))))))]
|
||||
[(_ ((~datum asserted) condition:<when> pat) expr ...)
|
||||
(quasisyntax/loc stx
|
||||
(assert #:when condition.E
|
||||
(Observe (:pattern pat)
|
||||
(ref (entity #:assert
|
||||
(lambda (bindings _handle)
|
||||
(match-define (list #,@(analyse-pattern-bindings #'pat)) bindings)
|
||||
expr ...))))))]
|
||||
(pattern-binding-let [pat bindings]
|
||||
expr ...)))))))]
|
||||
[(_ ((~datum retracted) condition:<when> pat) expr ...)
|
||||
(quasisyntax/loc stx
|
||||
(assert #:when condition.E
|
||||
|
@ -362,10 +370,10 @@
|
|||
(hash-set! assertion-map handle bindings))
|
||||
#:retract
|
||||
(lambda (handle)
|
||||
(match-define (list #,@(analyse-pattern-bindings #'pat))
|
||||
(hash-ref assertion-map handle))
|
||||
(hash-remove! assertion-map handle)
|
||||
expr ...)))))))]
|
||||
(pattern-binding-let
|
||||
[pat (hash-ref assertion-map handle)]
|
||||
(hash-remove! assertion-map handle)
|
||||
expr ...))))))))]
|
||||
[(_ (expander args ...) body ...) #:when (event-expander-form? #'(expander args ...))
|
||||
(event-expander-transform #'(expander [args ...] body ...) (lambda (r) (syntax-rearm r stx)))]
|
||||
[_
|
||||
|
@ -378,8 +386,8 @@
|
|||
(quasisyntax/loc stx
|
||||
(assert (Observe (:pattern pat)
|
||||
(ref (during* (lambda (bindings)
|
||||
(match-define (list #,@(analyse-pattern-bindings #'pat)) bindings)
|
||||
expr ...))))))])))
|
||||
(pattern-binding-let [pat bindings]
|
||||
expr ...)))))))])))
|
||||
|
||||
(define-syntax during/spawn
|
||||
(lambda (stx)
|
||||
|
@ -388,8 +396,8 @@
|
|||
(quasisyntax/loc stx
|
||||
(assert (Observe (:pattern pat)
|
||||
(ref (during* (lambda (bindings)
|
||||
(match-define (list #,@(analyse-pattern-bindings #'pat)) bindings)
|
||||
(spawn/link expr ...)))))))])))
|
||||
(pattern-binding-let [pat bindings]
|
||||
(spawn/link expr ...))))))))])))
|
||||
|
||||
(define (during* f #:name [name '?])
|
||||
(define assertion-map (make-hash))
|
||||
|
|
Loading…
Reference in New Issue