Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
Michael Ballantyne | 512783ec0f | |
Sam Caldwell | 8a74f7ffee | |
Sam Caldwell | 721fb1c30f | |
Sam Caldwell | 4e97151cc5 | |
Sam Caldwell | 0a8e400f63 | |
Sam Caldwell | 8d6a037841 | |
Sam Caldwell | 23616488ce |
|
@ -36,8 +36,3 @@
|
||||||
"scribble-lib"
|
"scribble-lib"
|
||||||
"sha"
|
"sha"
|
||||||
))
|
))
|
||||||
|
|
||||||
(define test-omit-paths
|
|
||||||
;; There's some shared library related build issue with the syndicate-gl things
|
|
||||||
'("syndicate-gl/"
|
|
||||||
"syndicate-ide/"))
|
|
||||||
|
|
|
@ -409,7 +409,6 @@
|
||||||
[(_ [id:id init maybe-contract ...] ...)
|
[(_ [id:id init maybe-contract ...] ...)
|
||||||
(quasisyntax/loc stx
|
(quasisyntax/loc stx
|
||||||
(begin
|
(begin
|
||||||
(ensure-in-endpoint-context! 'field)
|
|
||||||
(when (and (in-script?) (pair? (current-facet-id)))
|
(when (and (in-script?) (pair? (current-facet-id)))
|
||||||
(error 'field
|
(error 'field
|
||||||
"~a: Cannot declare fields in a script; are you missing a (react ...)?"
|
"~a: Cannot declare fields in a script; are you missing a (react ...)?"
|
||||||
|
@ -488,17 +487,13 @@
|
||||||
(syntax-parse stx
|
(syntax-parse stx
|
||||||
[(_ script ...)
|
[(_ script ...)
|
||||||
(quasisyntax/loc stx
|
(quasisyntax/loc stx
|
||||||
(begin
|
(schedule-script! (lambda () (begin/void-default script ...))))]))
|
||||||
(ensure-in-endpoint-context! 'on-start)
|
|
||||||
(schedule-script! (lambda () (begin/void-default script ...)))))]))
|
|
||||||
|
|
||||||
(define-syntax (on-stop stx)
|
(define-syntax (on-stop stx)
|
||||||
(syntax-parse stx
|
(syntax-parse stx
|
||||||
[(_ script ...)
|
[(_ script ...)
|
||||||
(quasisyntax/loc stx
|
(quasisyntax/loc stx
|
||||||
(begin
|
(add-stop-script! (lambda () (begin/void-default script ...))))]))
|
||||||
(ensure-in-endpoint-context! 'on-stop)
|
|
||||||
(add-stop-script! (lambda () (begin/void-default script ...)))))]))
|
|
||||||
|
|
||||||
(define-syntax (on-event stx)
|
(define-syntax (on-event stx)
|
||||||
(syntax-parse stx
|
(syntax-parse stx
|
||||||
|
@ -803,7 +798,7 @@
|
||||||
#:macro-definer-name define-event-expander
|
#:macro-definer-name define-event-expander
|
||||||
#:introducer-parameter-name current-event-expander-introducer
|
#:introducer-parameter-name current-event-expander-introducer
|
||||||
#:local-introduce-name syntax-local-event-expander-introduce
|
#:local-introduce-name syntax-local-event-expander-introduce
|
||||||
#:expander-form-predicate-name event-expander-form?
|
#:expander-id-predicate-name event-expander-id?
|
||||||
#:expander-transform-name event-expander-transform)
|
#:expander-transform-name event-expander-transform)
|
||||||
|
|
||||||
(provide (for-syntax
|
(provide (for-syntax
|
||||||
|
@ -811,7 +806,7 @@
|
||||||
event-expander?
|
event-expander?
|
||||||
event-expander-proc
|
event-expander-proc
|
||||||
syntax-local-event-expander-introduce
|
syntax-local-event-expander-introduce
|
||||||
event-expander-form?
|
event-expander-id?
|
||||||
event-expander-transform)
|
event-expander-transform)
|
||||||
define-event-expander)
|
define-event-expander)
|
||||||
|
|
||||||
|
@ -949,8 +944,8 @@
|
||||||
(define event-stx (syntax-disarm armed-event-stx orig-insp))
|
(define event-stx (syntax-disarm armed-event-stx orig-insp))
|
||||||
(syntax-parse event-stx
|
(syntax-parse event-stx
|
||||||
#:literals [core:message asserted retracted rising-edge know forget realize]
|
#:literals [core:message asserted retracted rising-edge know forget realize]
|
||||||
[expander
|
[(expander args ...)
|
||||||
#:when (event-expander-form? #'expander)
|
#:when (event-expander-id? #'expander)
|
||||||
(event-expander-transform
|
(event-expander-transform
|
||||||
event-stx
|
event-stx
|
||||||
(lambda (result)
|
(lambda (result)
|
||||||
|
@ -1121,12 +1116,11 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Endpoint Creation
|
;; Endpoint Creation
|
||||||
|
|
||||||
(define (ensure-in-endpoint-context! who)
|
|
||||||
(when (or (in-script?) (null? (current-facet-id)))
|
|
||||||
(error who "Attempt to add endpoint out of installation context; are you missing a (react ...)?")))
|
|
||||||
|
|
||||||
(define (add-endpoint! where internal? patch-fn handler-fn)
|
(define (add-endpoint! where internal? patch-fn handler-fn)
|
||||||
(ensure-in-endpoint-context! 'add-endpoint!)
|
(when (in-script?)
|
||||||
|
(error 'add-endpoint!
|
||||||
|
"~a: Cannot add endpoint in script; are you missing a (react ...)?"
|
||||||
|
where))
|
||||||
(define-values (new-eid delta-aggregate)
|
(define-values (new-eid delta-aggregate)
|
||||||
(let ()
|
(let ()
|
||||||
(define a (current-actor-state))
|
(define a (current-actor-state))
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
(require "main.rkt")
|
(require "main.rkt")
|
||||||
(require (submod "actor.rkt" for-module-begin))
|
(require (submod "actor.rkt" for-module-begin))
|
||||||
(require "store.rkt")
|
(require "store.rkt")
|
||||||
(require (only-in "core.rkt" clean-actions))
|
|
||||||
|
|
||||||
(provide (rename-out [module-begin #%module-begin])
|
(provide (rename-out [module-begin #%module-begin])
|
||||||
activate
|
activate
|
||||||
|
@ -72,13 +71,6 @@
|
||||||
#%declare
|
#%declare
|
||||||
begin-for-declarations))))
|
begin-for-declarations))))
|
||||||
|
|
||||||
(define (ensure-spawn-actions! acts)
|
|
||||||
(define cleaned-acts (clean-actions acts))
|
|
||||||
(for ([act (in-list cleaned-acts)]
|
|
||||||
#:unless (actor? act))
|
|
||||||
(raise-argument-error 'syndicate-module "top-level actor creation action" act))
|
|
||||||
cleaned-acts)
|
|
||||||
|
|
||||||
(define-syntax (syndicate-module stx)
|
(define-syntax (syndicate-module stx)
|
||||||
(syntax-parse stx
|
(syntax-parse stx
|
||||||
[(_ (action-ids ...) (form forms ...))
|
[(_ (action-ids ...) (form forms ...))
|
||||||
|
@ -97,9 +89,8 @@
|
||||||
#`(begin
|
#`(begin
|
||||||
(define-values (tmp ...) (values #,@(make-list (length (syntax->list #'(x ...))) #'#f)))
|
(define-values (tmp ...) (values #,@(make-list (length (syntax->list #'(x ...))) #'#f)))
|
||||||
(define action-id
|
(define action-id
|
||||||
(ensure-spawn-actions!
|
(capture-actor-actions
|
||||||
(capture-actor-actions
|
(lambda () (set!-values (tmp ...) e))))
|
||||||
(lambda () (set!-values (tmp ...) e)))))
|
|
||||||
(define-values (x ...) (values tmp ...))
|
(define-values (x ...) (values tmp ...))
|
||||||
(syndicate-module (action-ids ... action-id) (forms ...)))]
|
(syndicate-module (action-ids ... action-id) (forms ...)))]
|
||||||
[(head rest ...)
|
[(head rest ...)
|
||||||
|
@ -108,9 +99,8 @@
|
||||||
#`(begin #,expanded (syndicate-module (action-ids ...) (forms ...)))]
|
#`(begin #,expanded (syndicate-module (action-ids ...) (forms ...)))]
|
||||||
[else
|
[else
|
||||||
(with-syntax ([action-id (car (generate-temporaries (list #'form)))])
|
(with-syntax ([action-id (car (generate-temporaries (list #'form)))])
|
||||||
#`(begin
|
#`(begin (define action-id (capture-actor-actions (lambda () #,expanded)))
|
||||||
(define action-id (ensure-spawn-actions! (capture-actor-actions (lambda () #,expanded))))
|
(syndicate-module (action-ids ... action-id) (forms ...))))])]
|
||||||
(syndicate-module (action-ids ... action-id) (forms ...))))])]
|
|
||||||
[non-pair-syntax
|
[non-pair-syntax
|
||||||
#'(begin form (syndicate-module (action-ids ...) (forms ...)))])]
|
#'(begin form (syndicate-module (action-ids ...) (forms ...)))])]
|
||||||
[(_ (action-ids ...) ())
|
[(_ (action-ids ...) ())
|
||||||
|
|
|
@ -60,10 +60,7 @@
|
||||||
(quit))]
|
(quit))]
|
||||||
[_ #f]))
|
[_ #f]))
|
||||||
|
|
||||||
(actor (lambda (e s) (quit))
|
(message (set-timer 'tick 1000 'relative))
|
||||||
#f
|
|
||||||
(message (set-timer 'tick 1000 'relative)))
|
|
||||||
|
|
||||||
(actor ticker
|
(actor ticker
|
||||||
1
|
1
|
||||||
(patch-seq (sub (observe (set-timer ? ? ?)))
|
(patch-seq (sub (observe (set-timer ? ? ?)))
|
||||||
|
|
|
@ -7,7 +7,4 @@
|
||||||
'(;; Sam: example-plain is interactive, I think
|
'(;; Sam: example-plain is interactive, I think
|
||||||
"examples/example-plain.rkt"
|
"examples/example-plain.rkt"
|
||||||
;; Sam: for whatever reason I get a failure to load libcrypto for f-to-c
|
;; Sam: for whatever reason I get a failure to load libcrypto for f-to-c
|
||||||
"examples/actor/f-to-c.rkt"
|
"examples/actor/f-to-c.rkt"))
|
||||||
;; Sam: this test displays to stderr which the package server does not like
|
|
||||||
"tests/nested-spawn-exceptions.rkt"
|
|
||||||
))
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
(require (for-syntax syntax/parse))
|
(require (for-syntax syntax/parse))
|
||||||
(require rackunit)
|
(require rackunit)
|
||||||
(require racket/engine)
|
(require racket/engine)
|
||||||
(require racket/exn)
|
|
||||||
|
|
||||||
(define mt-scn (scn trie-empty))
|
(define mt-scn (scn trie-empty))
|
||||||
|
|
||||||
|
@ -290,7 +289,7 @@
|
||||||
;; leaf behavior function
|
;; leaf behavior function
|
||||||
(define (actor-behavior e s)
|
(define (actor-behavior e s)
|
||||||
(when e
|
(when e
|
||||||
(with-handlers ([exn:fail? (lambda (e) (printf "exception: ~v\n" (exn->string e)) (quit #:exception e (list)))])
|
(with-handlers ([exn:fail? (lambda (e) (eprintf "exception: ~v\n" e) (quit #:exception e (list)))])
|
||||||
(match-define (actor-state π-old fts) s)
|
(match-define (actor-state π-old fts) s)
|
||||||
(define-values (actions next-fts)
|
(define-values (actions next-fts)
|
||||||
(for/fold ([as '()]
|
(for/fold ([as '()]
|
||||||
|
@ -546,7 +545,7 @@
|
||||||
;; boot-actor : actor Γ -> Action
|
;; boot-actor : actor Γ -> Action
|
||||||
(define (boot-actor a Γ)
|
(define (boot-actor a Γ)
|
||||||
(with-handlers ([exn:fail? (lambda (e)
|
(with-handlers ([exn:fail? (lambda (e)
|
||||||
(printf "booting actor died with: ~a\n" (exn->string e))
|
(eprintf "booting actor died with: ~v\n" e)
|
||||||
#f)])
|
#f)])
|
||||||
(match a
|
(match a
|
||||||
[`(spawn ,O ...)
|
[`(spawn ,O ...)
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#:macro-definer-name define-assertion-expander
|
#:macro-definer-name define-assertion-expander
|
||||||
#:introducer-parameter-name current-assertion-expander-introducer
|
#:introducer-parameter-name current-assertion-expander-introducer
|
||||||
#:local-introduce-name syntax-local-assertion-expander-introduce
|
#:local-introduce-name syntax-local-assertion-expander-introduce
|
||||||
#:expander-form-predicate-name assertion-expander-form?
|
#:expander-id-predicate-name assertion-expander-id?
|
||||||
#:expander-transform-name assertion-expander-transform)
|
#:expander-transform-name assertion-expander-transform)
|
||||||
|
|
||||||
(provide (for-syntax
|
(provide (for-syntax
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
assertion-expander?
|
assertion-expander?
|
||||||
assertion-expander-proc
|
assertion-expander-proc
|
||||||
syntax-local-assertion-expander-introduce
|
syntax-local-assertion-expander-introduce
|
||||||
assertion-expander-form?
|
assertion-expander-id?
|
||||||
assertion-expander-transform)
|
assertion-expander-transform)
|
||||||
define-assertion-expander)
|
define-assertion-expander)
|
||||||
|
|
||||||
|
@ -153,8 +153,8 @@
|
||||||
bs
|
bs
|
||||||
ins))]
|
ins))]
|
||||||
|
|
||||||
[expander
|
[(expander args ...)
|
||||||
(assertion-expander-form? #'expander)
|
(assertion-expander-id? #'expander)
|
||||||
(assertion-expander-transform pat-stx (lambda (r) (walk (syntax-rearm r pat-stx))))]
|
(assertion-expander-transform pat-stx (lambda (r) (walk (syntax-rearm r pat-stx))))]
|
||||||
|
|
||||||
[(ctor p ...)
|
[(ctor p ...)
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
||||||
(provide start-tracing!)
|
|
||||||
|
|
||||||
(require racket/match)
|
(require racket/match)
|
||||||
(require racket/set)
|
(require racket/set)
|
||||||
(require racket/string)
|
(require racket/string)
|
||||||
|
@ -14,7 +12,7 @@
|
||||||
|
|
||||||
(define-logger syndicate/trace/msd)
|
(define-logger syndicate/trace/msd)
|
||||||
|
|
||||||
(define (start-tracing! output-filename)
|
(let ((output-filename (getenv "SYNDICATE_MSD")))
|
||||||
(when output-filename
|
(when output-filename
|
||||||
(define names (make-hash (list (cons '() "'ground"))))
|
(define names (make-hash (list (cons '() "'ground"))))
|
||||||
(define (open-output cause)
|
(define (open-output cause)
|
||||||
|
@ -106,5 +104,3 @@
|
||||||
(loop)))))
|
(loop)))))
|
||||||
(channel-get ch)
|
(channel-get ch)
|
||||||
(current-trace-procedures (cons msd-trace (current-trace-procedures))))))
|
(current-trace-procedures (cons msd-trace (current-trace-procedures))))))
|
||||||
|
|
||||||
(start-tracing! (getenv "SYNDICATE_MSD"))
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
*.pml
|
|
||||||
*.trail
|
|
||||||
*.rktd
|
|
||||||
*.tmp
|
|
|
@ -6,6 +6,5 @@ pan.c : leader-and-seller.pml
|
||||||
|
|
||||||
# -a to analyze, -f for (weak) fairness
|
# -a to analyze, -f for (weak) fairness
|
||||||
# -n to elide report of unreached states
|
# -n to elide report of unreached states
|
||||||
# -N spec-name to verify a particular specification
|
|
||||||
check: pan
|
check: pan
|
||||||
./pan -a -f -n
|
./pan -a -f
|
||||||
|
|
|
@ -0,0 +1,635 @@
|
||||||
|
#lang racket
|
||||||
|
|
||||||
|
;; TODO - syntax for LTL
|
||||||
|
|
||||||
|
(require "proto.rkt")
|
||||||
|
(require "ltl.rkt")
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(require rackunit)
|
||||||
|
(require "test-utils.rkt"))
|
||||||
|
|
||||||
|
;; a SpinProgram is a
|
||||||
|
;; (sprog Assignment [Listof SpinProcess] [LTL SName])
|
||||||
|
(struct sprog [assignment procs spec] #:transparent)
|
||||||
|
|
||||||
|
|
||||||
|
;; a SpinProcess is a
|
||||||
|
;; (sproc SName [Setof SName] Assignment [Listof SName] [Setof SpinState])
|
||||||
|
(struct sproc [name state-names init initial-assertions states] #:transparent)
|
||||||
|
|
||||||
|
;; an Assignment is a [Hashof SVar SValue]
|
||||||
|
|
||||||
|
;; a SName is a Symbol that is a legal variable name in Spin
|
||||||
|
|
||||||
|
;; a SVar is a
|
||||||
|
;; (svar SName SType)
|
||||||
|
(struct svar [name ty] #:transparent)
|
||||||
|
|
||||||
|
;; a SValue is one of
|
||||||
|
;; - Int
|
||||||
|
;; - Bool
|
||||||
|
;; - SName
|
||||||
|
;; and must be a valid Spin literal
|
||||||
|
|
||||||
|
;; a SType is one of
|
||||||
|
;; - 'SInt
|
||||||
|
;; - 'SBool
|
||||||
|
;; - 'mtype
|
||||||
|
(define SInt 'SInt)
|
||||||
|
(define SBool 'SBool)
|
||||||
|
(define mtype 'mtype)
|
||||||
|
|
||||||
|
;; a SpinState is a
|
||||||
|
;; (sstate SName [Sequenceof SBranch])
|
||||||
|
(struct sstate [name branches] #:transparent)
|
||||||
|
|
||||||
|
;; a SBranch is a
|
||||||
|
;; (sbranch D+ SName [Listof SAction])
|
||||||
|
(struct sbranch [event dest actions] #:transparent)
|
||||||
|
|
||||||
|
;; a SAction is one of
|
||||||
|
;; - (assert ?)
|
||||||
|
;; - (retract ?)
|
||||||
|
;; - (send ?)
|
||||||
|
;; - (incorporate D+)
|
||||||
|
;; - (transition-to SName)
|
||||||
|
(struct assert [ty] #:transparent)
|
||||||
|
(struct retract [ty] #:transparent)
|
||||||
|
;; send defined in proto.rkt
|
||||||
|
(struct incorporate [evt] #:transparent)
|
||||||
|
(struct transition-to [dest] #:transparent)
|
||||||
|
|
||||||
|
;; each process has a local variable that determines its current state
|
||||||
|
(define CURRENT-STATE (svar 'current mtype))
|
||||||
|
|
||||||
|
;; a NameEnvironment is a [Hashof τ SName]
|
||||||
|
|
||||||
|
;; [Sequenceof RoleGraph] [LTL τ] -> SpinProgram
|
||||||
|
(define (program->spin rgs [spec #t])
|
||||||
|
(define assertion-tys (all-assertions rgs))
|
||||||
|
(define event-tys (all-events rgs))
|
||||||
|
(define event-subty# (make-event-map assertion-tys event-tys))
|
||||||
|
(define all-mentioned-tys (set-union assertion-tys event-tys))
|
||||||
|
(define name-env (make-name-env all-mentioned-tys))
|
||||||
|
(define globals (initial-assertion-vars-for all-mentioned-tys name-env))
|
||||||
|
(define procs (for/list ([rg rgs]) (rg->spin rg event-subty# name-env)))
|
||||||
|
(define spec-spin (rename-ltl spec name-env))
|
||||||
|
(sprog globals procs spec-spin))
|
||||||
|
|
||||||
|
;; RoleGraph [Hashof τ [Setof τ]] NameEnvironment -> SpinProcess
|
||||||
|
(define (rg->spin rg event-subty# name-env #:name [name (gensym 'proc)])
|
||||||
|
(match-define (role-graph st0 states) rg)
|
||||||
|
(define all-events (all-event-types (in-hash-values states)))
|
||||||
|
(define state-renaming (make-state-rename (hash-keys states)))
|
||||||
|
(define states- (for/list ([st (in-hash-values states)])
|
||||||
|
(state->spin st states event-subty# name-env state-renaming)))
|
||||||
|
(define st0- (hash-ref state-renaming st0))
|
||||||
|
;; ergh the invariant for when I tack on _assertions to a name is getting tricksy
|
||||||
|
(define st0-assertions (rename-all name-env (super-type-closure (state-assertions (hash-ref states st0)) event-subty#)))
|
||||||
|
(define assignment (local-variables-for st0- all-events name-env))
|
||||||
|
(sproc name (hash-values-set state-renaming) assignment st0-assertions (list->set states-)))
|
||||||
|
|
||||||
|
;; State [Sequenceof State] [Hashof τ [Setof τ]] NameEnvironment [Hashof StateName SName] -> SpinState
|
||||||
|
(define (state->spin st states event-subty# name-env state-env)
|
||||||
|
(match-define (state name transitions assertions) st)
|
||||||
|
(define name- (hash-ref state-env name))
|
||||||
|
(define branches (for*/list ([(D+ txns) (in-hash transitions)]
|
||||||
|
[txn (in-set txns)])
|
||||||
|
(match-define (transition effs dest) txn)
|
||||||
|
(match-define (state _ _ dest-assertions) (hash-ref states dest))
|
||||||
|
(define dest- (hash-ref state-env dest))
|
||||||
|
(branch-on D+ assertions dest- dest-assertions effs event-subty# name-env)))
|
||||||
|
(sstate name- branches))
|
||||||
|
|
||||||
|
;; [Setof τ] -> NameEnvironment
|
||||||
|
(define (make-name-env tys)
|
||||||
|
(let loop ([name-depth 3])
|
||||||
|
(when (> name-depth 10)
|
||||||
|
(raise-argument-error 'make-name-env "types able to be named" tys))
|
||||||
|
(define renaming
|
||||||
|
(for/hash ([ty (in-set tys)])
|
||||||
|
(values ty
|
||||||
|
(type->id ty #:depth name-depth))))
|
||||||
|
(define names (hash-values-set renaming))
|
||||||
|
(cond
|
||||||
|
[(equal? (set-count names) (set-count tys))
|
||||||
|
renaming]
|
||||||
|
[else
|
||||||
|
(loop (add1 name-depth))])))
|
||||||
|
|
||||||
|
;; SName -> SName
|
||||||
|
(define (assertions-var-name s)
|
||||||
|
(string->symbol (format "~a_assertions" s)))
|
||||||
|
|
||||||
|
;; SName -> SName
|
||||||
|
(define (active-var-name s)
|
||||||
|
(string->symbol (format "know_~a" s)))
|
||||||
|
|
||||||
|
;; [Setof τ] [Setof τ] -> [Hashof τ [Setof τ]]
|
||||||
|
(define (make-event-map assertion-tys event-tys)
|
||||||
|
;; TODO - potentially use non-empty intersection
|
||||||
|
(for/hash ([a (in-set assertion-tys)])
|
||||||
|
(values a
|
||||||
|
(all-supertypes-of a event-tys))))
|
||||||
|
|
||||||
|
;; τ [Setof τ] -> [Setof τ]
|
||||||
|
(define (all-supertypes-of τ tys)
|
||||||
|
(for*/set ([ty (in-set tys)]
|
||||||
|
#:when (<:? τ ty))
|
||||||
|
ty))
|
||||||
|
|
||||||
|
;; [Setof τ] [Hashof τ [Setof τ]]
|
||||||
|
(define (super-type-closure asserts event-subty#)
|
||||||
|
(for*/set ([a (in-set asserts)]
|
||||||
|
[supers (in-value (hash-ref event-subty# a))]
|
||||||
|
[τ (in-set (set-add supers a))])
|
||||||
|
τ))
|
||||||
|
|
||||||
|
;; [Setof τ] NameEnvironment -> Assignment
|
||||||
|
(define (initial-assertion-vars-for assertion-tys name-env)
|
||||||
|
(for/hash ([τ (in-set assertion-tys)])
|
||||||
|
(values (svar (assertions-var-name (hash-ref name-env τ)) SInt)
|
||||||
|
0)))
|
||||||
|
|
||||||
|
;; NameEnvironment [Setof τ] -> [Sequenceof SName]
|
||||||
|
(define (rename-all name-env asserts)
|
||||||
|
(for/set ([a (in-set asserts)])
|
||||||
|
(hash-ref name-env a)))
|
||||||
|
|
||||||
|
;; [Sequenceof RoleGraph] -> [Setof τ]
|
||||||
|
(define (all-assertions rgs)
|
||||||
|
;; RoleGraph -> (Setof τ)
|
||||||
|
(define (all-assertions-of rg)
|
||||||
|
(for*/set ([st (in-hash-values (role-graph-states rg))]
|
||||||
|
[τ (in-set (state-assertions st))])
|
||||||
|
τ))
|
||||||
|
(for/fold ([as (set)])
|
||||||
|
([rg rgs])
|
||||||
|
(set-union as (all-assertions-of rg))))
|
||||||
|
|
||||||
|
;; [Sequenceof RoleGraph] -> [Setof τ]
|
||||||
|
(define (all-events rgs)
|
||||||
|
;; RoleGraph -> (Setof τ)
|
||||||
|
(define (all-events-of rg)
|
||||||
|
(all-event-types (hash-values (role-graph-states rg))))
|
||||||
|
(for/fold ([as (set)])
|
||||||
|
([rg rgs])
|
||||||
|
(set-union as (all-events-of rg)))
|
||||||
|
)
|
||||||
|
|
||||||
|
;; [Sequenceof State] -> ?
|
||||||
|
(define (all-event-types states)
|
||||||
|
(for*/set ([st states]
|
||||||
|
[D+ (in-hash-keys (state-transitions st))])
|
||||||
|
(match D+
|
||||||
|
[(or (Asserted τ) (Retracted τ))
|
||||||
|
τ]
|
||||||
|
[(Message τ)
|
||||||
|
(raise-argument-error 'all-event-types "messages not supported yet" D+)]
|
||||||
|
[_
|
||||||
|
(raise-argument-error 'all-event-types "internal events not allowed" D+)])))
|
||||||
|
|
||||||
|
;; SName [Setof τ] NameEnvironment -> Assignment
|
||||||
|
(define (local-variables-for st0 all-events name-env)
|
||||||
|
(define assign
|
||||||
|
(for/hash ([evt (in-set all-events)])
|
||||||
|
(values (svar (active-var-name (hash-ref name-env evt))
|
||||||
|
SBool)
|
||||||
|
#f)))
|
||||||
|
(hash-set assign CURRENT-STATE st0))
|
||||||
|
|
||||||
|
;; D+ [Setof τ] SName [Setof τ] [Listof TransitionEffect] [Hashof τ [Setof τ]] NameEnvironment -> SBranch
|
||||||
|
(define (branch-on D+ curr-assertions dest dest-assertions effs event-subty# name-env)
|
||||||
|
(define new-assertions (super-type-closure (set-subtract dest-assertions curr-assertions) event-subty#))
|
||||||
|
(define retractions (super-type-closure (set-subtract curr-assertions dest-assertions) event-subty#))
|
||||||
|
(define (lookup ty) (hash-ref name-env ty))
|
||||||
|
(define asserts (set-map new-assertions (compose assert lookup)))
|
||||||
|
(define retracts (set-map retractions (compose retract lookup)))
|
||||||
|
(unless (empty? effs)
|
||||||
|
(raise-argument-error 'branch-on "messages not supported" effs))
|
||||||
|
(define renamed-evt (rename-event D+ name-env))
|
||||||
|
(sbranch renamed-evt dest (list* (transition-to dest)
|
||||||
|
(incorporate renamed-evt)
|
||||||
|
(append asserts retracts effs))))
|
||||||
|
|
||||||
|
;; D+ NameEnvironment -> D+
|
||||||
|
(define (rename-event D+ name-env)
|
||||||
|
(match D+
|
||||||
|
[(Asserted τ)
|
||||||
|
(Asserted (hash-ref name-env τ))]
|
||||||
|
[(Retracted τ)
|
||||||
|
(Retracted (hash-ref name-env τ))]
|
||||||
|
[(Message τ)
|
||||||
|
(raise-argument-error 'rename-event "messages not implemented yet" D+)]))
|
||||||
|
|
||||||
|
;; [LTL τ] -> [LTL SName]
|
||||||
|
(define (rename-ltl ltl name-env)
|
||||||
|
(define (lookup τ) (hash-ref name-env τ))
|
||||||
|
(map-atomic ltl lookup))
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(test-case
|
||||||
|
"sanity: compile book seller type"
|
||||||
|
(define/timeout seller-rg (compile seller-actual))
|
||||||
|
(define name-env (hash
|
||||||
|
(Observe (Observe (Struct 'BookQuoteT (list (Base 'String) (Mk⋆)))))
|
||||||
|
'Obs_Obs_BookQuoteT
|
||||||
|
(Observe (Struct 'BookQuoteT (list (Base 'String) (Mk⋆))))
|
||||||
|
'Obs_BookQuoteT_String_star
|
||||||
|
(Struct 'BookQuoteT (list (Base 'String) (U (list (Base 'Int) (Base 'Int)))))
|
||||||
|
'BookQuoteT_String_U_Int_Int))
|
||||||
|
(define event# (hash
|
||||||
|
(Observe (Observe (Struct 'BookQuoteT (list (Base 'String) (Mk⋆)))))
|
||||||
|
(set)
|
||||||
|
(Struct 'BookQuoteT (list (Base 'String) (U (list (Base 'Int) (Base 'Int)))))
|
||||||
|
(set)))
|
||||||
|
(define/timeout seller-spin (rg->spin seller-rg event# name-env))
|
||||||
|
(check-true (sproc? seller-spin))))
|
||||||
|
|
||||||
|
(define tab-level (make-parameter 0))
|
||||||
|
|
||||||
|
(define TAB-WIDTH 2)
|
||||||
|
|
||||||
|
(define (indent)
|
||||||
|
(display (make-string (* TAB-WIDTH (tab-level)) #\space)))
|
||||||
|
|
||||||
|
(define-syntax-rule (with-indent bdy ...)
|
||||||
|
(parameterize ([tab-level (add1 (tab-level))])
|
||||||
|
bdy ...))
|
||||||
|
|
||||||
|
(define SPIN_ID_RX #rx"[a-zA-Z][a-zA-Z0-9_]*")
|
||||||
|
(define SPIN_ID_TRAILING_CHAR #rx"[a-zA-Z0-9_]+")
|
||||||
|
|
||||||
|
;; (U Symbol String) -> Bool
|
||||||
|
(define (spin-id? s)
|
||||||
|
(when (symbol? s)
|
||||||
|
(set! s (symbol->string s)))
|
||||||
|
(regexp-match? SPIN_ID_RX s))
|
||||||
|
|
||||||
|
(define SPIN-KEYWORDS
|
||||||
|
'(active assert atomic bit bool break byte chan d_step D_proctype do
|
||||||
|
else empty enabled fi full goto hidden if init int len mtype nempty
|
||||||
|
never nfull od of pc_value printf priority proctype provided run
|
||||||
|
short skip timeout typedef unless unsigned xr xs))
|
||||||
|
|
||||||
|
;; Symbol -> Symbol
|
||||||
|
(define (unkeyword s)
|
||||||
|
(if (member s SPIN-KEYWORDS)
|
||||||
|
(gensym s)
|
||||||
|
s))
|
||||||
|
|
||||||
|
;; (U Symbol String) -> SName
|
||||||
|
(define (make-spin-id s)
|
||||||
|
(when (symbol? s)
|
||||||
|
(set! s (symbol->string s)))
|
||||||
|
(define with_legal_prefix (string-append "ty_" s))
|
||||||
|
(match (regexp-match* SPIN_ID_TRAILING_CHAR with_legal_prefix)
|
||||||
|
['("ty_")
|
||||||
|
(raise-argument-error 'make-spin-id "unable to make spin id" s)]
|
||||||
|
[(cons fst rst)
|
||||||
|
(define match-str (apply string-append fst rst))
|
||||||
|
(define without-added-prefix (substring match-str 3))
|
||||||
|
(if (spin-id? without-added-prefix)
|
||||||
|
(unkeyword (string->symbol without-added-prefix))
|
||||||
|
(unkeyword (string->symbol match-str)))]))
|
||||||
|
|
||||||
|
;; τ -> SName
|
||||||
|
(define (type->id ty #:depth [depth 3])
|
||||||
|
(define ctors (type-constructors ty depth))
|
||||||
|
(define rough-name (string-join (map symbol->string ctors) "_"))
|
||||||
|
(make-spin-id rough-name))
|
||||||
|
|
||||||
|
;; [Listof StateName] -> [Hashof StateName SName]
|
||||||
|
(define (make-state-rename state-names)
|
||||||
|
(let loop ([prefix 3])
|
||||||
|
(define renaming (for/hash ([nm (in-list state-names)])
|
||||||
|
(values nm
|
||||||
|
(state-name->spin-id nm #:prefix prefix))))
|
||||||
|
(define distinct-names (hash-values-set renaming))
|
||||||
|
(cond
|
||||||
|
[(equal? (set-count distinct-names) (set-count state-names))
|
||||||
|
renaming]
|
||||||
|
[(> prefix 20)
|
||||||
|
(raise-argument-error 'make-state-rename "able to make renaming" state-names)]
|
||||||
|
[else
|
||||||
|
(loop (add1 prefix))])))
|
||||||
|
|
||||||
|
;; StateName -> SName
|
||||||
|
(define (state-name->spin-id nm #:prefix [prefix 3])
|
||||||
|
(cond
|
||||||
|
[(set-empty? nm)
|
||||||
|
(gensym 'inert)]
|
||||||
|
[else
|
||||||
|
(define (take-prefix s) (substring s 0 (min prefix (string-length s))))
|
||||||
|
(define rough-name (string-join (set-map nm (compose take-prefix symbol->string)) "_"))
|
||||||
|
(make-spin-id rough-name)]))
|
||||||
|
|
||||||
|
;; τ -> [Listof Symbol]
|
||||||
|
(define (type-constructors ty depth)
|
||||||
|
(cond
|
||||||
|
[(zero? depth) '()]
|
||||||
|
[else
|
||||||
|
(match ty
|
||||||
|
[(Struct name tys)
|
||||||
|
;; TODO - consider camel-casing struct name
|
||||||
|
(cons name (append-map (λ (ty) (type-constructors ty (sub1 depth))) tys))]
|
||||||
|
[(Observe ty)
|
||||||
|
(cons 'Obs (type-constructors ty (sub1 depth)))]
|
||||||
|
[(U tys)
|
||||||
|
(cons 'U (append-map (λ (ty) (type-constructors ty (sub1 depth))) tys))]
|
||||||
|
[(== ⋆)
|
||||||
|
(list 'star)]
|
||||||
|
[(Base name)
|
||||||
|
(list name)]
|
||||||
|
[(List _)
|
||||||
|
(list 'List)]
|
||||||
|
[(Set _)
|
||||||
|
(list 'Set)]
|
||||||
|
[(Hash _ _)
|
||||||
|
(list 'Hash)]
|
||||||
|
[(internal-label _ _)
|
||||||
|
(raise-argument-error 'type-constructors "internal events not supported" ty)])]))
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(test-case
|
||||||
|
"type-constructors basics"
|
||||||
|
(define bi (Struct 'BookInterestT (list (Base 'String) (Base 'String) (Base 'Bool))))
|
||||||
|
(check-equal? (type-constructors bi 1)
|
||||||
|
'(BookInterestT))
|
||||||
|
(check-equal? (type-constructors bi 2)
|
||||||
|
'(BookInterestT String String Bool))
|
||||||
|
(check-equal? (type-constructors bi 3)
|
||||||
|
'(BookInterestT String String Bool))
|
||||||
|
(check-equal? (type-constructors (Observe bi) 3)
|
||||||
|
'(Obs BookInterestT String String Bool)))
|
||||||
|
(test-case
|
||||||
|
"type->id basics"
|
||||||
|
(define bi (Struct 'BookInterestT (list (Base 'String) (Base 'String) (Base 'Bool))))
|
||||||
|
(check-equal? (type->id bi)
|
||||||
|
'BookInterestT_String_String_Bool)
|
||||||
|
(check-equal? (type->id (Observe bi))
|
||||||
|
'Obs_BookInterestT_String_String_Bool)
|
||||||
|
(check-equal? (type->id (Struct 'hi-mom '()))
|
||||||
|
'himom)
|
||||||
|
(check-equal? (type->id bi #:depth 1)
|
||||||
|
'BookInterestT)
|
||||||
|
(check-exn exn:fail?
|
||||||
|
(lambda () (type->id (Struct '--- '())))
|
||||||
|
"unable to make spin id")))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Code Generation
|
||||||
|
|
||||||
|
(define SPIN-PRELUDE (file->string "spin-prelude.pml"))
|
||||||
|
|
||||||
|
;; SpinThang FilePath -> Void
|
||||||
|
(define (gen-spin/to-file spin name)
|
||||||
|
(with-output-to-file name
|
||||||
|
(lambda () (gen-spin spin))
|
||||||
|
#:mode 'text
|
||||||
|
#:exists 'replace))
|
||||||
|
|
||||||
|
;; SpinThang -> Void
|
||||||
|
(define (gen-spin spin)
|
||||||
|
(match spin
|
||||||
|
[(sprog assignment procs spec)
|
||||||
|
(display SPIN-PRELUDE)
|
||||||
|
(gen-assignment assignment)
|
||||||
|
(newline)
|
||||||
|
(for ([p procs])
|
||||||
|
(gen-spin p)
|
||||||
|
(newline))
|
||||||
|
(gen-spec "spec" (lambda () (gen-ltl spec)))
|
||||||
|
(newline)
|
||||||
|
(gen-sanity-ltl assignment)]
|
||||||
|
[(sproc name state-names init asserts states)
|
||||||
|
(indent) (declare-mtype state-names)
|
||||||
|
(indent) (printf "active proctype ~a() {\n" name)
|
||||||
|
(with-indent
|
||||||
|
(gen-assignment init)
|
||||||
|
(for ([a asserts])
|
||||||
|
(gen-spin (assert a)))
|
||||||
|
(indent) (displayln "end: do")
|
||||||
|
(with-indent
|
||||||
|
(for ([st states])
|
||||||
|
(gen-spin st)))
|
||||||
|
(indent) (displayln "od;")
|
||||||
|
)
|
||||||
|
(indent) (displayln "}")]
|
||||||
|
[(sstate name branches)
|
||||||
|
(indent) (printf ":: ~a == ~a ->\n" (svar-name CURRENT-STATE) name)
|
||||||
|
(with-indent
|
||||||
|
(indent) (displayln "if")
|
||||||
|
(with-indent
|
||||||
|
(cond
|
||||||
|
[(empty? branches)
|
||||||
|
(indent) (displayln ":: true -> skip;")]
|
||||||
|
[else
|
||||||
|
(for ([branch branches])
|
||||||
|
(gen-spin branch))]))
|
||||||
|
(indent) (displayln "fi;"))]
|
||||||
|
[(sbranch event dest actions)
|
||||||
|
(indent) (printf ":: ~a ->\n" (predicate-for event))
|
||||||
|
;; TODO - make the body atomic
|
||||||
|
(with-indent
|
||||||
|
(indent) (displayln "atomic {")
|
||||||
|
(with-indent
|
||||||
|
(for ([act actions])
|
||||||
|
(gen-spin act)))
|
||||||
|
(indent) (displayln "}"))]
|
||||||
|
[(assert x)
|
||||||
|
(indent) (printf "ASSERT(~a);\n" x)]
|
||||||
|
[(retract x)
|
||||||
|
(indent) (printf "RETRACT(~a);\n" x)]
|
||||||
|
[(send x)
|
||||||
|
(raise-argument-error 'gen-spin "message sending not supported yet" spin)]
|
||||||
|
[(incorporate evt)
|
||||||
|
(indent) (update-for evt)]
|
||||||
|
[(transition-to dest)
|
||||||
|
(indent) (printf "~a = ~a;\n" (svar-name CURRENT-STATE) dest)]))
|
||||||
|
|
||||||
|
;; [Setof SName] -> Void
|
||||||
|
(define (declare-mtype state-names)
|
||||||
|
(display "mtype = {")
|
||||||
|
(display (string-join (set-map state-names symbol->string) ", "))
|
||||||
|
(displayln "}"))
|
||||||
|
|
||||||
|
;; Assignment -> Void
|
||||||
|
(define (gen-assignment assign)
|
||||||
|
(for ([(var val) (in-hash assign)])
|
||||||
|
(indent) (printf "~a = ~a;\n"
|
||||||
|
(declare-var var)
|
||||||
|
(spin-val->string val))))
|
||||||
|
|
||||||
|
;; SVar -> Void
|
||||||
|
(define (declare-var var)
|
||||||
|
(match-define (svar name ty) var)
|
||||||
|
(format "~a ~a" (spin-type->string ty) name))
|
||||||
|
|
||||||
|
;; SValue -> String
|
||||||
|
(define (spin-val->string v)
|
||||||
|
(cond
|
||||||
|
[(boolean? v)
|
||||||
|
(if v "true" "false")]
|
||||||
|
[(exact-integer? v)
|
||||||
|
(~a v)]
|
||||||
|
[(symbol? v)
|
||||||
|
(~a v)]))
|
||||||
|
|
||||||
|
;; SType -> String
|
||||||
|
(define (spin-type->string ty)
|
||||||
|
(match ty
|
||||||
|
[(== SInt) "int"]
|
||||||
|
[(== SBool) "bool"]
|
||||||
|
[(== mtype) "mtype"]))
|
||||||
|
|
||||||
|
;; D+ -> String
|
||||||
|
(define (predicate-for event)
|
||||||
|
(match event
|
||||||
|
[(Asserted nm)
|
||||||
|
(define assertion-var nm)
|
||||||
|
(define active-var (active-var-name nm))
|
||||||
|
(format "ASSERTED(~a) && !~a" assertion-var active-var)]
|
||||||
|
[(Retracted nm)
|
||||||
|
(define assertion-var nm)
|
||||||
|
(define active-var (active-var-name nm))
|
||||||
|
(format "RETRACTED(~a) && ~a" assertion-var active-var)]
|
||||||
|
[(Message nm)
|
||||||
|
(raise-argument-error 'predicate-for "message sending not supported yet" event)]))
|
||||||
|
|
||||||
|
;; D+ -> Void
|
||||||
|
(define (update-for event)
|
||||||
|
(match event
|
||||||
|
[(Asserted nm)
|
||||||
|
(define active-var (active-var-name nm))
|
||||||
|
(printf "~a = ~a;\n" active-var (spin-val->string #t))]
|
||||||
|
[(Retracted nm)
|
||||||
|
(define active-var (active-var-name nm))
|
||||||
|
(printf "~a = ~a;\n" active-var (spin-val->string #f))]
|
||||||
|
[(Message nm)
|
||||||
|
(raise-argument-error 'predicate-for "message sending not supported yet" event)]))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; LTL
|
||||||
|
|
||||||
|
;; String {-> Void} -> Void
|
||||||
|
(define (gen-spec name mk-body)
|
||||||
|
(indent) (printf "ltl ~a {\n" name)
|
||||||
|
(with-indent
|
||||||
|
(mk-body))
|
||||||
|
(newline)
|
||||||
|
(indent) (displayln "}"))
|
||||||
|
|
||||||
|
;; [LTL SName] -> Void
|
||||||
|
(define (gen-ltl ltl)
|
||||||
|
(match ltl
|
||||||
|
[(always p)
|
||||||
|
(indent) (displayln "[](")
|
||||||
|
(with-indent
|
||||||
|
(gen-ltl p))
|
||||||
|
(indent) (displayln ")")]
|
||||||
|
[(eventually p)
|
||||||
|
(indent) (displayln "<>(")
|
||||||
|
(with-indent
|
||||||
|
(gen-ltl p))
|
||||||
|
(indent) (displayln ")")]
|
||||||
|
[(weak-until p q)
|
||||||
|
(gen-ltl-bin-op "W" p q)]
|
||||||
|
[(strong-until p q)
|
||||||
|
(gen-ltl-bin-op "U" p q)]
|
||||||
|
[(ltl-implies p q)
|
||||||
|
(gen-ltl-bin-op "->" p q)]
|
||||||
|
[(ltl-and p q)
|
||||||
|
(gen-ltl-bin-op "&&" p q)]
|
||||||
|
[(ltl-or p q)
|
||||||
|
(gen-ltl-bin-op "||" p q)]
|
||||||
|
[(ltl-not p)
|
||||||
|
(indent) (display "!(")
|
||||||
|
(gen-ltl p)
|
||||||
|
(displayln ")")]
|
||||||
|
[(atomic nm)
|
||||||
|
(printf "ASSERTED(~a)\n" nm)]
|
||||||
|
[#t
|
||||||
|
(display "true")]
|
||||||
|
[#f
|
||||||
|
(display "false")]))
|
||||||
|
|
||||||
|
;; String [LTL SName] [LTL SName] -> Void
|
||||||
|
(define (gen-ltl-bin-op name p q)
|
||||||
|
(indent) (display "(") (gen-ltl p) (display ") ")
|
||||||
|
(displayln name)
|
||||||
|
(newline)
|
||||||
|
(indent) (display "(") (gen-ltl q) (displayln ")"))
|
||||||
|
|
||||||
|
;; Assignment -> Void
|
||||||
|
(define (gen-sanity-ltl assignment)
|
||||||
|
(gen-spec "sanity"
|
||||||
|
(lambda ()
|
||||||
|
(indent) (displayln "[](")
|
||||||
|
(with-indent
|
||||||
|
(for ([assertion-var (in-hash-keys assignment)])
|
||||||
|
(indent) (printf "~a >= 0 &&\n" (svar-name assertion-var)))
|
||||||
|
(indent) (displayln "true"))
|
||||||
|
(indent) (displayln ")"))))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Misc Utils
|
||||||
|
|
||||||
|
;; [Hashof K V] -> [Setof V]
|
||||||
|
(define (hash-values-set h)
|
||||||
|
(for/set ([x (in-hash-values h)])
|
||||||
|
x))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Test Case
|
||||||
|
|
||||||
|
(module+ leader-and-seller
|
||||||
|
(define leader-rg (compile (parse-T
|
||||||
|
'(Role ; = react
|
||||||
|
(get-quotes)
|
||||||
|
(Reacts ; = on
|
||||||
|
(Asserted (BookQuoteT String (Bind Int)))
|
||||||
|
(Branch
|
||||||
|
(Effs (Branch (Effs (Stop get-quotes)) (Effs)))
|
||||||
|
(Effs
|
||||||
|
(Role
|
||||||
|
(poll-members)
|
||||||
|
(Reacts
|
||||||
|
(Asserted (BookInterestT String (Bind String) Discard))
|
||||||
|
(Branch
|
||||||
|
(Effs (Stop poll-members (Branch (Effs (Stop get-quotes)) (Effs))))
|
||||||
|
(Effs))
|
||||||
|
(Branch
|
||||||
|
(Effs
|
||||||
|
(Stop get-quotes (Role (announce) (Shares (BookOfTheMonthT String)))))
|
||||||
|
(Effs)))
|
||||||
|
(Reacts (Retracted (BookInterestT String (Bind String) Bool)))
|
||||||
|
(Reacts (Asserted (BookInterestT String (Bind String) Bool)))
|
||||||
|
(Reacts (Retracted (BookInterestT String (Bind String) Bool)))
|
||||||
|
(Reacts (Asserted (BookInterestT String (Bind String) Bool)))))))
|
||||||
|
(Reacts (Retracted (ClubMemberT (Bind String))))
|
||||||
|
(Reacts (Asserted (ClubMemberT (Bind String))))))))
|
||||||
|
(define seller-rg (compile seller-actual))
|
||||||
|
(define member-rg (compile member-actual))
|
||||||
|
(define bq (book-quote String ⋆))
|
||||||
|
(define bi (book-interest String ⋆ ⋆))
|
||||||
|
(define book-club-spec
|
||||||
|
(&& (eventually (atomic bq))
|
||||||
|
(always (ltl-implies (atomic (Observe bq))
|
||||||
|
(eventually (atomic bq))))
|
||||||
|
(always (ltl-implies (atomic (Observe bi))
|
||||||
|
(eventually (atomic bi))))))
|
||||||
|
(define book-club-spin (program->spin (list leader-rg seller-rg member-rg)
|
||||||
|
book-club-spec))
|
||||||
|
(gen-spin/to-file book-club-spin "gen-book-club.pml"))
|
||||||
|
|
||||||
|
(module+ flink
|
||||||
|
(define (import r)
|
||||||
|
(define r+ (parse-T r))
|
||||||
|
(compile/internal-events (compile r+) #f))
|
||||||
|
(define jm-rg (import job-manager-actual))
|
||||||
|
(define tm-rg (import task-manager-ty))
|
||||||
|
(define tr-rg (import task-runner-ty))
|
||||||
|
(define flink-spin (program->spin (list tr-rg tm-rg jm-rg)))
|
||||||
|
(gen-spin/to-file flink-spin "gen-flink.pml"))
|
|
@ -17,8 +17,6 @@
|
||||||
error
|
error
|
||||||
define-tuple
|
define-tuple
|
||||||
match-define
|
match-define
|
||||||
mk-tuple
|
|
||||||
tuple-select
|
|
||||||
(for-syntax (all-defined-out)))
|
(for-syntax (all-defined-out)))
|
||||||
|
|
||||||
(require "core-types.rkt")
|
(require "core-types.rkt")
|
||||||
|
@ -44,30 +42,39 @@
|
||||||
|
|
||||||
;; copied from stlc
|
;; copied from stlc
|
||||||
(define-typed-syntax (ann e (~optional (~datum :)) τ:type) ≫
|
(define-typed-syntax (ann e (~optional (~datum :)) τ:type) ≫
|
||||||
[⊢ e ≫ e- (⇐ : τ.norm) (⇒ ν (~effs eff ...))]
|
[⊢ e ≫ e- (⇐ : τ.norm)]
|
||||||
|
#:fail-unless (pure? #'e-) "expression must be pure"
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
[⊢ e- (⇒ : τ.norm) (⇒ ν (eff ...))])
|
[⊢ e- (⇒ : τ.norm) ])
|
||||||
|
|
||||||
;; copied from ext-stlc
|
;; copied from ext-stlc
|
||||||
(define-typed-syntax if
|
(define-typed-syntax if
|
||||||
[(_ e_tst e1 e2) ⇐ τ-expected ≫
|
[(_ e_tst e1 e2) ⇐ τ-expected ≫
|
||||||
[⊢ e_tst ≫ e_tst- ⇒ _] ; Any non-false value is truthy.
|
[⊢ e_tst ≫ e_tst- ⇒ _] ; Any non-false value is truthy.
|
||||||
#:fail-unless (pure? #'e_tst-) "expression must be pure"
|
#:fail-unless (pure? #'e_tst-) "expression must be pure"
|
||||||
[⊢ e1 ≫ e1- (⇐ : τ-expected) (⇒ ν (~effs eff1 ...))]
|
[⊢ e1 ≫ e1- (⇐ : τ-expected)
|
||||||
[⊢ e2 ≫ e2- (⇐ : τ-expected) (⇒ ν (~effs eff2 ...))]
|
(⇒ ν-ep (~effs eps1 ...)) (⇒ ν-f (~effs fs1 ...)) (⇒ ν-s (~effs ss1 ...))]
|
||||||
|
[⊢ e2 ≫ e2- (⇐ : τ-expected)
|
||||||
|
(⇒ ν-ep (~effs eps2 ...)) (⇒ ν-f (~effs fs2 ...)) (⇒ ν-s (~effs ss2 ...))]
|
||||||
--------
|
--------
|
||||||
[⊢ (if- e_tst- e1- e2-)
|
[⊢ (if- e_tst- e1- e2-)
|
||||||
(⇒ : τ-expected)
|
(⇒ : τ-expected)
|
||||||
(⇒ ν #,(make-Branch #'((eff1 ...) (eff2 ...))))]]
|
(⇒ ν-ep (eps1 ... eps2 ...))
|
||||||
|
(⇒ ν-f #,(make-Branch #'((fs1 ...) (fs2 ...))))
|
||||||
|
(⇒ ν-s (ss1 ... ss2 ...))]]
|
||||||
[(_ e_tst e1 e2) ≫
|
[(_ e_tst e1 e2) ≫
|
||||||
[⊢ e_tst ≫ e_tst- ⇒ _] ; Any non-false value is truthy.
|
[⊢ e_tst ≫ e_tst- ⇒ _] ; Any non-false value is truthy.
|
||||||
#:fail-unless (pure? #'e_tst-) "expression must be pure"
|
#:fail-unless (pure? #'e_tst-) "expression must be pure"
|
||||||
[⊢ e1 ≫ e1- (⇒ : τ1) (⇒ ν (~effs eff1 ...))]
|
[⊢ e1 ≫ e1- (⇒ : τ1)
|
||||||
[⊢ e2 ≫ e2- (⇒ : τ2) (⇒ ν (~effs eff2 ...))]
|
(⇒ ν-ep (~effs eps1 ...)) (⇒ ν-f (~effs fs1 ...)) (⇒ ν-s (~effs ss1 ...))]
|
||||||
|
[⊢ e2 ≫ e2- (⇒ : τ2)
|
||||||
|
(⇒ ν-ep (~effs eps2 ...)) (⇒ ν-f (~effs fs2 ...)) (⇒ ν-s (~effs ss2 ...))]
|
||||||
#:with τ (mk-U- #'(τ1 τ2))
|
#:with τ (mk-U- #'(τ1 τ2))
|
||||||
--------
|
--------
|
||||||
[⊢ (if- e_tst- e1- e2-) (⇒ : τ)
|
[⊢ (if- e_tst- e1- e2-) (⇒ : τ)
|
||||||
(⇒ ν #,(make-Branch #'((eff1 ...) (eff2 ...))))]])
|
(⇒ ν-ep (eps1 ... eps2 ...))
|
||||||
|
(⇒ ν-f #,(make-Branch #'((fs1 ...) (fs2 ...))))
|
||||||
|
(⇒ ν-s (ss1 ... ss2 ...))]])
|
||||||
|
|
||||||
(define-typed-syntax (when e s ...+) ≫
|
(define-typed-syntax (when e s ...+) ≫
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
@ -84,18 +91,26 @@
|
||||||
[⊢ e ≫ e- ⇒ : τ_x] ...
|
[⊢ e ≫ e- ⇒ : τ_x] ...
|
||||||
#:fail-unless (stx-andmap pure? #'(e- ...)) "expressions must be pure"
|
#:fail-unless (stx-andmap pure? #'(e- ...)) "expressions must be pure"
|
||||||
[[x ≫ x- : τ_x] ... ⊢ (block e_body ...) ≫ e_body- (⇐ : τ_expected)
|
[[x ≫ x- : τ_x] ... ⊢ (block e_body ...) ≫ e_body- (⇐ : τ_expected)
|
||||||
(⇒ ν (~effs eff ...))]
|
(⇒ ν-ep (~effs eps ...))
|
||||||
|
(⇒ ν-f (~effs fs ...))
|
||||||
|
(⇒ ν-s (~effs ss ...))]
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
[⊢ (let- ([x- e-] ...) e_body-) (⇒ : τ_expected)
|
[⊢ (let- ([x- e-] ...) e_body-) (⇒ : τ_expected)
|
||||||
(⇒ ν (eff ...))]]
|
(⇒ ν-ep (eps ...))
|
||||||
|
(⇒ ν-f (fs ...))
|
||||||
|
(⇒ ν-s (ss ...))]]
|
||||||
[(_ ([x e] ...) e_body ...) ≫
|
[(_ ([x e] ...) e_body ...) ≫
|
||||||
[⊢ e ≫ e- ⇒ : τ_x] ...
|
[⊢ e ≫ e- ⇒ : τ_x] ...
|
||||||
#:fail-unless (stx-andmap pure? #'(e- ...)) "expressions must be pure"
|
#:fail-unless (stx-andmap pure? #'(e- ...)) "expressions must be pure"
|
||||||
[[x ≫ x- : τ_x] ... ⊢ (block e_body ...) ≫ e_body- (⇒ : τ_body)
|
[[x ≫ x- : τ_x] ... ⊢ (block e_body ...) ≫ e_body- (⇒ : τ_body)
|
||||||
(⇒ ν (~effs eff ...))]
|
(⇒ ν-ep (~effs eps ...))
|
||||||
|
(⇒ ν-f (~effs fs ...))
|
||||||
|
(⇒ ν-s (~effs ss ...))]
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
[⊢ (let- ([x- e-] ...) e_body-) (⇒ : τ_body)
|
[⊢ (let- ([x- e-] ...) e_body-) (⇒ : τ_body)
|
||||||
(⇒ ν (eff ...))]])
|
(⇒ ν-ep (eps ...))
|
||||||
|
(⇒ ν-f (fs ...))
|
||||||
|
(⇒ ν-s (ss ...))]])
|
||||||
|
|
||||||
;; copied from ext-stlc
|
;; copied from ext-stlc
|
||||||
(define-typed-syntax let*
|
(define-typed-syntax let*
|
||||||
|
@ -110,10 +125,14 @@
|
||||||
[⊢ pred ≫ pred- (⇐ : Bool)] ...
|
[⊢ pred ≫ pred- (⇐ : Bool)] ...
|
||||||
#:fail-unless (stx-andmap pure? #'(pred- ...)) "predicates must be pure"
|
#:fail-unless (stx-andmap pure? #'(pred- ...)) "predicates must be pure"
|
||||||
[⊢ (block s ...) ≫ s- (⇒ : τ-s)
|
[⊢ (block s ...) ≫ s- (⇒ : τ-s)
|
||||||
(⇒ ν (~effs eff ...))] ...
|
(⇒ ν-ep (~effs eps ...))
|
||||||
|
(⇒ ν-f (~effs fs ...))
|
||||||
|
(⇒ ν-s (~effs ss ...))] ...
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
[⊢ (cond- [pred- s-] ...) (⇒ : (U τ-s ...))
|
[⊢ (cond- [pred- s-] ...) (⇒ : (U τ-s ...))
|
||||||
(⇒ ν #,(make-Branch #'((eff ...) ...)))])
|
(⇒ ν-ep (eps ... ...))
|
||||||
|
(⇒ ν-f #,(make-Branch #'((fs ...) ...)))
|
||||||
|
(⇒ ν-s (ss ... ...))])
|
||||||
|
|
||||||
(define else #t)
|
(define else #t)
|
||||||
|
|
||||||
|
@ -124,7 +143,9 @@
|
||||||
(elaborate-pattern/with-type pat #'τ-e))
|
(elaborate-pattern/with-type pat #'τ-e))
|
||||||
#:with (([x τ:type] ...) ...) (stx-map pat-bindings #'(p/e ...))
|
#:with (([x τ:type] ...) ...) (stx-map pat-bindings #'(p/e ...))
|
||||||
[[x ≫ x- : τ.norm] ... ⊢ (block s ...) ≫ s- (⇒ : τ-s)
|
[[x ≫ x- : τ.norm] ... ⊢ (block s ...) ≫ s- (⇒ : τ-s)
|
||||||
(⇒ ν (~effs eff ...))] ...
|
(⇒ ν-ep (~effs eps ...))
|
||||||
|
(⇒ ν-f (~effs fs ...))
|
||||||
|
(⇒ ν-s (~effs ss ...))] ...
|
||||||
;; REALLY not sure how to handle p/p-/p.match-pattern,
|
;; REALLY not sure how to handle p/p-/p.match-pattern,
|
||||||
;; particularly w.r.t. typed terms that appear in p.match-pattern
|
;; particularly w.r.t. typed terms that appear in p.match-pattern
|
||||||
[⊢ p/e ≫ p-- ⇒ τ-p] ...
|
[⊢ p/e ≫ p-- ⇒ τ-p] ...
|
||||||
|
@ -138,29 +159,28 @@
|
||||||
[⊢ (match- e- [p- s-] ...
|
[⊢ (match- e- [p- s-] ...
|
||||||
[_ (#%app- error- "incomplete pattern match")])
|
[_ (#%app- error- "incomplete pattern match")])
|
||||||
(⇒ : (U τ-s ...))
|
(⇒ : (U τ-s ...))
|
||||||
(⇒ ν #,(make-Branch #'((eff ...) ...)))])
|
(⇒ ν-ep #,(make-Branch #'((eps ...) ...)))
|
||||||
|
(⇒ ν-f #,(make-Branch #'((fs ...) ...)))
|
||||||
|
(⇒ ν-s #,(make-Branch #'((ss ...) ...)))])
|
||||||
|
|
||||||
|
|
||||||
;; (Listof Value) -> Value
|
|
||||||
(define- (mk-tuple es)
|
|
||||||
(#%app- cons- 'tuple es))
|
|
||||||
|
|
||||||
(define-typed-syntax (tuple e:expr ...) ≫
|
(define-typed-syntax (tuple e:expr ...) ≫
|
||||||
[⊢ e ≫ e- (⇒ : τ) (⇒ ν (~effs F ...))] ...
|
[⊢ e ≫ e- (⇒ : τ)] ...
|
||||||
|
#:fail-unless (stx-andmap pure? #'(e- ...)) "expressions not allowed to have effects"
|
||||||
-----------------------
|
-----------------------
|
||||||
[⊢ (#%app- mk-tuple (#%app- list- e- ...))
|
[⊢ (#%app- list- 'tuple e- ...) (⇒ : (Tuple τ ...))])
|
||||||
(⇒ : (Tuple τ ...))
|
|
||||||
(⇒ ν (F ... ...))])
|
|
||||||
|
|
||||||
(define unit : Unit (tuple))
|
(define unit : Unit (tuple))
|
||||||
|
|
||||||
(define-typed-syntax (select n:nat e:expr) ≫
|
(define-typed-syntax (select n:nat e:expr) ≫
|
||||||
[⊢ e ≫ e- (⇒ : (~Tuple τ ...)) (⇒ ν (~effs F ...))]
|
[⊢ e ≫ e- (⇒ : (~Tuple τ ...))]
|
||||||
|
#:fail-unless (pure? #'e-) "expression not allowed to have effects"
|
||||||
#:do [(define i (syntax->datum #'n))]
|
#:do [(define i (syntax->datum #'n))]
|
||||||
#:fail-unless (< i (stx-length #'(τ ...))) "index out of range"
|
#:fail-unless (< i (stx-length #'(τ ...))) "index out of range"
|
||||||
#:with τr (list-ref (stx->list #'(τ ...)) i)
|
#:with τr (list-ref (stx->list #'(τ ...)) i)
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
[⊢ (#%app- tuple-select n e-) (⇒ : τr) (⇒ ν (F ...))])
|
[⊢ (#%app- tuple-select n e-) (⇒ : τr)])
|
||||||
|
|
||||||
(define- (tuple-select n t)
|
(define- (tuple-select n t)
|
||||||
(#%app- list-ref- t (#%app- add1- n)))
|
(#%app- list-ref- t (#%app- add1- n)))
|
||||||
|
@ -185,6 +205,8 @@
|
||||||
[(tuple p ...)
|
[(tuple p ...)
|
||||||
#:with (([x:id τ:type] ...) ...) (stx-map pat-bindings #'(p ...))
|
#:with (([x:id τ:type] ...) ...) (stx-map pat-bindings #'(p ...))
|
||||||
#'([x τ] ... ...)]
|
#'([x τ] ... ...)]
|
||||||
|
#;[(k:kons1 p)
|
||||||
|
(pat-bindings #'p)]
|
||||||
[(~constructor-exp cons p ...)
|
[(~constructor-exp cons p ...)
|
||||||
#:with (([x:id τ:type] ...) ...) (stx-map pat-bindings #'(p ...))
|
#:with (([x:id τ:type] ...) ...) (stx-map pat-bindings #'(p ...))
|
||||||
#'([x τ] ... ...)]
|
#'([x τ] ... ...)]
|
||||||
|
@ -238,16 +260,12 @@
|
||||||
[(tuple p ...)
|
[(tuple p ...)
|
||||||
(quasisyntax/loc pat
|
(quasisyntax/loc pat
|
||||||
(tuple #,@(stx-map elaborate-pattern #'(p ...))))]
|
(tuple #,@(stx-map elaborate-pattern #'(p ...))))]
|
||||||
[(~constructor-exp ctor p ...)
|
[(k:kons1 p)
|
||||||
(define field-tys (ctor-field-tys #'ctor))
|
|
||||||
(define sub-pats
|
|
||||||
(for/list ([field-pat (in-syntax #'(p ...))]
|
|
||||||
[field-ty? (in-list field-tys)])
|
|
||||||
(if field-ty?
|
|
||||||
(elaborate-pattern/with-type field-pat field-ty?)
|
|
||||||
(elaborate-pattern field-pat))))
|
|
||||||
(quasisyntax/loc pat
|
(quasisyntax/loc pat
|
||||||
(ctor #,@sub-pats))]
|
(k #,(elaborate-pattern #'p)))]
|
||||||
|
[(~constructor-exp ctor p ...)
|
||||||
|
(quasisyntax/loc pat
|
||||||
|
(ctor #,@(stx-map elaborate-pattern #'(p ...))))]
|
||||||
[e:expr
|
[e:expr
|
||||||
#'e]))
|
#'e]))
|
||||||
|
|
||||||
|
@ -259,14 +277,10 @@
|
||||||
[x:dollar-ann-id
|
[x:dollar-ann-id
|
||||||
(syntax/loc pat (bind x.id x.ty))]
|
(syntax/loc pat (bind x.id x.ty))]
|
||||||
[x:dollar-id
|
[x:dollar-id
|
||||||
(when (bot? ty)
|
|
||||||
(raise-syntax-error #f "unable to instantiate pattern with matching part of type" pat))
|
|
||||||
(quasisyntax/loc pat (bind x.id #,ty))]
|
(quasisyntax/loc pat (bind x.id #,ty))]
|
||||||
[($ x:id ty)
|
[($ x:id ty)
|
||||||
(syntax/loc pat (bind x ty))]
|
(syntax/loc pat (bind x ty))]
|
||||||
[($ x:id)
|
[($ x:id)
|
||||||
(when (bot? ty)
|
|
||||||
(raise-syntax-error #f "unable to instantiate pattern with matching part of type" pat))
|
|
||||||
(quasisyntax/loc pat (bind x #,ty))]
|
(quasisyntax/loc pat (bind x #,ty))]
|
||||||
[(tuple p ...)
|
[(tuple p ...)
|
||||||
(define (matching? t)
|
(define (matching? t)
|
||||||
|
@ -305,7 +319,6 @@
|
||||||
(define (proj t i)
|
(define (proj t i)
|
||||||
(syntax-parse t
|
(syntax-parse t
|
||||||
[(~constructor-type _ tt ...)
|
[(~constructor-type _ tt ...)
|
||||||
#:when (matching? t)
|
|
||||||
(if (= i -1)
|
(if (= i -1)
|
||||||
t
|
t
|
||||||
(stx-list-ref #'(tt ...) i))]
|
(stx-list-ref #'(tt ...) i))]
|
||||||
|
@ -332,6 +345,8 @@
|
||||||
#:datum-literals (tuple discard bind)
|
#:datum-literals (tuple discard bind)
|
||||||
[(tuple p ...)
|
[(tuple p ...)
|
||||||
#`(#,list-binding 'tuple #,@(stx-map loop #'(p ...)))]
|
#`(#,list-binding 'tuple #,@(stx-map loop #'(p ...)))]
|
||||||
|
#;[(k:kons1 p)
|
||||||
|
#`(#,(kons1->constructor #'k) #,(loop #'p))]
|
||||||
[(bind x:id τ:type)
|
[(bind x:id τ:type)
|
||||||
(bind-id-transformer #'x)]
|
(bind-id-transformer #'x)]
|
||||||
[discard
|
[discard
|
||||||
|
@ -358,6 +373,7 @@
|
||||||
[⊢ e ≫ e- (⇒ (~Tuple τ ...))]
|
[⊢ e ≫ e- (⇒ (~Tuple τ ...))]
|
||||||
#:fail-unless (stx-length=? #'(x ...) #'(τ ...))
|
#:fail-unless (stx-length=? #'(x ...) #'(τ ...))
|
||||||
"mismatched size"
|
"mismatched size"
|
||||||
|
#:fail-unless (pure? #'e-) "expr must be pure"
|
||||||
#:with (sel ...) (for/list ([y (in-syntax #'(x ...))]
|
#:with (sel ...) (for/list ([y (in-syntax #'(x ...))]
|
||||||
[t (in-syntax #'(τ ...))]
|
[t (in-syntax #'(τ ...))]
|
||||||
[i (in-naturals)])
|
[i (in-naturals)])
|
File diff suppressed because it is too large
Load Diff
|
@ -62,7 +62,7 @@
|
||||||
(U (Observe (Observe (TcpConnection ★/t (TcpListener ★/t))))
|
(U (Observe (Observe (TcpConnection ★/t (TcpListener ★/t))))
|
||||||
(Observe (TcpConnection ★/t (TcpListener Int)))
|
(Observe (TcpConnection ★/t (TcpListener Int)))
|
||||||
(Observe (TcpConnection ★/t (TcpListener Int)))
|
(Observe (TcpConnection ★/t (TcpListener Int)))
|
||||||
(Advertise (Observe (TcpChannel ★/t (TcpListener (TcpHandle (Seal ★/t))) ★/t)))
|
(Advertise (Observe (TcpChannel ★/t (TcpListener (TcpHandle (Seal ★/t)) ★/t))))
|
||||||
(Observe (Advertise (TcpChannel (TcpAddress String Int) (TcpHandle (Seal ★/t)) ★/t)))
|
(Observe (Advertise (TcpChannel (TcpAddress String Int) (TcpHandle (Seal ★/t)) ★/t)))
|
||||||
(TcpAccepted ★/t)
|
(TcpAccepted ★/t)
|
||||||
(Advertise (TcpChannel (TcpHandle (Seal ★/t)) (TcpAddress String Int) ★/t))
|
(Advertise (TcpChannel (TcpHandle (Seal ★/t)) (TcpAddress String Int) ★/t))
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
|
|
||||||
(require/typed syndicate/drivers/tcp2)
|
(require/typed syndicate/drivers/tcp2)
|
||||||
(require/typed (submod syndicate/drivers/tcp2 syndicate-main)
|
(require/typed (submod syndicate/drivers/tcp2 syndicate-main)
|
||||||
[activate! : (proc → (U) #:effects ((Actor Tcp2Driver))) #;(→ (Computation (Value (U))
|
[activate! : (→ (Computation (Value (U))
|
||||||
(Endpoints)
|
(Endpoints)
|
||||||
(Roles)
|
(Roles)
|
||||||
(Spawns (Actor Tcp2Driver))))])
|
(Spawns (Actor Tcp2Driver))))])
|
|
@ -19,17 +19,21 @@
|
||||||
(U (Left A)
|
(U (Left A)
|
||||||
(Right B)))
|
(Right B)))
|
||||||
|
|
||||||
|
(define (∀ (X) (f [x : X] -> X))
|
||||||
|
x)
|
||||||
|
|
||||||
|
|
||||||
(define (∀ (X Y Z) (partition/either [xs : (List X)]
|
(define (∀ (X Y Z) (partition/either [xs : (List X)]
|
||||||
[pred : (→fn X (Either Y Z))]
|
[pred : (→fn X (U (Left Y)
|
||||||
|
(Right Z)) #;(Either Y Z))]
|
||||||
-> (Tuple (List Y) (List Z))))
|
-> (Tuple (List Y) (List Z))))
|
||||||
(for/fold ([lefts (List Y) (list)]
|
(for/fold ([acc (Tuple (List Y) (List Z)) (tuple (list) (list))])
|
||||||
[rights (List Z) (list)])
|
|
||||||
([x xs])
|
([x xs])
|
||||||
(define y-or-z (pred x))
|
(define y-or-z (pred x))
|
||||||
(match y-or-z
|
(match y-or-z
|
||||||
[(left (bind y Y))
|
[(left (bind y Y))
|
||||||
(tuple (cons y lefts)
|
(tuple (cons y (select 0 acc))
|
||||||
rights)]
|
(select 1 acc))]
|
||||||
[(right (bind z Z))
|
[(right (bind z Z))
|
||||||
(tuple lefts
|
(tuple (select 0 acc)
|
||||||
(cons z rights))])))
|
(cons z (select 1 acc)))])))
|
|
@ -0,0 +1,27 @@
|
||||||
|
#lang typed/syndicate
|
||||||
|
|
||||||
|
(define-type-alias ds-type
|
||||||
|
(U (Observe (Tuple String ★)) (Tuple String Int)))
|
||||||
|
|
||||||
|
(dataspace ds-type
|
||||||
|
|
||||||
|
(spawn ds-type
|
||||||
|
(facet _
|
||||||
|
(fields [the-thing Int 0])
|
||||||
|
(assert (tuple "the thing" (ref the-thing)))
|
||||||
|
(on (asserted (tuple "set thing" (bind new-v Int)))
|
||||||
|
(set! the-thing new-v))))
|
||||||
|
|
||||||
|
(spawn ds-type
|
||||||
|
(let [k (λ [10 (begin)]
|
||||||
|
[(bind x Int)
|
||||||
|
(facet _ (fields)
|
||||||
|
(assert (tuple "set thing" (+ x 1))))])]
|
||||||
|
(facet _ (fields)
|
||||||
|
(on (asserted (tuple "the thing" (bind x Int)))
|
||||||
|
(k x)))))
|
||||||
|
|
||||||
|
(spawn ds-type
|
||||||
|
(facet _ (fields)
|
||||||
|
(on (asserted (tuple "the thing" (bind t Int)))
|
||||||
|
(displayln t)))))
|
|
@ -1,19 +1,14 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate
|
||||||
|
|
||||||
;; Expected Output
|
|
||||||
;; 0
|
|
||||||
;; 70
|
|
||||||
;; #f
|
|
||||||
|
|
||||||
(define-constructor (account balance)
|
(define-constructor (account balance)
|
||||||
#:type-constructor AccountT
|
#:type-constructor AccountT
|
||||||
#:with Account (AccountT Int)
|
#:with Account (AccountT Int)
|
||||||
#:with AccountRequest (AccountT ★/t))
|
#:with AccountRequest (AccountT ★))
|
||||||
|
|
||||||
(define-constructor (deposit amount)
|
(define-constructor (deposit amount)
|
||||||
#:type-constructor DepositT
|
#:type-constructor DepositT
|
||||||
#:with Deposit (DepositT Int)
|
#:with Deposit (DepositT Int)
|
||||||
#:with DepositRequest (DepositT ★/t))
|
#:with DepositRequest (DepositT ★))
|
||||||
|
|
||||||
(define-type-alias ds-type
|
(define-type-alias ds-type
|
||||||
(U Account
|
(U Account
|
||||||
|
@ -23,43 +18,45 @@
|
||||||
(Observe DepositRequest)
|
(Observe DepositRequest)
|
||||||
(Observe (Observe DepositRequest))))
|
(Observe (Observe DepositRequest))))
|
||||||
|
|
||||||
(define-type-alias account-manager-role
|
(dataspace ds-type
|
||||||
(Role (account-manager)
|
|
||||||
(Shares Account)
|
|
||||||
(Reacts (Asserted Deposit))))
|
|
||||||
|
|
||||||
(define-type-alias client-role
|
(spawn ds-type
|
||||||
(Role (client)
|
(facet _
|
||||||
(Reacts (Asserted Account))))
|
(fields [balance Int 0])
|
||||||
|
(assert (account (ref balance)))
|
||||||
|
(on (asserted (deposit (bind amount Int)))
|
||||||
|
(set! balance (+ (ref balance) amount)))))
|
||||||
|
|
||||||
|
(spawn ds-type
|
||||||
|
(facet _
|
||||||
|
(fields)
|
||||||
|
(on (asserted (account (bind amount Int)))
|
||||||
|
(displayln amount))))
|
||||||
|
|
||||||
(run-ground-dataspace ds-type
|
(spawn ds-type
|
||||||
|
(facet _
|
||||||
|
(fields)
|
||||||
|
(on (asserted (observe (deposit discard)))
|
||||||
|
(facet _
|
||||||
|
(fields)
|
||||||
|
(assert (deposit 100))
|
||||||
|
(assert (deposit -30)))))))
|
||||||
|
|
||||||
(spawn ds-type
|
#|
|
||||||
(lift+define-role acct-mngr-role
|
;; Hello-worldish "bank account" example.
|
||||||
(start-facet account-manager
|
|
||||||
(field [balance Int 0])
|
|
||||||
(assert (account (ref balance)))
|
|
||||||
(on (asserted (deposit (bind amount Int)))
|
|
||||||
(set! balance (+ (ref balance) amount))))))
|
|
||||||
|
|
||||||
(spawn ds-type
|
(struct account (balance) #:prefab)
|
||||||
(lift+define-role obs-role
|
(struct deposit (amount) #:prefab)
|
||||||
(start-facet observer
|
|
||||||
(on (asserted (account (bind amount Int)))
|
|
||||||
(displayln amount)))))
|
|
||||||
|
|
||||||
(spawn ds-type
|
(spawn (field [balance 0])
|
||||||
(lift+define-role buyer-role
|
(assert (account (balance)))
|
||||||
(start-facet buyer
|
(on (message (deposit $amount))
|
||||||
(on (asserted (observe (deposit discard)))
|
(balance (+ (balance) amount))))
|
||||||
(start-facet deposits
|
|
||||||
(assert (deposit 100))
|
|
||||||
(assert (deposit -30))))))))
|
|
||||||
|
|
||||||
(module+ test
|
(spawn (on (asserted (account $balance))
|
||||||
(check-simulates acct-mngr-role account-manager-role)
|
(printf "Balance changed to ~a\n" balance)))
|
||||||
(check-simulates obs-role client-role)
|
|
||||||
;; Tried to write this, then it failed, I looked and buyer doesn't actually implement that spec
|
(spawn* (until (asserted (observe (deposit _))))
|
||||||
#;(check-simulates buyer-role client-role)
|
(send! (deposit +100))
|
||||||
)
|
(send! (deposit -30)))
|
||||||
|
|#
|
|
@ -1,21 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
;; Expected Output:
|
|
||||||
;; got: new
|
|
||||||
|
|
||||||
(define-constructor* (something : SomethingT new blue)
|
|
||||||
#:with Something (SomethingT String Int))
|
|
||||||
|
|
||||||
(define-type-alias τc
|
|
||||||
(U Something
|
|
||||||
(Observe★ SomethingT)))
|
|
||||||
|
|
||||||
(run-ground-dataspace
|
|
||||||
τc
|
|
||||||
(spawn
|
|
||||||
(start-facet _
|
|
||||||
(assert (something "new" 42))))
|
|
||||||
(spawn
|
|
||||||
(start-facet _
|
|
||||||
(on (asserted (something $x 42))
|
|
||||||
(printf "got: ~a\n" x))))
|
|
||||||
)
|
|
|
@ -1,36 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
;; Expected Output
|
|
||||||
;; pong: 8339
|
|
||||||
|
|
||||||
(message-struct ping : Ping (v))
|
|
||||||
(message-struct pong : Pong (v))
|
|
||||||
|
|
||||||
(define-type-alias ds-type
|
|
||||||
(U (Message (Ping Int))
|
|
||||||
(Message (Pong Int))
|
|
||||||
(Observe (Ping ★/t))
|
|
||||||
(Observe (Pong ★/t))
|
|
||||||
(Observe (Observe (Ping ★/t)))))
|
|
||||||
|
|
||||||
(run-ground-dataspace ds-type
|
|
||||||
(spawn ds-type
|
|
||||||
(lift+define-role ponger
|
|
||||||
(start-facet echo
|
|
||||||
(on (message (ping $v))
|
|
||||||
(send! (pong v))))))
|
|
||||||
(spawn ds-type
|
|
||||||
(lift+define-role pinger
|
|
||||||
(start-facet serve
|
|
||||||
(on (asserted (observe (ping _)))
|
|
||||||
(send! (ping 8339)))
|
|
||||||
(on (message (pong $x))
|
|
||||||
(printf "pong: ~v\n" x))))))
|
|
||||||
|
|
||||||
(module+ test
|
|
||||||
(verify-actors (And (Eventually (M (Ping Int)))
|
|
||||||
(Eventually (M (Pong Int)))
|
|
||||||
(Always (Implies (M (Ping Int))
|
|
||||||
(Eventually (M (Pong Int))))))
|
|
||||||
pinger
|
|
||||||
ponger))
|
|
|
@ -1,17 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
;; using different syntax than "client.rkt"
|
|
||||||
|
|
||||||
(require/typed "driver.rkt" [#:struct msg])
|
|
||||||
|
|
||||||
(define m : (MsgT Int String) (msg 1 "hi"))
|
|
||||||
|
|
||||||
(msg-in m)
|
|
||||||
(msg-out m)
|
|
||||||
|
|
||||||
(match m
|
|
||||||
[(msg (bind x Int) discard)
|
|
||||||
(displayln x)])
|
|
||||||
|
|
||||||
;; error: msg/checked: arity mismatch
|
|
||||||
#;(msg 1 2 3)
|
|
|
@ -1,12 +0,0 @@
|
||||||
#lang racket
|
|
||||||
|
|
||||||
(struct egg (size day) #:transparent)
|
|
||||||
|
|
||||||
(provide (except-out (struct-out egg)
|
|
||||||
egg-size
|
|
||||||
egg-day))
|
|
||||||
|
|
||||||
|
|
||||||
(struct chicken (eggs) #:transparent)
|
|
||||||
|
|
||||||
(provide chicken)
|
|
|
@ -1,18 +0,0 @@
|
||||||
#lang typed/syndicate/roles
|
|
||||||
|
|
||||||
(require-struct egg #:as Egg #:from "lib.rkt" #:omit-accs)
|
|
||||||
|
|
||||||
(define e (egg 5 "Sun"))
|
|
||||||
|
|
||||||
(match e
|
|
||||||
[(egg $sz $d)
|
|
||||||
(displayln sz)
|
|
||||||
(displayln d)])
|
|
||||||
|
|
||||||
(require-struct chicken #:as Chicken #:from "lib.rkt" #:omit-accs)
|
|
||||||
|
|
||||||
(define c (chicken (list e e e)))
|
|
||||||
|
|
||||||
(match c
|
|
||||||
[(chicken $eggs)
|
|
||||||
(displayln eggs)])
|
|
|
@ -1,5 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
(require/typed "lib.rkt" [x : Int])
|
|
||||||
|
|
||||||
(displayln (+ x 1))
|
|
|
@ -1,8 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
(require/typed "lib.rkt"
|
|
||||||
[#:opaque Vec #:arity = 3]
|
|
||||||
[ones : (Vec Int Int Int)]
|
|
||||||
[vec+ : (→fn (Vec Int Int Int) (Vec Int Int Int) (Vec Int Int Int))])
|
|
||||||
|
|
||||||
(vec+ ones ones)
|
|
|
@ -1,8 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
(require/typed "lib.rkt"
|
|
||||||
[#:opaque Vec]
|
|
||||||
[ones : Vec]
|
|
||||||
[vec+ : (→fn Vec Vec Vec)])
|
|
||||||
|
|
||||||
(vec+ ones ones)
|
|
|
@ -1,13 +0,0 @@
|
||||||
#lang racket
|
|
||||||
|
|
||||||
(provide ones
|
|
||||||
vec+)
|
|
||||||
|
|
||||||
(struct vec (x y z) #:transparent)
|
|
||||||
|
|
||||||
(define ones (vec 1 1 1))
|
|
||||||
|
|
||||||
(define (vec+ v1 v2)
|
|
||||||
(vec (+ (vec-x v1) (vec-x v2))
|
|
||||||
(+ (vec-y v1) (vec-y v2))
|
|
||||||
(+ (vec-z v1) (vec-z v2))))
|
|
|
@ -1,5 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
(require "provides.rkt")
|
|
||||||
|
|
||||||
(a-fun 5)
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
|
;; Expected Output
|
||||||
|
;; 0
|
||||||
|
;; 70
|
||||||
|
;; #f
|
||||||
|
|
||||||
|
(define-constructor (account balance)
|
||||||
|
#:type-constructor AccountT
|
||||||
|
#:with Account (AccountT Int)
|
||||||
|
#:with AccountRequest (AccountT ★/t))
|
||||||
|
|
||||||
|
(define-constructor (deposit amount)
|
||||||
|
#:type-constructor DepositT
|
||||||
|
#:with Deposit (DepositT Int)
|
||||||
|
#:with DepositRequest (DepositT ★/t))
|
||||||
|
|
||||||
|
(define-type-alias ds-type
|
||||||
|
(U Account
|
||||||
|
(Observe AccountRequest)
|
||||||
|
(Observe (Observe AccountRequest))
|
||||||
|
Deposit
|
||||||
|
(Observe DepositRequest)
|
||||||
|
(Observe (Observe DepositRequest))))
|
||||||
|
|
||||||
|
(define-type-alias account-manager-role
|
||||||
|
(Role (account-manager)
|
||||||
|
(Shares Account)
|
||||||
|
(Reacts (Know (Deposit Int)))))
|
||||||
|
|
||||||
|
(define-type-alias client-role
|
||||||
|
(Role (client)
|
||||||
|
(Reacts (Know Account))))
|
||||||
|
|
||||||
|
(run-ground-dataspace ds-type
|
||||||
|
|
||||||
|
(spawn ds-type
|
||||||
|
(print-role
|
||||||
|
(start-facet account-manager
|
||||||
|
(field [balance Int 0])
|
||||||
|
(assert (account (ref balance)))
|
||||||
|
(on (asserted (deposit (bind amount Int)))
|
||||||
|
(set! balance (+ (ref balance) amount))))))
|
||||||
|
|
||||||
|
(spawn ds-type
|
||||||
|
(print-role
|
||||||
|
(start-facet observer
|
||||||
|
(on (asserted (account (bind amount Int)))
|
||||||
|
(displayln amount)))))
|
||||||
|
|
||||||
|
(spawn ds-type
|
||||||
|
(print-role
|
||||||
|
(start-facet buyer
|
||||||
|
(on (asserted (observe (deposit discard)))
|
||||||
|
(start-facet deposits
|
||||||
|
(assert (deposit 100))
|
||||||
|
(assert (deposit -30))))))))
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; Expected Output
|
;; Expected Output
|
||||||
;; leader learns that there are 5 copies of The Wind in the Willows
|
;; leader learns that there are 5 copies of The Wind in the Willows
|
||||||
|
@ -34,14 +34,14 @@
|
||||||
(define-type-alias τc
|
(define-type-alias τc
|
||||||
(U BookQuote
|
(U BookQuote
|
||||||
(Observe (BookQuoteT String ★/t))
|
(Observe (BookQuoteT String ★/t))
|
||||||
(Observe (Observe★ BookQuoteT))
|
(Observe (Observe (BookQuoteT ★/t ★/t)))
|
||||||
ClubMember
|
ClubMember
|
||||||
(Observe★ ClubMemberT)
|
(Observe (ClubMemberT ★/t))
|
||||||
BookInterest
|
BookInterest
|
||||||
(Observe (BookInterestT String ★/t ★/t))
|
(Observe (BookInterestT String ★/t ★/t))
|
||||||
(Observe (Observe★ BookInterestT))
|
(Observe (Observe (BookInterestT ★/t ★/t ★/t)))
|
||||||
BookOfTheMonth
|
BookOfTheMonth
|
||||||
(Observe★ BookOfTheMonthT)))
|
(Observe (BookOfTheMonthT ★/t))))
|
||||||
|
|
||||||
(define-type-alias Inventory (List (Tuple String Int)))
|
(define-type-alias Inventory (List (Tuple String Int)))
|
||||||
|
|
||||||
|
@ -59,19 +59,17 @@
|
||||||
(Role (_)
|
(Role (_)
|
||||||
;; nb no mention of retracting this assertion
|
;; nb no mention of retracting this assertion
|
||||||
(Shares (BookQuoteT String Int))))))
|
(Shares (BookQuoteT String Int))))))
|
||||||
(export-type "seller-role.rktd" seller-role)
|
|
||||||
|
|
||||||
(define (spawn-seller [inventory : Inventory])
|
(define (spawn-seller [inventory : Inventory])
|
||||||
(spawn τc
|
(spawn τc
|
||||||
(export-roles "seller-impl.rktd"
|
(begin
|
||||||
(lift+define-role seller-impl
|
|
||||||
(start-facet seller
|
(start-facet seller
|
||||||
(field [books Inventory inventory])
|
(field [books Inventory inventory])
|
||||||
|
|
||||||
;; Give quotes to interested parties.
|
;; Give quotes to interested parties.
|
||||||
(during (observe (book-quote $title _))
|
(during (observe (book-quote $title _))
|
||||||
;; TODO - lookup
|
;; TODO - lookup
|
||||||
(assert (book-quote title (lookup title (! books))))))))))
|
(assert (book-quote title (lookup title (ref books)))))))))
|
||||||
|
|
||||||
(define-type-alias leader-role
|
(define-type-alias leader-role
|
||||||
(Role (leader)
|
(Role (leader)
|
||||||
|
@ -79,16 +77,16 @@
|
||||||
(Role (poll)
|
(Role (poll)
|
||||||
(Reacts (Asserted (BookInterestT String String Bool))
|
(Reacts (Asserted (BookInterestT String String Bool))
|
||||||
;; this is actually implemented indirectly through dataflow
|
;; this is actually implemented indirectly through dataflow
|
||||||
(Branch (Stop leader
|
(U (Stop leader
|
||||||
(Role (_)
|
(Role (_)
|
||||||
(Shares (BookOfTheMonthT String))))
|
(Shares (BookOfTheMonthT String))))
|
||||||
(Stop poll)))))))
|
(Stop poll)))))))
|
||||||
|
|
||||||
(define-type-alias leader-actual
|
(define-type-alias leader-actual
|
||||||
(Role (get-quotes)
|
(Role (get-quotes31)
|
||||||
(Reacts (Asserted (BookQuoteT String (Bind Int)))
|
(Reacts (Asserted (BookQuoteT String (Bind Int)))
|
||||||
(Stop get-quotes)
|
(Stop get-quotes)
|
||||||
(Role (poll-members)
|
(Role (poll-members36)
|
||||||
(Reacts OnDataflow
|
(Reacts OnDataflow
|
||||||
(Stop poll-members
|
(Stop poll-members
|
||||||
(Stop get-quotes))
|
(Stop get-quotes))
|
||||||
|
@ -104,60 +102,59 @@
|
||||||
|
|
||||||
(define (spawn-leader [titles : (List String)])
|
(define (spawn-leader [titles : (List String)])
|
||||||
(spawn τc
|
(spawn τc
|
||||||
(export-roles "leader-impl.rktd"
|
(print-role
|
||||||
(lift+define-role leader-impl
|
|
||||||
(start-facet get-quotes
|
(start-facet get-quotes
|
||||||
(field [book-list (List String) (rest titles)]
|
(field [book-list (List String) (rest titles)]
|
||||||
[title String (first titles)])
|
[title String (first titles)])
|
||||||
(define (next-book)
|
(define (next-book)
|
||||||
(cond
|
(cond
|
||||||
[(empty? (! book-list))
|
[(empty? (ref book-list))
|
||||||
(printf "leader fails to find a suitable book\n")
|
(printf "leader fails to find a suitable book\n")
|
||||||
(stop get-quotes)]
|
(stop get-quotes)]
|
||||||
[#t
|
[#t
|
||||||
(:= title (first (! book-list)))
|
(set! title (first (ref book-list)))
|
||||||
(:= book-list (rest (! book-list)))]))
|
(set! book-list (rest (ref book-list)))]))
|
||||||
|
|
||||||
;; keep track of book club members
|
;; keep track of book club members
|
||||||
(define/query-set members (club-member $name) name
|
(define/query-set members (club-member $name) name
|
||||||
#;#:on-add #;(printf "leader acknowledges member ~a\n" name))
|
#;#:on-add #;(printf "leader acknowledges member ~a\n" name))
|
||||||
|
|
||||||
(on (asserted (book-quote (! title) $quantity))
|
(on (asserted (book-quote (ref title) $quantity))
|
||||||
(printf "leader learns that there are ~a copies of ~a\n" quantity (! title))
|
(printf "leader learns that there are ~a copies of ~a\n" quantity (ref title))
|
||||||
(cond
|
(cond
|
||||||
[(< quantity (+ 1 (set-count (! members))))
|
[(< quantity (+ 1 (set-count (ref members))))
|
||||||
;; not enough in stock for each member
|
;; not enough in stock for each member
|
||||||
(next-book)]
|
(next-book)]
|
||||||
[#t
|
[#t
|
||||||
;; find out if at least half of the members want to read the book
|
;; find out if at least half of the members want to read the book
|
||||||
(start-facet poll-members
|
(start-facet poll-members
|
||||||
(define/query-set yays (book-interest (! title) $name #t) name)
|
(define/query-set yays (book-interest (ref title) $name #t) name)
|
||||||
(define/query-set nays (book-interest (! title) $name #f) name)
|
(define/query-set nays (book-interest (ref title) $name #f) name)
|
||||||
(on (asserted (book-interest (! title) $name _))
|
(on (asserted (book-interest (ref title) $name _))
|
||||||
;; count the leader as a 'yay'
|
;; count the leader as a 'yay'
|
||||||
(when (>= (set-count (! yays))
|
(when (>= (set-count (ref yays))
|
||||||
(/ (set-count (! members)) 2))
|
(/ (set-count (ref members)) 2))
|
||||||
(printf "leader finds enough affirmation for ~a\n" (! title))
|
(printf "leader finds enough affirmation for ~a\n" (ref title))
|
||||||
(stop get-quotes
|
(stop get-quotes
|
||||||
(start-facet announce
|
(start-facet announce
|
||||||
(assert (book-of-the-month (! title))))))
|
(assert (book-of-the-month (ref title))))))
|
||||||
(when (> (set-count (! nays))
|
(when (> (set-count (ref nays))
|
||||||
(/ (set-count (! members)) 2))
|
(/ (set-count (ref members)) 2))
|
||||||
(printf "leader finds enough negative nancys for ~a\n" (! title))
|
(printf "leader finds enough negative nancys for ~a\n" (ref title))
|
||||||
(stop poll-members (next-book))))
|
(stop poll-members (next-book))))
|
||||||
;; begin/dataflow is a problem for simulation checking
|
;; begin/dataflow is a problem for simulation checking
|
||||||
#;(begin/dataflow
|
#;(begin/dataflow
|
||||||
;; count the leader as a 'yay'
|
;; count the leader as a 'yay'
|
||||||
(when (>= (set-count (! yays))
|
(when (>= (set-count (ref yays))
|
||||||
(/ (set-count (! members)) 2))
|
(/ (set-count (ref members)) 2))
|
||||||
(printf "leader finds enough affirmation for ~a\n" (! title))
|
(printf "leader finds enough affirmation for ~a\n" (ref title))
|
||||||
(stop get-quotes
|
(stop get-quotes
|
||||||
(start-facet announce
|
(start-facet announce
|
||||||
(assert (book-of-the-month (! title))))))
|
(assert (book-of-the-month (ref title))))))
|
||||||
(when (> (set-count (! nays))
|
(when (> (set-count (ref nays))
|
||||||
(/ (set-count (! members)) 2))
|
(/ (set-count (ref members)) 2))
|
||||||
(printf "leader finds enough negative nancys for ~a\n" (! title))
|
(printf "leader finds enough negative nancys for ~a\n" (ref title))
|
||||||
(stop poll-members (next-book)))))])))))))
|
(stop poll-members (next-book)))))]))))))
|
||||||
|
|
||||||
(define-type-alias member-role
|
(define-type-alias member-role
|
||||||
(Role (member)
|
(Role (member)
|
||||||
|
@ -170,8 +167,7 @@
|
||||||
(define (spawn-club-member [name : String]
|
(define (spawn-club-member [name : String]
|
||||||
[titles : (List String)])
|
[titles : (List String)])
|
||||||
(spawn τc
|
(spawn τc
|
||||||
(export-roles "member-impl.rktd"
|
(print-role
|
||||||
(lift+define-role member-impl
|
|
||||||
(start-facet member
|
(start-facet member
|
||||||
;; assert our presence
|
;; assert our presence
|
||||||
(assert (club-member name))
|
(assert (club-member name))
|
||||||
|
@ -179,7 +175,7 @@
|
||||||
(during (observe (book-interest $title _ _))
|
(during (observe (book-interest $title _ _))
|
||||||
(define answer (member? title titles))
|
(define answer (member? title titles))
|
||||||
(printf "~a responds to suggested book ~a: ~a\n" name title answer)
|
(printf "~a responds to suggested book ~a: ~a\n" name title answer)
|
||||||
(assert (book-interest title name answer))))))))
|
(assert (book-interest title name answer)))))))
|
||||||
|
|
||||||
(run-ground-dataspace τc
|
(run-ground-dataspace τc
|
||||||
(spawn-seller (list (tuple "The Wind in the Willows" 5)
|
(spawn-seller (list (tuple "The Wind in the Willows" 5)
|
||||||
|
@ -191,19 +187,3 @@
|
||||||
"Encyclopaedia Brittannica"))
|
"Encyclopaedia Brittannica"))
|
||||||
(spawn-club-member "tony" (list "Candide"))
|
(spawn-club-member "tony" (list "Candide"))
|
||||||
(spawn-club-member "sam" (list "Encyclopaedia Brittannica" "Candide")))
|
(spawn-club-member "sam" (list "Encyclopaedia Brittannica" "Candide")))
|
||||||
|
|
||||||
(module+ test
|
|
||||||
(verify-actors (And (Eventually (A BookQuote))
|
|
||||||
(Always (Implies (A (Observe (BookQuoteT String ★/t)))
|
|
||||||
(Eventually (A BookQuote))))
|
|
||||||
(Always (Implies (A (Observe (BookInterestT String ★/t ★/t)))
|
|
||||||
(Eventually (A BookInterest)))))
|
|
||||||
leader-impl
|
|
||||||
seller-impl
|
|
||||||
member-impl))
|
|
||||||
|
|
||||||
(module+ test
|
|
||||||
(check-simulates leader-impl leader-impl)
|
|
||||||
(check-has-simulating-subgraph leader-impl leader-role)
|
|
||||||
(check-simulates seller-impl seller-impl)
|
|
||||||
(check-has-simulating-subgraph seller-impl seller-role))
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; adapted from section 8.3 of Tony's dissertation
|
;; adapted from section 8.3 of Tony's dissertation
|
||||||
|
|
||||||
|
@ -22,11 +22,11 @@
|
||||||
(Role (cell-factory)
|
(Role (cell-factory)
|
||||||
(Reacts (Message (CreateCellT ID Value))
|
(Reacts (Message (CreateCellT ID Value))
|
||||||
;; want to say that what it spawns is a Cell
|
;; want to say that what it spawns is a Cell
|
||||||
(ActorWithRole ★/t Cell))))
|
(Spawn ★/t))))
|
||||||
|
|
||||||
(define-type-alias Reader
|
(define-type-alias Reader
|
||||||
(Role (reader)
|
(Role (reader)
|
||||||
(Shares (Observe (CellT ID ★/t)))))
|
(Shares (Observe (Cell ID ★/t)))))
|
||||||
|
|
||||||
(define-type-alias Writer
|
(define-type-alias Writer
|
||||||
(Role (writer)
|
(Role (writer)
|
|
@ -1,6 +1,6 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require typed/syndicate/drivers/tcp)
|
(require "../../drivers/tcp.rkt")
|
||||||
|
|
||||||
;; message
|
;; message
|
||||||
(define-constructor (speak who what)
|
(define-constructor (speak who what)
|
||||||
|
@ -26,7 +26,8 @@
|
||||||
|
|
||||||
(spawn chat-ds
|
(spawn chat-ds
|
||||||
(start-facet chat-server
|
(start-facet chat-server
|
||||||
(during/spawn (tcp-connection (bind id Symbol) (tcp-listener 5999))
|
;; TODO - should be during/spawn
|
||||||
|
(during (tcp-connection (bind id Symbol) (tcp-listener 5999))
|
||||||
(assert (tcp-accepted id))
|
(assert (tcp-accepted id))
|
||||||
(let ([me (gensym 'user)])
|
(let ([me (gensym 'user)])
|
||||||
(assert (present me))
|
(assert (present me))
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(define-constructor (file name content)
|
(define-constructor (file name content)
|
||||||
#:type-constructor FileT
|
#:type-constructor FileT
|
|
@ -1,8 +1,9 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; ---------------------------------------------------------------------------------------------------
|
;; ---------------------------------------------------------------------------------------------------
|
||||||
;; Protocol
|
;; Protocol
|
||||||
|
|
||||||
|
#|
|
||||||
|
|
||||||
#|
|
#|
|
||||||
Conversations in the flink dataspace primarily concern two topics: presence and
|
Conversations in the flink dataspace primarily concern two topics: presence and
|
||||||
|
@ -115,8 +116,7 @@ JobManager and the TaskManager, and one between the TaskManager and its
|
||||||
TaskRunners.
|
TaskRunners.
|
||||||
|#
|
|#
|
||||||
|
|
||||||
;; I think this is wrong by explicitly requiring that the facet stop in response
|
(define-type-alias TaskAssigner
|
||||||
(define-type-alias TaskAssigner-v1
|
|
||||||
(Role (assign)
|
(Role (assign)
|
||||||
(Shares (Observe (TaskPerformance ID ConcreteTask ★/t)))
|
(Shares (Observe (TaskPerformance ID ConcreteTask ★/t)))
|
||||||
;; would be nice to say how the TaskIDs relate to each other
|
;; would be nice to say how the TaskIDs relate to each other
|
||||||
|
@ -124,14 +124,6 @@ TaskRunners.
|
||||||
(Branch (Stop assign)
|
(Branch (Stop assign)
|
||||||
(Effs)))))
|
(Effs)))))
|
||||||
|
|
||||||
(define-type-alias TaskAssigner
|
|
||||||
(Role (assign)
|
|
||||||
;; would be nice to say how the TaskIDs relate to each other
|
|
||||||
(Reacts (Asserted (TaskPerformance ID ConcreteTask TaskStateDesc))
|
|
||||||
)))
|
|
||||||
|
|
||||||
(export-type "task-assigner.rktd" TaskAssigner)
|
|
||||||
|
|
||||||
(define-type-alias TaskPerformer
|
(define-type-alias TaskPerformer
|
||||||
(Role (listen)
|
(Role (listen)
|
||||||
(During (Observe (TaskPerformance ID ConcreteTask ★/t))
|
(During (Observe (TaskPerformance ID ConcreteTask ★/t))
|
||||||
|
@ -161,12 +153,12 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
(Observe (Observe (TaskPerformance ID ★/t ★/t)))
|
(Observe (Observe (TaskPerformance ID ★/t ★/t)))
|
||||||
(JobManagerAlive)
|
(JobManagerAlive)
|
||||||
(Observe (JobManagerAlive))
|
(Observe (JobManagerAlive))
|
||||||
(Observe★ TaskRunner)
|
(Observe (TaskRunner ★/t))
|
||||||
(TaskManager ID Int)
|
(TaskManager ID Int)
|
||||||
(Observe★ TaskManager)
|
(Observe (TaskManager ★/t ★/t))
|
||||||
(JobCompletion ID (List InputTask) TaskResult)
|
(JobCompletion ID (List InputTask) TaskResult)
|
||||||
(Observe (JobCompletion ID (List InputTask) ★/t))
|
(Observe (JobCompletion ID (List InputTask) ★/t))
|
||||||
(Observe (Observe★ JobCompletion))))
|
(Observe (Observe (JobCompletion ★/t ★/t ★/t)))))
|
||||||
|
|
||||||
;; ---------------------------------------------------------------------------------------------------
|
;; ---------------------------------------------------------------------------------------------------
|
||||||
;; Util Macros
|
;; Util Macros
|
||||||
|
@ -178,11 +170,13 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
(printf fmt . args)
|
(printf fmt . args)
|
||||||
(printf "\n")))
|
(printf "\n")))
|
||||||
|
|
||||||
|
|#
|
||||||
|
|
||||||
|
|
||||||
;; ---------------------------------------------------------------------------------------------------
|
;; ---------------------------------------------------------------------------------------------------
|
||||||
;; TaskRunner
|
;; TaskRunner
|
||||||
|
|
||||||
|
#|
|
||||||
|
|
||||||
(define (word-count-increment [h : WordCount]
|
(define (word-count-increment [h : WordCount]
|
||||||
[word : String]
|
[word : String]
|
||||||
|
@ -204,9 +198,8 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
|
|
||||||
(define (spawn-task-runner [id : ID] [tm-id : ID])
|
(define (spawn-task-runner [id : ID] [tm-id : ID])
|
||||||
(spawn τc
|
(spawn τc
|
||||||
(export-roles "task-runner-impl.rktd"
|
(begin
|
||||||
(lift+define-role task-runner-impl
|
(start-facet runner
|
||||||
(start-facet runner ;; #:includes-behavior TaskPerformer
|
|
||||||
(assert (task-runner id))
|
(assert (task-runner id))
|
||||||
(on (retracted (task-manager tm-id _))
|
(on (retracted (task-manager tm-id _))
|
||||||
(stop runner))
|
(stop runner))
|
||||||
|
@ -223,7 +216,7 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
(set! state (finished wc))]
|
(set! state (finished wc))]
|
||||||
[(reduce-work $left $right)
|
[(reduce-work $left $right)
|
||||||
(define wc (hash-union/combine left right +))
|
(define wc (hash-union/combine left right +))
|
||||||
(set! state (finished wc))])))))))
|
(set! state (finished wc))]))))))
|
||||||
|
|
||||||
;; ---------------------------------------------------------------------------------------------------
|
;; ---------------------------------------------------------------------------------------------------
|
||||||
;; TaskManager
|
;; TaskManager
|
||||||
|
@ -232,9 +225,8 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
(define (spawn-task-manager [num-task-runners : Int])
|
(define (spawn-task-manager [num-task-runners : Int])
|
||||||
(define id (gensym 'task-manager))
|
(define id (gensym 'task-manager))
|
||||||
(spawn τc
|
(spawn τc
|
||||||
(export-roles "task-manager-impl.rktd"
|
(begin
|
||||||
(#;begin lift+define-role task-manager-impl
|
(start-facet tm
|
||||||
(start-facet tm ;; #:includes-behavior TaskAssigner
|
|
||||||
(log "Task Manager (TM) ~a is running" id)
|
(log "Task Manager (TM) ~a is running" id)
|
||||||
(during (job-manager-alive)
|
(during (job-manager-alive)
|
||||||
(log "TM ~a learns about JM" id)
|
(log "TM ~a learns about JM" id)
|
||||||
|
@ -295,7 +287,7 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
[OVERLOAD/ts
|
[OVERLOAD/ts
|
||||||
(set! status OVERLOAD/ts)]
|
(set! status OVERLOAD/ts)]
|
||||||
[(finished discard)
|
[(finished discard)
|
||||||
(set! status st)]))))))))))
|
(set! status st)])))))))))
|
||||||
|
|
||||||
;; ---------------------------------------------------------------------------------------------------
|
;; ---------------------------------------------------------------------------------------------------
|
||||||
;; JobManager
|
;; JobManager
|
||||||
|
@ -322,10 +314,11 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
-> (Tuple (List X) (List X))))
|
-> (Tuple (List X) (List X))))
|
||||||
(define l (split-at/lenient- xs n))
|
(define l (split-at/lenient- xs n))
|
||||||
(tuple (first l) (second l)))
|
(tuple (first l) (second l)))
|
||||||
|
|#
|
||||||
|
|
||||||
;; Task -> Bool
|
;; Task -> Bool
|
||||||
;; Test if the task is ready to run
|
;; Test if the task is ready to run
|
||||||
(define (task-ready? [t : PendingTask] -> (Maybe ConcreteTask))
|
#;(define (task-ready? [t : PendingTask] -> (Maybe ConcreteTask))
|
||||||
(match t
|
(match t
|
||||||
[(task $tid (map-work $s))
|
[(task $tid (map-work $s))
|
||||||
;; having to re-produce this is directly bc of no occurrence typing
|
;; having to re-produce this is directly bc of no occurrence typing
|
||||||
|
@ -337,7 +330,7 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
none]))
|
none]))
|
||||||
|
|
||||||
|
|
||||||
(define (partition-ready-tasks [tasks : (List PendingTask)]
|
#;(define (partition-ready-tasks [tasks : (List PendingTask)]
|
||||||
-> (Tuple (List PendingTask)
|
-> (Tuple (List PendingTask)
|
||||||
(List ConcreteTask)))
|
(List ConcreteTask)))
|
||||||
(define part (inst partition/either PendingTask PendingTask ConcreteTask))
|
(define part (inst partition/either PendingTask PendingTask ConcreteTask))
|
||||||
|
@ -350,6 +343,27 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
(left t)]))))
|
(left t)]))))
|
||||||
|
|
||||||
|
|
||||||
|
(define (partition-ready-tasks [tasks : (List Int)]
|
||||||
|
-> (Tuple (List Int)
|
||||||
|
(List Int)))
|
||||||
|
(define part (inst partition/either Int Int Int))
|
||||||
|
(part tasks
|
||||||
|
(lambda ([t : Int])
|
||||||
|
(right 0)
|
||||||
|
#;(match (some 5)
|
||||||
|
[(some $ct)
|
||||||
|
(right ct)]
|
||||||
|
[none
|
||||||
|
(left 0)]))))
|
||||||
|
|
||||||
|
#;(define (debug [tasks : (List Int)] -> (Tuple (List String) (List Int)))
|
||||||
|
(define part (inst partition/either Int String Int))
|
||||||
|
(tuple (list) (list))
|
||||||
|
(part tasks
|
||||||
|
(lambda ([t : Int])
|
||||||
|
(left "hi"))))
|
||||||
|
#|
|
||||||
|
|
||||||
(define (input->pending-task [t : InputTask] -> PendingTask)
|
(define (input->pending-task [t : InputTask] -> PendingTask)
|
||||||
(match t
|
(match t
|
||||||
[(task $id (map-work $s))
|
[(task $id (map-work $s))
|
||||||
|
@ -371,8 +385,8 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
|
|
||||||
(define (spawn-job-manager)
|
(define (spawn-job-manager)
|
||||||
(spawn τc
|
(spawn τc
|
||||||
(lift+define-role job-manager-impl ;; export-roles "job-manager-impl.rktd"
|
(begin
|
||||||
(start-facet jm ;; #:includes-behavior TaskAssigner
|
(start-facet jm
|
||||||
(assert (job-manager-alive))
|
(assert (job-manager-alive))
|
||||||
(log "Job Manager Up")
|
(log "Job Manager Up")
|
||||||
|
|
||||||
|
@ -471,7 +485,7 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
;; Requires (task-ready? t)
|
;; Requires (task-ready? t)
|
||||||
(define (∀ (ρ) (perform-task [t : ConcreteTask]
|
(define (∀ (ρ) (perform-task [t : ConcreteTask]
|
||||||
[k : (proc TaskID TaskResult -> ★/t
|
[k : (proc TaskID TaskResult -> ★/t
|
||||||
#:effects (ρ))]))
|
#:roles (ρ))]))
|
||||||
(start-facet perform
|
(start-facet perform
|
||||||
(on start (set! tasks-in-progress (add1 (ref tasks-in-progress))))
|
(on start (set! tasks-in-progress (add1 (ref tasks-in-progress))))
|
||||||
(on stop (set! tasks-in-progress (sub1 (ref tasks-in-progress))))
|
(on stop (set! tasks-in-progress (sub1 (ref tasks-in-progress))))
|
||||||
|
@ -479,8 +493,8 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
(log "JM begins on task ~a" this-id)
|
(log "JM begins on task ~a" this-id)
|
||||||
|
|
||||||
;; ID -> ...
|
;; ID -> ...
|
||||||
(define (∀ (ρ) (assign-task [mngr : ID]
|
(define (assign-task [mngr : ID]
|
||||||
[request-again! : (proc -> ★/t #:effects (ρ))]))
|
[request-again! : (→fn ★/t)])
|
||||||
(start-facet assign
|
(start-facet assign
|
||||||
(on (retracted (task-manager mngr _))
|
(on (retracted (task-manager mngr _))
|
||||||
;; our task manager has crashed
|
;; our task manager has crashed
|
||||||
|
@ -513,7 +527,7 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
(on (realize (tasks-finished job-id $data:TaskResult))
|
(on (realize (tasks-finished job-id $data:TaskResult))
|
||||||
(stop delegate-tasks
|
(stop delegate-tasks
|
||||||
(start-facet done (assert (job-completion job-id tasks data)))))
|
(start-facet done (assert (job-completion job-id tasks data)))))
|
||||||
(on (realize (task-is-ready job-id $t:ConcreteTask))
|
(on (realize (task-is-ready job-id $t))
|
||||||
(perform-task t push-results)))
|
(perform-task t push-results)))
|
||||||
(for ([t (in-list ready)])
|
(for ([t (in-list ready)])
|
||||||
(add-ready-task! t))))))))
|
(add-ready-task! t))))))))
|
||||||
|
@ -524,12 +538,10 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
;; Job -> Void
|
;; Job -> Void
|
||||||
(define (spawn-client [j : JobDesc])
|
(define (spawn-client [j : JobDesc])
|
||||||
(spawn τc
|
(spawn τc
|
||||||
(export-roles "client-impl.rktd"
|
|
||||||
(lift+define-role client-impl
|
|
||||||
(start-facet _
|
(start-facet _
|
||||||
(match-define (job $id $tasks) j)
|
(match-define (job $id $tasks) j)
|
||||||
(on (asserted (job-completion id tasks $data))
|
(on (asserted (job-completion id tasks $data))
|
||||||
(printf "job done!\n~a\n" data)))))))
|
(printf "job done!\n~a\n" data)))))
|
||||||
|
|
||||||
;; ---------------------------------------------------------------------------------------------------
|
;; ---------------------------------------------------------------------------------------------------
|
||||||
;; Main
|
;; Main
|
||||||
|
@ -548,29 +560,4 @@ The JobManager then performs the job and, when finished, asserts
|
||||||
(spawn-task-manager 3)
|
(spawn-task-manager 3)
|
||||||
(spawn-client (file->job "lorem.txt"))
|
(spawn-client (file->job "lorem.txt"))
|
||||||
(spawn-client (string->job INPUT)))
|
(spawn-client (string->job INPUT)))
|
||||||
|
|#
|
||||||
(module+ test
|
|
||||||
#;(verify-actors #;(Eventually (A (JobCompletion ID (List InputTask) TaskResult)))
|
|
||||||
(Always (Implies (A (Observe (JobCompletion ID (List InputTask) ★/t)))
|
|
||||||
(Eventually (A (JobCompletion ID (List InputTask) TaskResult)))))
|
|
||||||
job-manager-impl
|
|
||||||
task-manager-impl
|
|
||||||
client-impl)
|
|
||||||
|
|
||||||
(verify-actors (And (Always (Implies (A (Observe (TaskPerformance ID ConcreteTask ★/t)))
|
|
||||||
(Eventually (A (TaskPerformance ID ConcreteTask TaskStateDesc)))))
|
|
||||||
(Eventually (A (TaskPerformance ID ConcreteTask TaskStateDesc))))
|
|
||||||
TaskAssigner
|
|
||||||
TaskPerformer))
|
|
||||||
|
|
||||||
(module+ test
|
|
||||||
(check-simulates task-runner-impl task-runner-impl)
|
|
||||||
(check-has-simulating-subgraph task-runner-impl TaskPerformer)
|
|
||||||
(check-simulates task-manager-impl task-manager-impl)
|
|
||||||
(check-has-simulating-subgraph task-manager-impl TaskPerformer)
|
|
||||||
(check-has-simulating-subgraph task-manager-impl TaskAssigner)
|
|
||||||
(check-has-simulating-subgraph job-manager-impl TaskAssigner))
|
|
||||||
|
|
||||||
;; infinite loop?
|
|
||||||
#;(module+ test
|
|
||||||
(check-simulates job-manager-impl job-manager-impl))
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; Expected Output:
|
;; Expected Output:
|
||||||
#|
|
#|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
|
;; Expected Output
|
||||||
|
;; pong: 8339
|
||||||
|
|
||||||
|
(define-type-alias ds-type
|
||||||
|
(U (Message (Tuple String Int))
|
||||||
|
(Observe (Tuple String ★/t))))
|
||||||
|
|
||||||
|
(run-ground-dataspace ds-type
|
||||||
|
(spawn ds-type
|
||||||
|
(start-facet echo
|
||||||
|
(on (message (tuple "ping" (bind x Int)))
|
||||||
|
(send! (tuple "pong" x)))))
|
||||||
|
(spawn ds-type
|
||||||
|
(start-facet serve
|
||||||
|
(on start
|
||||||
|
(send! (tuple "ping" 8339)))
|
||||||
|
(on (message (tuple "pong" (bind x Int)))
|
||||||
|
(printf "pong: ~v\n" x)))))
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(provide a-fun)
|
(provide a-fun)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; Expected Output:
|
;; Expected Output:
|
||||||
#|
|
#|
|
|
@ -1,13 +1,10 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require-struct msg #:as Msg
|
(require-struct msg #:as Msg
|
||||||
#:from "driver.rkt")
|
#:from "driver.rkt")
|
||||||
|
|
||||||
(define m (msg 1 "hi"))
|
(define m (msg 1 "hi"))
|
||||||
|
|
||||||
(msg-in m)
|
|
||||||
(msg-out m)
|
|
||||||
|
|
||||||
(match m
|
(match m
|
||||||
[(msg (bind x Int) discard)
|
[(msg (bind x Int) discard)
|
||||||
(displayln x)])
|
(displayln x)])
|
|
@ -0,0 +1,5 @@
|
||||||
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
|
(require/typed "lib.rkt" [x : Int])
|
||||||
|
|
||||||
|
(displayln (+ x 1))
|
|
@ -0,0 +1,5 @@
|
||||||
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
|
(require "provides.rkt")
|
||||||
|
|
||||||
|
(a-fun 5)
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; Expected Output
|
;; Expected Output
|
||||||
;; f: 0
|
;; f: 0
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(run-ground-dataspace Int
|
(run-ground-dataspace Int
|
||||||
(spawn Int
|
(spawn Int
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; Expected Output
|
;; Expected Output
|
||||||
;; +GO
|
;; +GO
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; Expected Output
|
;; Expected Output
|
||||||
;; adding key2 -> 88
|
;; adding key2 -> 88
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; Expected Output
|
;; Expected Output
|
||||||
;; size: 0
|
;; size: 0
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; Expected Output
|
;; Expected Output
|
||||||
;; query: 0
|
;; query: 0
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
;; Expected Output:
|
;; Expected Output:
|
||||||
;; +42
|
;; +42
|
|
@ -0,0 +1,150 @@
|
||||||
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
|
;; Expected Output
|
||||||
|
;; Completed Order:
|
||||||
|
;; Catch 22
|
||||||
|
;; 10001483
|
||||||
|
;; March 9th
|
||||||
|
|
||||||
|
(define-constructor (price v)
|
||||||
|
#:type-constructor PriceT
|
||||||
|
#:with Price (PriceT Int))
|
||||||
|
|
||||||
|
(define-constructor (out-of-stock)
|
||||||
|
#:type-constructor OutOfStockT
|
||||||
|
#:with OutOfStock (OutOfStockT))
|
||||||
|
|
||||||
|
(define-type-alias QuoteAnswer
|
||||||
|
(U Price OutOfStock))
|
||||||
|
|
||||||
|
(define-constructor (quote title answer)
|
||||||
|
#:type-constructor QuoteT
|
||||||
|
#:with Quote (QuoteT String QuoteAnswer)
|
||||||
|
#:with QuoteRequest (Observe (QuoteT String ★/t))
|
||||||
|
#:with QuoteInterest (Observe (QuoteT ★/t ★/t)))
|
||||||
|
|
||||||
|
(define-constructor (split-proposal title price contribution accepted)
|
||||||
|
#:type-constructor SplitProposalT
|
||||||
|
#:with SplitProposal (SplitProposalT String Int Int Bool)
|
||||||
|
#:with SplitRequest (Observe (SplitProposalT String Int Int ★/t))
|
||||||
|
#:with SplitInterest (Observe (SplitProposalT ★/t ★/t ★/t ★/t)))
|
||||||
|
|
||||||
|
(define-constructor (order-id id)
|
||||||
|
#:type-constructor OrderIdT
|
||||||
|
#:with OrderId (OrderIdT Int))
|
||||||
|
|
||||||
|
(define-constructor (delivery-date date)
|
||||||
|
#:type-constructor DeliveryDateT
|
||||||
|
#:with DeliveryDate (DeliveryDateT String))
|
||||||
|
|
||||||
|
(define-type-alias (Maybe t)
|
||||||
|
(U t Bool))
|
||||||
|
|
||||||
|
(define-constructor (order title price id delivery-date)
|
||||||
|
#:type-constructor OrderT
|
||||||
|
#:with Order (OrderT String Int (Maybe OrderId) (Maybe DeliveryDate))
|
||||||
|
#:with OrderRequest (Observe (OrderT String Int ★/t ★/t))
|
||||||
|
#:with OrderInterest (Observe (OrderT ★/t ★/t ★/t ★/t)))
|
||||||
|
|
||||||
|
(define-type-alias ds-type
|
||||||
|
(U ;; quotes
|
||||||
|
Quote
|
||||||
|
QuoteRequest
|
||||||
|
(Observe QuoteInterest)
|
||||||
|
;; splits
|
||||||
|
SplitProposal
|
||||||
|
SplitRequest
|
||||||
|
(Observe SplitInterest)
|
||||||
|
;; orders
|
||||||
|
Order
|
||||||
|
OrderRequest
|
||||||
|
(Observe OrderInterest)))
|
||||||
|
|
||||||
|
(define-type-alias seller-role
|
||||||
|
(Role (seller)
|
||||||
|
(Reacts (Asserted (Observe (QuoteT String ★/t)))
|
||||||
|
(Role (_)
|
||||||
|
(Shares (QuoteT String Int))))))
|
||||||
|
|
||||||
|
(run-ground-dataspace ds-type
|
||||||
|
|
||||||
|
;; seller
|
||||||
|
(spawn ds-type
|
||||||
|
(start-facet _
|
||||||
|
(field [book (Tuple String Int) (tuple "Catch 22" 22)]
|
||||||
|
[next-order-id Int 10001483])
|
||||||
|
(on (asserted (observe (quote (bind title String) discard)))
|
||||||
|
(start-facet x
|
||||||
|
(on (retracted (observe (quote title discard)))
|
||||||
|
(stop x))
|
||||||
|
(define answer
|
||||||
|
(match title
|
||||||
|
["Catch 22"
|
||||||
|
(price 22)]
|
||||||
|
[_
|
||||||
|
(out-of-stock)]))
|
||||||
|
(assert (quote title answer))))
|
||||||
|
(on (asserted (observe (order (bind title String) (bind offer Int) discard discard)))
|
||||||
|
(start-facet x
|
||||||
|
(on (retracted (observe (order title offer discard discard)))
|
||||||
|
(stop x))
|
||||||
|
(let ([asking-price 22])
|
||||||
|
(if (and (equal? title "Catch 22") (>= offer asking-price))
|
||||||
|
(let ([id (ref next-order-id)])
|
||||||
|
(set! next-order-id (+ 1 id))
|
||||||
|
(assert (order title offer (order-id id) (delivery-date "March 9th"))))
|
||||||
|
(assert (order title offer #f #f))))))))
|
||||||
|
|
||||||
|
;; buyer A
|
||||||
|
(spawn ds-type
|
||||||
|
(start-facet buyer
|
||||||
|
(field [title String "Catch 22"]
|
||||||
|
[budget Int 1000])
|
||||||
|
(on (asserted (quote (ref title) (bind answer QuoteAnswer)))
|
||||||
|
(match answer
|
||||||
|
[(out-of-stock)
|
||||||
|
(stop buyer)]
|
||||||
|
[(price (bind amount Int))
|
||||||
|
(start-facet negotiation
|
||||||
|
(field [contribution Int (/ amount 2)])
|
||||||
|
(on (asserted (split-proposal (ref title) amount (ref contribution) (bind accept? Bool)))
|
||||||
|
(if accept?
|
||||||
|
(stop buyer)
|
||||||
|
(if (> (ref contribution) (- amount 5))
|
||||||
|
(stop negotiation (displayln "negotiation failed"))
|
||||||
|
(set! contribution
|
||||||
|
(+ (ref contribution) (/ (- amount (ref contribution)) 2)))))))]))))
|
||||||
|
|
||||||
|
;; buyer B
|
||||||
|
(spawn ds-type
|
||||||
|
(start-facet buyer-b
|
||||||
|
(field [funds Int 5])
|
||||||
|
(on (asserted (observe (split-proposal (bind title String) (bind price Int) (bind their-contribution Int) discard)))
|
||||||
|
(let ([my-contribution (- price their-contribution)])
|
||||||
|
(cond
|
||||||
|
[(> my-contribution (ref funds))
|
||||||
|
(start-facet decline
|
||||||
|
(assert (split-proposal title price their-contribution #f))
|
||||||
|
(on (retracted (observe (split-proposal title price their-contribution discard)))
|
||||||
|
(stop decline)))]
|
||||||
|
[#t
|
||||||
|
(start-facet accept
|
||||||
|
(assert (split-proposal title price their-contribution #t))
|
||||||
|
(on (retracted (observe (split-proposal title price their-contribution discard)))
|
||||||
|
(stop accept))
|
||||||
|
(on start
|
||||||
|
(spawn ds-type
|
||||||
|
(start-facet purchase
|
||||||
|
(on (asserted (order title price (bind order-id? (Maybe OrderId)) (bind delivery-date? (Maybe DeliveryDate))))
|
||||||
|
(match (tuple order-id? delivery-date?)
|
||||||
|
[(tuple (order-id (bind id Int)) (delivery-date (bind date String)))
|
||||||
|
;; complete!
|
||||||
|
(begin (displayln "Completed Order:")
|
||||||
|
(displayln title)
|
||||||
|
(displayln id)
|
||||||
|
(displayln date)
|
||||||
|
(stop purchase))]
|
||||||
|
[discard
|
||||||
|
(begin (displayln "Order Rejected")
|
||||||
|
(stop purchase))]))))))])))))
|
||||||
|
)
|
|
@ -1,33 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
;; Expected Output
|
|
||||||
;; +parent
|
|
||||||
;; +GO
|
|
||||||
;; +ready
|
|
||||||
;; -parent
|
|
||||||
;; -GO
|
|
||||||
;; -ready
|
|
||||||
|
|
||||||
(define-type-alias ds-type
|
|
||||||
(U (Tuple String) (Observe (Tuple ★/t))))
|
|
||||||
|
|
||||||
(run-ground-dataspace ds-type
|
|
||||||
(spawn ds-type
|
|
||||||
(start-facet parent
|
|
||||||
(assert (tuple "parent"))
|
|
||||||
(during/spawn (tuple "GO")
|
|
||||||
(assert (tuple "ready")))
|
|
||||||
(on (asserted (tuple "ready"))
|
|
||||||
(stop parent))))
|
|
||||||
(spawn ds-type
|
|
||||||
(start-facet flag
|
|
||||||
(assert (tuple "GO"))
|
|
||||||
(on (retracted (tuple "parent"))
|
|
||||||
(stop flag))))
|
|
||||||
(spawn ds-type
|
|
||||||
(start-facet obs
|
|
||||||
(during (tuple (bind s String))
|
|
||||||
(on start
|
|
||||||
(printf "+~a\n" s))
|
|
||||||
(on stop
|
|
||||||
(printf "-~a\n" s))))))
|
|
|
@ -1,7 +0,0 @@
|
||||||
#lang typed/syndicate/roles
|
|
||||||
|
|
||||||
(require "typed-out.rkt")
|
|
||||||
|
|
||||||
(define c : (Cow Int) (cow 5))
|
|
||||||
|
|
||||||
(cow-moos c)
|
|
|
@ -1,7 +0,0 @@
|
||||||
#lang typed/syndicate/roles
|
|
||||||
|
|
||||||
(require "struct-out.rkt")
|
|
||||||
|
|
||||||
(happy-days (happy 5))
|
|
||||||
|
|
||||||
(define classic : (Happy Int) (happy 100))
|
|
|
@ -1,5 +0,0 @@
|
||||||
#lang typed/syndicate/roles
|
|
||||||
|
|
||||||
(provide (struct-out happy))
|
|
||||||
|
|
||||||
(define-constructor* (happy : Happy days))
|
|
|
@ -1,5 +0,0 @@
|
||||||
#lang typed/syndicate/roles
|
|
||||||
|
|
||||||
(require-struct cow #:as Cow #:from "untyped.rkt")
|
|
||||||
|
|
||||||
(provide (struct-out cow))
|
|
|
@ -1,5 +0,0 @@
|
||||||
#lang racket
|
|
||||||
|
|
||||||
(provide (struct-out cow))
|
|
||||||
|
|
||||||
(struct cow (moos) #:transparent)
|
|
|
@ -20,14 +20,14 @@
|
||||||
(define-constructor (quote title answer)
|
(define-constructor (quote title answer)
|
||||||
#:type-constructor QuoteT
|
#:type-constructor QuoteT
|
||||||
#:with Quote (QuoteT String QuoteAnswer)
|
#:with Quote (QuoteT String QuoteAnswer)
|
||||||
#:with QuoteRequest (Observe (QuoteT String ★/t))
|
#:with QuoteRequest (Observe (QuoteT String ★))
|
||||||
#:with QuoteInterest (Observe (QuoteT ★/t ★/t)))
|
#:with QuoteInterest (Observe (QuoteT ★ ★)))
|
||||||
|
|
||||||
(define-constructor (split-proposal title price contribution accepted)
|
(define-constructor (split-proposal title price contribution accepted)
|
||||||
#:type-constructor SplitProposalT
|
#:type-constructor SplitProposalT
|
||||||
#:with SplitProposal (SplitProposalT String Int Int Bool)
|
#:with SplitProposal (SplitProposalT String Int Int Bool)
|
||||||
#:with SplitRequest (Observe (SplitProposalT String Int Int ★/t))
|
#:with SplitRequest (Observe (SplitProposalT String Int Int ★))
|
||||||
#:with SplitInterest (Observe (SplitProposalT ★/t ★/t ★/t ★/t)))
|
#:with SplitInterest (Observe (SplitProposalT ★ ★ ★ ★)))
|
||||||
|
|
||||||
(define-constructor (order-id id)
|
(define-constructor (order-id id)
|
||||||
#:type-constructor OrderIdT
|
#:type-constructor OrderIdT
|
||||||
|
@ -40,11 +40,11 @@
|
||||||
(define-type-alias (Maybe t)
|
(define-type-alias (Maybe t)
|
||||||
(U t Bool))
|
(U t Bool))
|
||||||
|
|
||||||
(define-constructor (order title price oid delivery-date)
|
(define-constructor (order title price id delivery-date)
|
||||||
#:type-constructor OrderT
|
#:type-constructor OrderT
|
||||||
#:with Order (OrderT String Int (Maybe OrderId) (Maybe DeliveryDate))
|
#:with Order (OrderT String Int (Maybe OrderId) (Maybe DeliveryDate))
|
||||||
#:with OrderRequest (Observe (OrderT String Int ★/t ★/t))
|
#:with OrderRequest (Observe (OrderT String Int ★ ★))
|
||||||
#:with OrderInterest (Observe (OrderT ★/t ★/t ★/t ★/t)))
|
#:with OrderInterest (Observe (OrderT ★ ★ ★ ★)))
|
||||||
|
|
||||||
(define-type-alias ds-type
|
(define-type-alias ds-type
|
||||||
(U ;; quotes
|
(U ;; quotes
|
||||||
|
@ -60,104 +60,88 @@
|
||||||
OrderRequest
|
OrderRequest
|
||||||
(Observe OrderInterest)))
|
(Observe OrderInterest)))
|
||||||
|
|
||||||
(define-type-alias seller-role
|
(dataspace ds-type
|
||||||
(Role (seller)
|
|
||||||
(During (Observe (QuoteT String ★/t))
|
|
||||||
(Shares (QuoteT String QuoteAnswer)))
|
|
||||||
#;(Reacts (Asserted (Observe (QuoteT String ★/t)))
|
|
||||||
(Role (_)
|
|
||||||
;; QuoteAnswer was originally, erroneously, Int
|
|
||||||
(Shares (QuoteT String QuoteAnswer))))))
|
|
||||||
|
|
||||||
(run-ground-dataspace ds-type
|
|
||||||
|
|
||||||
;; seller
|
;; seller
|
||||||
(spawn ds-type
|
(spawn ds-type
|
||||||
(lift+define-role seller-impl
|
(facet _
|
||||||
(start-facet _ ;; #:implements seller-role
|
(fields [book (Tuple String Int) (tuple "Catch 22" 22)]
|
||||||
(field [book (Tuple String Int) (tuple "Catch 22" 22)]
|
[next-order-id Int 10001483])
|
||||||
[next-order-id Int 10001483])
|
(on (asserted (observe (quote (bind title String) discard)))
|
||||||
(on (asserted (observe (quote (bind title String) discard)))
|
(facet x
|
||||||
(start-facet x
|
(fields)
|
||||||
(on (retracted (observe (quote title discard)))
|
(on (retracted (observe (quote title discard)))
|
||||||
(stop x))
|
(stop x (begin)))
|
||||||
(define answer
|
(match title
|
||||||
(match title
|
["Catch 22"
|
||||||
["Catch 22"
|
(assert (quote title (price 22)))]
|
||||||
(price 22)]
|
[discard
|
||||||
[_
|
(assert (quote title (out-of-stock)))])))
|
||||||
(out-of-stock)]))
|
(on (asserted (observe (order (bind title String) (bind offer Int) discard discard)))
|
||||||
(assert (quote title answer))))
|
(facet x
|
||||||
(on (asserted (observe (order (bind title String) (bind offer Int) discard discard)))
|
(fields)
|
||||||
(start-facet x
|
(on (retracted (observe (order title offer discard discard)))
|
||||||
(on (retracted (observe (order title offer discard discard)))
|
(stop x (begin)))
|
||||||
(stop x))
|
(let [asking-price 22]
|
||||||
(let ([asking-price 22])
|
(if (and (equal? title "Catch 22") (>= offer asking-price))
|
||||||
(if (and (equal? title "Catch 22") (>= offer asking-price))
|
(let [id (ref next-order-id)]
|
||||||
(let ([id (ref next-order-id)])
|
(begin (set! next-order-id (+ 1 id))
|
||||||
(set! next-order-id (+ 1 id))
|
(assert (order title offer (order-id id) (delivery-date "March 9th")))))
|
||||||
(assert (order title offer (order-id id) (delivery-date "March 9th"))))
|
(assert (order title offer #f #f))))))))
|
||||||
(assert (order title offer #f #f)))))))))
|
|
||||||
|
|
||||||
;; buyer A
|
;; buyer A
|
||||||
(spawn ds-type
|
(spawn ds-type
|
||||||
(lift+define-role buyer-a-impl
|
(facet buyer
|
||||||
(start-facet buyer
|
(fields [title String "Catch 22"]
|
||||||
(field [title String "Catch 22"]
|
[budget Int 1000])
|
||||||
[budget Int 1000])
|
(on (asserted (quote (ref title) (bind answer QuoteAnswer)))
|
||||||
(on (asserted (quote (ref title) (bind answer QuoteAnswer)))
|
(match answer
|
||||||
(match answer
|
[(out-of-stock)
|
||||||
[(out-of-stock)
|
(stop buyer (begin))]
|
||||||
(stop buyer)]
|
[(price (bind amount Int))
|
||||||
[(price (bind amount Int))
|
(facet negotiation
|
||||||
(start-facet negotiation
|
(fields [contribution Int (/ amount 2)])
|
||||||
(field [contribution Int (/ amount 2)])
|
(on (asserted (split-proposal (ref title) amount (ref contribution) (bind accept? Bool)))
|
||||||
(on (asserted (split-proposal (ref title) amount (ref contribution) (bind accept? Bool)))
|
(if accept?
|
||||||
(if accept?
|
(stop buyer (begin))
|
||||||
(stop buyer)
|
(if (> (ref contribution) (- amount 5))
|
||||||
(if (> (ref contribution) (- amount 5))
|
(stop negotiation (displayln "negotiation failed"))
|
||||||
(stop negotiation (displayln "negotiation failed"))
|
(set! contribution
|
||||||
(set! contribution
|
(+ (ref contribution) (/ (- amount (ref contribution)) 2)))))))]))))
|
||||||
(+ (ref contribution) (/ (- amount (ref contribution)) 2)))))))])))))
|
|
||||||
|
|
||||||
;; buyer B
|
;; buyer B
|
||||||
(spawn ds-type
|
(spawn ds-type
|
||||||
(lift+define-role buyer-b-impl
|
(facet buyer-b
|
||||||
(start-facet buyer-b
|
(fields [funds Int 5])
|
||||||
(field [funds Int 5])
|
(on (asserted (observe (split-proposal (bind title String) (bind price Int) (bind their-contribution Int) discard)))
|
||||||
(on (asserted (observe (split-proposal (bind title String) (bind price Int) (bind their-contribution Int) discard)))
|
(let [my-contribution (- price their-contribution)]
|
||||||
(let ([my-contribution (- price their-contribution)])
|
(cond
|
||||||
(cond
|
[(> my-contribution (ref funds))
|
||||||
[(> my-contribution (ref funds))
|
(facet decline
|
||||||
(start-facet decline
|
(fields)
|
||||||
(assert (split-proposal title price their-contribution #f))
|
(assert (split-proposal title price their-contribution #f))
|
||||||
(on (retracted (observe (split-proposal title price their-contribution discard)))
|
(on (retracted (observe (split-proposal title price their-contribution discard)))
|
||||||
(stop decline)))]
|
(stop decline (begin))))]
|
||||||
[#t
|
[#t
|
||||||
(start-facet accept
|
(facet accept
|
||||||
(assert (split-proposal title price their-contribution #t))
|
(fields)
|
||||||
(on (retracted (observe (split-proposal title price their-contribution discard)))
|
(assert (split-proposal title price their-contribution #t))
|
||||||
(stop accept))
|
(on (retracted (observe (split-proposal title price their-contribution discard)))
|
||||||
(on start
|
(stop accept (begin)))
|
||||||
(spawn ds-type
|
(on start
|
||||||
(start-facet purchase
|
(spawn ds-type
|
||||||
(on (asserted (order title price (bind order-id? (Maybe OrderId)) (bind delivery-date? (Maybe DeliveryDate))))
|
(facet purchase
|
||||||
(match (tuple order-id? delivery-date?)
|
(fields)
|
||||||
[(tuple (order-id (bind id Int)) (delivery-date (bind date String)))
|
(on (asserted (order title price (bind order-id? (Maybe OrderId)) (bind delivery-date? (Maybe DeliveryDate))))
|
||||||
;; complete!
|
(match (tuple order-id? delivery-date?)
|
||||||
(begin (displayln "Completed Order:")
|
[(tuple (order-id (bind id Int)) (delivery-date (bind date String)))
|
||||||
(displayln title)
|
;; complete!
|
||||||
(displayln id)
|
(begin (displayln "Completed Order:")
|
||||||
(displayln date)
|
(displayln title)
|
||||||
(stop purchase))]
|
(displayln id)
|
||||||
[discard
|
(displayln date)
|
||||||
(begin (displayln "Order Rejected")
|
(stop purchase (begin)))]
|
||||||
(stop purchase))]))))))]))))))
|
[discard
|
||||||
|
(begin (displayln "Order Rejected")
|
||||||
|
(stop purchase (begin)))]))))))])))))
|
||||||
)
|
)
|
||||||
|
|
||||||
(module+ test
|
|
||||||
(check-simulates seller-impl seller-impl)
|
|
||||||
;; found a bug in spec, see seller-role above
|
|
||||||
(check-simulates seller-impl seller-role)
|
|
||||||
(check-simulates buyer-a-impl buyer-a-impl)
|
|
||||||
(check-simulates buyer-b-impl buyer-b-impl))
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
(define (wf1)
|
|
||||||
(spawn
|
|
||||||
(with-facets
|
|
||||||
([onn (facet (assert (tuple 'on))
|
|
||||||
(on start (printf "on\n")))]
|
|
||||||
[off (facet (on (asserted (tuple 'go))
|
|
||||||
(stop off
|
|
||||||
(start onn)))
|
|
||||||
(on start (printf "off\n")))])
|
|
||||||
off)))
|
|
||||||
|
|
||||||
(run-ground-dataspace
|
|
||||||
(wf1)
|
|
||||||
(spawn (start-facet _ (assert (tuple 'go)))))
|
|
||||||
|
|
||||||
;; BAD
|
|
||||||
#;(spawn
|
|
||||||
(with-facets
|
|
||||||
[on (facet (on start (start on)))]
|
|
||||||
on))
|
|
|
@ -12,8 +12,8 @@
|
||||||
(require (only-in "list.rkt" List ~List))
|
(require (only-in "list.rkt" List ~List))
|
||||||
(require (only-in "set.rkt" Set ~Set))
|
(require (only-in "set.rkt" Set ~Set))
|
||||||
(require (only-in "hash.rkt" Hash ~Hash))
|
(require (only-in "hash.rkt" Hash ~Hash))
|
||||||
(require (only-in "prim.rkt" Int Bool + #%datum))
|
(require (only-in "prim.rkt" Bool + #%datum))
|
||||||
(require (only-in "core-expressions.rkt" let unit tuple-select mk-tuple))
|
(require (only-in "core-expressions.rkt" let unit))
|
||||||
(require "maybe.rkt")
|
(require "maybe.rkt")
|
||||||
|
|
||||||
(require (postfix-in - (only-in racket/set
|
(require (postfix-in - (only-in racket/set
|
||||||
|
@ -125,64 +125,36 @@
|
||||||
#,body))]))
|
#,body))]))
|
||||||
|
|
||||||
(define-typed-syntax for/fold
|
(define-typed-syntax for/fold
|
||||||
[(for/fold ([acc:id (~optional (~datum :)) τ-acc init] ...+)
|
[(for/fold ([acc:id (~optional (~datum :)) τ-acc init])
|
||||||
(clause:iter-clause
|
(clause:iter-clause
|
||||||
...)
|
...)
|
||||||
e-body ...+) ≫
|
e-body ...+) ≫
|
||||||
[⊢ init ≫ init- (⇐ : τ-acc)] ...
|
[⊢ init ≫ init- (⇐ : τ-acc)]
|
||||||
#:fail-unless (all-pure? #'(init- ...)) "expression must be pure"
|
#:fail-unless (pure? #'init-) "expression must be pure"
|
||||||
#:with (clauses- ([x x- τ] ...)) (analyze-for-clauses #'(clause.parend ...))
|
#:with (clauses- ([x x- τ] ...)) (analyze-for-clauses #'(clause.parend ...))
|
||||||
#:do [(define num-accs (length (syntax->list #'(τ-acc ...))))]
|
[[x ≫ x-- : τ] ...
|
||||||
#:with body-ty (if (= 1 num-accs)
|
[acc ≫ acc- : τ-acc] ⊢ (block e-body ...) ≫ e-body-
|
||||||
(first (syntax->list #'(τ-acc ...)))
|
(⇐ : τ-acc)
|
||||||
(type-eval #'(Tuple (~@ τ-acc ...))))
|
(⇒ ν-ep (~effs τ-ep ...))
|
||||||
[[[x ≫ x-- : τ] ...]
|
(⇒ ν-s (~effs τ-s ...))
|
||||||
[[acc ≫ acc- : τ-acc] ...] ⊢ (block e-body ...) ≫ e-body-
|
(⇒ ν-f (~effs τ-f ...))]
|
||||||
(⇐ : body-ty)
|
|
||||||
(⇒ ν (~effs F ...))]
|
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
[⊢ (values->tuple #,num-accs
|
[⊢ (for/fold- ([acc- init-])
|
||||||
(for/fold- ([acc- init-] ...)
|
clauses-
|
||||||
clauses-
|
#,(bind-renames #'([x-- x-] ...) #'e-body-))
|
||||||
#,(bind-renames #'([x-- x-] ...) #`(tuple->values #,num-accs e-body-))))
|
(⇒ : τ-acc)
|
||||||
(⇒ : body-ty)
|
(⇒ ν-ep (τ-ep ...))
|
||||||
(⇒ ν (F ...))]]
|
(⇒ ν-s (τ-s ...))
|
||||||
[(for/fold (accs ... [acc:id init] more-accs ...)
|
(⇒ ν-f (τ-f ...))]]
|
||||||
|
[(for/fold ([acc:id init])
|
||||||
clauses
|
clauses
|
||||||
e-body ...+) ≫
|
e-body ...+) ≫
|
||||||
[⊢ init ≫ _ (⇒ : τ-acc)]
|
[⊢ init ≫ _ (⇒ : τ-acc)]
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
[≻ (for/fold (accs ... [acc τ-acc init] more-accs ...)
|
[≻ (for/fold ([acc τ-acc init])
|
||||||
clauses
|
clauses
|
||||||
e-body ...)]])
|
e-body ...)]])
|
||||||
|
|
||||||
(define-syntax-parser tuple->values
|
|
||||||
[(_ n:nat e:expr)
|
|
||||||
(define arity (syntax-e #'n))
|
|
||||||
(cond
|
|
||||||
[(= 1 arity)
|
|
||||||
#'e]
|
|
||||||
[else
|
|
||||||
(define/with-syntax tmp (generate-temporary 'tup))
|
|
||||||
(define projections
|
|
||||||
(for/list ([i (in-range arity)])
|
|
||||||
#`(#%app- tuple-select #,i tmp)))
|
|
||||||
#`(let- ([tmp e])
|
|
||||||
(#%app- values- #,@projections))])])
|
|
||||||
|
|
||||||
#;(tuple->values 1 (tuple 0))
|
|
||||||
|
|
||||||
(define-syntax-parser values->tuple
|
|
||||||
[(_ n:nat e:expr)
|
|
||||||
(define arity (syntax-e #'n))
|
|
||||||
(cond
|
|
||||||
[(= 1 arity)
|
|
||||||
#'e]
|
|
||||||
[else
|
|
||||||
(define/with-syntax (tmp ...) (generate-temporaries (make-list arity 'values->tuple)))
|
|
||||||
#`(let-values- ([(tmp ...) e])
|
|
||||||
(#%app- mk-tuple (#%app- list- tmp ...)))])])
|
|
||||||
|
|
||||||
(define-typed-syntax (for/list (clause:iter-clause ...)
|
(define-typed-syntax (for/list (clause:iter-clause ...)
|
||||||
e-body ...+) ≫
|
e-body ...+) ≫
|
||||||
#:with (clauses- ([x x- τ] ...)) (analyze-for-clauses #'(clause.parend ...))
|
#:with (clauses- ([x x- τ] ...)) (analyze-for-clauses #'(clause.parend ...))
|
||||||
|
@ -204,17 +176,21 @@
|
||||||
#:with (clauses- ([x x- τ] ...)) (analyze-for-clauses #'(clause.parend ...))
|
#:with (clauses- ([x x- τ] ...)) (analyze-for-clauses #'(clause.parend ...))
|
||||||
[[x ≫ x-- : τ] ... ⊢ (block e-body ...) ≫ e-body-
|
[[x ≫ x-- : τ] ... ⊢ (block e-body ...) ≫ e-body-
|
||||||
(⇒ : τ-body)
|
(⇒ : τ-body)
|
||||||
(⇒ ν (~effs F ...))]
|
(⇒ ν-ep (~effs τ-ep ...))
|
||||||
|
(⇒ ν-s (~effs τ-s ...))
|
||||||
|
(⇒ ν-f (~effs τ-f ...))]
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
[⊢ (for/set- clauses-
|
[⊢ (for/set- clauses-
|
||||||
#,(bind-renames #'([x-- x-] ...) #'e-body-))
|
#,(bind-renames #'([x-- x-] ...) #'e-body-))
|
||||||
(⇒ : (Set τ-body))
|
(⇒ : (Set τ-body))
|
||||||
(⇒ ν (F ...))])
|
(⇒ ν-ep (τ-ep ...))
|
||||||
|
(⇒ ν-s (τ-s ...))
|
||||||
|
(⇒ ν-f (τ-f ...))])
|
||||||
|
|
||||||
(define-typed-syntax (for/sum (clause ...)
|
(define-typed-syntax (for/sum (clause ...)
|
||||||
e-body ...+) ≫
|
e-body ...+) ≫
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
[≻ (for/fold ([acc Int 0])
|
[≻ (for/fold ([acc 0])
|
||||||
(clause ...)
|
(clause ...)
|
||||||
(+ acc (let () e-body ...)))])
|
(+ acc (let () e-body ...)))])
|
||||||
|
|
||||||
|
@ -231,7 +207,9 @@
|
||||||
#:with (clauses- ([x x- τ] ...)) (analyze-for-clauses #'(clause.parend ...))
|
#:with (clauses- ([x x- τ] ...)) (analyze-for-clauses #'(clause.parend ...))
|
||||||
[[x ≫ x-- : τ] ... ⊢ (block e-body ...) ≫ e-body-
|
[[x ≫ x-- : τ] ... ⊢ (block e-body ...) ≫ e-body-
|
||||||
(⇒ : τ-body)
|
(⇒ : τ-body)
|
||||||
(⇒ ν (~effs F ...))]
|
(⇒ ν-ep (~effs τ-ep ...))
|
||||||
|
(⇒ ν-s (~effs τ-s ...))
|
||||||
|
(⇒ ν-f (~effs τ-f ...))]
|
||||||
[[res ≫ _ : τ-body] ⊢ res ≫ res- (⇒ : _)]
|
[[res ≫ _ : τ-body] ⊢ res ≫ res- (⇒ : _)]
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
[⊢ (let- ()
|
[⊢ (let- ()
|
||||||
|
@ -242,4 +220,6 @@
|
||||||
(some res-)
|
(some res-)
|
||||||
none))
|
none))
|
||||||
(⇒ : (Maybe τ-body))
|
(⇒ : (Maybe τ-body))
|
||||||
(⇒ ν (F ...))])
|
(⇒ ν-ep (τ-ep ...))
|
||||||
|
(⇒ ν-s (τ-s ...))
|
||||||
|
(⇒ ν-f (τ-f ...))])
|
|
@ -33,20 +33,32 @@
|
||||||
|
|
||||||
(define-container-type Hash #:arity = 2)
|
(define-container-type Hash #:arity = 2)
|
||||||
|
|
||||||
(define-typed-syntax (hash (~seq key:expr val:expr) ...) ≫
|
(begin-for-syntax
|
||||||
|
(define-splicing-syntax-class key-val-list
|
||||||
|
#:attributes (items)
|
||||||
|
(pattern (~seq k1 v1 rest:key-val-list)
|
||||||
|
#:attr items #`((k1 v1) #,@#'rest.items))
|
||||||
|
(pattern (~seq)
|
||||||
|
#:attr items #'())))
|
||||||
|
|
||||||
|
(define-typed-syntax (hash keys&vals:key-val-list) ≫
|
||||||
|
#:with ((key val) ...) #'keys&vals.items
|
||||||
[⊢ key ≫ key- (⇒ : τ-k)] ...
|
[⊢ key ≫ key- (⇒ : τ-k)] ...
|
||||||
[⊢ val ≫ val- (⇒ : τ-val)] ...
|
[⊢ val ≫ val- (⇒ : τ-val)] ...
|
||||||
#:fail-unless (all-pure? #'(key- ... val- ...)) "gotta be pure"
|
#:fail-unless (all-pure? #'(key- ... val- ...)) "gotta be pure"
|
||||||
|
#:with together-again (stx-flatten #'((key- val-) ...))
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
[⊢ (#%app- hash- (~@ key val) ...) (⇒ : (Hash (U τ-k ...) (U τ-val ...)))])
|
[⊢ (#%app- hash- #,@#'together-again) (⇒ : (Hash (U τ-k ...) (U τ-val ...)))])
|
||||||
|
|
||||||
(require/typed racket/base
|
(require/typed racket/base
|
||||||
;; don't have a type for ConsPair
|
;; don't have a type for ConsPair
|
||||||
#;[make-hash : (∀ (K V) (→fn (List (ConsPair K V)) (Hash K V)))]
|
#;[make-hash : (∀ (K V) (→fn (List (ConsPair K V)) (Hash K V)))]
|
||||||
[hash-set : (∀ (K V) (→fn (Hash K V) K V (Hash K V)))]
|
[hash-set : (∀ (K V) (→fn (Hash K V) K V (Hash K V)))]
|
||||||
[hash-ref : (∀ (K V) (→fn (Hash K V) K V))]
|
[hash-ref : (∀ (K V) (→fn (Hash K V) K V))]
|
||||||
|
;; TODO hash-ref/failure
|
||||||
[hash-has-key? : (∀ (K V) (→fn (Hash K V) K Bool))]
|
[hash-has-key? : (∀ (K V) (→fn (Hash K V) K Bool))]
|
||||||
[hash-update : (∀ (K V) (→fn (Hash K V) K (→fn V V) (Hash K V)))]
|
[hash-update : (∀ (K V) (→fn (Hash K V) K (→fn V V) (Hash K V)))]
|
||||||
|
;; TODO hash-update/failure
|
||||||
[hash-remove : (∀ (K V) (→fn (Hash K V) K (Hash K V)))]
|
[hash-remove : (∀ (K V) (→fn (Hash K V) K (Hash K V)))]
|
||||||
[hash-map : (∀ (K V R) (→fn (Hash K V) (→fn K V R) (List R)))]
|
[hash-map : (∀ (K V R) (→fn (Hash K V) (→fn K V R) (List R)))]
|
||||||
[hash-keys : (∀ (K V) (→fn (Hash K V) (List K)))]
|
[hash-keys : (∀ (K V) (→fn (Hash K V) (List K)))]
|
||||||
|
@ -59,6 +71,7 @@
|
||||||
|
|
||||||
(require/typed racket/hash
|
(require/typed racket/hash
|
||||||
[hash-union : (∀ (K1 V1 K2 V2) (→fn (Hash K1 V1) (Hash K2 V2) (Hash (U K1 K2) (U V1 V2))))]
|
[hash-union : (∀ (K1 V1 K2 V2) (→fn (Hash K1 V1) (Hash K2 V2) (Hash (U K1 K2) (U V1 V2))))]
|
||||||
|
;; TODO - hash-union with #:combine
|
||||||
)
|
)
|
||||||
|
|
||||||
(define- (hash-ref/failure- h k err)
|
(define- (hash-ref/failure- h k err)
|
|
@ -1,13 +1,8 @@
|
||||||
#lang info
|
#lang info
|
||||||
|
|
||||||
(define scribblings '(("scribblings/typed-syndicate.scrbl" ())))
|
|
||||||
|
|
||||||
(define compile-omit-paths
|
(define compile-omit-paths
|
||||||
'("examples"
|
'("examples"
|
||||||
"tests"))
|
"tests"))
|
||||||
|
|
||||||
(define test-omit-paths
|
(define test-omit-paths
|
||||||
;; a number of the examples use SPIN for model checking which I need
|
'("examples/roles/chat-tcp2.rkt"))
|
||||||
;; to figure out how to get working on the package server
|
|
||||||
'("examples/"
|
|
||||||
"tests/spin/"))
|
|
||||||
|
|
|
@ -3,24 +3,18 @@
|
||||||
(provide List
|
(provide List
|
||||||
(for-syntax ~List)
|
(for-syntax ~List)
|
||||||
list
|
list
|
||||||
(typed-out [[empty- : (List ⊥)] empty]
|
(typed-out [[cons- : (∀ (X) (→fn X (List X) (List X)))] cons]
|
||||||
[[empty?- : (∀ (X) (→fn (List X) Bool))] empty?]
|
|
||||||
[[cons- : (∀ (X) (→fn X (List X) (List X)))] cons]
|
|
||||||
[[cons?- : (∀ (X) (→fn X (List X) Bool))] cons?]
|
|
||||||
[[first- : (∀ (X) (→fn (List X) X))] first]
|
[[first- : (∀ (X) (→fn (List X) X))] first]
|
||||||
[[second- : (∀ (X) (→fn (List X) X))] second]
|
[[second- : (∀ (X) (→fn (List X) X))] second]
|
||||||
[[rest- : (∀ (X) (→fn (List X) (List X)))] rest]
|
[[rest- : (∀ (X) (→fn (List X) (List X)))] rest]
|
||||||
[[member?- (∀ (X) (→fn X (List X) Bool))] member?]
|
[[member?- (∀ (X) (→fn X (List X) Bool))] member?]
|
||||||
|
[[empty?- (∀ (X) (→fn (List X) Bool))] empty?]
|
||||||
[[reverse- (∀ (X) (→fn (List X) (List X)))] reverse]
|
[[reverse- (∀ (X) (→fn (List X) (List X)))] reverse]
|
||||||
[[partition- (∀ (X) (→fn (List X) (→fn X Bool) (List X)))] partition]
|
[[partition- (∀ (X) (→fn (List X) (→fn X Bool) (List X)))] partition]
|
||||||
[[map- (∀ (X Y) (→fn (→fn X Y) (List X) (List Y)))] map]
|
[[map- (∀ (X Y) (→fn (→fn X Y) (List X) (List Y)))] map]))
|
||||||
[[argmax- : (∀ (X) (→fn (→fn X Int) (List X) X))] argmax]
|
|
||||||
[[argmin- : (∀ (X) (→fn (→fn X Int) (List X) X))] argmin]
|
|
||||||
[[remove- : (∀ (X) (→fn X (List X) (List X)))] remove]
|
|
||||||
[[length- : (∀ (X) (→fn (List X) Int))] length]))
|
|
||||||
|
|
||||||
(require "core-types.rkt")
|
(require "core-types.rkt")
|
||||||
(require (only-in "prim.rkt" Bool Int))
|
(require (only-in "prim.rkt" Bool))
|
||||||
(require (postfix-in - racket/list))
|
(require (postfix-in - racket/list))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
@ -7,25 +7,23 @@
|
||||||
;; - (eventually [LTL X])
|
;; - (eventually [LTL X])
|
||||||
;; - (weak-until [LTL X] [LTL X])
|
;; - (weak-until [LTL X] [LTL X])
|
||||||
;; - (strong-until [LTL X] [LTL X])
|
;; - (strong-until [LTL X] [LTL X])
|
||||||
;; - (release [LTL X] [LTL X])
|
|
||||||
;; - (ltl-implies [LTL X] [LTL X])
|
;; - (ltl-implies [LTL X] [LTL X])
|
||||||
;; - (ltl-and [LTL X] [LTL X])
|
;; - (ltl-and [Listof [LTL X]])
|
||||||
;; - (ltl-or [LTL X] [LTL X])
|
;; - (ltl-or [Listof [LTL X]])
|
||||||
;; - (ltl-not [LTL X])
|
;; - (ltl-not [LTL X])
|
||||||
;; - (atomic X)
|
;; - (atomic X)
|
||||||
;; - Bool
|
;; - Bool
|
||||||
;; where X represents the type of atomic propositions
|
;; where X represents the type of atomic propositions
|
||||||
|
|
||||||
(struct always [p] #:prefab)
|
(struct always [p] #:transparent)
|
||||||
(struct eventually [p] #:prefab)
|
(struct eventually [p] #:transparent)
|
||||||
(struct atomic [p] #:prefab)
|
(struct atomic [p] #:transparent)
|
||||||
(struct weak-until [p q] #:prefab)
|
(struct weak-until [p q] #:transparent)
|
||||||
(struct strong-until [p q] #:prefab)
|
(struct strong-until [p q] #:transparent)
|
||||||
(struct release [p q] #:prefab)
|
(struct ltl-implies [p q] #:transparent)
|
||||||
(struct ltl-implies [p q] #:prefab)
|
(struct ltl-and [p q] #:transparent)
|
||||||
(struct ltl-and [p q] #:prefab)
|
(struct ltl-or [p q] #:transparent)
|
||||||
(struct ltl-or [p q] #:prefab)
|
(struct ltl-not [p] #:transparent)
|
||||||
(struct ltl-not [p] #:prefab)
|
|
||||||
|
|
||||||
;; [LTL X] {X -> Y} -> [LTL Y]
|
;; [LTL X] {X -> Y} -> [LTL Y]
|
||||||
(define (map-atomic ltl op)
|
(define (map-atomic ltl op)
|
||||||
|
@ -39,8 +37,6 @@
|
||||||
(weak-until (loop p) (loop q))]
|
(weak-until (loop p) (loop q))]
|
||||||
[(strong-until p q)
|
[(strong-until p q)
|
||||||
(strong-until (loop p) (loop q))]
|
(strong-until (loop p) (loop q))]
|
||||||
[(release p q)
|
|
||||||
(release (loop p) (loop q))]
|
|
||||||
[(ltl-implies p q)
|
[(ltl-implies p q)
|
||||||
(ltl-implies (loop p) (loop q))]
|
(ltl-implies (loop p) (loop q))]
|
||||||
[(ltl-and p q)
|
[(ltl-and p q)
|
|
@ -5,12 +5,9 @@
|
||||||
None*
|
None*
|
||||||
Some
|
Some
|
||||||
some
|
some
|
||||||
none
|
none)
|
||||||
has?)
|
|
||||||
|
|
||||||
(require "core-types.rkt")
|
(require "core-types.rkt")
|
||||||
(require "prim.rkt")
|
|
||||||
(require "core-expressions.rkt")
|
|
||||||
|
|
||||||
|
|
||||||
(define-constructor* (none* : None*))
|
(define-constructor* (none* : None*))
|
||||||
|
@ -38,10 +35,3 @@
|
||||||
(error "some")]
|
(error "some")]
|
||||||
[none
|
[none
|
||||||
(error "none")]))
|
(error "none")]))
|
||||||
|
|
||||||
(define (∀ (X) (has? [v : (Maybe X)] [p : (→fn X Bool)] -> Bool))
|
|
||||||
(match v
|
|
||||||
[none
|
|
||||||
#f]
|
|
||||||
[(some $x)
|
|
||||||
(p x)]))
|
|
|
@ -1,31 +1,28 @@
|
||||||
#lang turnstile
|
#lang turnstile
|
||||||
|
|
||||||
(provide (all-defined-out)
|
(provide (all-defined-out)
|
||||||
True False Bool
|
|
||||||
(for-syntax (all-defined-out)))
|
(for-syntax (all-defined-out)))
|
||||||
|
|
||||||
(require "core-types.rkt")
|
(require "core-types.rkt")
|
||||||
(require (rename-in racket/math [exact-truncate exact-truncate-]))
|
(require (rename-in racket/math [exact-truncate exact-truncate-]))
|
||||||
(require (postfix-in - (only-in racket/format ~a ~v)))
|
(require (postfix-in - (only-in racket/format ~a)))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Primitives
|
;; Primitives
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(define-base-types Zero NonZero String ByteString Symbol)
|
(define-base-types Int Bool String ByteString Symbol)
|
||||||
|
|
||||||
(define-type-alias Int (U Zero NonZero))
|
|
||||||
|
|
||||||
;; hmmm
|
;; hmmm
|
||||||
(define-primop + (→fn Int Int Int))
|
(define-primop + (→ Int Int (Computation (Value Int) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop - (→fn Int Int Int))
|
(define-primop - (→ Int Int (Computation (Value Int) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop * (→fn Int Int Int))
|
(define-primop * (→ Int Int (Computation (Value Int) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop not (→fn Bool Bool))
|
(define-primop not (→ Bool (Computation (Value Bool) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop < (→fn Int Int Bool))
|
(define-primop < (→ Int Int (Computation (Value Bool) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop > (→fn Int Int Bool))
|
(define-primop > (→ Int Int (Computation (Value Bool) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop <= (→fn Int Int Bool))
|
(define-primop <= (→ Int Int (Computation (Value Bool) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop >= (→fn Int Int Bool))
|
(define-primop >= (→ Int Int (Computation (Value Bool) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop = (→fn Int Int Bool))
|
(define-primop = (→ Int Int (Computation (Value Bool) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop even? (→fn Int Bool))
|
(define-primop even? (→fn Int Bool))
|
||||||
(define-primop odd? (→fn Int Bool))
|
(define-primop odd? (→fn Int Bool))
|
||||||
(define-primop add1 (→fn Int Int))
|
(define-primop add1 (→fn Int Int))
|
||||||
|
@ -35,14 +32,12 @@
|
||||||
(define-primop zero? (→fn Int Bool))
|
(define-primop zero? (→fn Int Bool))
|
||||||
(define-primop positive? (→fn Int Bool))
|
(define-primop positive? (→fn Int Bool))
|
||||||
(define-primop negative? (→fn Int Bool))
|
(define-primop negative? (→fn Int Bool))
|
||||||
(define-primop current-inexact-milliseconds (→fn Int))
|
|
||||||
(define-primop string=? (→fn String String Bool))
|
|
||||||
|
|
||||||
(define-primop bytes->string/utf-8 (→fn ByteString String))
|
(define-primop bytes->string/utf-8 (→ ByteString (Computation (Value String) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop string->bytes/utf-8 (→fn String ByteString))
|
(define-primop string->bytes/utf-8 (→ String (Computation (Value ByteString) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop gensym (→fn Symbol Symbol))
|
(define-primop gensym (→ Symbol (Computation (Value Symbol) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop symbol->string (→fn Symbol String))
|
(define-primop symbol->string (→ Symbol (Computation (Value String) (Endpoints) (Roles) (Spawns))))
|
||||||
(define-primop string->symbol (→fn String Symbol))
|
(define-primop string->symbol (→ String (Computation (Value Symbol) (Endpoints) (Roles) (Spawns))))
|
||||||
|
|
||||||
(define-typed-syntax (/ e1 e2) ≫
|
(define-typed-syntax (/ e1 e2) ≫
|
||||||
[⊢ e1 ≫ e1- (⇐ : Int)]
|
[⊢ e1 ≫ e1- (⇐ : Int)]
|
||||||
|
@ -99,35 +94,17 @@
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
[⊢ (#%app- ~a- e- ...) (⇒ : String)])
|
[⊢ (#%app- ~a- e- ...) (⇒ : String)])
|
||||||
|
|
||||||
(define-typed-syntax (~v e ...) ≫
|
|
||||||
[⊢ e ≫ e- (⇒ : τ)] ...
|
|
||||||
#:fail-unless (stx-andmap flat-type? #'(τ ...))
|
|
||||||
"expressions must be string-able"
|
|
||||||
--------------------------------------------------
|
|
||||||
[⊢ (#%app- ~v- e- ...) (⇒ : String)])
|
|
||||||
|
|
||||||
(define-typed-syntax (format s e ...) ≫
|
|
||||||
[⊢ s ≫ s- (⇐ : String)]
|
|
||||||
[⊢ e ≫ e- (⇒ : τ)] ...
|
|
||||||
#:fail-unless (stx-andmap flat-type? #'(τ ...))
|
|
||||||
"expressions must be string-able"
|
|
||||||
--------------------------------------------------
|
|
||||||
[⊢ (#%app- format- s- e- ...) (⇒ : String)])
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Basic Values
|
;; Basic Values
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(define-typed-syntax #%datum
|
(define-typed-syntax #%datum
|
||||||
[(_ . n:integer) ≫
|
[(_ . n:integer) ≫
|
||||||
#:with T (if (zero? (syntax-e #'n)) #'Zero #'NonZero)
|
|
||||||
----------------
|
----------------
|
||||||
[⊢ (#%datum- . n) (⇒ : T)]]
|
[⊢ (#%datum- . n) (⇒ : Int)]]
|
||||||
[(_ . b:boolean)
|
[(_ . b:boolean) ≫
|
||||||
≫
|
|
||||||
#:with T (if (syntax-e #'b) #'True #'False)
|
|
||||||
----------------
|
----------------
|
||||||
[⊢ (#%datum- . b) (⇒ : T)]]
|
[⊢ (#%datum- . b) (⇒ : Bool)]]
|
||||||
[(_ . s:string) ≫
|
[(_ . s:string) ≫
|
||||||
----------------
|
----------------
|
||||||
[⊢ (#%datum- . s) (⇒ : String)]])
|
[⊢ (#%datum- . s) (⇒ : String)]])
|
|
@ -13,7 +13,6 @@
|
||||||
;; Role Type Data Definitions
|
;; Role Type Data Definitions
|
||||||
|
|
||||||
;; a FacetName is a symbol
|
;; a FacetName is a symbol
|
||||||
;; a Name is a Symbol
|
|
||||||
|
|
||||||
;; a T is one of
|
;; a T is one of
|
||||||
;; - (Role FacetName (Listof EP)), also abbreviated as just Role
|
;; - (Role FacetName (Listof EP)), also abbreviated as just Role
|
||||||
|
@ -21,31 +20,26 @@
|
||||||
;; - (Sends τ)
|
;; - (Sends τ)
|
||||||
;; - (Realizes τ)
|
;; - (Realizes τ)
|
||||||
;; - (Stop FacetName Body)
|
;; - (Stop FacetName Body)
|
||||||
;; - (WriteField Name τ)
|
(struct Role (nm eps) #:transparent)
|
||||||
(struct Role (nm eps) #:prefab)
|
(struct Spawn (ty) #:transparent)
|
||||||
(struct Spawn (ty) #:prefab)
|
(struct Sends (ty) #:transparent)
|
||||||
(struct Sends (ty) #:prefab)
|
(struct Realizes (ty) #:transparent)
|
||||||
(struct Realizes (ty) #:prefab)
|
(struct Stop (nm body) #:transparent)
|
||||||
(struct Stop (nm body) #:prefab)
|
|
||||||
(struct WriteField (nm ty) #:prefab)
|
|
||||||
(struct ReadField (nm) #:prefab)
|
|
||||||
|
|
||||||
;; a EP is one of
|
;; a EP is one of
|
||||||
;; - (Reacts D Body), describing an event handler
|
;; - (Reacts D Body), describing an event handler
|
||||||
;; - (Shares τ), describing an assertion
|
;; - (Shares τ), describing an assertion
|
||||||
;; - (Know τ), describing an internal assertion
|
;; - (Know τ), describing an internal assertion
|
||||||
;; - (Field Name τ), describing a field declaration
|
(struct Reacts (evt body) #:transparent)
|
||||||
(struct Reacts (evt body) #:prefab)
|
(struct Shares (ty) #:transparent)
|
||||||
(struct Shares (ty) #:prefab)
|
(struct Know (ty) #:transparent)
|
||||||
(struct Know (ty) #:prefab)
|
|
||||||
(struct Field (nm ty) #:prefab)
|
|
||||||
|
|
||||||
;; a Body describes actions carried out in response to some event, and
|
;; a Body describes actions carried out in response to some event, and
|
||||||
;; is one of
|
;; is one of
|
||||||
;; - T
|
;; - T
|
||||||
;; - (Listof Body)
|
;; - (Listof Body)
|
||||||
;; - (Branch (Listof Body))
|
;; - (Branch (Listof Body))
|
||||||
(struct Branch (arms) #:prefab)
|
(struct Branch (arms) #:transparent)
|
||||||
|
|
||||||
;; a D is one of
|
;; a D is one of
|
||||||
;; - (Asserted τ), reaction to assertion
|
;; - (Asserted τ), reaction to assertion
|
||||||
|
@ -57,11 +51,11 @@
|
||||||
;; - StartEvt, reaction to facet startup
|
;; - StartEvt, reaction to facet startup
|
||||||
;; - StopEvt, reaction to facet shutdown
|
;; - StopEvt, reaction to facet shutdown
|
||||||
;; - DataflowEvt, reaction to field updates
|
;; - DataflowEvt, reaction to field updates
|
||||||
(struct Asserted (ty) #:prefab)
|
(struct Asserted (ty) #:transparent)
|
||||||
(struct Retracted (ty) #:prefab)
|
(struct Retracted (ty) #:transparent)
|
||||||
(struct Message (ty) #:prefab)
|
(struct Message (ty) #:transparent)
|
||||||
(struct Forget (ty) #:prefab)
|
(struct Forget (ty) #:transparent)
|
||||||
(struct Realize (ty) #:prefab)
|
(struct Realize (ty) #:transparent)
|
||||||
(define StartEvt 'Start)
|
(define StartEvt 'Start)
|
||||||
(define StopEvt 'Stop)
|
(define StopEvt 'Stop)
|
||||||
(define DataflowEvt 'Dataflow)
|
(define DataflowEvt 'Dataflow)
|
||||||
|
@ -74,8 +68,8 @@
|
||||||
;; specified facet,
|
;; specified facet,
|
||||||
;; - (StartOf FacetName)
|
;; - (StartOf FacetName)
|
||||||
;; - (StopOf FacetName)
|
;; - (StopOf FacetName)
|
||||||
(struct StartOf (fn) #:prefab)
|
(struct StartOf (fn) #:transparent)
|
||||||
(struct StopOf (fn) #:prefab)
|
(struct StopOf (fn) #:transparent)
|
||||||
|
|
||||||
;; NOTE: because I'm adding D+ after writing a bunch of code using only D,
|
;; NOTE: because I'm adding D+ after writing a bunch of code using only D,
|
||||||
;; expect inconsistencies in signatures and names
|
;; expect inconsistencies in signatures and names
|
||||||
|
@ -90,20 +84,17 @@
|
||||||
;; - ⋆
|
;; - ⋆
|
||||||
;; - (Base Symbol)
|
;; - (Base Symbol)
|
||||||
;; - (internal-label Symbol τ)
|
;; - (internal-label Symbol τ)
|
||||||
;; - (VarTy Name (NEListof (List τ τ))), describing an assertion endpoint
|
(struct U (tys) #:transparent)
|
||||||
;; whose type varies depending on the type of the named field
|
(struct Struct (nm tys) #:transparent)
|
||||||
(struct U (tys) #:prefab)
|
(struct Observe (ty) #:transparent)
|
||||||
(struct Struct (nm tys) #:prefab)
|
(struct List (ty) #:transparent)
|
||||||
(struct Observe (ty) #:prefab)
|
(struct Set (ty) #:transparent)
|
||||||
(struct List (ty) #:prefab)
|
(struct Hash (ty-k ty-v) #:transparent)
|
||||||
(struct Set (ty) #:prefab)
|
(struct Mk⋆ () #:transparent)
|
||||||
(struct Hash (ty-k ty-v) #:prefab)
|
(struct internal-label (actor-id ty) #:transparent)
|
||||||
(struct Mk⋆ () #:prefab)
|
|
||||||
(struct internal-label (actor-id ty) #:prefab)
|
|
||||||
(struct VarTy (nm tys) #:prefab)
|
|
||||||
;; TODO this might be a problem when used as a match pattern
|
;; TODO this might be a problem when used as a match pattern
|
||||||
(define ⋆ (Mk⋆))
|
(define ⋆ (Mk⋆))
|
||||||
(struct Base (name) #:prefab)
|
(struct Base (name) #:transparent)
|
||||||
(define Int (Base 'Int))
|
(define Int (Base 'Int))
|
||||||
(define String (Base 'String))
|
(define String (Base 'String))
|
||||||
(define Bool (Base 'Bool))
|
(define Bool (Base 'Bool))
|
||||||
|
@ -142,8 +133,8 @@
|
||||||
;; a TransitionEffect is one of
|
;; a TransitionEffect is one of
|
||||||
;; - (send τ)
|
;; - (send τ)
|
||||||
;; - (realize τ)
|
;; - (realize τ)
|
||||||
(struct send (ty) #:prefab)
|
(struct send (ty) #:transparent)
|
||||||
(struct realize (ty) #:prefab)
|
(struct realize (ty) #:transparent)
|
||||||
|
|
||||||
;; a TransitionDesc is a (Hashof D+ (Setof (Listof RoleEffect)), describing the
|
;; a TransitionDesc is a (Hashof D+ (Setof (Listof RoleEffect)), describing the
|
||||||
;; possible ways an event (+/- of an assertion) can alter the facet tree.
|
;; possible ways an event (+/- of an assertion) can alter the facet tree.
|
||||||
|
@ -213,14 +204,13 @@
|
||||||
(values D txns)))
|
(values D txns)))
|
||||||
(define assertions (assertions-in-state current assertion#))
|
(define assertions (assertions-in-state current assertion#))
|
||||||
(define new-work
|
(define new-work
|
||||||
(for*/set ([txns (in-hash-values transitions)]
|
(for*/list ([txns (in-hash-values transitions)]
|
||||||
[txn (in-set txns)]
|
[txn (in-set txns)]
|
||||||
[st (in-value (transition-dest txn))]
|
[st (in-value (transition-dest txn))]
|
||||||
#:unless (or (equal? st current)
|
#:unless (equal? st current)
|
||||||
(hash-has-key? states st)
|
#:unless (hash-has-key? states st))
|
||||||
(member st more)))
|
|
||||||
st))
|
st))
|
||||||
(loop (append more (set->list new-work))
|
(loop (append more new-work)
|
||||||
(hash-set states current (state current transitions assertions)))]
|
(hash-set states current (state current transitions assertions)))]
|
||||||
['()
|
['()
|
||||||
(role-graph (set (Role-nm role)) states)])))
|
(role-graph (set (Role-nm role)) states)])))
|
||||||
|
@ -247,25 +237,24 @@
|
||||||
(match-define (role-graph st0 st#) rg)
|
(match-define (role-graph st0 st#) rg)
|
||||||
(check-true (hash-has-key? st# (set 'x 'y)))))
|
(check-true (hash-has-key? st# (set 'x 'y)))))
|
||||||
|
|
||||||
;; a DetectedCylce is a (detected-cycle StateName (Listof TraversalStep)), as in
|
;; a DetectedCylce is a (List (Listof StateName) D D D), as in
|
||||||
;; (detected-cycle start steps)
|
;; (list path init evt D)
|
||||||
;; where path represents the sequences of states containing a cycle,
|
;; where
|
||||||
(struct detected-cycle (start steps) #:transparent)
|
;; - path represents the sequences of states containing a cycle,
|
||||||
|
;; - init is the external event that initiated this activity
|
||||||
;; a TraversalStep is a (traversal-step D StateName)
|
;; - evt is the last-taken internal event
|
||||||
;; representing a state transition along an edge matching D to a destination state
|
;; - D is the edge in the graph that matched evt
|
||||||
(struct traversal-step (evt dest) #:transparent)
|
|
||||||
|
|
||||||
;; RoleGraph Role -> (U RoleGraph DetectedCycle)
|
;; RoleGraph Role -> (U RoleGraph DetectedCycle)
|
||||||
;; "Optimize" the given role graph with respect to internal events.
|
;; "Optimize" the given role graph with respect to internal events.
|
||||||
;; The resulting graph will have transitions of only external events.
|
;; The resulting graph will have transitions of only external events.
|
||||||
(define (compile/internal-events rg)
|
(define (compile/internal-events rg role)
|
||||||
(match-define (role-graph st0 orig-st#) rg)
|
(match-define (role-graph st0 orig-st#) rg)
|
||||||
;; doing funny business with state (set) here
|
;; doing funny business with state (set) here
|
||||||
(define orig-st#+ (hash-set orig-st# (set) (state (set) (hash) (set))))
|
(define orig-st#+ (hash-set orig-st# (set) (state (set) (hash) (set))))
|
||||||
|
|
||||||
;; a WorkItem is a
|
;; a WorkItem is a
|
||||||
;; (work-item TraversalStep (Listof TraversalStep) D+ (Listof D+) (Listof TransitionEffect))
|
;; (work-item StateName (Listof StateName) D+ (Listof D+) (Listof TransitionEffect))
|
||||||
;; such as (work-item from path/r to by with effs), where
|
;; such as (work-item from path/r to by with effs), where
|
||||||
;; - from is the origin state for this chain of events
|
;; - from is the origin state for this chain of events
|
||||||
;; - path/r is the list of states in the path to this point, *after* from, in reverse
|
;; - path/r is the list of states in the path to this point, *after* from, in reverse
|
||||||
|
@ -275,7 +264,6 @@
|
||||||
;; - with is a list of pending events to be processed
|
;; - with is a list of pending events to be processed
|
||||||
;; - effs are the external effects emitted on this path
|
;; - effs are the external effects emitted on this path
|
||||||
(struct work-item (from path/r to by with effs) #:transparent)
|
(struct work-item (from path/r to by with effs) #:transparent)
|
||||||
|
|
||||||
(let/ec fail
|
(let/ec fail
|
||||||
(define (walk work visited st#)
|
(define (walk work visited st#)
|
||||||
(match work
|
(match work
|
||||||
|
@ -302,21 +290,20 @@
|
||||||
(set! states (hash-set states (set) (state (set) (hash) (set)))))
|
(set! states (hash-set states (set) (state (set) (hash) (set)))))
|
||||||
(role-graph new-st0 states)]
|
(role-graph new-st0 states)]
|
||||||
[(cons (work-item from path/r to by with effs) more-work)
|
[(cons (work-item from path/r to by with effs) more-work)
|
||||||
(match-define (traversal-step last-evt cur-st) to)
|
(define prev (if (empty? path/r) from (first path/r)))
|
||||||
(define prev (if (empty? path/r) from (traversal-step-dest (first path/r))))
|
|
||||||
(define prev-assertions (state-assertions (hash-ref orig-st#+ prev)))
|
(define prev-assertions (state-assertions (hash-ref orig-st#+ prev)))
|
||||||
(match-define (state _ txn# cur-assertions) (hash-ref orig-st#+ cur-st))
|
(match-define (state _ txn# cur-assertions) (hash-ref orig-st#+ to))
|
||||||
(define new-state-changes (route-internal prev-assertions
|
(define new-state-changes (route-internal prev-assertions
|
||||||
cur-assertions))
|
cur-assertions))
|
||||||
(define state-changes* (for/list ([D (in-set new-state-changes)]
|
(define state-changes* (for/list ([D (in-set new-state-changes)]
|
||||||
#:when (for/or ([D/actual (in-hash-keys txn#)])
|
#:when (for/or ([D/actual (in-hash-keys txn#)])
|
||||||
(D<:? D D/actual)))
|
(D<:? D D/actual)))
|
||||||
D))
|
D))
|
||||||
(define started (for*/list ([fn (in-set (set-subtract cur-st prev))]
|
(define started (for*/list ([fn (in-set (set-subtract to prev))]
|
||||||
[D (in-value (StartOf fn))]
|
[D (in-value (StartOf fn))]
|
||||||
#:when (hash-has-key? txn# D))
|
#:when (hash-has-key? txn# D))
|
||||||
D))
|
D))
|
||||||
(define stopped (for*/list ([fn (in-set (set-subtract prev cur-st))]
|
(define stopped (for*/list ([fn (in-set (set-subtract prev to))]
|
||||||
[D (in-value (StopOf fn))]
|
[D (in-value (StopOf fn))]
|
||||||
#:when (hash-has-key? txn# D))
|
#:when (hash-has-key? txn# D))
|
||||||
D))
|
D))
|
||||||
|
@ -345,12 +332,18 @@
|
||||||
#:when (implies (DataflowEvt? D) (DataflowEvt? evt))
|
#:when (implies (DataflowEvt? D) (DataflowEvt? evt))
|
||||||
[t (in-set ts)])
|
[t (in-set ts)])
|
||||||
(match-define (transition more-effs dest) t)
|
(match-define (transition more-effs dest) t)
|
||||||
(check-for-cycle! from path/r+ evt dest fail)
|
(when (and (member dest path/r+)
|
||||||
|
;; TODO - cycles involving Start/Stop are tricky. Punt for now
|
||||||
|
(not (start/stop-evt? evt)))
|
||||||
|
(fail (list (cons from (reverse (cons dest path/r+)))
|
||||||
|
by
|
||||||
|
evt
|
||||||
|
D)))
|
||||||
(define-values (internal-effs external-effs)
|
(define-values (internal-effs external-effs)
|
||||||
(partition-transition-effects more-effs))
|
(partition-transition-effects more-effs))
|
||||||
(work-item from
|
(work-item from
|
||||||
path/r+
|
path/r+
|
||||||
(traversal-step evt dest)
|
dest
|
||||||
by
|
by
|
||||||
(append more-pending internal-effs)
|
(append more-pending internal-effs)
|
||||||
(append effs external-effs)))]))
|
(append effs external-effs)))]))
|
||||||
|
@ -368,9 +361,9 @@
|
||||||
(cond
|
(cond
|
||||||
[(ormap empty? induced-work)
|
[(ormap empty? induced-work)
|
||||||
;; this is the end of some path
|
;; this is the end of some path
|
||||||
(define visited+ (set-add visited cur-st))
|
(define visited+ (set-add visited to))
|
||||||
(define new-paths-work
|
(define new-paths-work
|
||||||
(for*/list (#:unless (set-member? visited cur-st)
|
(for*/list (#:unless (set-member? visited to)
|
||||||
[(D txns) (in-hash txn#)]
|
[(D txns) (in-hash txn#)]
|
||||||
#:when (external-evt? D)
|
#:when (external-evt? D)
|
||||||
#:unless (equal? D DataflowEvt)
|
#:unless (equal? D DataflowEvt)
|
||||||
|
@ -378,52 +371,21 @@
|
||||||
(match-define (transition es dst) t)
|
(match-define (transition es dst) t)
|
||||||
(define-values (internal-effs external-effs)
|
(define-values (internal-effs external-effs)
|
||||||
(partition-transition-effects es))
|
(partition-transition-effects es))
|
||||||
(work-item cur-st '() (traversal-step D dst) D internal-effs external-effs)))
|
(work-item to '() dst D internal-effs external-effs)))
|
||||||
(define new-st# (update-path st# from cur-st by effs))
|
(define new-st# (update-path st# from to by effs))
|
||||||
(walk (append more-work induced-work* new-paths-work) visited+ new-st#)]
|
(walk (append more-work induced-work* new-paths-work) visited+ new-st#)]
|
||||||
[else
|
[else
|
||||||
(walk (append more-work induced-work*) visited st#)])]))
|
(walk (append more-work induced-work*) visited st#)])]))
|
||||||
(walk (list (work-item (set) '() (traversal-step StartEvt st0) StartEvt '() '()))
|
(walk (list (work-item (set) '() st0 StartEvt '() '()))
|
||||||
(set)
|
(set)
|
||||||
(hash))))
|
(hash))))
|
||||||
|
|
||||||
#|
|
|
||||||
(define input (file->value "va2.rktd"))
|
|
||||||
(define rg (compile input))
|
|
||||||
(render-to-file rg "va2.dot")
|
|
||||||
|
|
||||||
(define rgi (compile/internal-events rg))
|
|
||||||
(render-to-file rgi "va2i.dot")
|
|
||||||
|#
|
|
||||||
|
|
||||||
;; (Listof TraceStep) D StateName (DetectedCycle -> X) -> (U X Void)
|
|
||||||
;; the path is in reverse, and the final step is the pair evt/dest;
|
|
||||||
;; so their is a cycle if the sequence from the first occurrence of
|
|
||||||
;; dest in the path matches the sequence from the second occurrence to
|
|
||||||
;; the first.
|
|
||||||
(define (check-for-cycle! from path/r evt dest fail)
|
|
||||||
;; TraceStep -> Bool
|
|
||||||
(define (same-state? step) (equal? dest (traversal-step-dest step)))
|
|
||||||
|
|
||||||
;; (Listof TraceStep) -> (Values (Listof TraceStep) (Listof TraceStep))
|
|
||||||
(define (split-at-same-state steps) (splitf-at steps (compose not same-state?)))
|
|
||||||
|
|
||||||
(define-values (loop1 trail) (split-at-same-state path/r))
|
|
||||||
(when (cons? trail)
|
|
||||||
(match-define (cons prior-last trail2) trail)
|
|
||||||
(define-values (loop2 trail3) (split-at-same-state trail2))
|
|
||||||
(define last-step (traversal-step evt dest))
|
|
||||||
(when (and (cons? trail3)
|
|
||||||
(equal? (cons last-step loop1)
|
|
||||||
(cons prior-last loop2)))
|
|
||||||
(fail (detected-cycle from (reverse (cons last-step path/r)))))))
|
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(test-case
|
(test-case
|
||||||
"most minimal functionality for removing internal events"
|
"most minimal functionality for removing internal events"
|
||||||
;; manager role has basically nothing to it
|
;; manager role has basically nothing to it
|
||||||
(define m (compile manager))
|
(define m (compile manager))
|
||||||
(define i (compile/internal-events m))
|
(define i (compile/internal-events m manager))
|
||||||
(check-true (role-graph? i))
|
(check-true (role-graph? i))
|
||||||
(check-true (simulates?/rg i m))
|
(check-true (simulates?/rg i m))
|
||||||
(check-true (simulates?/rg m i))
|
(check-true (simulates?/rg m i))
|
||||||
|
@ -434,7 +396,7 @@
|
||||||
;; because it doesn't use any internal events, it should be unaffected
|
;; because it doesn't use any internal events, it should be unaffected
|
||||||
(define tmr (parse-T task-runner-ty))
|
(define tmr (parse-T task-runner-ty))
|
||||||
(define tm (compile tmr))
|
(define tm (compile tmr))
|
||||||
(define tmi (compile/internal-events tm))
|
(define tmi (compile/internal-events tm tmr))
|
||||||
(check-true (role-graph? tmi))
|
(check-true (role-graph? tmi))
|
||||||
;; I'm not exactly sure how the two should be related via simulation :S
|
;; I'm not exactly sure how the two should be related via simulation :S
|
||||||
(check-true (simulates?/rg tmi tm)))
|
(check-true (simulates?/rg tmi tm)))
|
||||||
|
@ -448,15 +410,15 @@
|
||||||
(Realizes Int))))
|
(Realizes Int))))
|
||||||
(define r (parse-T cyclic))
|
(define r (parse-T cyclic))
|
||||||
(define rg (compile r))
|
(define rg (compile r))
|
||||||
(define i (run/timeout (thunk (compile/internal-events rg))))
|
(define i (run/timeout (thunk (compile/internal-events rg r))))
|
||||||
(check-true (detected-cycle? i))
|
(check-true (list? i))
|
||||||
(check-match i
|
(check-equal? (length i) 4)
|
||||||
(detected-cycle
|
(match-define (list path kick-off evt edge) i)
|
||||||
(== (set))
|
;; the first 'x -> 'x cycle is ignored because it's a Start event
|
||||||
(list (traversal-step 'Start (== (set 'x)))
|
(check-equal? path (list (set) (set 'x) (set 'x) (set 'x)))
|
||||||
(traversal-step (StartOf 'x) (== (set 'x)))
|
(check-equal? kick-off StartEvt)
|
||||||
(traversal-step (Realize (internal-label _ (== Int))) (== (set 'x)))
|
(check-match evt (Realize (internal-label _ (== Int))))
|
||||||
(traversal-step (Realize (internal-label _ (== Int))) (== (set 'x)))))))
|
(check-match edge (Realize (internal-label _ (== Int)))))
|
||||||
(test-case
|
(test-case
|
||||||
"interesting internal start event"
|
"interesting internal start event"
|
||||||
(test-case
|
(test-case
|
||||||
|
@ -471,7 +433,7 @@
|
||||||
(define r (parse-T strt))
|
(define r (parse-T strt))
|
||||||
(define rg (run/timeout (thunk (compile r))))
|
(define rg (run/timeout (thunk (compile r))))
|
||||||
(check-true (role-graph? rg))
|
(check-true (role-graph? rg))
|
||||||
(define rgi (run/timeout (thunk (compile/internal-events rg))))
|
(define rgi (run/timeout (thunk (compile/internal-events rg r))))
|
||||||
(check-true (role-graph? rgi))
|
(check-true (role-graph? rgi))
|
||||||
(match-define (role-graph st0 st#) rgi)
|
(match-define (role-graph st0 st#) rgi)
|
||||||
(check-equal? st0 (set 'x 'y))
|
(check-equal? st0 (set 'x 'y))
|
||||||
|
@ -492,7 +454,7 @@
|
||||||
(Role 'y (list)))))))
|
(Role 'y (list)))))))
|
||||||
(define rg (run/timeout (thunk (compile role))))
|
(define rg (run/timeout (thunk (compile role))))
|
||||||
(check-true (role-graph? rg))
|
(check-true (role-graph? rg))
|
||||||
(define rgi (run/timeout (thunk (compile/internal-events rg))))
|
(define rgi (run/timeout (thunk (compile/internal-events rg role))))
|
||||||
(check-true (role-graph? rgi))
|
(check-true (role-graph? rgi))
|
||||||
(define state# (role-graph-states rgi))
|
(define state# (role-graph-states rgi))
|
||||||
(check-true (hash-has-key? state# (set 'x)))
|
(check-true (hash-has-key? state# (set 'x)))
|
||||||
|
@ -509,7 +471,7 @@
|
||||||
(define role (run/timeout (thunk (parse-T desc))))
|
(define role (run/timeout (thunk (parse-T desc))))
|
||||||
(define rg (run/timeout (thunk (compile role))))
|
(define rg (run/timeout (thunk (compile role))))
|
||||||
(check-true (role-graph? rg))
|
(check-true (role-graph? rg))
|
||||||
(define rgi (run/timeout (thunk (compile/internal-events rg))))
|
(define rgi (run/timeout (thunk (compile/internal-events rg role))))
|
||||||
(check-true (role-graph? rgi))
|
(check-true (role-graph? rgi))
|
||||||
(check-match rgi
|
(check-match rgi
|
||||||
(role-graph (== (set 'x 'y))
|
(role-graph (== (set 'x 'y))
|
||||||
|
@ -684,9 +646,9 @@
|
||||||
(check-equal? sn0 (set 'seller))
|
(check-equal? sn0 (set 'seller))
|
||||||
(check-true (hash-has-key? seller# (set 'seller)))
|
(check-true (hash-has-key? seller# (set 'seller)))
|
||||||
(check-true (hash-has-key? seller# (set 'seller 'fulfill)))
|
(check-true (hash-has-key? seller# (set 'seller 'fulfill)))
|
||||||
(check-equal? (list->set (hash-keys seller#))
|
(check-equal? (hash-keys seller#)
|
||||||
(set (set 'seller 'fulfill)
|
(list (set 'seller 'fulfill)
|
||||||
(set 'seller)))
|
(set 'seller)))
|
||||||
(define st0 (hash-ref seller# (set 'seller)))
|
(define st0 (hash-ref seller# (set 'seller)))
|
||||||
(define transitions (state-transitions st0))
|
(define transitions (state-transitions st0))
|
||||||
(define quote-request
|
(define quote-request
|
||||||
|
@ -840,12 +802,12 @@
|
||||||
(define seller+spawn (Role 'start (list (Reacts StartEvt (Spawn seller)))))
|
(define seller+spawn (Role 'start (list (Reacts StartEvt (Spawn seller)))))
|
||||||
(define rg (run/timeout (thunk (compile seller+spawn))))
|
(define rg (run/timeout (thunk (compile seller+spawn))))
|
||||||
(check-true (role-graph? rg))
|
(check-true (role-graph? rg))
|
||||||
(define rgi (compile/internal-events rg))
|
(define rgi (compile/internal-events rg seller+spawn))
|
||||||
(check-true (role-graph? rgi))
|
(check-true (role-graph? rgi))
|
||||||
(define srg (compile seller))
|
(define srg (compile seller))
|
||||||
(check-true (run/timeout (thunk (simulates?/rg rg rg))))
|
(check-true (run/timeout (thunk (simulates?/rg rg rg))))
|
||||||
(check-false (run/timeout (thunk (simulates?/rg rg srg))))
|
(check-false (run/timeout (thunk (simulates?/rg rg srg))))
|
||||||
(check-true (run/timeout (thunk (simulates?/rg srg rg))))
|
(check-false (run/timeout (thunk (simulates?/rg srg rg))))
|
||||||
(check-true (run/timeout (thunk (simulates?/rg rgi srg))))
|
(check-true (run/timeout (thunk (simulates?/rg rgi srg))))
|
||||||
(check-true (run/timeout (thunk (simulates?/rg srg rgi)))))
|
(check-true (run/timeout (thunk (simulates?/rg srg rgi)))))
|
||||||
(test-case
|
(test-case
|
||||||
|
@ -860,7 +822,7 @@
|
||||||
(Role 'know (list))))))))))
|
(Role 'know (list))))))))))
|
||||||
(define rg (run/timeout (thunk (compile role))))
|
(define rg (run/timeout (thunk (compile role))))
|
||||||
(check-true (role-graph? rg))
|
(check-true (role-graph? rg))
|
||||||
(define rgi (run/timeout (thunk (compile/internal-events rg))))
|
(define rgi (run/timeout (thunk (compile/internal-events rg role))))
|
||||||
(check-true (role-graph? rgi))
|
(check-true (role-graph? rgi))
|
||||||
(define state-names (hash-keys (role-graph-states rgi)))
|
(define state-names (hash-keys (role-graph-states rgi)))
|
||||||
(for ([sn (in-list state-names)])
|
(for ([sn (in-list state-names)])
|
||||||
|
@ -1017,24 +979,19 @@
|
||||||
(for/fold ([st st])
|
(for/fold ([st st])
|
||||||
([c (in-list children)])
|
([c (in-list children)])
|
||||||
(set-remove st c)))
|
(set-remove st c)))
|
||||||
(define-values (final-txns _)
|
(for/fold ([txns (set (transition '() st-))])
|
||||||
(for/fold ([txns (set (transition '() st-))]
|
([f-name (in-list children)])
|
||||||
[pending-effs rest])
|
(define stop-effs (hash-ref (hash-ref txn# f-name) (StopOf f-name)))
|
||||||
([f-name (in-list children)])
|
(define stop-effs+ (if (set-empty? stop-effs)
|
||||||
(define stop-effs (hash-ref (hash-ref txn# f-name) (StopOf f-name)))
|
(set '())
|
||||||
(define stop-effs+ (if (set-empty? stop-effs)
|
stop-effs))
|
||||||
(set '())
|
(for*/set ([txn (in-set txns)]
|
||||||
stop-effs))
|
[st (in-value (transition-dest txn))]
|
||||||
(define new-txns
|
[effs* (in-set stop-effs+)]
|
||||||
(for*/set ([txn (in-set txns)]
|
[next-txn (in-set (loop st (append effs* rest)))])
|
||||||
[st (in-value (transition-dest txn))]
|
(transition (append (transition-effs txn)
|
||||||
[effs* (in-set stop-effs+)]
|
(transition-effs next-txn))
|
||||||
[next-txn (in-set (loop st (append pending-effs effs*)))])
|
(transition-dest next-txn))))])])))
|
||||||
(transition (append (transition-effs txn)
|
|
||||||
(transition-effs next-txn))
|
|
||||||
(transition-dest next-txn))))
|
|
||||||
(values new-txns '())))
|
|
||||||
final-txns])])))
|
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(test-case
|
(test-case
|
||||||
|
@ -1044,61 +1001,7 @@
|
||||||
(set)
|
(set)
|
||||||
(facet-tree (hash) (hash))
|
(facet-tree (hash) (hash))
|
||||||
(hash)))
|
(hash)))
|
||||||
(check-equal? txns (set (transition (list (realize Int) (realize String)) (set)))))
|
(check-equal? txns (set (transition (list (realize Int) (realize String)) (set))))))
|
||||||
(test-case
|
|
||||||
"another bug in apply-effects"
|
|
||||||
;; was duplicating some effects
|
|
||||||
(define r #s(Role
|
|
||||||
run-a-round342
|
|
||||||
(#s(Shares
|
|
||||||
#s(Struct
|
|
||||||
RoundT
|
|
||||||
(#s(Base Symbol) #s(Base String) #s(List #s(Base String)))))
|
|
||||||
#s(Reacts
|
|
||||||
Start
|
|
||||||
#s(Role
|
|
||||||
wait364
|
|
||||||
(#s(Reacts
|
|
||||||
#s(Asserted #s(Struct LaterThanT (#s(Base Int))))
|
|
||||||
#s(Branch
|
|
||||||
((#s(Branch
|
|
||||||
((#s(Stop
|
|
||||||
run-a-round342
|
|
||||||
(#s(Role
|
|
||||||
over356
|
|
||||||
(#s(Shares
|
|
||||||
#s(Struct
|
|
||||||
ElectedT
|
|
||||||
(#s(Base String)
|
|
||||||
#s(Base String)))))))))
|
|
||||||
(#s(Stop
|
|
||||||
run-a-round342
|
|
||||||
(#s(Realizes
|
|
||||||
#s(Struct
|
|
||||||
StartRoundT
|
|
||||||
(#s(Set #s(Base String))
|
|
||||||
#s(Set #s(Base String)))))))))))
|
|
||||||
())))))))))
|
|
||||||
(define labeled-role (label-internal-events r))
|
|
||||||
(define roles# (describe-roles labeled-role))
|
|
||||||
(define ft (make-facet-tree r))
|
|
||||||
(define current (set 'wait364 'run-a-round342))
|
|
||||||
(define eff* (list
|
|
||||||
(stop 'run-a-round342)
|
|
||||||
(realize
|
|
||||||
'#s(internal-label
|
|
||||||
initial31336
|
|
||||||
#s(Struct
|
|
||||||
StartRoundT
|
|
||||||
(#s(Set #s(Base String)) #s(Set #s(Base String))))))))
|
|
||||||
(check-equal? (apply-effects eff* current ft roles#)
|
|
||||||
(set (transition
|
|
||||||
(list
|
|
||||||
(realize
|
|
||||||
'#s(internal-label
|
|
||||||
initial31336
|
|
||||||
#s(Struct StartRoundT (#s(Set #s(Base String)) #s(Set #s(Base String)))))))
|
|
||||||
(set))))))
|
|
||||||
|
|
||||||
;; FacetTree FacetName (Setof FacetName) -> (List FacetName)
|
;; FacetTree FacetName (Setof FacetName) -> (List FacetName)
|
||||||
;; return the facets in names that are children of the given facet nm, ordered
|
;; return the facets in names that are children of the given facet nm, ordered
|
||||||
|
@ -1615,7 +1518,6 @@
|
||||||
(verify g (set-add assumptions goal)))
|
(verify g (set-add assumptions goal)))
|
||||||
(unless (same-on-specified-events? transitions1
|
(unless (same-on-specified-events? transitions1
|
||||||
transitions2
|
transitions2
|
||||||
sn1
|
|
||||||
verify/with-current-assumed)
|
verify/with-current-assumed)
|
||||||
(return #f))
|
(return #f))
|
||||||
(return (same-on-extra-events? transitions1
|
(return (same-on-extra-events? transitions1
|
||||||
|
@ -1642,178 +1544,6 @@
|
||||||
))])))
|
))])))
|
||||||
(verify (equiv st0-1 st0-2) (set)))
|
(verify (equiv st0-1 st0-2) (set)))
|
||||||
|
|
||||||
;; Role Role -> Bool
|
|
||||||
(define (simulates?/report-error impl spec)
|
|
||||||
(define impl-rg (compile/internal-events (compile impl)))
|
|
||||||
(define spec-rg (compile/internal-events (compile spec)))
|
|
||||||
(cond
|
|
||||||
[(detected-cycle? impl-rg)
|
|
||||||
(printf "Detected Cycle in Implementation!\n")
|
|
||||||
(describe-detected-cycle impl-rg)
|
|
||||||
#f]
|
|
||||||
[(detected-cycle? spec-rg)
|
|
||||||
(printf "Detected Cycle in Specification!\n")
|
|
||||||
(describe-detected-cycle spec-rg)
|
|
||||||
#f]
|
|
||||||
[(simulates?/rg impl-rg spec-rg)
|
|
||||||
#t]
|
|
||||||
[else
|
|
||||||
(define trace (find-simulation-counterexample impl-rg spec-rg))
|
|
||||||
(print-failing-trace trace impl-rg spec-rg)
|
|
||||||
#f]))
|
|
||||||
|
|
||||||
;; DetectedCycle -> Void
|
|
||||||
(define (describe-detected-cycle dc)
|
|
||||||
(printf "Initial State: ~a\n" (detected-cycle-start dc))
|
|
||||||
(for ([step (in-list (detected-cycle-steps dc))])
|
|
||||||
(printf " :: ~a ==> ~a\n" (D->label (traversal-step-evt step)) (traversal-step-dest step))))
|
|
||||||
|
|
||||||
;; a FailingTrace is a (failing-trace (Listof Transition) (Listof Transition) (Listof TraceStep))
|
|
||||||
(struct failing-trace (impl-path spec-path steps) #:transparent)
|
|
||||||
|
|
||||||
;; a TraceStep is one of
|
|
||||||
;; - (both-step D)
|
|
||||||
;; - (impl-step D)
|
|
||||||
;; - (spec-step D)
|
|
||||||
;; describing either both the spec and the implementation responding to an
|
|
||||||
;; event, only the implementation, or only the spec
|
|
||||||
(struct both-step (evt) #:transparent)
|
|
||||||
(struct impl-step (evt) #:transparent)
|
|
||||||
(struct spec-step (evt) #:transparent)
|
|
||||||
|
|
||||||
;; FailingTrace RoleGraph RoleGraph -> Void
|
|
||||||
(define (print-failing-trace trace impl-rg spec-rg)
|
|
||||||
(match-define (role-graph _ impl-st#) impl-rg)
|
|
||||||
(match-define (role-graph _ spec-st#) spec-rg)
|
|
||||||
(match-define (failing-trace impl-path spec-path steps) trace)
|
|
||||||
(define SEP (make-string 40 #\;))
|
|
||||||
(define (print-sep)
|
|
||||||
(newline)
|
|
||||||
(displayln SEP)
|
|
||||||
(newline))
|
|
||||||
(let loop ([steps steps]
|
|
||||||
[impl-path impl-path]
|
|
||||||
[spec-path spec-path]
|
|
||||||
;; because the path might end with an impl-step or spec-step, remember the last
|
|
||||||
;; states we've seen so we can print its assertions at the right time
|
|
||||||
[last-spec-state (transition-dest (car spec-path))]
|
|
||||||
[last-impl-state (transition-dest (car impl-path))])
|
|
||||||
(define (get-spec-dest)
|
|
||||||
(transition-dest (car spec-path)))
|
|
||||||
(define (get-impl-dest)
|
|
||||||
(transition-dest (car impl-path)))
|
|
||||||
(match steps
|
|
||||||
[(cons step more-steps)
|
|
||||||
(print-sep)
|
|
||||||
(printf "In response to event:\n")
|
|
||||||
(match step
|
|
||||||
[(or (both-step D)
|
|
||||||
(impl-step D)
|
|
||||||
(spec-step D))
|
|
||||||
(pretty-print D)])
|
|
||||||
(when (or (both-step? step) (impl-step? step))
|
|
||||||
(define impl-effs (transition-effs (car impl-path)))
|
|
||||||
(printf "Implementation steps to state:\n")
|
|
||||||
(pretty-print (get-impl-dest))
|
|
||||||
(unless (empty? impl-effs)
|
|
||||||
(printf "With Effects:\n")
|
|
||||||
(pretty-print impl-effs)))
|
|
||||||
(when (empty? more-steps)
|
|
||||||
(define impl-final (if (spec-step? step) last-impl-state (get-impl-dest)))
|
|
||||||
(printf "Implementation Assertions:\n")
|
|
||||||
(pretty-print (state-assertions (hash-ref impl-st# impl-final))))
|
|
||||||
(when (or (both-step? step) (spec-step? step))
|
|
||||||
(define spec-effs (transition-effs (car spec-path)))
|
|
||||||
(printf "Specification steps to state:\n")
|
|
||||||
(pretty-print (get-spec-dest))
|
|
||||||
(unless (empty? spec-effs)
|
|
||||||
(printf "With Effects:\n")
|
|
||||||
(pretty-print spec-effs)))
|
|
||||||
(when (empty? more-steps)
|
|
||||||
(define spec-final (if (impl-step? step) last-spec-state (get-spec-dest)))
|
|
||||||
(printf "Specification Assertions:\n")
|
|
||||||
(pretty-print (state-assertions (hash-ref spec-st# spec-final))))
|
|
||||||
(loop more-steps
|
|
||||||
(if (spec-step? step) impl-path (cdr impl-path))
|
|
||||||
(if (impl-step? step) spec-path (cdr spec-path))
|
|
||||||
(if (impl-step? step) last-spec-state (get-spec-dest))
|
|
||||||
(if (spec-step? step) last-impl-state (get-impl-dest)))]
|
|
||||||
[_
|
|
||||||
(newline)
|
|
||||||
(void)])))
|
|
||||||
|
|
||||||
;; RoleGraph RoleGraph -> Trace
|
|
||||||
;; assuming impl-rg does not simulate spec-rg, find a trace of transitions
|
|
||||||
;; (event + effects + destination assertions) demonstrating different behaviors
|
|
||||||
(define (find-simulation-counterexample impl-rg spec-rg)
|
|
||||||
(match-define (role-graph impl-st0 impl-st#) impl-rg)
|
|
||||||
(match-define (role-graph spec-st0 spec-st#) spec-rg)
|
|
||||||
;; inside loop, the each trace field is in reverse
|
|
||||||
(let loop ([work (list (failing-trace (list (transition '() impl-st0))
|
|
||||||
(list (transition '() spec-st0))
|
|
||||||
(list (both-step StartEvt))))]
|
|
||||||
#;[visited (set)])
|
|
||||||
(match work
|
|
||||||
[(cons (failing-trace impl-path/rev spec-path/rev steps/rev) more-work)
|
|
||||||
(match-define (transition impl-effs impl-dest) (car impl-path/rev))
|
|
||||||
(match-define (transition spec-effs spec-dest) (car spec-path/rev))
|
|
||||||
(define last-step (car steps/rev))
|
|
||||||
(cond
|
|
||||||
[(or (impl-step? last-step)
|
|
||||||
;; when only the implementation steps, no need to compare effects on transitions
|
|
||||||
(and (spec-step? last-step) (empty? spec-effs))
|
|
||||||
(effects-subsequence? spec-effs impl-effs))
|
|
||||||
;; cascading conds will help with development and isolating where things go wrong
|
|
||||||
(match-define (state _ impl-transition# impl-assertions) (hash-ref impl-st# impl-dest))
|
|
||||||
(match-define (state _ spec-transition# spec-assertions) (hash-ref spec-st# spec-dest))
|
|
||||||
(cond
|
|
||||||
;; n.b. internal events should be compiled away by now or this wouldn't work
|
|
||||||
[(assertion-superset? impl-assertions spec-assertions)
|
|
||||||
;; same effects and same assertions, compare transitions
|
|
||||||
;; TODO: similarity to `same-on-specified-events?`
|
|
||||||
(define spec-matching-txns
|
|
||||||
(for*/list ([(spec-D spec-txns) (in-hash spec-transition#)]
|
|
||||||
[(impl-D impl-txns) (in-hash impl-transition#)]
|
|
||||||
#:when (D<:? spec-D impl-D)
|
|
||||||
[spec-txn (in-set spec-txns)]
|
|
||||||
[impl-txn (in-set impl-txns)])
|
|
||||||
(failing-trace (cons impl-txn impl-path/rev)
|
|
||||||
(cons spec-txn spec-path/rev)
|
|
||||||
(cons (both-step spec-D) steps/rev))))
|
|
||||||
;; transitions that the spec has but the implementation doesn't respond to
|
|
||||||
;; TODO: similarity to `same-on-extra-events?`
|
|
||||||
(define impl-evts (hash-keys impl-transition#))
|
|
||||||
(define spec-extra-txns
|
|
||||||
(for*/list ([(spec-D spec-txns) (in-hash spec-transition#)]
|
|
||||||
;; TODO - this more or less assumes that *any* event matching impl-D also matches spec-evt, which I'm not sure is quite right
|
|
||||||
#:unless (for/or ([impl-evt (in-list impl-evts)])
|
|
||||||
(D<:? impl-evt spec-D))
|
|
||||||
[spec-txn (in-set spec-txns)])
|
|
||||||
(failing-trace impl-path/rev
|
|
||||||
(cons spec-txn spec-path/rev)
|
|
||||||
(cons (spec-step spec-D) steps/rev))))
|
|
||||||
;; TODO: similarity to above code
|
|
||||||
;; transitions that the implementation has that the spec doesn't respond to
|
|
||||||
(define spec-evts (hash-keys spec-transition#))
|
|
||||||
(define impl-extra-txns
|
|
||||||
(for*/list ([(impl-D impl-txns) (in-hash impl-transition#)]
|
|
||||||
;; TODO - this more or less assumes that *any* event matching impl-D also matches spec-evt, which I'm not sure is quite right
|
|
||||||
#:unless (for/or ([spec-evt (in-list spec-evts)])
|
|
||||||
(D<:? spec-evt impl-D))
|
|
||||||
[impl-txn (in-set impl-txns)])
|
|
||||||
(failing-trace (cons impl-txn impl-path/rev)
|
|
||||||
spec-path/rev
|
|
||||||
(cons (impl-step impl-D) steps/rev))))
|
|
||||||
(loop (append more-work spec-matching-txns spec-extra-txns impl-extra-txns))]
|
|
||||||
[else
|
|
||||||
;; states have different assertions
|
|
||||||
(failing-trace (reverse impl-path/rev) (reverse spec-path/rev) (reverse steps/rev))])]
|
|
||||||
[else
|
|
||||||
;; transitions have different effects
|
|
||||||
(failing-trace (reverse impl-path/rev) (reverse spec-path/rev) (reverse steps/rev))])]
|
|
||||||
[_
|
|
||||||
(error "ran out of work")])))
|
|
||||||
|
|
||||||
;; (List Role) -> (Hashof RoleName (Setof τ))
|
;; (List Role) -> (Hashof RoleName (Setof τ))
|
||||||
;; map each role's name to the assertions it contributes
|
;; map each role's name to the assertions it contributes
|
||||||
(define (all-roles-assertions roles)
|
(define (all-roles-assertions roles)
|
||||||
|
@ -1841,11 +1571,7 @@
|
||||||
;; as determined by the verify procedure
|
;; as determined by the verify procedure
|
||||||
;; and the effects on the edge going to Y are a supersequence of the effects
|
;; and the effects on the edge going to Y are a supersequence of the effects
|
||||||
;; on the edge to Y
|
;; on the edge to Y
|
||||||
;; and:
|
(define (same-on-specified-events? transitions1 transitions2 verify)
|
||||||
;; Determine if the events in transitions2 that don't have any match in transitions1, are:
|
|
||||||
;; - all effect free
|
|
||||||
;; - verify with sn1 matched to each destination
|
|
||||||
(define (same-on-specified-events? transitions1 transitions2 sn1 verify)
|
|
||||||
(for/and ([(D2 edges2) (in-hash transitions2)])
|
(for/and ([(D2 edges2) (in-hash transitions2)])
|
||||||
(define edges1
|
(define edges1
|
||||||
(for/fold ([agg (set)])
|
(for/fold ([agg (set)])
|
||||||
|
@ -1859,11 +1585,7 @@
|
||||||
(set-union agg txns1)))
|
(set-union agg txns1)))
|
||||||
(cond
|
(cond
|
||||||
[(set-empty? edges1)
|
[(set-empty? edges1)
|
||||||
;; - I think this is right, as long as the current state of the implementation
|
#f]
|
||||||
;; matches all states the spec steps to --- unless there are effects on the transition
|
|
||||||
(for/and ([txn (in-set edges2)])
|
|
||||||
(and (empty? (transition-effs txn))
|
|
||||||
(verify (equiv sn1 (transition-dest txn)))))]
|
|
||||||
[else
|
[else
|
||||||
(define combos (make-combinations edges1 edges2))
|
(define combos (make-combinations edges1 edges2))
|
||||||
(verify (one-of combos))])))
|
(verify (one-of combos))])))
|
||||||
|
@ -1972,69 +1694,19 @@
|
||||||
(define (simulating-subgraphs impl spec)
|
(define (simulating-subgraphs impl spec)
|
||||||
;; assume spec doesn't have any internal events
|
;; assume spec doesn't have any internal events
|
||||||
(define spec-rg (compile spec))
|
(define spec-rg (compile spec))
|
||||||
(define impl-rg (compile/internal-events (compile impl)))
|
(define impl-rg (compile/internal-events (compile impl) impl))
|
||||||
(define evts (relevant-events spec-rg))
|
(define evts (relevant-events spec-rg))
|
||||||
(for/list ([srg (subgraphs impl-rg evts)]
|
(for/list ([srg (subgraphs impl-rg evts)]
|
||||||
#:when (simulates?/rg srg spec-rg))
|
#:when (simulates?/rg srg spec-rg))
|
||||||
srg))
|
srg))
|
||||||
|
|
||||||
;; Role Role -> (Maybe RoleGraph)
|
|
||||||
;; try to find any subgraph of the implementation simulating the spec
|
|
||||||
;; TODO: would be nice to find the largest
|
|
||||||
(define (find-simulating-subgraph impl spec)
|
|
||||||
(define spec-rg (compile spec))
|
|
||||||
(define impl-rg (compile/internal-events (compile impl)))
|
|
||||||
(find-simulating-subgraph/rg impl-rg spec-rg))
|
|
||||||
|
|
||||||
;; RoleGraph RoleGraph -> (Maybe RoleGraph)
|
|
||||||
(define (find-simulating-subgraph/rg impl-rg spec-rg)
|
|
||||||
(define evts (relevant-events spec-rg))
|
|
||||||
(for/first ([srg (subgraphs impl-rg evts)]
|
|
||||||
#:when (simulates?/rg srg spec-rg))
|
|
||||||
srg))
|
|
||||||
|
|
||||||
;; Role Role -> Bool
|
|
||||||
(define (find-simulating-subgraph/report-error impl spec)
|
|
||||||
(define spec-rg (compile spec))
|
|
||||||
(define impl-rg (compile/internal-events (compile impl)))
|
|
||||||
(define ans (find-simulating-subgraph/rg impl-rg spec-rg))
|
|
||||||
(cond
|
|
||||||
[ans
|
|
||||||
#t]
|
|
||||||
[else
|
|
||||||
(define-values (ft sg) (find-largest-simulating-subgraph-counterexample impl-rg spec-rg))
|
|
||||||
(print-failing-trace ft impl-rg spec-rg)
|
|
||||||
#f]))
|
|
||||||
|
|
||||||
;; RoleGraph RoleGraph -> (Values FailingTrace RoleGraph)
|
|
||||||
;; assuming impl does not have any simulating subgraphs of spec
|
|
||||||
;; largest *trace*, not largest subgraph
|
|
||||||
(define (find-largest-simulating-subgraph-counterexample impl-rg spec-rg)
|
|
||||||
(define evts (relevant-events spec-rg))
|
|
||||||
(define-values (trace len rg)
|
|
||||||
(for/fold ([best-trace #f]
|
|
||||||
[best-length 0]
|
|
||||||
[best-subgraph #f])
|
|
||||||
([srg (subgraphs impl-rg evts)])
|
|
||||||
(define ft (find-simulation-counterexample srg spec-rg))
|
|
||||||
(define len (failing-trace-length ft))
|
|
||||||
;; thing >= will prefer larger graphs
|
|
||||||
(if (>= len best-length)
|
|
||||||
(values ft len srg)
|
|
||||||
(values best-trace best-length best-subgraph))))
|
|
||||||
(values trace rg))
|
|
||||||
|
|
||||||
;; FailingTrace -> Int
|
|
||||||
(define (failing-trace-length ft)
|
|
||||||
(length (failing-trace-steps ft)))
|
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(test-case
|
(test-case
|
||||||
"task manager has task performer subgraphs"
|
"task manager has task performer subgraphs"
|
||||||
(define tpr (parse-T task-performer-spec))
|
(define tpr (parse-T task-performer-spec))
|
||||||
(define tmr (parse-T task-manager-ty))
|
(define tmr (parse-T task-manager-ty))
|
||||||
(define ans (simulating-subgraphs tmr tpr))
|
(define ans (simulating-subgraphs tmr tpr))
|
||||||
(check-equal? (length ans) 340)
|
(check-equal? (length ans) 68)
|
||||||
(define tprg (compile tpr))
|
(define tprg (compile tpr))
|
||||||
(check-true (simulates?/rg (first ans) tprg))
|
(check-true (simulates?/rg (first ans) tprg))
|
||||||
(check-true (simulates?/rg (second ans) tprg))))
|
(check-true (simulates?/rg (second ans) tprg))))
|
||||||
|
@ -2074,16 +1746,15 @@
|
||||||
(define st#
|
(define st#
|
||||||
(for/hash ([st (in-list states*)])
|
(for/hash ([st (in-list states*)])
|
||||||
(match-define (state _ orig-txn# assertions) (hash-ref state# st))
|
(match-define (state _ orig-txn# assertions) (hash-ref state# st))
|
||||||
(define (enabled-txns D)
|
|
||||||
(define orig-txns (hash-ref orig-txn# D))
|
|
||||||
(for/set ([txn (in-set orig-txns)]
|
|
||||||
#:when (set-member? states (transition-dest txn)))
|
|
||||||
txn))
|
|
||||||
(define txn#
|
(define txn#
|
||||||
(for*/hash ([D (in-hash-keys orig-txn#)]
|
(for/hash ([D (in-hash-keys orig-txn#)]
|
||||||
#:when (event-enabled? D)
|
#:when (event-enabled? D))
|
||||||
[new-txns (in-value (enabled-txns D))]
|
(define orig-txns (hash-ref orig-txn# D))
|
||||||
#:unless (set-empty? new-txns))
|
(define new-txns
|
||||||
|
(for/set ([txn (in-set orig-txns)]
|
||||||
|
#:when (set-member? states (transition-dest txn)))
|
||||||
|
txn))
|
||||||
|
;; TODO - what if new-txns is empty?
|
||||||
(values D new-txns)))
|
(values D new-txns)))
|
||||||
(values st (state st txn# assertions))))
|
(values st (state st txn# assertions))))
|
||||||
(for ([st0 (in-list states*)])
|
(for ([st0 (in-list states*)])
|
||||||
|
@ -2906,12 +2577,10 @@
|
||||||
"job manager reads and compiles"
|
"job manager reads and compiles"
|
||||||
(define jmr (run/timeout (thunk (parse-T job-manager-actual))))
|
(define jmr (run/timeout (thunk (parse-T job-manager-actual))))
|
||||||
(check-true (Role? jmr))
|
(check-true (Role? jmr))
|
||||||
(define jm (run/timeout (thunk (compile jmr)) 5000))
|
(define jm (run/timeout (thunk (compile jmr))))
|
||||||
(check-true (role-graph? jm))
|
(check-true (role-graph? jm))
|
||||||
(define jmi (run/timeout (thunk (compile/internal-events jm)) 5000))
|
(define jmi (run/timeout (thunk (compile/internal-events jm jmr))))
|
||||||
(check-true (role-graph? jmi))
|
(check-true (run/timeout (thunk (simulates?/rg jmi jmi))))))
|
||||||
;; TODO : times out, probably due to infinite loop
|
|
||||||
#;(check-true (run/timeout (thunk (simulates?/rg jmi jmi)) 100000))))
|
|
||||||
|
|
||||||
(define task-runner-ty
|
(define task-runner-ty
|
||||||
'(Role
|
'(Role
|
||||||
|
@ -3046,12 +2715,12 @@
|
||||||
(check-false (simulates? tm (parse-T task-performer-spec)))))
|
(check-false (simulates? tm (parse-T task-performer-spec)))))
|
||||||
|
|
||||||
|
|
||||||
#;(module+ test
|
(module+ test
|
||||||
(test-case
|
(test-case
|
||||||
"job manager subgraph(s) implement task assigner"
|
"job manager subgraph(s) implement task assigner"
|
||||||
(define jmr (run/timeout (thunk (parse-T job-manager-actual))))
|
(define jmr (run/timeout (thunk (parse-T job-manager-actual))))
|
||||||
(define tar (parse-T task-assigner-spec))
|
(define tar (parse-T task-assigner-spec))
|
||||||
(define ans (run/timeout (thunk (simulating-subgraphs jmr tar)) 4000))
|
(define ans (run/timeout (thunk (simulating-subgraphs jmr tar)) 1800))
|
||||||
(check-true (list? ans))
|
(check-true (list? ans))
|
||||||
(check-false (empty? ans))))
|
(check-false (empty? ans))))
|
||||||
|
|
||||||
|
@ -3321,40 +2990,7 @@
|
||||||
(Stop y))))))
|
(Stop y))))))
|
||||||
(define r (parse-T ty))
|
(define r (parse-T ty))
|
||||||
(define rg (compile r))
|
(define rg (compile r))
|
||||||
(define rgi (compile/internal-events rg))
|
(define rgi (compile/internal-events rg r))
|
||||||
(render-to-file rg "before.dot")
|
(render-to-file rg "before.dot")
|
||||||
(render-to-file rgi "after.dot")
|
(render-to-file rgi "after.dot")
|
||||||
)
|
)
|
||||||
|
|
||||||
(module+ test
|
|
||||||
(test-case
|
|
||||||
"regression: ok for implementation not to have edges if the current state matches"
|
|
||||||
(define a (role-graph
|
|
||||||
(set 'seller341 'during-inner343)
|
|
||||||
(hash
|
|
||||||
(set 'seller341 'during-inner343)
|
|
||||||
(state
|
|
||||||
(set 'seller341 'during-inner343)
|
|
||||||
'#hash()
|
|
||||||
(set
|
|
||||||
'#s(Observe #s(Observe #s(Struct BookQuoteT (#s(Base String) #s(Mk⋆)))))
|
|
||||||
'#s(Struct BookQuoteT (#s(Base String) #s(Base Int))))))))
|
|
||||||
(define b (role-graph
|
|
||||||
(set 'seller)
|
|
||||||
(hash
|
|
||||||
(set 'seller)
|
|
||||||
(state
|
|
||||||
(set 'seller)
|
|
||||||
(hash
|
|
||||||
'#s(Asserted #s(Observe #s(Struct BookQuoteT (#s(Base String) #s(Mk⋆)))))
|
|
||||||
(set (transition '() (set '_ 'seller))))
|
|
||||||
(set
|
|
||||||
'#s(Observe #s(Observe #s(Struct BookQuoteT (#s(Base String) #s(Mk⋆)))))))
|
|
||||||
(set '_ 'seller)
|
|
||||||
(state
|
|
||||||
(set '_ 'seller)
|
|
||||||
'#hash()
|
|
||||||
(set
|
|
||||||
'#s(Observe #s(Observe #s(Struct BookQuoteT (#s(Base String) #s(Mk⋆)))))
|
|
||||||
'#s(Struct BookQuoteT (#s(Base String) #s(Base Int))))))))
|
|
||||||
(check-true (run/timeout (thunk (simulates?/rg a b))))))
|
|
|
@ -0,0 +1,657 @@
|
||||||
|
#lang turnstile
|
||||||
|
|
||||||
|
(provide #%module-begin
|
||||||
|
#%app
|
||||||
|
(rename-out [typed-quote quote])
|
||||||
|
#%top-interaction
|
||||||
|
require only-in
|
||||||
|
;; Start dataspace programs
|
||||||
|
run-ground-dataspace
|
||||||
|
;; Types
|
||||||
|
Tuple Bind Discard → ∀
|
||||||
|
Role Reacts Shares Asserted Retracted Message OnDataflow Stop OnStart OnStop
|
||||||
|
Know Forget Realize
|
||||||
|
Branch Effs
|
||||||
|
FacetName Field ★/t
|
||||||
|
Observe Inbound Outbound Actor U ⊥
|
||||||
|
Computation Value Endpoints Roles Spawns Sends
|
||||||
|
→fn proc
|
||||||
|
;; Statements
|
||||||
|
let let* if spawn dataspace start-facet set! begin stop begin/dataflow #;unsafe-do
|
||||||
|
when unless send! realize! define
|
||||||
|
;; Derived Forms
|
||||||
|
during During
|
||||||
|
define/query-value
|
||||||
|
define/query-set
|
||||||
|
define/query-hash
|
||||||
|
define/dataflow
|
||||||
|
on-start on-stop
|
||||||
|
;; endpoints
|
||||||
|
assert know on field
|
||||||
|
;; expressions
|
||||||
|
tuple select lambda ref observe inbound outbound
|
||||||
|
Λ inst call/inst
|
||||||
|
;; making types
|
||||||
|
define-type-alias
|
||||||
|
assertion-struct
|
||||||
|
message-struct
|
||||||
|
define-constructor define-constructor*
|
||||||
|
;; values
|
||||||
|
#%datum
|
||||||
|
;; patterns
|
||||||
|
bind discard
|
||||||
|
;; primitives
|
||||||
|
(all-from-out "prim.rkt")
|
||||||
|
;; expressions
|
||||||
|
(all-from-out "core-expressions.rkt")
|
||||||
|
;; lists
|
||||||
|
(all-from-out "list.rkt")
|
||||||
|
;; sets
|
||||||
|
(all-from-out "set.rkt")
|
||||||
|
;; sequences
|
||||||
|
(all-from-out "sequence.rkt")
|
||||||
|
;; hash tables
|
||||||
|
(all-from-out "hash.rkt")
|
||||||
|
;; for loops
|
||||||
|
(all-from-out "for-loops.rkt")
|
||||||
|
;; utility datatypes
|
||||||
|
(all-from-out "maybe.rkt")
|
||||||
|
(all-from-out "either.rkt")
|
||||||
|
;; DEBUG and utilities
|
||||||
|
print-type print-role role-strings
|
||||||
|
;; Extensions
|
||||||
|
match cond
|
||||||
|
;; require & provides
|
||||||
|
require provide
|
||||||
|
submod for-syntax for-meta only-in except-in
|
||||||
|
require/typed
|
||||||
|
require-struct
|
||||||
|
)
|
||||||
|
(require "core-types.rkt")
|
||||||
|
(require "core-expressions.rkt")
|
||||||
|
(require "list.rkt")
|
||||||
|
(require "set.rkt")
|
||||||
|
(require "prim.rkt")
|
||||||
|
(require "sequence.rkt")
|
||||||
|
(require "hash.rkt")
|
||||||
|
(require "for-loops.rkt")
|
||||||
|
(require "maybe.rkt")
|
||||||
|
(require "either.rkt")
|
||||||
|
|
||||||
|
(require (prefix-in syndicate: syndicate/actor-lang))
|
||||||
|
(require (submod syndicate/actor priorities))
|
||||||
|
|
||||||
|
(require (for-meta 2 macrotypes/stx-utils racket/list syntax/stx syntax/parse racket/base))
|
||||||
|
(require macrotypes/postfix-in)
|
||||||
|
(require (for-syntax turnstile/mode))
|
||||||
|
(require turnstile/typedefs)
|
||||||
|
(require (postfix-in - racket/list))
|
||||||
|
(require (postfix-in - racket/set))
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(require rackunit)
|
||||||
|
(require rackunit/turnstile))
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Creating Communication Types
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(define-simple-macro (assertion-struct name:id (~datum :) Name:id (slot:id ...))
|
||||||
|
(define-constructor* (name : Name slot ...)))
|
||||||
|
|
||||||
|
(define-simple-macro (message-struct name:id (~datum :) Name:id (slot:id ...))
|
||||||
|
(define-constructor* (name : Name slot ...)))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Compile-time State
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(begin-for-syntax
|
||||||
|
(define current-communication-type (make-parameter #f))
|
||||||
|
;; Type -> Mode
|
||||||
|
(define (communication-type-mode ty)
|
||||||
|
(make-param-mode current-communication-type ty))
|
||||||
|
|
||||||
|
(define (elaborate-pattern/with-com-ty pat)
|
||||||
|
(define τ? (current-communication-type))
|
||||||
|
(if τ?
|
||||||
|
(elaborate-pattern/with-type pat τ?)
|
||||||
|
(elaborate-pattern pat))))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Core forms
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(define-typed-syntax (start-facet name:id ep ...+) ≫
|
||||||
|
#:with name- (syntax-local-identifier-as-binding (syntax-local-introduce (generate-temporary #'name)))
|
||||||
|
#:with name+ (syntax-local-identifier-as-binding #'name)
|
||||||
|
#:with facet-name-ty (type-eval #'FacetName)
|
||||||
|
#:do [(define ctx (syntax-local-make-definition-context))
|
||||||
|
(define unique (gensym 'start-facet))
|
||||||
|
(define name-- (add-orig (internal-definition-context-introduce ctx #'name- 'add)
|
||||||
|
#'name))
|
||||||
|
(int-def-ctx-bind-type-rename #'name+ #'name- #'facet-name-ty ctx)
|
||||||
|
(define-values (ep-... τ... ep-effects facet-effects spawn-effects)
|
||||||
|
(walk/bind #'(ep ...) ctx unique))
|
||||||
|
(unless (and (stx-null? facet-effects) (stx-null? spawn-effects))
|
||||||
|
(type-error #:src #'(ep ...) #:msg "only endpoint effects allowed"))]
|
||||||
|
#:with ((~or (~and τ-a (~Shares _))
|
||||||
|
(~and τ-k (~Know _))
|
||||||
|
;; untyped syndicate might allow this - TODO
|
||||||
|
#;(~and τ-m (~Sends _))
|
||||||
|
(~and τ-r (~Reacts _ _ ...))
|
||||||
|
~MakesField)
|
||||||
|
...)
|
||||||
|
ep-effects
|
||||||
|
#:with τ (type-eval #`(Role (#,name--)
|
||||||
|
τ-a ...
|
||||||
|
τ-k ...
|
||||||
|
;; τ-m ...
|
||||||
|
τ-r ...))
|
||||||
|
--------------------------------------------------------------
|
||||||
|
[⊢ (syndicate:react (let- ([#,name-- (#%app- syndicate:current-facet-id)])
|
||||||
|
#,@ep-...))
|
||||||
|
(⇒ : ★/t)
|
||||||
|
(⇒ ν-f (τ))])
|
||||||
|
|
||||||
|
(define-typed-syntax (field [x:id τ-f:type e:expr] ...) ≫
|
||||||
|
#:fail-unless (stx-andmap flat-type? #'(τ-f ...)) "keep your uppity data outta my fields"
|
||||||
|
[⊢ e ≫ e- (⇐ : τ-f)] ...
|
||||||
|
#:fail-unless (stx-andmap pure? #'(e- ...)) "field initializers not allowed to have effects"
|
||||||
|
#:with (x- ...) (generate-temporaries #'(x ...))
|
||||||
|
#:with (τ ...) (stx-map type-eval #'((Field τ-f.norm) ...))
|
||||||
|
#:with MF (type-eval #'MakesField)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
[⊢ (erased (field/intermediate [x x- τ e-] ...))
|
||||||
|
(⇒ : ★/t)
|
||||||
|
(⇒ ν-ep (MF))])
|
||||||
|
|
||||||
|
(define-typed-syntax (assert e:expr) ≫
|
||||||
|
[⊢ e ≫ e- (⇒ : τ)]
|
||||||
|
#:fail-unless (pure? #'e-) "expression not allowed to have effects"
|
||||||
|
#:with τs (mk-Shares- #'(τ))
|
||||||
|
-------------------------------------
|
||||||
|
[⊢ (syndicate:assert e-) (⇒ : ★/t)
|
||||||
|
(⇒ ν-ep (τs))])
|
||||||
|
|
||||||
|
(define-typed-syntax (know e:expr) ≫
|
||||||
|
[⊢ e ≫ e- (⇒ : τ)]
|
||||||
|
#:fail-unless (pure? #'e-) "expression not allowed to have effects"
|
||||||
|
#:with τs (mk-Know- #'(τ))
|
||||||
|
-------------------------------------
|
||||||
|
[⊢ (syndicate:know e-) (⇒ : ★/t)
|
||||||
|
(⇒ ν-ep (τs))])
|
||||||
|
|
||||||
|
(define-typed-syntax (send! e:expr) ≫
|
||||||
|
[⊢ e ≫ e- (⇒ : τ)]
|
||||||
|
#:fail-unless (pure? #'e-) "expression not allowed to have effects"
|
||||||
|
#:with τm (mk-Sends- #'(τ))
|
||||||
|
--------------------------------------
|
||||||
|
[⊢ (#%app- syndicate:send! e-) (⇒ : ★/t)
|
||||||
|
(⇒ ν-f (τm))])
|
||||||
|
|
||||||
|
(define-typed-syntax (realize! e:expr) ≫
|
||||||
|
[⊢ e ≫ e- (⇒ : τ)]
|
||||||
|
#:fail-unless (pure? #'e-) "expression not allowed to have effects"
|
||||||
|
#:with τm (mk-Realizes- #'(τ))
|
||||||
|
--------------------------------------
|
||||||
|
[⊢ (#%app- syndicate:realize! e-) (⇒ : ★/t)
|
||||||
|
(⇒ ν-f (τm))])
|
||||||
|
|
||||||
|
(define-typed-syntax (stop facet-name:id cont ...) ≫
|
||||||
|
[⊢ facet-name ≫ facet-name- (⇐ : FacetName)]
|
||||||
|
[⊢ (block #f cont ...) ≫ cont-
|
||||||
|
(⇒ ν-ep (~effs))
|
||||||
|
(⇒ ν-s (~effs))
|
||||||
|
(⇒ ν-f (~effs τ-f ...))]
|
||||||
|
#:with τ #'(Stop facet-name- τ-f ...)
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
[⊢ (syndicate:stop-facet facet-name- cont-) (⇒ : ★/t)
|
||||||
|
(⇒ ν-f (τ))])
|
||||||
|
|
||||||
|
(begin-for-syntax
|
||||||
|
(define-syntax-class event-cons
|
||||||
|
#:attributes (syndicate-kw ty-cons)
|
||||||
|
#:datum-literals (asserted retracted message know forget realize)
|
||||||
|
(pattern (~or (~and asserted
|
||||||
|
(~bind [syndicate-kw #'syndicate:asserted]
|
||||||
|
[ty-cons #'Asserted]))
|
||||||
|
(~and retracted
|
||||||
|
(~bind [syndicate-kw #'syndicate:retracted]
|
||||||
|
[ty-cons #'Retracted]))
|
||||||
|
(~and message
|
||||||
|
(~bind [syndicate-kw #'syndicate:message]
|
||||||
|
[ty-cons #'Message]))
|
||||||
|
(~and know
|
||||||
|
(~bind [syndicate-kw #'syndicate:know]
|
||||||
|
[ty-cons #'Know]))
|
||||||
|
(~and forget
|
||||||
|
(~bind [syndicate-kw #'syndicate:forget]
|
||||||
|
[ty-cons #'Forget]))
|
||||||
|
(~and realize
|
||||||
|
(~bind [syndicate-kw #'syndicate:realize]
|
||||||
|
[ty-cons #'Realize])))))
|
||||||
|
(define-syntax-class priority-level
|
||||||
|
#:literals (*query-priority-high*
|
||||||
|
*query-priority*
|
||||||
|
*query-handler-priority*
|
||||||
|
*normal-priority*
|
||||||
|
*gc-priority*
|
||||||
|
*idle-priority*)
|
||||||
|
(pattern (~and level
|
||||||
|
(~or *query-priority-high*
|
||||||
|
*query-priority*
|
||||||
|
*query-handler-priority*
|
||||||
|
*normal-priority*
|
||||||
|
*gc-priority*
|
||||||
|
*idle-priority*))))
|
||||||
|
(define-splicing-syntax-class priority
|
||||||
|
#:attributes (level)
|
||||||
|
(pattern (~seq #:priority l:priority-level)
|
||||||
|
#:attr level #'l.level)
|
||||||
|
(pattern (~seq)
|
||||||
|
#:attr level #'*normal-priority*))
|
||||||
|
)
|
||||||
|
|
||||||
|
(define-typed-syntax on
|
||||||
|
#:datum-literals (start stop)
|
||||||
|
[(on start s ...) ≫
|
||||||
|
[⊢ (block s ...) ≫ s- (⇒ ν-ep (~effs))
|
||||||
|
(⇒ ν-f (~effs τ-f ...))
|
||||||
|
(⇒ ν-s (~effs τ-s ...))]
|
||||||
|
#:with τ-r (type-eval #'(Reacts OnStart τ-f ... τ-s ...))
|
||||||
|
-----------------------------------
|
||||||
|
[⊢ (syndicate:on-start s-) (⇒ : ★/t)
|
||||||
|
(⇒ ν-ep (τ-r))]]
|
||||||
|
[(on stop s ...) ≫
|
||||||
|
[⊢ (block s ...) ≫ s- (⇒ ν-ep (~effs))
|
||||||
|
(⇒ ν-f (~effs τ-f ...))
|
||||||
|
(⇒ ν-s (~effs τ-s ...))]
|
||||||
|
#:with τ-r (type-eval #'(Reacts OnStop τ-f ... τ-s ...))
|
||||||
|
-----------------------------------
|
||||||
|
[⊢ (syndicate:on-stop s-) (⇒ : ★/t)
|
||||||
|
(⇒ ν-ep (τ-r))]]
|
||||||
|
[(on (evt:event-cons p)
|
||||||
|
priority:priority
|
||||||
|
s ...) ≫
|
||||||
|
#:do [(define msg? (free-identifier=? #'syndicate:message (attribute evt.syndicate-kw)))
|
||||||
|
(define elab
|
||||||
|
(elaborate-pattern/with-com-ty (if msg? #'(message p) #'p)))]
|
||||||
|
#:with p/e (if msg? (stx-cadr elab) elab)
|
||||||
|
[⊢ p/e ≫ p-- (⇒ : τp)]
|
||||||
|
#:fail-unless (pure? #'p--) "pattern not allowed to have effects"
|
||||||
|
#:with ([x:id τ:type] ...) (pat-bindings #'p/e)
|
||||||
|
[[x ≫ x- : τ] ... ⊢ (block s ...) ≫ s-
|
||||||
|
(⇒ ν-ep (~effs))
|
||||||
|
(⇒ ν-f (~effs τ-f ...))
|
||||||
|
(⇒ ν-s (~effs τ-s ...))]
|
||||||
|
#:with p- (substs #'(x- ...) #'(x ...) (compile-syndicate-pattern #'p/e))
|
||||||
|
#:with τ-r (type-eval #'(Reacts (evt.ty-cons τp) τ-f ... τ-s ...))
|
||||||
|
-----------------------------------
|
||||||
|
[⊢ (syndicate:on (evt.syndicate-kw p-)
|
||||||
|
#:priority priority.level
|
||||||
|
s-)
|
||||||
|
(⇒ : ★/t)
|
||||||
|
(⇒ ν-ep (τ-r))]])
|
||||||
|
|
||||||
|
(define-typed-syntax (begin/dataflow s ...+) ≫
|
||||||
|
[⊢ (block s ...) ≫ s-
|
||||||
|
(⇒ : _)
|
||||||
|
(⇒ ν-ep (~effs))
|
||||||
|
(⇒ ν-f (~effs τ-f ...))
|
||||||
|
(⇒ ν-s (~effs τ-s ...))]
|
||||||
|
#:with τ-r (type-eval #'(Reacts OnDataflow τ-f ... τ-s ...))
|
||||||
|
--------------------------------------------------
|
||||||
|
[⊢ (syndicate:begin/dataflow s-)
|
||||||
|
(⇒ : ★/t)
|
||||||
|
(⇒ ν-ep (τ-r))])
|
||||||
|
|
||||||
|
(define-for-syntax (compile-syndicate-pattern pat)
|
||||||
|
(compile-pattern pat
|
||||||
|
#'list-
|
||||||
|
(lambda (id) #`($ #,id))
|
||||||
|
identity))
|
||||||
|
|
||||||
|
(define-typed-syntax spawn
|
||||||
|
;; TODO - do the lack of #:cut-s cause bad error messages here?
|
||||||
|
[(spawn τ-c:type s) ≫
|
||||||
|
#:fail-unless (flat-type? #'τ-c.norm) "Communication type must be first-order"
|
||||||
|
;; TODO: check that each τ-f is a Role
|
||||||
|
#:mode (communication-type-mode #'τ-c.norm)
|
||||||
|
[
|
||||||
|
[⊢ (block s) ≫ s- (⇒ ν-ep (~effs)) (⇒ ν-s (~effs)) (⇒ ν-f (~effs τ-f ...))]
|
||||||
|
]
|
||||||
|
;; TODO: s shouldn't refer to facets or fields!
|
||||||
|
#:with (τ-i τ-o τ-i/i τ-o/i τ-a) (analyze-roles #'(τ-f ...))
|
||||||
|
#:fail-unless (<: #'τ-o #'τ-c.norm)
|
||||||
|
(format "Output ~a not valid in dataspace ~a" (type->str #'τ-o) (type->str #'τ-c.norm))
|
||||||
|
#:with τ-final (mk-Actor- #'(τ-c.norm))
|
||||||
|
#:fail-unless (<: #'τ-a #'τ-final)
|
||||||
|
"Spawned actors not valid in dataspace"
|
||||||
|
#:fail-unless (project-safe? (∩ (strip-? #'τ-o) #'τ-c.norm)
|
||||||
|
#'τ-i)
|
||||||
|
(string-append "Not prepared to handle inputs:\n" (make-actor-error-message #'τ-i #'τ-o #'τ-c.norm))
|
||||||
|
#:fail-unless (project-safe? (∩ (strip-? #'τ-o/i) #'τ-o/i) #'τ-i/i)
|
||||||
|
(string-append "Not prepared to handle internal events:\n" (make-actor-error-message #'τ-i/i #'τ-o/i #'τ-o/i))
|
||||||
|
--------------------------------------------------------------------------------------------
|
||||||
|
[⊢ (syndicate:spawn (syndicate:on-start s-)) (⇒ : ★/t)
|
||||||
|
(⇒ ν-s (τ-final))]]
|
||||||
|
[(spawn s) ≫
|
||||||
|
#:do [(define τc (current-communication-type))]
|
||||||
|
#:when τc
|
||||||
|
----------------------------------------
|
||||||
|
[≻ (spawn #,τc s)]])
|
||||||
|
|
||||||
|
;; Type Type Type -> String
|
||||||
|
(define-for-syntax (make-actor-error-message τ-i τ-o τ-c)
|
||||||
|
(define mismatches (find-surprising-inputs τ-i τ-o τ-c))
|
||||||
|
(string-join (map type->str mismatches) ",\n"))
|
||||||
|
|
||||||
|
;; Type Type Type -> (Listof Type)
|
||||||
|
(define-for-syntax (find-surprising-inputs τ-i τ-o τ-c)
|
||||||
|
(define incoming (∩ (strip-? τ-o) τ-c))
|
||||||
|
;; Type -> (Listof Type)
|
||||||
|
(let loop ([ty incoming])
|
||||||
|
(syntax-parse ty
|
||||||
|
[(~U* τ ...)
|
||||||
|
(apply append (map loop (syntax->list #'(τ ...))))]
|
||||||
|
[_
|
||||||
|
(cond
|
||||||
|
[(project-safe? ty τ-i)
|
||||||
|
'()]
|
||||||
|
[else
|
||||||
|
(list ty)])])))
|
||||||
|
|
||||||
|
(define-typed-syntax (dataspace τ-c:type s ...) ≫
|
||||||
|
#:fail-unless (flat-type? #'τ-c.norm) "Communication type must be first-order"
|
||||||
|
#:mode (communication-type-mode #'τ-c.norm)
|
||||||
|
[
|
||||||
|
[⊢ s ≫ s- (⇒ ν-ep (~effs)) (⇒ ν-s (~effs τ-s ...)) (⇒ ν-f (~effs))] ...
|
||||||
|
]
|
||||||
|
#:with τ-actor (mk-Actor- #'(τ-c.norm))
|
||||||
|
#:fail-unless (stx-andmap (lambda (t) (<: t #'τ-actor)) #'(τ-s ... ...))
|
||||||
|
"Not all actors conform to communication type"
|
||||||
|
#:with τ-ds-i (strip-inbound #'τ-c.norm)
|
||||||
|
#:with τ-ds-o (strip-outbound #'τ-c.norm)
|
||||||
|
#:with τ-relay (relay-interests #'τ-c.norm)
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
[⊢ (syndicate:dataspace s- ...) (⇒ : ★/t)
|
||||||
|
(⇒ ν-s ((Actor (U τ-ds-i τ-ds-o τ-relay))))])
|
||||||
|
|
||||||
|
(define-typed-syntax (set! x:id e:expr) ≫
|
||||||
|
[⊢ e ≫ e- (⇒ : τ)]
|
||||||
|
#:fail-unless (pure? #'e-) "expression not allowed to have effects"
|
||||||
|
[⊢ x ≫ x- (⇒ : (~Field τ-x:type))]
|
||||||
|
#:fail-unless (<: #'τ #'τ-x) "Ill-typed field write"
|
||||||
|
----------------------------------------------------
|
||||||
|
[⊢ (#%app- x- e-) (⇒ : ★/t)])
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Derived Forms
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(define-typed-syntax during
|
||||||
|
#:literals (know)
|
||||||
|
[(_ (~or (~and k (know p)) p) s ...) ≫
|
||||||
|
#:with p+ (elaborate-pattern/with-com-ty #'p)
|
||||||
|
#:with inst-p (instantiate-pattern #'p+)
|
||||||
|
#:with start-e (if (attribute k) #'know #'asserted)
|
||||||
|
#:with stop-e (if (attribute k) #'forget #'retracted)
|
||||||
|
#:with res #'(on (start-e p+)
|
||||||
|
(start-facet during-inner
|
||||||
|
(on (stop-e inst-p)
|
||||||
|
(stop during-inner))
|
||||||
|
s ...))
|
||||||
|
----------------------------------------
|
||||||
|
[≻ (on (start-e p+)
|
||||||
|
(start-facet during-inner
|
||||||
|
(on (stop-e inst-p)
|
||||||
|
(stop during-inner))
|
||||||
|
s ...))]])
|
||||||
|
|
||||||
|
(define-simple-macro (During (~or (~and K ((~literal Know) τ:type)) τ:type)
|
||||||
|
EP ...)
|
||||||
|
#:with τ/inst (instantiate-pattern-type #'τ.norm)
|
||||||
|
#:with start-e (if (attribute K) #'Know #'Asserted)
|
||||||
|
#:with stop-e (if (attribute K) #'Forget #'Retracted)
|
||||||
|
(Reacts (start-e τ)
|
||||||
|
(Role (during-inner)
|
||||||
|
(Reacts (stop-e τ/inst)
|
||||||
|
(Stop during-inner))
|
||||||
|
EP ...)))
|
||||||
|
|
||||||
|
;; TODO - reconcile this with `compile-pattern`
|
||||||
|
(define-for-syntax (instantiate-pattern pat)
|
||||||
|
(let loop ([pat pat])
|
||||||
|
(syntax-parse pat
|
||||||
|
#:datum-literals (tuple discard bind)
|
||||||
|
[(tuple p ...)
|
||||||
|
#`(tuple #,@(stx-map loop #'(p ...)))]
|
||||||
|
[(k:kons1 p)
|
||||||
|
#`(k #,(loop #'p))]
|
||||||
|
[(bind x:id τ)
|
||||||
|
#'x]
|
||||||
|
;; not sure about this
|
||||||
|
[discard
|
||||||
|
#'discard]
|
||||||
|
[(~constructor-exp ctor p ...)
|
||||||
|
(define/with-syntax uctor (untyped-ctor #'ctor))
|
||||||
|
#`(ctor #,@(stx-map loop #'(p ...)))]
|
||||||
|
[_
|
||||||
|
pat])))
|
||||||
|
|
||||||
|
;; Type -> Type
|
||||||
|
;; replace occurrences of (Bind τ) with τ in a type, in much the same way
|
||||||
|
;; instantiate-pattern does for patterns
|
||||||
|
;; TODO - this is almost exactly the same as replace-bind-and-discard-with-★
|
||||||
|
(define-for-syntax (instantiate-pattern-type ty)
|
||||||
|
(syntax-parse ty
|
||||||
|
[(~Bind τ)
|
||||||
|
#'τ]
|
||||||
|
[(~U* τ ...)
|
||||||
|
(mk-U- (stx-map instantiate-pattern-type #'(τ ...)))]
|
||||||
|
[(~Any/new τ-cons τ ...)
|
||||||
|
#:when (reassemblable? #'τ-cons)
|
||||||
|
(define subitems (for/list ([t (in-syntax #'(τ ...))])
|
||||||
|
(instantiate-pattern-type t)))
|
||||||
|
(reassemble-type #'τ-cons subitems)]
|
||||||
|
[_ ty]))
|
||||||
|
|
||||||
|
(begin-for-syntax
|
||||||
|
(define-splicing-syntax-class on-add
|
||||||
|
#:attributes (expr)
|
||||||
|
(pattern (~seq #:on-add add-e)
|
||||||
|
#:attr expr #'add-e)
|
||||||
|
(pattern (~seq)
|
||||||
|
#:attr expr #'#f))
|
||||||
|
|
||||||
|
(define-splicing-syntax-class on-remove
|
||||||
|
#:attributes (expr)
|
||||||
|
(pattern (~seq #:on-remove remove-e)
|
||||||
|
#:attr expr #'remove-e)
|
||||||
|
(pattern (~seq)
|
||||||
|
#:attr expr #'#f)))
|
||||||
|
|
||||||
|
|
||||||
|
(define-typed-syntax (define/query-value x:id e0 p e
|
||||||
|
(~optional add:on-add)
|
||||||
|
(~optional remove:on-remove)) ≫
|
||||||
|
[⊢ e0 ≫ e0- (⇒ : τ)]
|
||||||
|
#:fail-unless (pure? #'e0-) "expression must be pure"
|
||||||
|
----------------------------------------
|
||||||
|
[≻ (begin (field [x τ e0-])
|
||||||
|
(on (asserted p)
|
||||||
|
#:priority *query-priority*
|
||||||
|
(set! x e)
|
||||||
|
add.expr)
|
||||||
|
(on (retracted p)
|
||||||
|
#:priority *query-priority-high*
|
||||||
|
(set! x e0-)
|
||||||
|
remove.expr))])
|
||||||
|
|
||||||
|
(define-typed-syntax (define/query-set x:id p e
|
||||||
|
(~optional add:on-add)
|
||||||
|
(~optional remove:on-remove)) ≫
|
||||||
|
#:with p+ (elaborate-pattern/with-com-ty #'p)
|
||||||
|
#:with ([y τ] ...) (pat-bindings #'p+)
|
||||||
|
;; e will be re-expanded :/
|
||||||
|
[[y ≫ y- : τ] ... ⊢ e ≫ e- ⇒ τ-e]
|
||||||
|
----------------------------------------
|
||||||
|
[≻ (begin (field [x (Set τ-e) (set)])
|
||||||
|
(on (asserted p+)
|
||||||
|
#:priority *query-priority*
|
||||||
|
(set! x (set-add (ref x) e))
|
||||||
|
add.expr)
|
||||||
|
(on (retracted p+)
|
||||||
|
#:priority *query-priority-high*
|
||||||
|
(set! x (set-remove (ref x) e))
|
||||||
|
remove.expr))])
|
||||||
|
|
||||||
|
(define-typed-syntax (define/query-hash x:id p e-key e-value
|
||||||
|
(~optional add:on-add)
|
||||||
|
(~optional remove:on-remove)) ≫
|
||||||
|
#:with p+ (elaborate-pattern/with-com-ty #'p)
|
||||||
|
#:with ([y τ] ...) (pat-bindings #'p+)
|
||||||
|
;; e-key and e-value will be re-expanded :/
|
||||||
|
;; but it's the most straightforward way to keep bindings in sync with
|
||||||
|
;; pattern
|
||||||
|
[[y ≫ y- : τ] ... ⊢ e-key ≫ e-key- ⇒ τ-key]
|
||||||
|
[[y ≫ y-- : τ] ... ⊢ e-value ≫ e-value- ⇒ τ-value]
|
||||||
|
;; TODO - this is gross, is there a better way to do this?
|
||||||
|
;; #:with e-value-- (substs #'(y- ...) #'(y-- ...) #'e-value- free-identifier=?)
|
||||||
|
;; I thought I could put e-key- and e-value-(-) in the output below, but that
|
||||||
|
;; gets their references to pattern variables out of sync with `p`
|
||||||
|
----------------------------------------
|
||||||
|
[≻ (begin (field [x (Hash τ-key τ-value) (hash)])
|
||||||
|
(on (asserted p+)
|
||||||
|
#:priority *query-priority*
|
||||||
|
(set! x (hash-set (ref x) e-key e-value))
|
||||||
|
add.expr)
|
||||||
|
(on (retracted p+)
|
||||||
|
#:priority *query-priority-high*
|
||||||
|
(set! x (hash-remove (ref x) e-key))
|
||||||
|
remove.expr))])
|
||||||
|
|
||||||
|
(define-simple-macro (on-start e ...)
|
||||||
|
(on start e ...))
|
||||||
|
|
||||||
|
(define-simple-macro (on-stop e ...)
|
||||||
|
(on stop e ...))
|
||||||
|
|
||||||
|
(define-typed-syntax define/dataflow
|
||||||
|
[(define/dataflow x:id τ:type e) ≫
|
||||||
|
[⊢ e ≫ e- (⇐ : τ)]
|
||||||
|
#:fail-unless (pure? #'e-) "expression must be pure"
|
||||||
|
;; because the begin/dataflow body is scheduled to run at some later point,
|
||||||
|
;; the initial value is visible e.g. immediately after the define/dataflow
|
||||||
|
;; #:with place-holder (attach #'(#%datum- #f) ': #'τ.norm)
|
||||||
|
----------------------------------------
|
||||||
|
[≻ (begin (field [x τ e-])
|
||||||
|
(begin/dataflow (set! x e-)))]]
|
||||||
|
[(define/dataflow x:id e) ≫
|
||||||
|
[⊢ e ≫ e- (⇒ : τ)]
|
||||||
|
#:fail-unless (pure? #'e-) "expression must be pure"
|
||||||
|
----------------------------------------
|
||||||
|
[≻ (define/dataflow x τ e-)]])
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Expressions
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(define-typed-syntax (ref x:id) ≫
|
||||||
|
[⊢ x ≫ x- ⇒ (~Field τ)]
|
||||||
|
------------------------
|
||||||
|
[⊢ (#%app- x-) (⇒ : τ)])
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Ground Dataspace
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; n.b. this is a blocking operation, so an actor that uses this internally
|
||||||
|
;; won't necessarily terminate.
|
||||||
|
(define-typed-syntax (run-ground-dataspace τ-c:type s ...) ≫
|
||||||
|
;;#:fail-unless (flat-type? #'τ-c.norm) "Communication type must be first-order"
|
||||||
|
#:mode (communication-type-mode #'τ-c.norm)
|
||||||
|
[
|
||||||
|
[⊢ s ≫ s- (⇒ : t1)] ...
|
||||||
|
[⊢ (dataspace τ-c.norm s- ...) ≫ _ (⇒ : t2)]
|
||||||
|
]
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
[⊢ (#%app- syndicate:run-ground s- ...) (⇒ : (AssertionSet τ-c))])
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Utilities
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(define-typed-syntax (print-type e) ≫
|
||||||
|
[⊢ e ≫ e- (⇒ : τ) (⇒ ν-ep (~effs eps ...)) (⇒ ν-f (~effs fs ...)) (⇒ ν-s (~effs ss ...))]
|
||||||
|
#:do [(pretty-display (type->strX #'τ))]
|
||||||
|
----------------------------------
|
||||||
|
[⊢ e- (⇒ : τ) (⇒ ν-ep (eps ...)) (⇒ ν-f (fs ...)) (⇒ ν-s (ss ...))])
|
||||||
|
|
||||||
|
(define-typed-syntax (print-role e) ≫
|
||||||
|
[⊢ e ≫ e- (⇒ : τ) (⇒ ν-ep (~effs eps ...)) (⇒ ν-f (~effs fs ...)) (⇒ ν-s (~effs ss ...))]
|
||||||
|
#:do [(for ([r (in-syntax #'(fs ...))])
|
||||||
|
(pretty-display (type->strX r)))]
|
||||||
|
----------------------------------
|
||||||
|
[⊢ e- (⇒ : τ) (⇒ ν-ep (eps ...)) (⇒ ν-f (fs ...)) (⇒ ν-s (ss ...))])
|
||||||
|
|
||||||
|
;; this is mainly for testing
|
||||||
|
(define-typed-syntax (role-strings e) ≫
|
||||||
|
[⊢ e ≫ e- (⇒ : τ) (⇒ ν-f (~effs fs ...))]
|
||||||
|
#:with (s ...) (for/list ([r (in-syntax #'(fs ...))])
|
||||||
|
(type->strX r))
|
||||||
|
----------------------------------------
|
||||||
|
[⊢ (#%app- list- (#%datum- . s) ...) (⇒ : (List String))])
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Tests
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(check-type
|
||||||
|
(spawn (U (Observe (Tuple Int ★/t)))
|
||||||
|
(start-facet echo
|
||||||
|
(on (message (tuple 1 $x))
|
||||||
|
#f)))
|
||||||
|
: ★/t)
|
||||||
|
(check-type (spawn (U (Message (Tuple String Int))
|
||||||
|
(Observe (Tuple String ★/t)))
|
||||||
|
(start-facet echo
|
||||||
|
(on (message (tuple "ping" $x))
|
||||||
|
(send! (tuple "pong" x)))))
|
||||||
|
: ★/t)
|
||||||
|
(typecheck-fail (spawn (U (Message (Tuple String Int))
|
||||||
|
(Message (Tuple String String))
|
||||||
|
(Observe (Tuple String ★/t)))
|
||||||
|
(start-facet echo
|
||||||
|
(on (message (tuple "ping" (bind x Int)))
|
||||||
|
(send! (tuple "pong" x)))))))
|
||||||
|
|
||||||
|
;; local definitions
|
||||||
|
#;(module+ test
|
||||||
|
;; these cause an error in rackunit-typechecking, don't know why :/
|
||||||
|
#;(check-type (let ()
|
||||||
|
(begin
|
||||||
|
(define id : Int 1234)
|
||||||
|
id))
|
||||||
|
: Int
|
||||||
|
-> 1234)
|
||||||
|
#;(check-type (let ()
|
||||||
|
(define (spawn-cell [initial-value : Int])
|
||||||
|
(define id 1234)
|
||||||
|
id)
|
||||||
|
(typed-app spawn-cell 42))
|
||||||
|
: Int
|
||||||
|
-> 1234)
|
||||||
|
(check-equal? (let ()
|
||||||
|
(define id : Int 1234)
|
||||||
|
id)
|
||||||
|
1234)
|
||||||
|
#;(check-equal? (let ()
|
||||||
|
(define (spawn-cell [initial-value : Int])
|
||||||
|
(define id 1234)
|
||||||
|
id)
|
||||||
|
(typed-app spawn-cell 42))
|
||||||
|
1234))
|
|
@ -1,778 +0,0 @@
|
||||||
#lang scribble/manual
|
|
||||||
|
|
||||||
@(require (for-label (only-in racket struct)
|
|
||||||
typed/syndicate/roles)
|
|
||||||
(prefix-in racket: (for-label racket))
|
|
||||||
(prefix-in untyped: (for-label syndicate/actor)))
|
|
||||||
|
|
||||||
@title{Typed Syndicate}
|
|
||||||
|
|
||||||
|
|
||||||
@defmodule[typed/syndicate/roles]
|
|
||||||
|
|
||||||
@section{Overview}
|
|
||||||
|
|
||||||
@section{Types}
|
|
||||||
|
|
||||||
@deftogether[(@defidform[Int]
|
|
||||||
@defidform[Bool]
|
|
||||||
@defidform[String]
|
|
||||||
@defidform[ByteString]
|
|
||||||
@defidform[Symbol])]{
|
|
||||||
Base types.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(U type ...)]{
|
|
||||||
The type representing the union of @racket[type ...].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defidform[⊥]{
|
|
||||||
An alias for @racket[(U)].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defidform[★/t]{
|
|
||||||
The type representing any possible assertion, and, in an @racket[AssertionSet],
|
|
||||||
the possibility for an infinite set of assertions.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defidform[Discard]{
|
|
||||||
The type of @racket[_] patterns.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(Bind type)]{
|
|
||||||
The type of @racket[$] patterns.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defidform[FacetName]{
|
|
||||||
The type associated with identifiers bound by @racket[start-facet].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(Role (x) type ...)]{
|
|
||||||
The type of a facet named @racket[x] and endpoints described by @racket[type
|
|
||||||
...].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(Stop X type ...)]{
|
|
||||||
The type of a @racket[stop] action.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(Field type)]{
|
|
||||||
The type of a field containing values of @racket[type].
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@defform[(Shares type)]{
|
|
||||||
The type of an @racket[assert] endpoint.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[#:literals (OnStart OnStop Asserted Retracted)
|
|
||||||
(Reacts EventDesc type ...)
|
|
||||||
#:grammar
|
|
||||||
[(EventDesc (code:line OnStart)
|
|
||||||
(code:line OnStart)
|
|
||||||
(code:line (Asserted event-type))
|
|
||||||
(code:line (Retracted event-type)))]]{
|
|
||||||
The type of a @racket[on] endpoint that reacts to events described by
|
|
||||||
@racket[EventDesc] with the behavior given by @racket[type ...].
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(@defidform[OnStart]
|
|
||||||
@defidform[OnStop]
|
|
||||||
@defform[(Asserted type)]
|
|
||||||
@defform[(Retracted type)])]{
|
|
||||||
See @racket[Reacts].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(Actor type)]{
|
|
||||||
The type of an actor that operates in a dataspace with a certain communication
|
|
||||||
@racket[type].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(ActorWithRole comm-type behavior-type)]{
|
|
||||||
An @racket[Actor] type with the additional @racket[behavior-type] describing the
|
|
||||||
actor's behavior in terms of a @racket[Role].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(Sends type)]{
|
|
||||||
The type of a @racket[send!] action.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(Realize type)]{
|
|
||||||
The type of a @racket[realize!] action.
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(@defform[(Branch type ...)]
|
|
||||||
@defform[(Effs type ...)])]{
|
|
||||||
Types that may arise in descriptions in @racket[Role] types due to branching and
|
|
||||||
sequencing.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(Tuple type ...)]{
|
|
||||||
The type of @racket[tuple] expressions.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defidform[Unit]{
|
|
||||||
An alias for @racket[(Tuple)].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(AssertionSet type)]{
|
|
||||||
The type for a set of assertions of a certain @racket[type]. Note that these are
|
|
||||||
not interoperable with the general purpose @racket[set] data structures.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(∀ (X ...) type)]{
|
|
||||||
Universal quantification over types.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[#:literals (Computation Value Endpoints Roles Spawns)
|
|
||||||
(→ type ... (Computation (Value result-type)
|
|
||||||
(Endpoints ep-type ...)
|
|
||||||
(Roles role-type ...)
|
|
||||||
(Spawns spawn-type ...)))]{
|
|
||||||
The type of a function with parameters @racket[type ...] that returns @racket[result-type]. The type includes the effects of any actions performed by the function:
|
|
||||||
@itemlist[
|
|
||||||
@item{@racket[Endpoints]: includes any endpoint installation effects, such as from @racket[assert] and @racket[on].}
|
|
||||||
@item{@racket[Roles]: includes any script action effects, such as from @racket[start-facet], @racket[stop], and @racket[send!].}
|
|
||||||
@item{@racket[Spawns]: includes descriptions of any @racket[spawn] actions.}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(→fn type-in ... type-out)]{
|
|
||||||
Shorthand for a @racket[→] type with no effects.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(proc maybe-quantifiers type-in ... maybe-arrow type-out
|
|
||||||
maybe-endpoints
|
|
||||||
maybe-roles
|
|
||||||
maybe-spawns)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-quantifiers (code:line)
|
|
||||||
(code:line #:forall (X ...)))
|
|
||||||
(maybe-arrow (code:line)
|
|
||||||
(code:line →)
|
|
||||||
(code:line ->))
|
|
||||||
(maybe-endpoints (code:line)
|
|
||||||
(code:line #:endpoints (e ...)))
|
|
||||||
(maybe-roles (code:line)
|
|
||||||
(code:line #:roles (r ...)))
|
|
||||||
(maybe-spawns (code:line)
|
|
||||||
(code:line #:spawns (s ...)))]]{
|
|
||||||
A more convenient notation for writing (potentially polymorphic) function types
|
|
||||||
with effects. Shorthand for @racket[(∀ (X ...) (→ type-in ... (Computation
|
|
||||||
(Value type-out) (Endpoints e ...) (Roles r ...) (Spawns s ...))))].
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(@defform[(Computation type ...)]
|
|
||||||
@defform[(Value type)]
|
|
||||||
@defform[(Endpoints type)]
|
|
||||||
@defform[(Roles type)]
|
|
||||||
@defform[(Spawns type)])]{
|
|
||||||
See @racket[→].
|
|
||||||
}
|
|
||||||
|
|
||||||
@section{User Defined Types}
|
|
||||||
|
|
||||||
@defform*[[(define-type-alias id type)
|
|
||||||
(define-type-alias (ty-cons-id arg-id ...) type)]]{
|
|
||||||
Define @racket[id] to be the same as @racket[type], or create a type constructor
|
|
||||||
@racket[(ty-cons-id ty ...)] whose meaning is @racket[type] with references to
|
|
||||||
@racket[arg-id ...] replaced by @racket[ty ...].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(define-constructor (ctor-id slot-id ...)
|
|
||||||
maybe-type-ctor
|
|
||||||
maybe-alias ...)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-type-ctor (code:line)
|
|
||||||
(code:line #:type-constructor type-ctor-id))
|
|
||||||
(maybe-alias (code:line)
|
|
||||||
(code:line #:with alias alias-body))]]{
|
|
||||||
Defines a container analagous to a prefab @racket[struct]. Includes accessor
|
|
||||||
functions for each @racket[slot-id]. (But not, presently, a predicate function).
|
|
||||||
|
|
||||||
When a @racket[type-ctor-id] is provided, the type of such structures is
|
|
||||||
@racket[(type-ctor-id type ...)], where each @racket[type] describes the value
|
|
||||||
of the corresponding slot. When not provided, the type constructor is named by
|
|
||||||
appending @racket["/t"] to @racket[ctor-id].
|
|
||||||
|
|
||||||
Each @racket[alias] and @racket[alias-body] creates an instance of
|
|
||||||
@racket[define-type-alias].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[#:literals (:)
|
|
||||||
(define-constructor* (ctor-id : type-ctor-id slot-id ...)
|
|
||||||
maybe-alias ...)]{
|
|
||||||
An abbreviated form of @racket[define-constructor].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[#:literals (:)
|
|
||||||
(assertion-struct ctor-id : type-ctor-id (slot-id ...))]{
|
|
||||||
An abbreviated form of @racket[define-constructor].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[#:literals (:)
|
|
||||||
(message-struct ctor-id : type-ctor-id (slot-id ...))]{
|
|
||||||
An abbreviated form of @racket[define-constructor].
|
|
||||||
}
|
|
||||||
|
|
||||||
@section{Actor Forms}
|
|
||||||
|
|
||||||
@defform[(run-ground-dataspace type expr ...)]{
|
|
||||||
Starts a ground, i.e. main, dataspace of the program, with the given
|
|
||||||
communication @racket[type] and initial actors spawned by @racket[expr ...].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(spawn maybe-type s)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-type (code:line)
|
|
||||||
(code:line type))]]{
|
|
||||||
Spawns an actor with behavior given by @racket[s]. The @racket[type] gives the
|
|
||||||
communication type of the enclosing dataspace. When absent, @racket[type] is
|
|
||||||
supplied by the nearest lexically enclosing @racket[spawn] or @racket[dataspace]
|
|
||||||
form, if any exist.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(dataspace type expr ...)]{
|
|
||||||
Spawns a dataspace with communication type @racket[type] as a child of the
|
|
||||||
dataspace enclosing the executing actor. The script @racket[expr ...] spawns the
|
|
||||||
initial actors of the new dataspace.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(start-facet id maybe-spec expr ...+)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-spec (code:line)
|
|
||||||
(code:line #:implements type)
|
|
||||||
(code:line #:includes-behavior type))]]{
|
|
||||||
Start a facet with name @racket[id] and endpoints installed through the
|
|
||||||
evaluation of @racket[expr ...].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(stop id expr ...)]{
|
|
||||||
Terminate the facet @racket[id] with continuation script @racket[expr ...]. Any
|
|
||||||
facets started by the continuation script survive the termination of facet
|
|
||||||
@racket[id].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[#:literals (start stop message asserted retracted _ $)
|
|
||||||
(on event-description body ...+)
|
|
||||||
#:grammar
|
|
||||||
[(event-description (code:line start)
|
|
||||||
(code:line stop)
|
|
||||||
(code:line (message pattern))
|
|
||||||
(code:line (asserted pattern))
|
|
||||||
(code:line (retracted pattern)))
|
|
||||||
(pattern (code:line _)
|
|
||||||
(code:line ($ id type))
|
|
||||||
(code:line ($ id))
|
|
||||||
(code:line $id)
|
|
||||||
(code:line $id:type)
|
|
||||||
(code:line (ctor pattern ...))
|
|
||||||
(code:line expr))]]{
|
|
||||||
Creates an event handler endpoint that responds to the event specified by
|
|
||||||
@racket[event-description]. Executes the @racket[body ...] for each matching
|
|
||||||
event, with any pattern variables bound to their matched value.
|
|
||||||
|
|
||||||
Patterns have the following meanings:
|
|
||||||
@itemlist[
|
|
||||||
@item{@racket[_] matches anything.}
|
|
||||||
|
|
||||||
@item{@racket[($ id type)] matches any value and binds it to @racket[id] with
|
|
||||||
assumed type @racket[type].}
|
|
||||||
|
|
||||||
@item{@racket[($ id)] is like @racket[($ id type)], but attempts to use the
|
|
||||||
current communication type to fill in the @racket[type] of potential matches.
|
|
||||||
May raise an error if no suitable communication type is in scope.}
|
|
||||||
|
|
||||||
@item{@racket[(? pred pattern)] matches values where @racket[(pred val)] is not
|
|
||||||
@racket[#f] and that match @racket[pattern].}
|
|
||||||
|
|
||||||
@item{@racket[$id:type] is shorthand for @racket[($ id type)].}
|
|
||||||
|
|
||||||
@item{@racket[$id] is shorthand for @racket[($ id)].}
|
|
||||||
|
|
||||||
@item{@racket[(ctor pat ...)] matches values built by applying the constructor
|
|
||||||
@racket[ctor] to values matching @racket[pat ...]. @racket[ctor] is usually
|
|
||||||
a @racket[struct] name.}
|
|
||||||
|
|
||||||
@item{@racket[expr] patterns match values that are @racket[equal?] to
|
|
||||||
@racket[expr].}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(on-start expr ...+)]{
|
|
||||||
Shorthand for @racket[(on start expr ...)].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(on-stop expr ...+)]{
|
|
||||||
Shorthand for @racket[(on stop expr ...)].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(assert expr)]{
|
|
||||||
Creates an assertion endpoint with the value of @racket[expr].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(know expr)]{
|
|
||||||
Creates an internal assertion endpoint with the value of @racket[expr].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(send! expr)]{
|
|
||||||
Broadcast a dataspace message with the value of @racket[expr].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(realize! expr)]{
|
|
||||||
Broadcast an actor-internal message with the value of @racket[expr].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[#:literals (:)
|
|
||||||
(field [id maybe-type expr] ...)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-type (code:line)
|
|
||||||
(code:line type)
|
|
||||||
(code:line : type))]]{
|
|
||||||
Defines fields of type @racket[type] with names @racket[id] and initial values
|
|
||||||
@racket[expr]. If @racket[type] is not provided, the type of the initial
|
|
||||||
expression is used as the type of the field.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(ref id)]{
|
|
||||||
Reference the @racket[field] named @racket[id].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(set! id expr)]{
|
|
||||||
Update the value the @racket[field] named @racket[id].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(begin/dataflow expr ...+)]{
|
|
||||||
Evaluate and perform the script @racket[expr ...], and then again each time a
|
|
||||||
field referenced by the script updates.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(during pattern expr ...+)]{
|
|
||||||
Engage in behavior for the duration of a matching assertion. The syntax of
|
|
||||||
@racket[pattern] is the same as described by @racket[on].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(during/spawn pattern expr ...+)]{
|
|
||||||
Like @racket[during], but spawns an actor for the behavior @racket[expr ...].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(define/query-value name absent-expr pattern expr
|
|
||||||
maybe-on-add
|
|
||||||
maybe-on-remove)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-on-add (code:line)
|
|
||||||
(code:line #:on-add on-add-expr))
|
|
||||||
(maybe-on-remove (code:line)
|
|
||||||
(code:line #:on-remove on-remove-expr))]]{
|
|
||||||
Equivalent to the untyped @racket[untyped:define/query-value]. The
|
|
||||||
@racket[on-add-expr] and @racket[on-remove-expr], when given, execute after
|
|
||||||
@racket[name] has been updated.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(define/query-set name pattern expr
|
|
||||||
maybe-on-add
|
|
||||||
maybe-on-remove)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-on-add (code:line)
|
|
||||||
(code:line #:on-add on-add-expr))
|
|
||||||
(maybe-on-remove (code:line)
|
|
||||||
(code:line #:on-remove on-remove-expr))]]{
|
|
||||||
Equivalent to the untyped @racket[untyped:define/query-set].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(define/query-hash name pattern key-expr value-expr
|
|
||||||
maybe-on-add
|
|
||||||
maybe-on-remove)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-on-add (code:line)
|
|
||||||
(code:line #:on-add on-add-expr))
|
|
||||||
(maybe-on-remove (code:line)
|
|
||||||
(code:line #:on-remove on-remove-expr))]]{
|
|
||||||
Equivalent to the untyped @racket[untyped:define/query-hash].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(define/dataflow name maybe-type expr)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-type (code:line)
|
|
||||||
(code:line type))]]{
|
|
||||||
Define a @racket[field] named @racket[name], whose value is reevaluated to the
|
|
||||||
result of @racket[expr] each time any referenced field changes. When
|
|
||||||
@racket[type] is not supplied, the field has the type of the given
|
|
||||||
@racket[expr].
|
|
||||||
}
|
|
||||||
|
|
||||||
@section{Expressions}
|
|
||||||
|
|
||||||
@defform*[#:literals (:)
|
|
||||||
[(ann expr : type)
|
|
||||||
(ann expr type)]]{
|
|
||||||
Ensure that @racket[expr] has the given @racket[type].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(if test-expr then-expr else-expr)]{
|
|
||||||
The same as Racket's @racket[racket:if].
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(@defform[(cond [test-expr body-expr ...+] ...+)]
|
|
||||||
@defthing[else Bool #:value #t])]{
|
|
||||||
Like Racket's @racket[racket:cond].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(when test-expr expr)]{
|
|
||||||
Like Racket's @racket[racket:when], but results in @racket[#f] when
|
|
||||||
@racket[test-expr] is @racket[#f].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(unless test-expr expr)]{
|
|
||||||
Like Racket's @racket[racket:unless], but results in @racket[#f] when
|
|
||||||
@racket[test-expr] is @racket[#f].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(let ([id expr] ...) body ...+)]{
|
|
||||||
The same as Racket's @racket[racket:let].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(let* ([id expr] ...) body ...+)]{
|
|
||||||
The same as Racket's @racket[racket:let*].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[#:literals (:)
|
|
||||||
(lambda ([x opt-: type] ...) expr ...+)
|
|
||||||
#:grammar
|
|
||||||
[(opt-: (code:line)
|
|
||||||
(code:line :))]]{
|
|
||||||
Constructsa an anonymous function.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defidform[λ]{Synonym for @racket[lambda].}
|
|
||||||
|
|
||||||
@defform[(Λ (X ...) expr)]{
|
|
||||||
Parametric abstraction over type variables @racket[X ...].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(inst expr type ...)]{
|
|
||||||
Instantiates the type variables @racket[X ...] with @racket[type ...], where
|
|
||||||
@racket[expr] has type @racket[(∀ (X ...) t)].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform*[#:literals (: → -> ∀)
|
|
||||||
[(define id : type expr)
|
|
||||||
(define id expr)
|
|
||||||
(define (id [arg-id opt-: arg-type] ... opt-res-ty) expr ...+)
|
|
||||||
(define (∀ (X ...) (id [arg-id opt-: arg-type] ... opt-res-ty)) expr ...+)]
|
|
||||||
#:grammar
|
|
||||||
[(opt-: (code:line) (code:line :))
|
|
||||||
(opt-res-ty (code:line)
|
|
||||||
(code:line arr res-type))
|
|
||||||
(arr (code:line →) (code:line ->))]]{
|
|
||||||
Define a constant or a (potentially polymorphic) function. Note that the
|
|
||||||
function name @racket[id] is @emph{not} bound in the body.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(define-tuple (id ...) expr)]{
|
|
||||||
Define @racket[id ...] to each of the slots of the tuple produced by
|
|
||||||
@racket[expr].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(match-define pattern expr)]{
|
|
||||||
Define the binders of @racket[pattern] to the matching values of @racket[expr].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(begin expr ...+)]{
|
|
||||||
Sequencing form whose value and type is that of the final @racket[expr].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(block expr ...+)]{
|
|
||||||
Like @racket[begin], but also introduces a definition context for its body.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(match expr [pattern body-expr ...+] ...+)]{
|
|
||||||
Like Racket's @racket[racket:match] but with the pattern syntax described by
|
|
||||||
@racket[on].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(tuple expr ...)]{
|
|
||||||
Constructs a tuple of arbitrary arity.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(select i expr)]{
|
|
||||||
Extract the @racket[i]th element of a @racket[tuple].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defthing[unit Unit #:value (tuple)]
|
|
||||||
|
|
||||||
@defform[(error format-expr arg-expr ...)]{
|
|
||||||
Raises an exception using @racket[format-expr] as a format string together with
|
|
||||||
@racket[arg-expr ...].
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(
|
|
||||||
@defthing[+ (→fn Int Int Int)]
|
|
||||||
@defthing[- (→fn Int Int Int)]
|
|
||||||
@defthing[* (→fn Int Int Int)]
|
|
||||||
@defthing[< (→fn Int Int Bool)]
|
|
||||||
@defthing[> (→fn Int Int Bool)]
|
|
||||||
@defthing[<= (→fn Int Int Bool)]
|
|
||||||
@defthing[>= (→fn Int Int Bool)]
|
|
||||||
@defthing[= (→fn Int Int Bool)]
|
|
||||||
@defthing[even? (→fn Int Bool)]
|
|
||||||
@defthing[odd? (→fn Int Bool)]
|
|
||||||
@defthing[add1 (→fn Int Int)]
|
|
||||||
@defthing[sub1 (→fn Int Int)]
|
|
||||||
@defthing[max (→fn Int Int Int)]
|
|
||||||
@defthing[min (→fn Int Int Int)]
|
|
||||||
@defthing[zero? (→fn Int Bool)]
|
|
||||||
@defthing[positive? (→fn Int Bool)]
|
|
||||||
@defthing[negative? (→fn Int Bool)]
|
|
||||||
@defthing[current-inexact-milleseconds? (→fn Int)]
|
|
||||||
@defthing[string=? (→fn String String Bool)]
|
|
||||||
@defthing[bytes->string/utf-8 (→fn ByteString String)]
|
|
||||||
@defthing[string->bytes/utf-8 (→fn String ByteString)]
|
|
||||||
@defthing[gensym (→fn Symbol Symbol)]
|
|
||||||
@defthing[symbol->string (→fn Symbol String)]
|
|
||||||
@defthing[string->symbol (→fn String Symbol)]
|
|
||||||
@defthing[not (→fn Bool Bool)]
|
|
||||||
@defform[(/ e1 e2)]
|
|
||||||
@defform[(and e ...)]
|
|
||||||
@defform[(or e ...)]
|
|
||||||
@defform[(equal? e1 e2)]
|
|
||||||
@defform[(displayln e)]
|
|
||||||
@defform[(printf fmt-expr val-expr ...)]
|
|
||||||
@defform[(~a e ...)]
|
|
||||||
)]{
|
|
||||||
Primitive operations imported from Racket.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[#:literals (:)
|
|
||||||
(for/fold ([acc-id maybe-:ty acc-expr] ...+)
|
|
||||||
(for-clause ...)
|
|
||||||
body-expr ...+)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-:ty (code:line)
|
|
||||||
(code:line : acc-type))
|
|
||||||
(for-clause (code:line [id seq-expr])
|
|
||||||
(code:line [id : type seq-expr])
|
|
||||||
(code:line [(k-id v-id) hash-expr])
|
|
||||||
(code:line #:when test-expr)
|
|
||||||
(code:line #:unless test-expr)
|
|
||||||
(code:line #:break test-expr))]]{
|
|
||||||
Similar to Racket's @racket[racket:for/fold].
|
|
||||||
|
|
||||||
When more than one @racket[acc-id] is used, the body of the loop must evaluate
|
|
||||||
to a @racket[tuple] with one value for each accumulator, with the final tuple
|
|
||||||
also being the result of the entire expression.
|
|
||||||
|
|
||||||
Each @racket[seq-expr] should be of type @racket[Sequence], though expressions
|
|
||||||
of type @racket[List] and @racket[Set] are automatically converted.
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(
|
|
||||||
@defform[(for/list (for-clause ...) body ...+)]
|
|
||||||
@defform[(for/set (for-clause ...) body ...+)]
|
|
||||||
@defform[(for/sum (for-clause ...) body ...+)]
|
|
||||||
@defform[(for (for-clause ...) body ...+)]
|
|
||||||
@defform[(for/first (for-clause ...) body ...+)]
|
|
||||||
)]{
|
|
||||||
Like their Racket counterparts. See @racket[for/fold] for the description of
|
|
||||||
@racket[for-clause].
|
|
||||||
|
|
||||||
Unlike @racket[racket:for/first], @racket[for/first] returns a @racket[Maybe]
|
|
||||||
value to indicate success/failure.
|
|
||||||
}
|
|
||||||
|
|
||||||
@section{Require & Provide}
|
|
||||||
|
|
||||||
@defform[(struct-out ctor-id)]{
|
|
||||||
}
|
|
||||||
|
|
||||||
@subsection{Requiring From Outside Typed Syndicate}
|
|
||||||
|
|
||||||
@defform[#:literals (:)
|
|
||||||
(require/typed lib clause ...)
|
|
||||||
#:grammar
|
|
||||||
[(clause (code:line [id : type])
|
|
||||||
(code:line opaque))
|
|
||||||
(opaque (code:line [#:opaque type-name])
|
|
||||||
(code:line [#:opaque type-name #:arity op arity-nat]))
|
|
||||||
(opaque (code:line =) (code:line >) (code:line >=))]]{
|
|
||||||
Import and assign types to bindings from outside Typed Syndicate.
|
|
||||||
|
|
||||||
Note that @emph{unlike} Typed Racket, Typed Syndicate does not attach contracts
|
|
||||||
to imported bindings.
|
|
||||||
|
|
||||||
An @racket[#:opaque] declaration defines a type @racket[type-name] (or, in the
|
|
||||||
@racket[#:arity] case, a type constructor) that may be used to describe imports
|
|
||||||
but otherwise has no other operations.
|
|
||||||
}
|
|
||||||
|
|
||||||
@defform[(require-struct ctor-id #:as ty-ctor-id #:from lib maybe-omit-accs)
|
|
||||||
#:grammar
|
|
||||||
[(maybe-omit-accs (code:line)
|
|
||||||
(code:line #:omit-accs))]]{
|
|
||||||
Import a Racket @racket[struct] named @racket[ctor-id] and create a type
|
|
||||||
constructor @racket[ty-ctor-id] for its instances.
|
|
||||||
|
|
||||||
Unless @racket[#:omit-accs] is specified, defines the accessor functions for the
|
|
||||||
struct.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@section{Builtin Data Structures}
|
|
||||||
|
|
||||||
@deftogether[(@defstruct[observe ([claim any?]) #:omit-constructor]
|
|
||||||
@defform[(Observe type)])]{
|
|
||||||
Constructs an assertion of interest.
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(@defstruct[inbound ([assertion any?]) #:omit-constructor]
|
|
||||||
@defform[(Inbound type)])]{
|
|
||||||
Constructor for an assertion inbound from an outer dataspace.
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(@defstruct[outbound ([assertion any?]) #:omit-constructor]
|
|
||||||
@defform[(Outbound type)])]{
|
|
||||||
Constructor for an assertion outbound to an outer dataspace.
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(@defstruct[message ([body any?]) #:omit-constructor]
|
|
||||||
@defform[(Message type)])]{
|
|
||||||
Constructor for a broadcast message.
|
|
||||||
}
|
|
||||||
|
|
||||||
@subsection{Lists}
|
|
||||||
|
|
||||||
@defform[(List type)]{
|
|
||||||
The type for @racket[cons] lists whose elements are of type @racket[type].
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(
|
|
||||||
@defthing[empty (List ⊥)]
|
|
||||||
@defthing[empty? (∀ (X) (→fn (List X) Bool))]
|
|
||||||
@defthing[cons (∀ (X) (→fn X (List X) (List X)))]
|
|
||||||
@defthing[cons? (∀ (X) (→fn X (List X) Bool))]
|
|
||||||
@defthing[first (∀ (X) (→fn (List X) X))]
|
|
||||||
@defthing[second (∀ (X) (→fn (List X) X))]
|
|
||||||
@defthing[rest (∀ (X) (→fn (List X) (List X)))]
|
|
||||||
@defthing[member? (∀ (X) (→fn X (List X) Bool))]
|
|
||||||
@defthing[reverse (∀ (X) (→fn (List X) (List X)))]
|
|
||||||
@defthing[partition (∀ (X) (→fn (List X) (→fn X Bool) (List X)))]
|
|
||||||
@defthing[map (∀ (X Y) (→fn (→fn X Y) (List X) (List Y)))]
|
|
||||||
@defthing[argmax (∀ (X) (→fn (→fn X Int) (List X) X))]
|
|
||||||
@defthing[argmin (∀ (X) (→fn (→fn X Int) (List X) X))]
|
|
||||||
@defthing[remove (∀ (X) (→fn X (List X) (List X)))]
|
|
||||||
@defthing[length (∀ (X) (→fn (List X) Int))]
|
|
||||||
@defform[(list e ...)]
|
|
||||||
)]{
|
|
||||||
Like their Racket counterparts.
|
|
||||||
}
|
|
||||||
|
|
||||||
@subsection{Sets}
|
|
||||||
|
|
||||||
@defform[(Set type)]{
|
|
||||||
The type for sets whose elements are of type @racket[type].
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(
|
|
||||||
@defform[(set e ...)]
|
|
||||||
@defform[(set-union st ...+)]
|
|
||||||
@defform[(set-intersect st ...+)]
|
|
||||||
@defform[(set-subtract st ...+)]
|
|
||||||
@defthing[set-first (∀ (X) (→fn (Set X) X))]
|
|
||||||
@defthing[set-empty? (∀ (X) (→fn (Set X) Bool))]
|
|
||||||
@defthing[set-count (∀ (X) (→fn (Set X) Int))]
|
|
||||||
@defthing[set-add (∀ (X) (→fn (Set X) X (Set X)))]
|
|
||||||
@defthing[set-remove (∀ (X) (→fn (Set X) X (Set X)))]
|
|
||||||
@defthing[set-member? (∀ (X) (→fn (Set X) X Bool))]
|
|
||||||
@defthing[list->set (∀ (X) (→fn (List X) (Set X)))]
|
|
||||||
@defthing[set->list (∀ (X) (→fn (Set X) (List X)))]
|
|
||||||
)]{
|
|
||||||
Like their Racket counterparts.
|
|
||||||
}
|
|
||||||
|
|
||||||
@subsection{Hashes}
|
|
||||||
|
|
||||||
@defform[(Hash key-type value-type)]{
|
|
||||||
The type for key/value hash tables.
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(
|
|
||||||
@defform[(hash key val ... ...)]
|
|
||||||
@defthing[hash-set (∀ (K V) (→fn (Hash K V) K V (Hash K V)))]
|
|
||||||
@defthing[hash-ref (∀ (K V) (→fn (Hash K V) K V))]
|
|
||||||
@defthing[hash-ref/failure (∀ (K V) (→fn (Hash K V) K V V))]
|
|
||||||
@defthing[hash-empty? (∀ (K V) (→fn (Hash K V) Bool))]
|
|
||||||
@defthing[hash-has-key? (∀ (K V) (→fn (Hash K V) K Bool))]
|
|
||||||
@defthing[hash-count (∀ (K V) (→fn (Hash K V) Int))]
|
|
||||||
@defthing[hash-update (∀ (K V) (→fn (Hash K V) K (→fn V V) (Hash K V)))]
|
|
||||||
@defthing[hash-update/failure (∀ (K V) (→fn (Hash K V) K (→fn V V) V (Hash K V)))]
|
|
||||||
@defthing[hash-remove (∀ (K V) (→fn (Hash K V) K (Hash K V)))]
|
|
||||||
@defthing[hash-map (∀ (K V R) (→fn (Hash K V) (→fn K V R) (List R)))]
|
|
||||||
@defthing[hash-keys (∀ (K V) (→fn (Hash K V) (List K)))]
|
|
||||||
@defthing[hash-values (∀ (K V) (→fn (Hash K V) (List V)))]
|
|
||||||
@defthing[hash-union (∀ (K1 V1 K2 V2) (→fn (Hash K1 V1) (Hash K2 V2) (Hash (U K1 K2) (U V1 V2))))]
|
|
||||||
@defthing[hash-union/combine (∀ (K V) (→fn (Hash K V) (Hash K V) (→fn V V V) (Hash K V)))]
|
|
||||||
@defthing[hash-keys-subset? (∀ (K1 V1 K2 V2) (→fn (Hash K1 V1) (Hash K2 V2) Bool))]
|
|
||||||
)]{
|
|
||||||
Like their Racket counterparts. The /failure and /combine suffixes are in place
|
|
||||||
of keyword arguments, which Typed Syndicate does not presently support.
|
|
||||||
}
|
|
||||||
|
|
||||||
@subsection{Sequences}
|
|
||||||
|
|
||||||
@defform[(Sequence type)]{
|
|
||||||
The type for a sequence of @racket[type] values.
|
|
||||||
}
|
|
||||||
|
|
||||||
@deftogether[(
|
|
||||||
@defthing[empty-sequence (Sequence ⊥)]
|
|
||||||
@defthing[sequence->list (∀ (X) (→fn (Sequence X) (List X)))]
|
|
||||||
@defthing[sequence-length (∀ (X) (→fn (Sequence X) Int))]
|
|
||||||
@defthing[sequence-ref (∀ (X) (→fn (Sequence X) Int Int))]
|
|
||||||
@defthing[sequence-tail (∀ (X) (→fn (Sequence X) Int (Sequence X)))]
|
|
||||||
@defthing[sequence-append (∀ (X) (→fn (Sequence X) (Sequence X) (Sequence X)))]
|
|
||||||
@defthing[sequence-map (∀ (A B) (→fn (→fn A B) (Sequence A) (Sequence B)))]
|
|
||||||
@defthing[sequence-andmap (∀ (X) (→fn (→fn X Bool) (Sequence X) Bool))]
|
|
||||||
@defthing[sequence-ormap (∀ (X) (→fn (→fn X Bool) (Sequence X) Bool))]
|
|
||||||
@defthing[sequence-fold (∀ (A B) (→fn (→fn A B A) (Sequence B) A))]
|
|
||||||
@defthing[sequence-count (∀ (X) (→fn (→fn X Bool) (Sequence X) Int))]
|
|
||||||
@defthing[sequence-filter (∀ (X) (→fn (→fn X Bool) (Sequence X) (Sequence X)))]
|
|
||||||
@defthing[sequence-add-between (∀ (X) (→fn (Sequence X) X (Sequence X)))]
|
|
||||||
@defthing[in-list (∀ (X) (→fn (List X) (Sequence X)))]
|
|
||||||
@defthing[in-hash-keys (∀ (K V) (→fn (Hash K V) (Sequence K)))]
|
|
||||||
@defthing[in-hash-values (∀ (K V) (→fn (Hash K V) (Sequence V)))]
|
|
||||||
@defthing[in-range (→fn Int (Sequence Int))]
|
|
||||||
@defthing[in-set (∀ (X) (→fn (Set X) (Sequence X)))]
|
|
||||||
)]{
|
|
||||||
Like their Racket counterparts.
|
|
||||||
}
|
|
||||||
|
|
||||||
@subsection{Maybe}
|
|
||||||
|
|
||||||
@deftogether[(
|
|
||||||
@defidform[None]
|
|
||||||
@defthing[none None]
|
|
||||||
@defstruct[some ([v any?]) #:omit-constructor]
|
|
||||||
@defform[(Some type)]
|
|
||||||
@defform[(Maybe type)]
|
|
||||||
)]{
|
|
||||||
@racket[(Maybe type)] is an alias for @racket[(U None (Some type))].
|
|
||||||
}
|
|
||||||
|
|
||||||
@subsection{Either}
|
|
||||||
|
|
||||||
@deftogether[(
|
|
||||||
@defstruct[left ([v any?]) #:omit-constructor]
|
|
||||||
@defform[(Left type)]
|
|
||||||
@defstruct[right ([v any?]) #:omit-constructor]
|
|
||||||
@defform[(Right type)]
|
|
||||||
@defform[(Either left-type right-type)]
|
|
||||||
)]{
|
|
||||||
@racket[(Either left-type right-type)] is an alias for @racket[(U (Left
|
|
||||||
left-type) (Right right-type))].
|
|
||||||
}
|
|
||||||
|
|
||||||
@defthing[partition/either (∀ (X Y Z) (→fn (List X) (→fn X (Either Y Z)) (Tuple (List Y) (List Z))))]{
|
|
||||||
Partition a list based on a function that returns an @racket[Either] value.
|
|
||||||
}
|
|
||||||
|
|
||||||
@section{Behavioral Checking}
|
|
|
@ -17,15 +17,12 @@
|
||||||
sequence-add-between
|
sequence-add-between
|
||||||
in-list
|
in-list
|
||||||
in-set
|
in-set
|
||||||
in-hash-keys
|
|
||||||
in-hash-values
|
|
||||||
in-range
|
in-range
|
||||||
)
|
)
|
||||||
|
|
||||||
(require "core-types.rkt")
|
(require "core-types.rkt")
|
||||||
(require (only-in "list.rkt" List))
|
(require (only-in "list.rkt" List))
|
||||||
(require (only-in "set.rkt" Set))
|
(require (only-in "set.rkt" Set))
|
||||||
(require (only-in "hash.rkt" Hash))
|
|
||||||
(require (only-in "prim.rkt" Int Bool))
|
(require (only-in "prim.rkt" Int Bool))
|
||||||
#;(require (postfix-in - racket/sequence))
|
#;(require (postfix-in - racket/sequence))
|
||||||
|
|
||||||
|
@ -53,8 +50,25 @@
|
||||||
|
|
||||||
(require/typed racket/base
|
(require/typed racket/base
|
||||||
[in-list : (∀ (X) (→fn (List X) (Sequence X)))]
|
[in-list : (∀ (X) (→fn (List X) (Sequence X)))]
|
||||||
[in-hash-keys : (∀ (K V) (→fn (Hash K V) (Sequence K)))]
|
|
||||||
[in-hash-values : (∀ (K V) (→fn (Hash K V) (Sequence V)))]
|
|
||||||
[in-range : (→fn Int (Sequence Int))])
|
[in-range : (→fn Int (Sequence Int))])
|
||||||
(require/typed racket/set
|
(require/typed racket/set
|
||||||
[in-set : (∀ (X) (→fn (Set X) (Sequence X)))])
|
[in-set : (∀ (X) (→fn (Set X) (Sequence X)))])
|
||||||
|
|
||||||
|
#;(define-typed-syntax empty-sequence
|
||||||
|
[_ ≫
|
||||||
|
--------------------
|
||||||
|
[⊢ empty-sequence- (⇒ : (Sequence (U)))]])
|
||||||
|
|
||||||
|
;; er, this is making everything a macro, as opposed to a procedure...
|
||||||
|
;; think I ought to add polymorphous first :\
|
||||||
|
#;(define-typed-syntax (sequence->list s) ≫
|
||||||
|
[⊢ s ≫ s- (⇒ : (~Sequence τ))]
|
||||||
|
#:fail-unless (pure? #'s-)
|
||||||
|
------------------------------
|
||||||
|
[⊢ (sequence->list- s-) (⇒ : (List τ))])
|
||||||
|
|
||||||
|
#;(define-typed-syntax (sequence-length s) ≫
|
||||||
|
[⊢ s ≫ s- (⇒ : (~Sequence τ))]
|
||||||
|
#:fail-unless (pure? #'s-)
|
||||||
|
------------------------------
|
||||||
|
[⊢ (sequence-length- s-) (⇒ : Int)])
|
|
@ -3,28 +3,23 @@
|
||||||
(provide Set
|
(provide Set
|
||||||
(for-syntax ~Set)
|
(for-syntax ~Set)
|
||||||
set
|
set
|
||||||
;; set-member?
|
set-member?
|
||||||
;; set-add
|
set-add
|
||||||
;; set-remove
|
set-remove
|
||||||
;; set-count
|
set-count
|
||||||
set-union
|
set-union
|
||||||
set-subtract
|
set-subtract
|
||||||
set-intersect
|
set-intersect
|
||||||
;; list->set
|
list->set
|
||||||
;; set->list
|
set->list
|
||||||
(typed-out [[set-first- : (∀ (X) (→fn (Set X) X))] set-first]
|
(typed-out [[set-first- : (∀ (X) (→fn (Set X) X))]
|
||||||
[[set-empty?- : (∀ (X) (→fn (Set X) Bool))] set-empty?]
|
set-first]
|
||||||
[[set-count- : (∀ (X) (→fn (Set X) Int))] set-count]
|
[[set-empty?- : (∀ (X) (→fn (Set X) Bool))]
|
||||||
[[set-add- : (∀ (X) (→fn (Set X) X (Set X)))] set-add]
|
set-empty?]))
|
||||||
[[set-remove- : (∀ (X) (→fn (Set X) X (Set X)))] set-remove]
|
|
||||||
[[set-member?- : (∀ (X) (→fn (Set X) X Bool))] set-member?]
|
|
||||||
[[list->set- : (∀ (X) (→fn (List X) (Set X)))] list->set]
|
|
||||||
[[set->list- : (∀ (X) (→fn (Set X) (List X)))] set->list]
|
|
||||||
))
|
|
||||||
|
|
||||||
(require "core-types.rkt")
|
(require "core-types.rkt")
|
||||||
(require (only-in "prim.rkt" Int Bool))
|
(require (only-in "prim.rkt" Int Bool))
|
||||||
(require (only-in "list.rkt" ~List List))
|
(require (only-in "list.rkt" ~List))
|
||||||
|
|
||||||
(require (postfix-in - racket/set))
|
(require (postfix-in - racket/set))
|
||||||
|
|
||||||
|
@ -40,6 +35,38 @@
|
||||||
---------------
|
---------------
|
||||||
[⊢ (#%app- set- e- ...) ⇒ (Set (U τ ...))])
|
[⊢ (#%app- set- e- ...) ⇒ (Set (U τ ...))])
|
||||||
|
|
||||||
|
(define-typed-syntax (set-count e) ≫
|
||||||
|
[⊢ e ≫ e- ⇒ (~Set _)]
|
||||||
|
#:fail-unless (pure? #'e-) "expression must be pure"
|
||||||
|
----------------------
|
||||||
|
[⊢ (#%app- set-count- e-) ⇒ Int])
|
||||||
|
|
||||||
|
(define-typed-syntax (set-add st v) ≫
|
||||||
|
[⊢ st ≫ st- ⇒ (~Set τs)]
|
||||||
|
#:fail-unless (pure? #'st-) "expression must be pure"
|
||||||
|
[⊢ v ≫ v- ⇒ τv]
|
||||||
|
#:fail-unless (pure? #'v-) "expression must be pure"
|
||||||
|
-------------------------
|
||||||
|
[⊢ (#%app- set-add- st- v-) ⇒ (Set (U τs τv))])
|
||||||
|
|
||||||
|
(define-typed-syntax (set-remove st v) ≫
|
||||||
|
[⊢ st ≫ st- ⇒ (~Set τs)]
|
||||||
|
#:fail-unless (pure? #'st-) "expression must be pure"
|
||||||
|
[⊢ v ≫ v- ⇐ τs]
|
||||||
|
#:fail-unless (pure? #'v-) "expression must be pure"
|
||||||
|
-------------------------
|
||||||
|
[⊢ (#%app- set-remove- st- v-) ⇒ (Set τs)])
|
||||||
|
|
||||||
|
(define-typed-syntax (set-member? st v) ≫
|
||||||
|
[⊢ st ≫ st- ⇒ (~Set τs)]
|
||||||
|
#:fail-unless (pure? #'st-) "expression must be pure"
|
||||||
|
[⊢ v ≫ v- ⇒ τv]
|
||||||
|
#:fail-unless (pure? #'v-) "expression must be pure"
|
||||||
|
#:fail-unless (<: #'τv #'τs)
|
||||||
|
"type mismatch"
|
||||||
|
-------------------------------------
|
||||||
|
[⊢ (#%app- set-member?- st- v-) ⇒ Bool])
|
||||||
|
|
||||||
(define-typed-syntax (set-union st0 st ...) ≫
|
(define-typed-syntax (set-union st0 st ...) ≫
|
||||||
[⊢ st0 ≫ st0- ⇒ (~Set τ-st0)]
|
[⊢ st0 ≫ st0- ⇒ (~Set τ-st0)]
|
||||||
#:fail-unless (pure? #'st0-) "expression must be pure"
|
#:fail-unless (pure? #'st0-) "expression must be pure"
|
||||||
|
@ -64,3 +91,15 @@
|
||||||
#:fail-unless (all-pure? #'(st- ...)) "expressions must be pure"
|
#:fail-unless (all-pure? #'(st- ...)) "expressions must be pure"
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
[⊢ (#%app- set-subtract- st0- st- ...) ⇒ (Set τ-st0)])
|
[⊢ (#%app- set-subtract- st0- st- ...) ⇒ (Set τ-st0)])
|
||||||
|
|
||||||
|
(define-typed-syntax (list->set l) ≫
|
||||||
|
[⊢ l ≫ l- ⇒ (~List τ)]
|
||||||
|
#:fail-unless (pure? #'l-) "expression must be pure"
|
||||||
|
-----------------------
|
||||||
|
[⊢ (#%app- list->set- l-) ⇒ (Set τ)])
|
||||||
|
|
||||||
|
(define-typed-syntax (set->list s) ≫
|
||||||
|
[⊢ s ≫ s- ⇒ (~Set τ)]
|
||||||
|
#:fail-unless (pure? #'s-) "expression must be pure"
|
||||||
|
-----------------------
|
||||||
|
[⊢ (#%app- set->list- s-) ⇒ (List τ)])
|
|
@ -0,0 +1,9 @@
|
||||||
|
/* Useful macros */
|
||||||
|
|
||||||
|
#define ASSERTED(x) (x##_assertions > 0)
|
||||||
|
#define RETRACTED(x) (x##_assertions == 0)
|
||||||
|
#define ASSERT(x) x##_assertions = x##_assertions + 1
|
||||||
|
#define RETRACT(x) x##_assertions = x##_assertions - 1
|
||||||
|
|
||||||
|
/* Rest of Program */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +0,0 @@
|
||||||
#lang typed/syndicate/roles
|
|
||||||
|
|
||||||
(provide activate!
|
|
||||||
later-than
|
|
||||||
LaterThanT
|
|
||||||
LaterThan
|
|
||||||
TimeStateDriver)
|
|
||||||
|
|
||||||
(require-struct later-than
|
|
||||||
#:as LaterThanT
|
|
||||||
#:from syndicate/drivers/timestate)
|
|
||||||
|
|
||||||
(define-type-alias LaterThan (LaterThanT Int))
|
|
||||||
|
|
||||||
(define-type-alias TimeStateDriver
|
|
||||||
(U LaterThan
|
|
||||||
(Observe (LaterThanT ★/t))))
|
|
||||||
|
|
||||||
;; TODO ignoring other driver underneath it
|
|
||||||
|
|
||||||
(require/typed (submod syndicate/drivers/timestate syndicate-main)
|
|
||||||
[activate! : (proc → ⊥ #:spawns ((Actor TimeStateDriver)))])
|
|
|
@ -1,2 +1,2 @@
|
||||||
#lang s-exp syntax/module-reader
|
#lang s-exp syntax/module-reader
|
||||||
typed/syndicate/roles
|
typed/main
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
spin -p -t $1
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,2 +1,2 @@
|
||||||
#lang s-exp syntax/module-reader
|
#lang s-exp syntax/module-reader
|
||||||
typed/syndicate/roles
|
typed/roles
|
|
@ -1,21 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
pushd ${1%/*}/ > /dev/null
|
|
||||||
|
|
||||||
EXE="$1-verifier.o"
|
|
||||||
|
|
||||||
spin -a $1
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
popd > /dev/null
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
gcc -o $EXE -D NFAIR=3 pan.c
|
|
||||||
|
|
||||||
# -a to analyze, -f for (weak) fairness
|
|
||||||
# -n to elide report of unreached states
|
|
||||||
# -N spec-name to verify a particular specification
|
|
||||||
$EXE -a -f -n -N $2
|
|
||||||
rm $EXE pan.*
|
|
||||||
|
|
||||||
popd > /dev/null
|
|
|
@ -1,10 +0,0 @@
|
||||||
/* Useful macros */
|
|
||||||
|
|
||||||
#define ASSERTED(x) (x##_assertions > 0)
|
|
||||||
#define RETRACTED(x) (x##_assertions == 0)
|
|
||||||
#define ASSERT(x) x##_update = x##_update + 1
|
|
||||||
#define RETRACT(x) x##_update = x##_update - 1
|
|
||||||
#define SEND(x) x##_messages = x##_messages + 1
|
|
||||||
|
|
||||||
/* Rest of Program */
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
#lang turnstile
|
|
||||||
|
|
||||||
(provide Observe★
|
|
||||||
RoleNTimes
|
|
||||||
(for-syntax RoleNTimes*))
|
|
||||||
|
|
||||||
(require "core-types.rkt")
|
|
||||||
(require turnstile/typedefs)
|
|
||||||
|
|
||||||
(define-syntax (Observe★ stx)
|
|
||||||
(define star (type-eval #'★/t))
|
|
||||||
(syntax-parse stx
|
|
||||||
[(_ TyCons:id)
|
|
||||||
#:do [(define arity? (get-type-arity #'TyCons))]
|
|
||||||
#:when arity?
|
|
||||||
(mk-Observe- (list (reassemble-type #'TyCons (make-list (arity-min arity?) star))))]
|
|
||||||
[(_ t)
|
|
||||||
#:with (~Any/new TyCons τ ...) (type-eval #'t)
|
|
||||||
#:when (reassemblable? #'TyCons)
|
|
||||||
(mk-Observe- (list (reassemble-type #'TyCons (stx-map (lambda (_) star) #'(τ ...)))))]
|
|
||||||
[_
|
|
||||||
(raise-syntax-error #f "Not a type that can automatically be subscribed to" stx)]))
|
|
||||||
|
|
||||||
(begin-for-syntax
|
|
||||||
;; Arity -> Nat
|
|
||||||
(define (arity-min a)
|
|
||||||
(match a
|
|
||||||
[(arity-eq n) n]
|
|
||||||
[(arity-ge n) n])))
|
|
||||||
|
|
||||||
(define-for-syntax (RoleNTimes* n Step behav)
|
|
||||||
(let loop ([i 1])
|
|
||||||
(define nm (format-id behav "step~a" i))
|
|
||||||
(quasisyntax/loc behav
|
|
||||||
(Role (#,nm)
|
|
||||||
#,@(if (= i 1)
|
|
||||||
(list #'(Shares Unit))
|
|
||||||
(list))
|
|
||||||
(Reacts #,(if (= i 1)
|
|
||||||
#'(Asserted Unit)
|
|
||||||
#`(Message #,Step))
|
|
||||||
#,@(if (= i n)
|
|
||||||
(list)
|
|
||||||
(list #`(Sends #,Step))))
|
|
||||||
(Reacts (Message #,Step)
|
|
||||||
(Effs #,behav
|
|
||||||
(Stop #,nm
|
|
||||||
#,@(if (< i n)
|
|
||||||
(if (= i 1)
|
|
||||||
(list #`(Sends #,Step) (loop (add1 i)))
|
|
||||||
(list (loop (add1 i))))
|
|
||||||
(list)))))))))
|
|
||||||
|
|
||||||
(define-syntax-parser RoleNTimes
|
|
||||||
[(_ ~! n:nat Step:type behav:type)
|
|
||||||
(RoleNTimes* (syntax-e #'n) #'Step.norm #'behav.norm)])
|
|
|
@ -15,13 +15,6 @@
|
||||||
(define (serialize-syntax stx)
|
(define (serialize-syntax stx)
|
||||||
(define unique-tag (gensym))
|
(define unique-tag (gensym))
|
||||||
(define table (hasheq))
|
(define table (hasheq))
|
||||||
(define dedup-table (hasheq))
|
|
||||||
(define (dedup k f)
|
|
||||||
(if (hash-has-key? dedup-table k)
|
|
||||||
(hash-ref dedup-table k)
|
|
||||||
(let ([res (f)])
|
|
||||||
(set! dedup-table (hash-set dedup-table k res))
|
|
||||||
res)))
|
|
||||||
|
|
||||||
(define (lift! el)
|
(define (lift! el)
|
||||||
(define tag-sym (gensym))
|
(define tag-sym (gensym))
|
||||||
|
@ -41,43 +34,29 @@
|
||||||
(cons k serialized-val))))
|
(cons k serialized-val))))
|
||||||
|
|
||||||
(define (serialize-element! el #:always-lift? [always-lift? #f])
|
(define (serialize-element! el #:always-lift? [always-lift? #f])
|
||||||
(dedup
|
(syntax-map
|
||||||
el
|
el
|
||||||
(lambda ()
|
(lambda (tail? d) d)
|
||||||
(syntax-map
|
(lambda (orig-s d)
|
||||||
el
|
(if (or always-lift?
|
||||||
(lambda (tail? d) d)
|
(ormap (lambda (p) (syntax-property-preserved? orig-s p))
|
||||||
(lambda (orig-s d)
|
(syntax-property-symbol-keys orig-s)))
|
||||||
;(when (and always-lift? (not (ref? (hash-ref dedup-table orig-s)))) ; TODO
|
(lift! (build-props! orig-s d))
|
||||||
;(error 'dedup "lift error"))
|
(datum->syntax orig-s d orig-s #f)))
|
||||||
(dedup
|
syntax-e))
|
||||||
orig-s
|
|
||||||
(lambda ()
|
|
||||||
(if (or always-lift?
|
|
||||||
(ormap (lambda (p) (syntax-property-preserved? orig-s p))
|
|
||||||
(syntax-property-symbol-keys orig-s)))
|
|
||||||
(lift! (build-props! orig-s d))
|
|
||||||
(datum->syntax orig-s d orig-s #f)))))
|
|
||||||
syntax-e))))
|
|
||||||
|
|
||||||
(define top-s (serialize-element! stx))
|
(define top-s (serialize-element! stx))
|
||||||
(define res (datum->syntax #f (serialized-syntax unique-tag table top-s)))
|
(datum->syntax #f (serialized-syntax unique-tag table top-s)))
|
||||||
|
|
||||||
res)
|
|
||||||
|
|
||||||
(define (deserialize-syntax ser)
|
(define (deserialize-syntax ser)
|
||||||
|
;(displayln 'deserialize-in)
|
||||||
|
;(print-syntax-width +inf.0)
|
||||||
|
;(println ser)
|
||||||
|
;(pretty-print (syntax->datum ser))
|
||||||
(match (syntax-e ser)
|
(match (syntax-e ser)
|
||||||
[(serialized-syntax unique-tag-stx table-stx contents)
|
[(serialized-syntax unique-tag-stx table-stx contents)
|
||||||
(define unique-tag (syntax-e unique-tag-stx))
|
(define unique-tag (syntax-e unique-tag-stx))
|
||||||
(define table (syntax-e table-stx))
|
(define table (syntax-e table-stx))
|
||||||
(define dedup-table (hasheq))
|
|
||||||
(define (dedup k f)
|
|
||||||
(if (hash-has-key? dedup-table k)
|
|
||||||
(hash-ref dedup-table k)
|
|
||||||
(let ([res (f)])
|
|
||||||
(set! dedup-table (hash-set dedup-table k res))
|
|
||||||
res)))
|
|
||||||
|
|
||||||
|
|
||||||
(define (maybe-syntax-e v)
|
(define (maybe-syntax-e v)
|
||||||
(if (syntax? v) (syntax-e v) v))
|
(if (syntax? v) (syntax-e v) v))
|
||||||
|
@ -99,26 +78,21 @@
|
||||||
(syntax-property stx k prop-val #t)))
|
(syntax-property stx k prop-val #t)))
|
||||||
|
|
||||||
(define (deserialize-element el)
|
(define (deserialize-element el)
|
||||||
(dedup
|
(syntax-map
|
||||||
el
|
el
|
||||||
(lambda ()
|
(lambda (tail? d)
|
||||||
(syntax-map
|
(match d
|
||||||
el
|
[(ref tag sym)
|
||||||
(lambda (tail? d)
|
#:when (equal? (maybe-syntax-e tag) unique-tag)
|
||||||
(match d
|
(deserialize-stx-with-props (maybe-syntax-e sym))]
|
||||||
[(ref tag sym)
|
[_ d]))
|
||||||
#:when (equal? (maybe-syntax-e tag) unique-tag)
|
(lambda (orig-s d) (datum->syntax orig-s d orig-s #f))
|
||||||
(dedup
|
syntax-e))
|
||||||
sym
|
|
||||||
(lambda () (deserialize-stx-with-props (maybe-syntax-e sym))))]
|
|
||||||
[_ d]))
|
|
||||||
(lambda (orig-s d)
|
|
||||||
(dedup
|
|
||||||
orig-s
|
|
||||||
(lambda () (datum->syntax orig-s d orig-s #f))))
|
|
||||||
syntax-e))))
|
|
||||||
|
|
||||||
(define res (deserialize-element contents))
|
(define res (deserialize-element contents))
|
||||||
|
;(displayln 'deserialize-out)
|
||||||
|
;(println res)
|
||||||
|
;(pretty-print (syntax->datum res))
|
||||||
res]))
|
res]))
|
||||||
|
|
||||||
(module+ test
|
(module+ test
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
(assertion-struct ping : Ping (v))
|
|
||||||
(assertion-struct pong : Pong (v))
|
|
||||||
|
|
||||||
(assertion-struct flip : Flip (v))
|
|
||||||
(assertion-struct flop : Flop (v))
|
|
||||||
|
|
||||||
(define-type-alias Pinger (Ping Int))
|
|
||||||
(define-type-alias Ponger (U (Ping Int)
|
|
||||||
(Pong Int)
|
|
||||||
(Observe (Ping ★/t))))
|
|
||||||
(define-type-alias PingPong (U Pinger Ponger))
|
|
||||||
|
|
||||||
(define-type-alias Flipper (Flip Int))
|
|
||||||
(define-type-alias Flopper (U (Flip Int)
|
|
||||||
(Flop Int)
|
|
||||||
(Observe (Flip ★/t))))
|
|
||||||
(define-type-alias FlipFlop (U Flipper Flopper))
|
|
||||||
|
|
||||||
(run-ground-dataspace (U PingPong FlipFlop)
|
|
||||||
(spawn Pinger (start-facet _ (assert (ping 5))))
|
|
||||||
(spawn Ponger (start-facet _ (during (ping $v) (assert (pong v)))))
|
|
||||||
|
|
||||||
(spawn Flipper (start-facet _ (assert (flip 8))))
|
|
||||||
(spawn Flopper (start-facet _ (during (flip $v) (assert (flop v))))))
|
|
|
@ -1,22 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
|
||||||
|
|
||||||
(define-constructor* (trust lvl))
|
|
||||||
|
|
||||||
(check-type (trust 5) : (TrustT Int))
|
|
||||||
|
|
||||||
(define-constructor* (hungry-hippos count appetite)
|
|
||||||
#:with HungryHippos (HungryHipposT Int String))
|
|
||||||
|
|
||||||
(check-type (hungry-hippos 12 "massive") : HungryHippos)
|
|
||||||
|
|
||||||
(define-constructor* (doggy [color : String] [weight : Int]))
|
|
||||||
|
|
||||||
(check-type (doggy "black" 60) : (DoggyT String Int))
|
|
||||||
(check-type (doggy "brown" 45) : Doggy)
|
|
||||||
|
|
||||||
(define-constructor* (leaf))
|
|
||||||
|
|
||||||
(check-type (leaf) : (LeafT))
|
|
||||||
(check-type (leaf) : Leaf)
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(run-ground-dataspace (U)
|
(run-ground-dataspace (U)
|
||||||
(spawn (U)
|
(spawn (U)
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
(define (∀ (ρ) (assert-something! [p : (proc → ★/t #:effects (ρ))]))
|
(define (∀ (ρ) (assert-something! [p : (proc → ★/t #:endpoints (ρ))]))
|
||||||
(p))
|
(p))
|
||||||
|
|
||||||
(define (test-fun)
|
(define (test-fun)
|
||||||
(call/inst assert-something! (lambda () (assert 5))))
|
(call/inst assert-something! (lambda () (assert 5))))
|
||||||
|
|
||||||
(check-type test-fun : (proc → ★/t #:effects ((Shares NonZero))))
|
|
||||||
|
(check-type test-fun : (proc → ★/t #:endpoints ((Shares Int))))
|
||||||
|
|
||||||
(define (test-call/inst-insertion)
|
(define (test-call/inst-insertion)
|
||||||
(assert-something! (lambda () (assert 5))))
|
(assert-something! (lambda () (assert 5))))
|
||||||
|
|
||||||
(check-type test-call/inst-insertion : (proc → ★/t #:effects ((Shares NonZero))))
|
(check-type test-call/inst-insertion : (proc → ★/t #:endpoints ((Shares Int))))
|
||||||
|
|
||||||
(define (∀ (ρ) (start-something! [p : (proc → ★/t #:effects (ρ))]))
|
|
||||||
(p))
|
|
||||||
|
|
||||||
(define (test-call-start-something)
|
|
||||||
(start-something! (lambda () (start-facet x (assert 5)))))
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
(lambda ()
|
|
||||||
(start-facet x
|
|
||||||
(if #f
|
|
||||||
(assert (tuple 0))
|
|
||||||
(assert (tuple 1)))))
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
: Int
|
: Int
|
||||||
⇒ 0)
|
⇒ 0)
|
||||||
|
|
||||||
(check-type (for/fold ([x : Int 0])
|
(check-type (for/fold ([x 0])
|
||||||
([y (list 1 2 3)])
|
([y (list 1 2 3)])
|
||||||
y)
|
y)
|
||||||
: Int
|
: Int
|
||||||
|
@ -20,13 +20,13 @@
|
||||||
(define inventory0 (list (tuple "The Wind in the Willows" 5)
|
(define inventory0 (list (tuple "The Wind in the Willows" 5)
|
||||||
(tuple "Catch 22" 2)
|
(tuple "Catch 22" 2)
|
||||||
(tuple "Candide" 33)))
|
(tuple "Candide" 33)))
|
||||||
(check-type (for/fold ([stock : Int 0])
|
(check-type (for/fold ([stock 0])
|
||||||
([item inventory0])
|
([item inventory0])
|
||||||
(select 1 item))
|
(select 1 item))
|
||||||
: Int
|
: Int
|
||||||
⇒ 33)
|
⇒ 33)
|
||||||
|
|
||||||
(check-type (for/fold ([stock : Int 0])
|
(check-type (for/fold ([stock 0])
|
||||||
([item inventory0])
|
([item inventory0])
|
||||||
(if (equal? "Catch 22" (select 0 item))
|
(if (equal? "Catch 22" (select 0 item))
|
||||||
(select 1 item)
|
(select 1 item)
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
(define (lookup [title : String]
|
(define (lookup [title : String]
|
||||||
[inv : Inventory] -> Int)
|
[inv : Inventory] -> Int)
|
||||||
(for/fold ([stock : Int 0])
|
(for/fold ([stock 0])
|
||||||
([item inv])
|
([item inv])
|
||||||
(if (equal? title (select 0 item))
|
(if (equal? title (select 0 item))
|
||||||
(select 1 item)
|
(select 1 item)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
#lang typed/syndicate
|
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
|
||||||
|
|
||||||
(typecheck-fail (spawn ⊥
|
|
||||||
(start-facet x
|
|
||||||
(on (asserted $x:Int)
|
|
||||||
#f)))
|
|
||||||
#:with-msg "overly broad interest")
|
|
||||||
|
|
||||||
(typecheck-fail (spawn ⊥
|
|
||||||
(start-facet x
|
|
||||||
(on (asserted (observe $x:Int))
|
|
||||||
#f)))
|
|
||||||
#:with-msg "overly broad interest")
|
|
||||||
|
|
||||||
;; TODO - but this one seems fine?
|
|
||||||
(typecheck-fail (spawn ⊥
|
|
||||||
(start-facet x
|
|
||||||
(on (asserted _)
|
|
||||||
#f)))
|
|
||||||
#:with-msg "overly broad interest")
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang typed/syndicate
|
#lang typed/syndicate/roles
|
||||||
|
|
||||||
(require rackunit/turnstile)
|
(require rackunit/turnstile)
|
||||||
|
|
||||||
|
@ -18,4 +18,4 @@
|
||||||
(on start (call/inst perform-task push-results))))
|
(on start (call/inst perform-task push-results))))
|
||||||
: (List String)
|
: (List String)
|
||||||
-> (list
|
-> (list
|
||||||
"(Role (x) (Reacts OnStart (Role (perform) (Reacts OnStart (Stop perform (Branch (Effs (Role (done) (Shares True))) (Effs)))))))"))
|
"(Role (x) (Reacts OnStart (Role (perform) (Reacts OnStart (Stop perform (Branch (Effs (Role (done) (Shares Bool))) (Effs)))))))"))
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue