2018-04-08 06:39:39 +00:00
|
|
|
#lang racket/base
|
|
|
|
;; DSL syntax over the API of dataspace.rkt
|
|
|
|
|
|
|
|
(provide spawn
|
|
|
|
spawn*
|
|
|
|
|
|
|
|
react
|
|
|
|
react/suspend
|
|
|
|
until
|
|
|
|
|
|
|
|
field
|
|
|
|
assert
|
|
|
|
stop-facet
|
|
|
|
stop-current-facet
|
|
|
|
stop-when
|
|
|
|
stop-when-true
|
|
|
|
on-start
|
|
|
|
on-stop
|
|
|
|
on
|
2019-05-04 21:58:45 +00:00
|
|
|
add-raw-observer-endpoint!
|
|
|
|
add-observer-endpoint!
|
2018-04-19 16:55:52 +00:00
|
|
|
during
|
2018-04-22 20:07:35 +00:00
|
|
|
during/spawn
|
2018-04-08 06:39:39 +00:00
|
|
|
begin/dataflow
|
|
|
|
define/dataflow
|
|
|
|
|
|
|
|
asserted
|
|
|
|
retracted
|
|
|
|
message
|
|
|
|
|
|
|
|
let-event
|
|
|
|
|
2018-04-30 21:48:50 +00:00
|
|
|
query-value
|
2018-05-01 19:58:02 +00:00
|
|
|
query-set
|
|
|
|
query-hash
|
2018-04-08 10:44:32 +00:00
|
|
|
;; query-hash-set
|
2019-01-29 20:47:06 +00:00
|
|
|
query-count
|
2018-04-30 21:48:50 +00:00
|
|
|
query-value*
|
2018-05-01 19:58:02 +00:00
|
|
|
query-set*
|
|
|
|
query-hash*
|
2018-04-08 10:44:32 +00:00
|
|
|
;; query-hash-set*
|
2019-01-29 20:47:06 +00:00
|
|
|
query-count*
|
2018-04-30 21:48:50 +00:00
|
|
|
define/query-value
|
2018-05-01 19:58:02 +00:00
|
|
|
define/query-set
|
|
|
|
define/query-hash
|
2018-04-08 10:44:32 +00:00
|
|
|
;; define/query-hash-set
|
2019-01-29 20:47:06 +00:00
|
|
|
define/query-count
|
2019-01-28 13:46:54 +00:00
|
|
|
immediate-query
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
send!
|
2018-04-29 13:54:14 +00:00
|
|
|
defer-turn!
|
2018-04-08 06:39:39 +00:00
|
|
|
flush!
|
2018-04-19 16:55:52 +00:00
|
|
|
assert!
|
|
|
|
retract!
|
|
|
|
current-adhoc-assertions
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
;;
|
|
|
|
|
2018-04-08 10:44:32 +00:00
|
|
|
;; current-action-transformer
|
2018-04-08 06:39:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
(require (for-syntax racket/base))
|
|
|
|
(require (for-syntax syntax/parse))
|
|
|
|
(require (for-syntax syntax/srcloc))
|
|
|
|
(require "syntax-classes.rkt")
|
|
|
|
|
2018-05-03 15:14:30 +00:00
|
|
|
(require "assertions.rkt")
|
2018-04-08 06:39:39 +00:00
|
|
|
(require "dataspace.rkt")
|
|
|
|
(require (submod "dataspace.rkt" priorities))
|
2018-04-08 10:44:32 +00:00
|
|
|
(require "event-expander.rkt")
|
|
|
|
(require "skeleton.rkt")
|
|
|
|
(require "pattern.rkt")
|
2019-05-04 21:58:45 +00:00
|
|
|
(require "term.rkt")
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2019-01-29 20:47:06 +00:00
|
|
|
(require racket/match)
|
2018-04-08 10:44:32 +00:00
|
|
|
(require racket/set)
|
|
|
|
(require syndicate/dataflow)
|
2018-04-22 20:07:35 +00:00
|
|
|
(require syndicate/protocol/instance)
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
(begin-for-syntax
|
|
|
|
(define-splicing-syntax-class actor-wrapper
|
|
|
|
(pattern (~seq #:spawn wrapper))
|
|
|
|
(pattern (~seq) #:attr wrapper #'spawn))
|
|
|
|
|
|
|
|
(define-splicing-syntax-class on-crash-option
|
|
|
|
(pattern (~seq #:on-crash expr))
|
|
|
|
(pattern (~seq) #:attr expr #f))
|
|
|
|
|
|
|
|
(define-splicing-syntax-class let-option
|
|
|
|
(pattern (~seq #:let clauses))
|
|
|
|
(pattern (~seq) #:attr clauses #'()))
|
|
|
|
|
|
|
|
(define-splicing-syntax-class when-pred
|
|
|
|
(pattern (~seq #:when Pred))
|
|
|
|
(pattern (~seq) #:attr Pred #'#t))
|
|
|
|
|
|
|
|
(define-splicing-syntax-class priority
|
|
|
|
(pattern (~seq #:priority level))
|
|
|
|
(pattern (~seq) #:attr level #'*normal-priority*)))
|
|
|
|
|
|
|
|
(define-syntax (spawn stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ (~or (~optional (~seq #:name name-expr) #:defaults ([name-expr #'#f])
|
|
|
|
#:name "#:name")
|
|
|
|
(~optional (~seq #:assertions [assertion-exprs ...])
|
|
|
|
#:name "#:assertions")
|
|
|
|
(~optional (~seq #:linkage [linkage-expr ...]) #:defaults ([(linkage-expr 1) '()])
|
|
|
|
#:name "#:linkage"))
|
|
|
|
...
|
|
|
|
O ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(spawn** #:name name-expr
|
|
|
|
#:assertions #,(cond [(attribute assertion-exprs) #'[assertion-exprs ...]]
|
|
|
|
[else #'[]])
|
|
|
|
linkage-expr ... O ...))]))
|
|
|
|
|
|
|
|
(define-syntax (spawn* stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ name:name assertions:assertions script ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(spawn** #:name name.N
|
|
|
|
#:assertions [assertions.exprs ...]
|
|
|
|
(on-start script ...)))]))
|
|
|
|
|
|
|
|
(define-syntax (spawn** stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ name:name assertions:assertions script ...)
|
|
|
|
(quasisyntax/loc stx
|
2018-04-29 13:54:14 +00:00
|
|
|
(begin
|
|
|
|
(ensure-in-script! 'spawn!)
|
|
|
|
(spawn!
|
|
|
|
(current-actor)
|
|
|
|
name.N
|
|
|
|
(lambda () (begin/void-default script ...))
|
|
|
|
(set assertions.exprs ...))))]))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
2018-04-08 10:44:32 +00:00
|
|
|
(define-syntax (begin/void-default stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_) (syntax/loc stx (void))]
|
|
|
|
[(_ expr0 expr ...) (syntax/loc stx (begin expr0 expr ...))]))
|
|
|
|
|
2018-04-08 06:39:39 +00:00
|
|
|
(define (react* where boot-proc)
|
2018-04-27 17:03:31 +00:00
|
|
|
(add-facet! where
|
2018-04-08 07:52:37 +00:00
|
|
|
(current-actor)
|
|
|
|
(current-facet)
|
2018-04-08 06:39:39 +00:00
|
|
|
boot-proc))
|
|
|
|
|
|
|
|
(define-syntax (react stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ O ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(react* #,(source-location->string stx)
|
|
|
|
(lambda () (begin/void-default O ...))))]))
|
|
|
|
|
|
|
|
(define-syntax (react/suspend stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ (resume-parent) O ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(suspend-script* #,(source-location->string stx)
|
|
|
|
(lambda (resume-parent)
|
|
|
|
(react* #,(source-location->string stx)
|
|
|
|
(lambda () (begin/void-default O ...))))))]))
|
|
|
|
|
|
|
|
(define-syntax (until stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ E O ...)
|
|
|
|
(syntax/loc stx
|
|
|
|
(react/suspend (continue)
|
|
|
|
(stop-when E (continue (void)))
|
|
|
|
O ...))]))
|
|
|
|
|
|
|
|
(define (make-field name init)
|
2018-04-27 17:03:31 +00:00
|
|
|
(let ((ac (current-actor)))
|
|
|
|
(field-handle name (generate-id! (actor-dataspace ac)) ac init)))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
(define-syntax (define-field stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ id init)
|
|
|
|
#'(define id (make-field 'id init))]))
|
|
|
|
|
|
|
|
(define-syntax (field stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ [id:id init] ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(begin (define-field id init)
|
|
|
|
...))]))
|
|
|
|
|
|
|
|
(define-syntax (assert stx)
|
|
|
|
(syntax-parse stx
|
2018-04-29 21:27:55 +00:00
|
|
|
[(_ w:when-pred snapshot:snapshot P)
|
2018-04-08 06:39:39 +00:00
|
|
|
(quasisyntax/loc stx
|
2018-04-27 17:03:31 +00:00
|
|
|
(add-endpoint! (current-facet)
|
2018-04-08 06:39:39 +00:00
|
|
|
#,(source-location->string stx)
|
2018-04-29 21:27:55 +00:00
|
|
|
snapshot.dynamic?
|
|
|
|
(lambda () (values (when w.Pred P) #f))))]))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
(define-syntax (stop-facet stx)
|
|
|
|
(syntax-parse stx
|
2018-04-08 10:44:32 +00:00
|
|
|
[(_ f-expr script ...)
|
2018-04-08 06:39:39 +00:00
|
|
|
(quasisyntax/loc stx
|
2018-04-08 10:44:32 +00:00
|
|
|
(let ((f f-expr))
|
|
|
|
(when (not (equal? (facet-actor f) (current-actor)))
|
|
|
|
(error 'stop-facet "Attempt to stop unrelated facet ~a from actor ~a" f (current-actor)))
|
2018-04-27 17:03:31 +00:00
|
|
|
(stop-facet! f (lambda () (begin/void-default script ...)))))]))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
(define-syntax-rule (stop-current-facet script ...)
|
2018-04-08 10:44:32 +00:00
|
|
|
(stop-facet (current-facet) script ...))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
(define-syntax-rule (stop-when-true condition script ...)
|
|
|
|
(begin/dataflow
|
|
|
|
(when condition
|
2018-04-08 10:44:32 +00:00
|
|
|
(stop-facet (current-facet) script ...))))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
(define-syntax (on-start stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ script ...)
|
|
|
|
(quasisyntax/loc stx
|
2018-04-27 17:03:31 +00:00
|
|
|
(schedule-script! (current-actor)
|
2018-04-08 06:39:39 +00:00
|
|
|
(lambda () (begin/void-default script ...))))]))
|
|
|
|
|
|
|
|
(define-syntax (on-stop stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ script ...)
|
|
|
|
(quasisyntax/loc stx
|
2018-04-27 17:03:31 +00:00
|
|
|
(add-stop-script! (current-facet)
|
2018-04-08 06:39:39 +00:00
|
|
|
(lambda () (begin/void-default script ...))))]))
|
|
|
|
|
|
|
|
(define-syntax (stop-when stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ w:when-pred E prio:priority script ...)
|
2018-04-08 10:44:32 +00:00
|
|
|
(analyse-event stx
|
2018-04-08 06:39:39 +00:00
|
|
|
#'w.Pred
|
|
|
|
#'E
|
|
|
|
(syntax/loc stx (stop-current-facet script ...))
|
|
|
|
#'prio.level)]))
|
|
|
|
|
|
|
|
(define-syntax (on stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ w:when-pred E prio:priority script ...)
|
2018-04-08 10:44:32 +00:00
|
|
|
(analyse-event stx
|
2018-04-08 06:39:39 +00:00
|
|
|
#'w.Pred
|
|
|
|
#'E
|
|
|
|
(syntax/loc stx (begin/void-default script ...))
|
|
|
|
#'prio.level)]))
|
|
|
|
|
2019-05-04 21:58:45 +00:00
|
|
|
(define (add-raw-observer-endpoint! spec-thunk
|
|
|
|
#:on-add [on-add void]
|
|
|
|
#:on-remove [on-remove void]
|
|
|
|
#:on-message [on-message void]
|
|
|
|
#:cleanup [cleanup #f])
|
|
|
|
(add-endpoint! (current-facet)
|
|
|
|
"add-observer-endpoint!/add-raw-observer-endpoint!"
|
|
|
|
#t
|
|
|
|
(lambda ()
|
|
|
|
(define spec (spec-thunk))
|
|
|
|
(if (void? spec)
|
|
|
|
(values (void) #f)
|
|
|
|
(values (observe spec)
|
|
|
|
(term->skeleton-interest
|
|
|
|
spec
|
|
|
|
(lambda (op . captured-values)
|
|
|
|
(match op
|
|
|
|
['+ (on-add captured-values)]
|
|
|
|
['- (on-remove captured-values)]
|
|
|
|
['! (on-message captured-values)]))
|
|
|
|
#:cleanup cleanup))))))
|
|
|
|
|
|
|
|
(define (add-observer-endpoint! spec-thunk
|
|
|
|
#:on-add [on-add void]
|
|
|
|
#:on-remove [on-remove void]
|
|
|
|
#:on-message [on-message void]
|
|
|
|
#:cleanup [cleanup #f])
|
|
|
|
(define (scriptify f)
|
|
|
|
(if (eq? f void)
|
|
|
|
void
|
|
|
|
(capture-facet-context
|
|
|
|
(lambda (captured-values)
|
|
|
|
(schedule-script! (current-actor) (lambda () (f captured-values)))))))
|
|
|
|
(add-raw-observer-endpoint! spec-thunk
|
|
|
|
#:on-add (scriptify on-add)
|
|
|
|
#:on-remove (scriptify on-remove)
|
|
|
|
#:on-message (scriptify on-message)
|
|
|
|
#:cleanup cleanup))
|
|
|
|
|
2018-04-08 06:39:39 +00:00
|
|
|
(define-syntax (begin/dataflow stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ prio:priority expr ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(let ()
|
2018-04-27 17:03:31 +00:00
|
|
|
(add-endpoint! (current-facet)
|
2018-04-08 06:39:39 +00:00
|
|
|
#,(source-location->string stx)
|
2018-04-29 21:27:55 +00:00
|
|
|
#t
|
2018-04-08 06:39:39 +00:00
|
|
|
(lambda ()
|
|
|
|
(define subject-id (current-dataflow-subject-id))
|
|
|
|
(schedule-script!
|
|
|
|
#:priority prio.level
|
2018-04-11 11:28:09 +00:00
|
|
|
(current-actor)
|
2018-04-08 06:39:39 +00:00
|
|
|
(lambda ()
|
|
|
|
(parameterize ((current-dataflow-subject-id subject-id))
|
|
|
|
expr ...)))
|
2018-04-29 21:27:55 +00:00
|
|
|
(values (void) #f)))))]))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
(define-syntax (define/dataflow stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ fieldname expr)
|
|
|
|
(quasisyntax/loc stx (define/dataflow fieldname expr #:default #f))]
|
|
|
|
[(_ fieldname expr #:default default-expr)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(begin
|
|
|
|
(field [fieldname default-expr])
|
|
|
|
(begin/dataflow (fieldname expr))))]))
|
|
|
|
|
|
|
|
(define-syntax (asserted stx) (raise-syntax-error #f "asserted: Used outside event spec" stx))
|
|
|
|
(define-syntax (retracted stx) (raise-syntax-error #f "retracted: Used outside event spec" stx))
|
2018-04-08 10:44:32 +00:00
|
|
|
(define-syntax (message stx) (raise-syntax-error #f "message: Used outside event spec" stx))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
(define-syntax (suspend-script stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ proc)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(suspend-script* #,(source-location->string stx) proc))]))
|
|
|
|
|
|
|
|
(define-syntax (let-event stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ [e ...] body ...)
|
|
|
|
(syntax/loc stx
|
|
|
|
((react/suspend (k)
|
|
|
|
(on-start (-let-event [e ...] (stop-current-facet (k (lambda () body ...))))))))]))
|
|
|
|
|
|
|
|
(define-syntax (-let-event stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ [] expr) #'expr]
|
|
|
|
[(_ [e es ...] expr) (quasisyntax/loc #'e (react (stop-when e (-let-event [es ...] expr))))]))
|
|
|
|
|
|
|
|
(define-for-syntax orig-insp
|
|
|
|
(variable-reference->module-declaration-inspector (#%variable-reference)))
|
|
|
|
|
2018-04-08 10:44:32 +00:00
|
|
|
(define-for-syntax (analyse-event outer-expr-stx
|
2018-04-08 06:39:39 +00:00
|
|
|
when-pred-stx
|
|
|
|
armed-event-stx
|
|
|
|
script-stx
|
|
|
|
priority-stx)
|
|
|
|
(define event-stx (syntax-disarm armed-event-stx orig-insp))
|
|
|
|
(syntax-parse event-stx
|
2018-04-08 10:44:32 +00:00
|
|
|
#:literals [message asserted retracted]
|
|
|
|
[(expander args ...) #:when (event-expander-id? #'expander)
|
|
|
|
(event-expander-transform event-stx
|
|
|
|
(lambda (result)
|
|
|
|
(analyse-event outer-expr-stx
|
|
|
|
when-pred-stx
|
|
|
|
(syntax-rearm result event-stx)
|
|
|
|
script-stx
|
|
|
|
priority-stx)))]
|
2018-04-29 21:27:55 +00:00
|
|
|
[(message snapshot:snapshot P)
|
2018-04-08 10:44:32 +00:00
|
|
|
(define desc (analyse-pattern #'P))
|
2018-04-08 06:39:39 +00:00
|
|
|
(quasisyntax/loc outer-expr-stx
|
2018-04-27 17:03:31 +00:00
|
|
|
(add-endpoint! (current-facet)
|
2018-04-08 10:44:32 +00:00
|
|
|
#,(source-location->string outer-expr-stx)
|
2018-04-29 21:27:55 +00:00
|
|
|
snapshot.dynamic?
|
|
|
|
(lambda ()
|
|
|
|
(if #,when-pred-stx
|
|
|
|
(values (observe #,(desc->assertion-stx desc))
|
|
|
|
(skeleton-interest #,(desc->skeleton-stx desc)
|
|
|
|
'#,(desc->skeleton-proj desc)
|
|
|
|
(list #,@(desc->key desc))
|
|
|
|
'#,(desc->capture-proj desc)
|
|
|
|
(capture-facet-context
|
|
|
|
(lambda (op #,@(desc->capture-names desc))
|
|
|
|
(when (eq? op '!)
|
2018-05-01 21:39:50 +00:00
|
|
|
;; (log-info "~a ~a ~v"
|
|
|
|
;; (current-facet)
|
|
|
|
;; op
|
|
|
|
;; (list #,@(desc->capture-names desc)))
|
2018-04-29 21:27:55 +00:00
|
|
|
(schedule-script!
|
|
|
|
#:priority #,priority-stx
|
|
|
|
(current-actor)
|
|
|
|
#,(quasisyntax/loc script-stx
|
|
|
|
(lambda ()
|
|
|
|
#,script-stx))))))
|
|
|
|
#f))
|
|
|
|
(values (void) #f)))))]
|
|
|
|
[(asserted snapshot:snapshot P)
|
|
|
|
(analyse-asserted/retracted outer-expr-stx
|
|
|
|
#'snapshot.dynamic?
|
|
|
|
when-pred-stx
|
|
|
|
script-stx
|
|
|
|
#t
|
|
|
|
#'P
|
|
|
|
priority-stx)]
|
|
|
|
[(retracted snapshot:snapshot P)
|
|
|
|
(analyse-asserted/retracted outer-expr-stx
|
|
|
|
#'snapshot.dynamic?
|
|
|
|
when-pred-stx
|
|
|
|
script-stx
|
|
|
|
#f
|
|
|
|
#'P
|
|
|
|
priority-stx)]))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
2018-04-22 20:06:18 +00:00
|
|
|
(define-for-syntax (analyse-asserted/retracted outer-expr-stx
|
2018-04-29 21:27:55 +00:00
|
|
|
snapshot-dynamic?-stx
|
2018-04-08 10:44:32 +00:00
|
|
|
when-pred-stx
|
|
|
|
script-stx
|
|
|
|
asserted?
|
|
|
|
P-stx
|
|
|
|
priority-stx)
|
|
|
|
(define desc (analyse-pattern P-stx))
|
|
|
|
(quasisyntax/loc outer-expr-stx
|
2018-04-27 17:03:31 +00:00
|
|
|
(add-endpoint! (current-facet)
|
2018-04-08 10:44:32 +00:00
|
|
|
#,(source-location->string outer-expr-stx)
|
2018-04-29 21:27:55 +00:00
|
|
|
#,snapshot-dynamic?-stx
|
|
|
|
(lambda ()
|
|
|
|
(if #,when-pred-stx
|
|
|
|
(values (observe #,(desc->assertion-stx desc))
|
|
|
|
(skeleton-interest #,(desc->skeleton-stx desc)
|
|
|
|
'#,(desc->skeleton-proj desc)
|
|
|
|
(list #,@(desc->key desc))
|
|
|
|
'#,(desc->capture-proj desc)
|
|
|
|
(capture-facet-context
|
|
|
|
(lambda (op #,@(desc->capture-names desc))
|
|
|
|
(when (eq? op #,(if asserted? #''+ #''-))
|
2018-05-01 21:39:50 +00:00
|
|
|
;; (log-info "~a ~a ~v"
|
|
|
|
;; (current-facet)
|
|
|
|
;; op
|
|
|
|
;; (list #,@(desc->capture-names desc)))
|
2018-04-29 21:27:55 +00:00
|
|
|
(schedule-script!
|
|
|
|
#:priority #,priority-stx
|
|
|
|
(current-actor)
|
|
|
|
#,(quasisyntax/loc script-stx
|
|
|
|
(lambda ()
|
|
|
|
#,script-stx))))))
|
|
|
|
#f))
|
|
|
|
(values (void) #f))))))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2018-04-19 16:55:52 +00:00
|
|
|
(define-syntax (during stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ P O ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(on (asserted P)
|
2018-04-29 21:27:55 +00:00
|
|
|
(react (stop-when (retracted #:snapshot #,(instantiate-pattern->pattern #'P)))
|
2018-04-19 16:55:52 +00:00
|
|
|
O ...)))]))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2018-04-22 20:07:35 +00:00
|
|
|
(define-syntax (during/spawn stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ P w:actor-wrapper name:name assertions:assertions parent-let:let-option
|
|
|
|
oncrash:on-crash-option
|
|
|
|
O ...)
|
|
|
|
(define Q-stx (instantiate-pattern->pattern #'P))
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(on (asserted P)
|
|
|
|
(let* ((id (gensym 'during/spawn))
|
|
|
|
(inst (instance id #,(instantiate-pattern->value #'P)))
|
|
|
|
;; ^ this is the assertion representing supply
|
|
|
|
)
|
|
|
|
(react (stop-when (asserted inst)
|
|
|
|
;; Supply (inst) appeared before demand (p) retracted.
|
|
|
|
;; Transition to a state where we monitor demand, but also
|
|
|
|
;; express interest in supply: this latter acts as a signal
|
|
|
|
;; to the supply that it should stick around. We react to
|
|
|
|
;; retraction of supply before retraction of demand by
|
|
|
|
;; invoking the on-crash expression, if supplied. Once
|
|
|
|
;; demand is retracted, this facet terminates, retracting
|
|
|
|
;; its interest in supply, thereby signalling to the supply
|
|
|
|
;; that it is no longer wanted.
|
|
|
|
(react (stop-when (retracted inst) ;; NOT OPTIONAL
|
|
|
|
#,@(if (attribute oncrash.expr)
|
|
|
|
#'(oncrash.expr)
|
|
|
|
#'()))
|
2018-04-29 21:27:55 +00:00
|
|
|
(stop-when (retracted #:snapshot #,Q-stx))))
|
|
|
|
(stop-when (retracted #:snapshot #,Q-stx)
|
2018-04-22 20:07:35 +00:00
|
|
|
;; Demand (p) retracted before supply (inst) appeared. We
|
|
|
|
;; MUST wait for the supply to fully appear so that we can
|
|
|
|
;; reliably tell it to shut down. We must maintain interest
|
|
|
|
;; in supply until we see supply, and then terminate, thus
|
|
|
|
;; signalling to supply that it is no longer wanted.
|
|
|
|
(react (stop-when (asserted inst)))))
|
|
|
|
(let parent-let.clauses
|
|
|
|
(w.wrapper #:linkage [(assert inst)
|
|
|
|
(stop-when (retracted (observe inst)))]
|
|
|
|
#:name name.N
|
2018-11-04 13:43:17 +00:00
|
|
|
#:assertions [inst
|
|
|
|
(observe (observe inst))
|
|
|
|
assertions.exprs ...]
|
2018-04-22 20:07:35 +00:00
|
|
|
O ...)))))]))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2018-04-08 10:44:32 +00:00
|
|
|
;; Queries
|
2018-04-08 06:39:39 +00:00
|
|
|
|
2018-04-30 21:48:50 +00:00
|
|
|
(begin-for-syntax
|
|
|
|
(define-splicing-syntax-class on-add
|
|
|
|
(pattern (~optional (~seq #:on-add expr) #:defaults ([expr #f]))))
|
|
|
|
(define-splicing-syntax-class on-remove
|
|
|
|
(pattern (~optional (~seq #:on-remove expr) #:defaults ([expr #f]))))
|
|
|
|
|
|
|
|
(define (schedule-query-handler-stxs maybe-expr-stx)
|
|
|
|
(if maybe-expr-stx
|
|
|
|
(quasisyntax/loc maybe-expr-stx
|
|
|
|
((schedule-script! #:priority *query-handler-priority*
|
2018-05-01 19:57:42 +00:00
|
|
|
(current-actor)
|
2018-04-30 21:48:50 +00:00
|
|
|
(lambda () #,maybe-expr-stx))))
|
|
|
|
#'())))
|
|
|
|
|
|
|
|
(define-syntax (query-value stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ field-name absent-expr args ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(let ()
|
|
|
|
(field [field-name absent-expr])
|
|
|
|
(query-value* field-name absent-expr args ...)))]))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2018-04-30 21:48:50 +00:00
|
|
|
(define-syntax (query-value* stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ field-name absent-expr P expr on-add:on-add on-remove:on-remove)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(let ((F field-name))
|
|
|
|
(on (asserted P) #:priority *query-priority*
|
|
|
|
#,@(schedule-query-handler-stxs (attribute on-add.expr))
|
|
|
|
(F expr))
|
|
|
|
(on (retracted P) #:priority *query-priority-high*
|
|
|
|
#,@(schedule-query-handler-stxs (attribute on-remove.expr))
|
|
|
|
(F absent-expr))
|
|
|
|
F))]))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2018-05-01 19:58:02 +00:00
|
|
|
(define-syntax (query-set stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ field-name args ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(let ()
|
|
|
|
(field [field-name (set)])
|
|
|
|
(query-set* field-name args ...)))]))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2018-05-01 19:58:02 +00:00
|
|
|
(define-syntax (query-set* stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ field-name P expr on-add:on-add on-remove:on-remove)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(let ((F field-name))
|
|
|
|
(on (asserted P) #:priority *query-priority*
|
|
|
|
(let ((V expr))
|
|
|
|
(when (not (set-member? (F) V))
|
|
|
|
#,@(schedule-query-handler-stxs (attribute on-add.expr))
|
|
|
|
(F (set-add (F) V)))))
|
|
|
|
(on (retracted P) #:priority *query-priority-high*
|
|
|
|
(let ((V expr))
|
|
|
|
(when (set-member? (F) V)
|
|
|
|
#,@(schedule-query-handler-stxs (attribute on-remove.expr))
|
|
|
|
(F (set-remove (F) V)))))
|
|
|
|
F))]))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2018-05-01 19:58:02 +00:00
|
|
|
(define-syntax (query-hash stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ field-name args ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(let ()
|
|
|
|
(field [field-name (hash)])
|
|
|
|
(query-hash* field-name args ...)))]))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2018-05-01 19:58:02 +00:00
|
|
|
(define-syntax (query-hash* stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ field-name P key-expr value-expr on-add:on-add on-remove:on-remove)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(let ((F field-name))
|
|
|
|
(on (asserted P) #:priority *query-priority*
|
|
|
|
(let ((key key-expr))
|
|
|
|
(when (hash-has-key? (F) key)
|
|
|
|
(log-warning "query-hash: field ~v with pattern ~v: overwriting existing entry ~v"
|
|
|
|
'field-name
|
|
|
|
'P
|
|
|
|
key))
|
|
|
|
#,@(schedule-query-handler-stxs (attribute on-add.expr))
|
|
|
|
(F (hash-set (F) key value-expr))))
|
|
|
|
(on (retracted P) #:priority *query-priority-high*
|
|
|
|
#,@(schedule-query-handler-stxs (attribute on-remove.expr))
|
|
|
|
(F (hash-remove (F) key-expr)))
|
|
|
|
F))]))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
|
|
|
;; (define-syntax (query-hash-set stx)
|
|
|
|
;; (syntax-parse stx
|
|
|
|
;; [(_ field-name args ...)
|
|
|
|
;; (quasisyntax/loc stx
|
|
|
|
;; (let ()
|
|
|
|
;; (field [field-name (hash)])
|
|
|
|
;; (query-hash-set* field-name args ...)))]))
|
|
|
|
|
|
|
|
;; (define-syntax (query-hash-set* stx)
|
|
|
|
;; (syntax-parse stx
|
|
|
|
;; [(_ field-name P key-expr value-expr on-add:on-add on-remove:on-remove)
|
|
|
|
;; (quasisyntax/loc stx
|
|
|
|
;; (let ((F field-name))
|
|
|
|
;; (on (asserted P) #:priority *query-priority*
|
|
|
|
;; (let ((K key-expr) (V value-expr))
|
|
|
|
;; (when (not (hashset-member? (F) K V))
|
|
|
|
;; #,@(schedule-query-handler-stxs (attribute on-add.expr))
|
|
|
|
;; (F (hashset-add (F) K V)))))
|
|
|
|
;; (on (retracted P) #:priority *query-priority-high*
|
|
|
|
;; (let ((K key-expr) (V value-expr))
|
|
|
|
;; (when (hashset-member? (F) K V)
|
|
|
|
;; #,@(schedule-query-handler-stxs (attribute on-remove.expr))
|
|
|
|
;; (F (hashset-remove (F) K V)))))
|
|
|
|
;; F))]))
|
|
|
|
|
2019-01-29 20:47:06 +00:00
|
|
|
(define-syntax (query-count stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ field-name args ...)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(let ()
|
|
|
|
(field [field-name (hash)])
|
|
|
|
(query-count* field-name args ...)))]))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2019-01-29 20:47:06 +00:00
|
|
|
(define-syntax (query-count* stx)
|
|
|
|
(syntax-parse stx
|
|
|
|
[(_ field-name P expr on-add:on-add on-remove:on-remove)
|
|
|
|
(quasisyntax/loc stx
|
|
|
|
(let ((F field-name))
|
|
|
|
(on (asserted P) #:priority *query-priority*
|
|
|
|
(let ((E expr))
|
|
|
|
#,@(schedule-query-handler-stxs (attribute on-add.expr))
|
|
|
|
(F (hash-set (F) E (+ 1 (hash-ref (F) E 0))))))
|
|
|
|
(on (retracted P) #:priority *query-priority-high*
|
|
|
|
(let ((E expr))
|
|
|
|
#,@(schedule-query-handler-stxs (attribute on-remove.expr))
|
|
|
|
(let ((F0 (F)))
|
|
|
|
(F (match (hash-ref F0 E 0)
|
|
|
|
[0 F0] ;; huh
|
|
|
|
[1 (hash-remove F0 E)]
|
|
|
|
[n (hash-set F0 E (- n 1))])))))
|
|
|
|
F))]))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2018-04-30 21:48:50 +00:00
|
|
|
(define-syntax-rule (define/query-value id ae P x ...) (define id (query-value id ae P x ...)))
|
2018-05-01 19:58:02 +00:00
|
|
|
(define-syntax-rule (define/query-set id P x ...) (define id (query-set id P x ...)))
|
|
|
|
(define-syntax-rule (define/query-hash id P x ...) (define id (query-hash id P x ...)))
|
2018-04-08 10:44:32 +00:00
|
|
|
;; (define-syntax-rule (define/query-hash-set id P x ...) (define id (query-hash-set id P x ...)))
|
2019-01-29 20:47:06 +00:00
|
|
|
(define-syntax-rule (define/query-count id P x ...) (define id (query-count id P x ...)))
|
2018-04-08 10:44:32 +00:00
|
|
|
|
2019-01-28 13:46:54 +00:00
|
|
|
(define-syntax (immediate-query stx)
|
|
|
|
(syntax-case stx ()
|
|
|
|
[(_ [op args ...] ...)
|
|
|
|
(with-syntax [((query-result ...) (generate-temporaries #'(op ...)))]
|
|
|
|
(syntax/loc stx
|
|
|
|
(react/suspend (k)
|
|
|
|
(define query-result (op query-result args ...)) ...
|
|
|
|
(on-start (flush!) (k (query-result) ...)))))]))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
2018-04-08 10:44:32 +00:00
|
|
|
(define (send! m)
|
2018-04-29 13:54:14 +00:00
|
|
|
(ensure-in-script! 'send!)
|
2018-04-11 11:28:09 +00:00
|
|
|
(enqueue-send! (current-actor) m))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
2018-04-29 13:54:14 +00:00
|
|
|
(define (defer-turn! k)
|
|
|
|
(ensure-in-script! 'defer-turn!)
|
|
|
|
(enqueue-deferred-turn! (current-actor) k))
|
|
|
|
|
2018-04-08 06:39:39 +00:00
|
|
|
(define (flush!)
|
|
|
|
(ensure-in-script! 'flush!)
|
|
|
|
(define ack (gensym 'flush!))
|
2018-04-08 10:44:32 +00:00
|
|
|
(until (message ack)
|
|
|
|
(on-start (send! ack))))
|
2018-04-08 06:39:39 +00:00
|
|
|
|
2018-05-01 19:58:26 +00:00
|
|
|
(define (assert! a [count 1])
|
2018-04-19 16:55:52 +00:00
|
|
|
(ensure-in-script! 'assert!)
|
2018-05-01 19:58:26 +00:00
|
|
|
(adhoc-assert! (current-actor) a count))
|
2018-04-19 16:55:52 +00:00
|
|
|
|
2018-05-01 19:58:26 +00:00
|
|
|
(define (retract! a [count 1])
|
2018-04-19 16:55:52 +00:00
|
|
|
(ensure-in-script! 'retract!)
|
2018-05-01 19:58:26 +00:00
|
|
|
(adhoc-retract! (current-actor) a count))
|
2018-04-19 16:55:52 +00:00
|
|
|
|
|
|
|
(define (current-adhoc-assertions)
|
|
|
|
(actor-adhoc-assertions (current-actor)))
|