#lang racket/base ;; Rewrite assertions at a boundary between a containing dataspace and ;; a contained actor (or dataspace). (provide (struct-out relay) spawn-relay relay-handle-event pretty-print-relay) (require racket/match) (require (only-in racket/list filter-map)) (require "core.rkt") (require "trie.rkt") (require "pretty.rkt") (require "hierarchy.rkt") (struct relay (outbound? ;; Assertion -> Boolean outbound-assertion ;; Assertion -> Assertion outbound-parenthesis ;; OpenParenthesis/1 inbound-constructor ;; Assertion -> Assertion inbound-parenthesis ;; OpenParenthesis/1 inner ;; Process ) #:transparent #:methods gen:syndicate-pretty-printable [(define (syndicate-pretty-print r [p (current-output-port)]) (pretty-print-relay r p))]) (define (relay-lift-event e r) (match e [#f #f] [(? targeted-event?) e] [(message c) (message ((relay-inbound-constructor r) c))] [(patch a d) (patch (trie-prepend (relay-inbound-parenthesis r) a) (trie-prepend (relay-inbound-parenthesis r) d))])) (define (relay-drop-interests t r) (define interesting-inbound-assertions (trie-step (trie-step t observe-parenthesis) (relay-inbound-parenthesis r))) (define ordinary-outbound-assertions (trie-step t (relay-outbound-parenthesis r))) (define additional-outbound-assertions-of-interest (trie-prepend observe-parenthesis interesting-inbound-assertions)) (trie-union ordinary-outbound-assertions additional-outbound-assertions-of-interest)) (define (relay-drop-action ac r) (match ac [(message c) (and ((relay-outbound? r) c) (message ((relay-outbound-assertion r) c)))] [(patch a d) (define p (patch (relay-drop-interests a r) (relay-drop-interests d r))) (and (patch-non-empty? p) p)] [_ ;; TODO: What should be done about actor? Anything? ;; TODO: How about quit-dataspace? Could this be a better place for it than core.rkt? (error 'relay-drop-action "Cannot drop action ~v" ac)])) (define (relay-drop-actions acs r) (filter-map (lambda (ac) (relay-drop-action ac r)) (clean-actions acs))) (define (relay-transition t r) (match t [( exn actions) ( exn (relay-drop-actions actions r))] [(transition st actions) (transition (struct-copy relay r [inner (update-process-state (relay-inner r) st)]) (relay-drop-actions actions r))] [(or #f (? void?)) t])) (define (relay-handle-event e r) (define i (relay-inner r)) (relay-transition ((process-behavior i) (relay-lift-event e r) (process-state i)) r)) (define ((inject-relay-subscription r) initial-inner-state) (define initial-patch (patch-seq (patch (trie-prepend observe-parenthesis (trie-prepend (relay-outbound-parenthesis r) (pattern->trie ' ?))) trie-empty) (sub (observe ((relay-inbound-constructor r) ?))))) (define i (relay-inner r)) ((process-behavior i) initial-patch initial-inner-state)) (define (spawn-relay outbound? outbound-assertion outbound-parenthesis inbound-constructor inbound-parenthesis inner-spawn) (make-actor (lambda () (define-values (proc initial-transition) (boot->process+transition (actor-boot inner-spawn))) (define initial-relay-state (relay outbound? outbound-assertion outbound-parenthesis inbound-constructor inbound-parenthesis proc)) (list relay-handle-event (relay-transition (transition-bind (inject-relay-subscription initial-relay-state) initial-transition) initial-relay-state) (process-name proc))) (actor-initial-assertions inner-spawn))) (define (pretty-print-relay r p) (fprintf p "RELAY ~a/~a\n" (open-parenthesis-type (relay-outbound-parenthesis r)) (open-parenthesis-type (relay-inbound-parenthesis r))) (syndicate-pretty-print (process-state (relay-inner r)) p))