2013-03-29 03:00:29 +00:00
|
|
|
#lang typed/racket/base
|
|
|
|
|
|
|
|
(require racket/match)
|
|
|
|
(require "types.rkt")
|
|
|
|
(require "roles.rkt")
|
|
|
|
(require (rename-in "tr-struct-copy.rkt" [tr-struct-copy struct-copy])) ;; PR13149 workaround
|
|
|
|
|
|
|
|
(provide vm-processes ;; (struct-out vm) doesn't work because of make-vm below (See PR13161)
|
|
|
|
vm-next-process-id
|
|
|
|
vm ;; really just want to export the type here, not the ctor
|
|
|
|
vm?
|
|
|
|
|
|
|
|
(struct-out process)
|
|
|
|
(struct-out endpoint)
|
|
|
|
(struct-out eid)
|
|
|
|
Process
|
|
|
|
CoProcess
|
|
|
|
mkProcess
|
|
|
|
unwrap-process
|
|
|
|
|
|
|
|
make-vm
|
|
|
|
inject-process
|
|
|
|
extract-process
|
|
|
|
always-false
|
|
|
|
reset-pending-actions
|
|
|
|
process-map
|
|
|
|
endpoint-fold)
|
|
|
|
|
|
|
|
(struct: vm ([processes : (HashTable PID Process)]
|
|
|
|
[next-process-id : PID])
|
|
|
|
#:transparent)
|
|
|
|
|
|
|
|
(struct: (State)
|
|
|
|
process ([debug-name : Any]
|
|
|
|
[pid : PID]
|
|
|
|
[state : State]
|
|
|
|
[spawn-ks : (Listof (Pairof Integer (TrapK PID State)))] ;; hmm
|
|
|
|
[endpoints : (HashTable PreEID (endpoint State))]
|
|
|
|
[meta-endpoints : (HashTable PreEID (endpoint State))]
|
|
|
|
[pending-actions : (QuasiQueue (Action State))])
|
|
|
|
#:transparent)
|
|
|
|
|
|
|
|
(struct: (State)
|
|
|
|
endpoint ([id : eid]
|
|
|
|
[role : role]
|
|
|
|
[handler : (Handler State)])
|
|
|
|
#:transparent)
|
|
|
|
|
|
|
|
(struct: eid ([pid : PID]
|
|
|
|
[pre-eid : PreEID])
|
2013-05-10 19:32:40 +00:00
|
|
|
#:transparent)
|
2013-03-29 03:00:29 +00:00
|
|
|
|
|
|
|
(define-type Process (All (R) (CoProcess R) -> R))
|
|
|
|
(define-type (CoProcess R) (All (State) (process State) -> R))
|
|
|
|
|
|
|
|
(: mkProcess : (All (State) ((CoProcess Process) State)))
|
|
|
|
;; A kind of identity function, taking the components of a process to
|
|
|
|
;; a process.
|
|
|
|
(define (mkProcess p)
|
|
|
|
(lambda (k) ((inst k State) p)))
|
|
|
|
|
|
|
|
(: Process-pid : Process -> PID)
|
|
|
|
(define (Process-pid wp) ((inst wp PID) process-pid))
|
|
|
|
|
|
|
|
;; Unwraps a process. Result is the type of the result of the
|
|
|
|
;; expression; State is a type variable to be bound to the process's
|
|
|
|
;; private state type. p is to be bound to the unwrapped process; wp
|
|
|
|
;; is the expression producing the wrapped process. body... are the
|
|
|
|
;; forms computing a value of type Result.
|
|
|
|
(define-syntax-rule (unwrap-process State Result (p wp) body ...)
|
|
|
|
(let ()
|
|
|
|
(: coproc : (All (State) (process State) -> Result))
|
|
|
|
(define (coproc p)
|
|
|
|
body ...)
|
|
|
|
((inst wp Result) coproc)))
|
|
|
|
|
|
|
|
;;---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
(: make-vm : process-spec -> vm)
|
|
|
|
(define (make-vm boot)
|
|
|
|
(define primordial (mkProcess ((inst process Void)
|
|
|
|
'#:primordial
|
|
|
|
-1
|
|
|
|
(void)
|
|
|
|
(list)
|
|
|
|
#hash()
|
|
|
|
#hash()
|
|
|
|
(quasiqueue ((inst spawn Void) boot #f '#:boot-process)))))
|
|
|
|
(vm (hash-set (ann #hash() (HashTable PID Process))
|
|
|
|
(Process-pid primordial)
|
|
|
|
primordial)
|
|
|
|
0))
|
|
|
|
|
|
|
|
(: inject-process : vm Process -> vm)
|
|
|
|
(define (inject-process state wp)
|
|
|
|
(struct-copy vm state [processes (hash-set (vm-processes state) (Process-pid wp) wp)]))
|
|
|
|
|
|
|
|
(: always-false : -> False)
|
|
|
|
(define (always-false) #f)
|
|
|
|
|
|
|
|
(: extract-process : vm PID -> (values vm (Option Process)))
|
|
|
|
(define (extract-process state pid)
|
|
|
|
(define wp (hash-ref (vm-processes state) pid always-false))
|
|
|
|
(values (if wp
|
|
|
|
(struct-copy vm state [processes (hash-remove (vm-processes state) pid)])
|
|
|
|
state)
|
|
|
|
wp))
|
|
|
|
|
|
|
|
(: reset-pending-actions : (All (State) (process State) -> (process State)))
|
|
|
|
(define (reset-pending-actions p)
|
|
|
|
(struct-copy process p [pending-actions ((inst empty-quasiqueue (Action State)))]))
|
|
|
|
|
|
|
|
(: process-map : (All (State) (process State) -> (process State)) vm -> vm)
|
|
|
|
(define (process-map f state)
|
|
|
|
(for/fold ([state state]) ([pid (in-hash-keys (vm-processes state))])
|
|
|
|
(let-values (((state wp) (extract-process state pid)))
|
|
|
|
(if (not wp)
|
|
|
|
state
|
|
|
|
(unwrap-process State vm (p wp)
|
|
|
|
(inject-process state (mkProcess (f p))))))))
|
|
|
|
|
|
|
|
(: endpoint-fold : (All (A) (All (State) (process State) (endpoint State) A -> A) A vm -> A))
|
|
|
|
(define (endpoint-fold f seed state)
|
|
|
|
(for/fold ([seed seed]) ([pid (in-hash-keys (vm-processes state))])
|
|
|
|
(let-values (((state wp) (extract-process state pid)))
|
|
|
|
(if (not wp)
|
|
|
|
seed
|
|
|
|
(unwrap-process State A (p wp)
|
|
|
|
(for/fold ([seed seed]) ([pre-eid (in-hash-keys (process-endpoints p))])
|
|
|
|
(define ep (hash-ref (process-endpoints p) pre-eid))
|
|
|
|
((inst f State) p ep seed)))))))
|
|
|
|
|
|
|
|
;;; Local Variables:
|
|
|
|
;;; eval: (put 'unwrap-process 'scheme-indent-function 3)
|
|
|
|
;;; End:
|