2018-07-25 21:26:47 +00:00
|
|
|
|
#lang turnstile
|
|
|
|
|
|
2019-01-25 15:51:46 +00:00
|
|
|
|
(provide #%module-begin
|
2019-05-13 19:35:38 +00:00
|
|
|
|
#%app
|
2019-01-18 19:15:43 +00:00
|
|
|
|
(rename-out [typed-quote quote])
|
2018-07-25 21:26:47 +00:00
|
|
|
|
#%top-interaction
|
2020-11-05 16:09:00 +00:00
|
|
|
|
module+ module*
|
2020-10-23 18:47:27 +00:00
|
|
|
|
;; require & provides
|
|
|
|
|
require only-in prefix-in except-in rename-in
|
|
|
|
|
provide all-defined-out all-from-out rename-out except-out
|
2020-11-06 21:01:48 +00:00
|
|
|
|
for-syntax for-template for-label for-meta struct-out
|
2019-01-25 15:51:46 +00:00
|
|
|
|
;; Start dataspace programs
|
|
|
|
|
run-ground-dataspace
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;; Types
|
2019-05-09 14:23:15 +00:00
|
|
|
|
Tuple Bind Discard → ∀
|
2019-06-13 12:34:34 +00:00
|
|
|
|
Role Reacts Shares Asserted Retracted Message OnDataflow Stop OnStart OnStop
|
2019-06-14 15:43:15 +00:00
|
|
|
|
Know Forget Realize
|
2019-06-07 13:46:02 +00:00
|
|
|
|
Branch Effs
|
2018-10-23 12:36:05 +00:00
|
|
|
|
FacetName Field ★/t
|
2019-05-13 19:35:38 +00:00
|
|
|
|
Observe Inbound Outbound Actor U ⊥
|
2020-09-17 19:11:34 +00:00
|
|
|
|
Computation Value Endpoints Roles Spawns Sends
|
2019-05-23 15:13:51 +00:00
|
|
|
|
→fn proc
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;; Statements
|
2018-08-14 21:02:39 +00:00
|
|
|
|
let let* if spawn dataspace start-facet set! begin stop begin/dataflow #;unsafe-do
|
2019-06-14 15:43:15 +00:00
|
|
|
|
when unless send! realize! define
|
2018-08-01 15:30:25 +00:00
|
|
|
|
;; Derived Forms
|
2019-06-06 17:48:37 +00:00
|
|
|
|
during During
|
2019-05-17 14:37:49 +00:00
|
|
|
|
define/query-value
|
|
|
|
|
define/query-set
|
|
|
|
|
define/query-hash
|
2019-10-03 19:24:31 +00:00
|
|
|
|
define/dataflow
|
2019-06-14 15:43:15 +00:00
|
|
|
|
on-start on-stop
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;; endpoints
|
2019-06-14 15:43:15 +00:00
|
|
|
|
assert know on field
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;; expressions
|
2020-11-30 22:47:53 +00:00
|
|
|
|
tuple select lambda λ ref observe inbound outbound
|
2019-05-23 15:13:51 +00:00
|
|
|
|
Λ inst call/inst
|
2018-08-01 14:35:22 +00:00
|
|
|
|
;; making types
|
2018-10-23 12:35:38 +00:00
|
|
|
|
define-type-alias
|
2019-05-15 19:18:46 +00:00
|
|
|
|
assertion-struct
|
2019-06-14 15:43:15 +00:00
|
|
|
|
message-struct
|
2018-10-23 12:35:38 +00:00
|
|
|
|
define-constructor define-constructor*
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;; values
|
|
|
|
|
#%datum
|
|
|
|
|
;; patterns
|
|
|
|
|
bind discard
|
|
|
|
|
;; primitives
|
2019-04-26 19:33:07 +00:00
|
|
|
|
(all-from-out "prim.rkt")
|
2019-05-13 19:35:38 +00:00
|
|
|
|
;; expressions
|
2020-10-22 20:46:33 +00:00
|
|
|
|
(except-out (all-from-out "core-expressions.rkt") mk-tuple tuple-select)
|
2018-10-23 12:35:38 +00:00
|
|
|
|
;; lists
|
2019-04-26 19:16:08 +00:00
|
|
|
|
(all-from-out "list.rkt")
|
2018-10-23 12:35:38 +00:00
|
|
|
|
;; sets
|
2019-04-26 19:16:08 +00:00
|
|
|
|
(all-from-out "set.rkt")
|
2019-04-29 22:07:23 +00:00
|
|
|
|
;; sequences
|
|
|
|
|
(all-from-out "sequence.rkt")
|
2019-04-30 15:22:40 +00:00
|
|
|
|
;; hash tables
|
|
|
|
|
(all-from-out "hash.rkt")
|
2019-04-30 21:42:03 +00:00
|
|
|
|
;; for loops
|
|
|
|
|
(all-from-out "for-loops.rkt")
|
2019-05-17 14:36:13 +00:00
|
|
|
|
;; utility datatypes
|
|
|
|
|
(all-from-out "maybe.rkt")
|
|
|
|
|
(all-from-out "either.rkt")
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;; DEBUG and utilities
|
2019-06-03 15:15:47 +00:00
|
|
|
|
print-type print-role role-strings
|
2020-10-28 18:06:19 +00:00
|
|
|
|
;; Behavioral Roles
|
2020-12-14 16:50:24 +00:00
|
|
|
|
export-roles export-type check-simulates check-has-simulating-subgraph lift+define-role
|
2021-01-11 16:52:00 +00:00
|
|
|
|
verify-actors
|
|
|
|
|
;; LTL Syntax
|
|
|
|
|
True False Always Eventually Until WeakUntil Implies And Or Not A
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;; Extensions
|
2018-07-31 18:03:15 +00:00
|
|
|
|
match cond
|
2019-01-18 19:15:43 +00:00
|
|
|
|
submod for-syntax for-meta only-in except-in
|
2019-01-03 19:01:09 +00:00
|
|
|
|
require/typed
|
2019-01-03 17:06:14 +00:00
|
|
|
|
require-struct
|
2018-07-25 21:26:47 +00:00
|
|
|
|
)
|
2019-04-26 19:16:08 +00:00
|
|
|
|
(require "core-types.rkt")
|
2019-05-13 19:35:38 +00:00
|
|
|
|
(require "core-expressions.rkt")
|
2019-04-26 19:16:08 +00:00
|
|
|
|
(require "list.rkt")
|
|
|
|
|
(require "set.rkt")
|
2019-04-26 19:33:07 +00:00
|
|
|
|
(require "prim.rkt")
|
2019-04-29 22:07:23 +00:00
|
|
|
|
(require "sequence.rkt")
|
2019-04-30 15:22:40 +00:00
|
|
|
|
(require "hash.rkt")
|
2019-04-30 21:42:03 +00:00
|
|
|
|
(require "for-loops.rkt")
|
2019-05-17 14:36:13 +00:00
|
|
|
|
(require "maybe.rkt")
|
|
|
|
|
(require "either.rkt")
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
|
|
|
|
(require (prefix-in syndicate: syndicate/actor-lang))
|
2019-05-24 19:06:55 +00:00
|
|
|
|
(require (submod syndicate/actor priorities))
|
2020-12-14 19:22:32 +00:00
|
|
|
|
(require (prefix-in syndicate: (submod syndicate/actor for-module-begin)))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
2019-04-26 18:15:34 +00:00
|
|
|
|
(require (for-meta 2 macrotypes/stx-utils racket/list syntax/stx syntax/parse racket/base))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(require macrotypes/postfix-in)
|
2019-05-24 15:12:06 +00:00
|
|
|
|
(require (for-syntax turnstile/mode))
|
2020-09-17 19:11:34 +00:00
|
|
|
|
(require turnstile/typedefs)
|
2018-10-23 12:35:38 +00:00
|
|
|
|
(require (postfix-in - racket/list))
|
|
|
|
|
(require (postfix-in - racket/set))
|
2019-01-03 17:06:14 +00:00
|
|
|
|
|
2020-10-28 18:06:19 +00:00
|
|
|
|
(require (for-syntax (prefix-in proto: "proto.rkt")
|
2021-01-11 16:52:00 +00:00
|
|
|
|
(prefix-in proto: "ltl.rkt")
|
2020-12-14 16:50:24 +00:00
|
|
|
|
syntax/id-table)
|
2021-01-11 16:52:00 +00:00
|
|
|
|
(prefix-in proto: "proto.rkt")
|
|
|
|
|
(prefix-in proto: "compile-spin.rkt"))
|
2020-10-28 18:06:19 +00:00
|
|
|
|
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(module+ test
|
|
|
|
|
(require rackunit)
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(require rackunit/turnstile))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
2019-05-15 19:18:46 +00:00
|
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
;; Creating Communication Types
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
|
|
(define-simple-macro (assertion-struct name:id (~datum :) Name:id (slot:id ...))
|
|
|
|
|
(define-constructor* (name : Name slot ...)))
|
|
|
|
|
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(define-simple-macro (message-struct name:id (~datum :) Name:id (slot:id ...))
|
|
|
|
|
(define-constructor* (name : Name slot ...)))
|
|
|
|
|
|
2019-05-24 15:12:06 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
;; 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))))
|
|
|
|
|
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
;; Core forms
|
2018-08-08 19:20:09 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
2020-11-30 22:47:53 +00:00
|
|
|
|
(define-typed-syntax start-facet
|
2020-12-01 22:31:15 +00:00
|
|
|
|
[(_ name:id #:implements ~! spec:type ep ...+) ≫
|
2020-11-30 22:47:53 +00:00
|
|
|
|
[⊢ (start-facet name ep ...) ≫ e- (⇒ ν-f (~effs impl-ty))]
|
|
|
|
|
#:fail-unless (simulating-types? #'impl-ty #'spec.norm)
|
|
|
|
|
"facet does not implement specification"
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
[≻ e-]]
|
2020-12-01 22:31:15 +00:00
|
|
|
|
[(_ name:id #:includes-behavior ~! spec:type ep ...+) ≫
|
2020-11-30 22:47:53 +00:00
|
|
|
|
[⊢ (start-facet name ep ...) ≫ e- (⇒ ν-f (~effs impl-ty))]
|
|
|
|
|
#:fail-unless (type-has-simulating-subgraphs? #'impl-ty #'spec.norm)
|
|
|
|
|
"no subset implements specified behavior"
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
[≻ e-]]
|
|
|
|
|
[(_ name:id ep ...+) ≫
|
2018-08-08 19:20:09 +00:00
|
|
|
|
#: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))
|
2019-05-29 15:28:46 +00:00
|
|
|
|
(define name-- (add-orig (internal-definition-context-introduce ctx #'name- 'add)
|
|
|
|
|
#'name))
|
2018-08-10 01:42:20 +00:00
|
|
|
|
(int-def-ctx-bind-type-rename #'name+ #'name- #'facet-name-ty ctx)
|
2018-08-10 02:06:08 +00:00
|
|
|
|
(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"))]
|
2018-08-08 19:20:09 +00:00
|
|
|
|
#:with ((~or (~and τ-a (~Shares _))
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(~and τ-k (~Know _))
|
2018-09-12 21:03:19 +00:00
|
|
|
|
;; untyped syndicate might allow this - TODO
|
|
|
|
|
#;(~and τ-m (~Sends _))
|
2020-09-17 19:11:34 +00:00
|
|
|
|
(~and τ-r (~Reacts _ _ ...))
|
2018-08-10 02:06:08 +00:00
|
|
|
|
~MakesField)
|
2018-08-08 19:20:09 +00:00
|
|
|
|
...)
|
2018-08-10 02:06:08 +00:00
|
|
|
|
ep-effects
|
2018-08-08 19:20:09 +00:00
|
|
|
|
#:with τ (type-eval #`(Role (#,name--)
|
|
|
|
|
τ-a ...
|
2019-06-14 15:43:15 +00:00
|
|
|
|
τ-k ...
|
2018-09-12 21:03:19 +00:00
|
|
|
|
;; τ-m ...
|
2018-08-08 19:20:09 +00:00
|
|
|
|
τ-r ...))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
--------------------------------------------------------------
|
2019-05-13 19:35:38 +00:00
|
|
|
|
[⊢ (syndicate:react (let- ([#,name-- (#%app- syndicate:current-facet-id)])
|
2018-08-10 02:06:08 +00:00
|
|
|
|
#,@ep-...))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(⇒ : ★/t)
|
2020-11-30 22:47:53 +00:00
|
|
|
|
(⇒ ν-f (τ))]])
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
2020-10-23 18:51:07 +00:00
|
|
|
|
(define-typed-syntax field
|
|
|
|
|
[(_ [x:id τ-f:type e:expr] ...) ≫
|
|
|
|
|
#:cut
|
|
|
|
|
#: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))]]
|
|
|
|
|
[(_ flds ... [x:id e:expr] more-flds ...) ≫
|
|
|
|
|
#:cut
|
|
|
|
|
[⊢ e ≫ e- (⇒ : τ)]
|
|
|
|
|
--------------------
|
|
|
|
|
[≻ (field flds ... [x τ e-] more-flds ...)]])
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
|
|
|
|
(define-typed-syntax (assert e:expr) ≫
|
2018-07-27 15:37:22 +00:00
|
|
|
|
[⊢ e ≫ e- (⇒ : τ)]
|
|
|
|
|
#:fail-unless (pure? #'e-) "expression not allowed to have effects"
|
2019-05-31 14:01:36 +00:00
|
|
|
|
#:with τs (mk-Shares- #'(τ))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
-------------------------------------
|
|
|
|
|
[⊢ (syndicate:assert e-) (⇒ : ★/t)
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-ep (τs))])
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(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))])
|
|
|
|
|
|
2018-09-12 21:03:19 +00:00
|
|
|
|
(define-typed-syntax (send! e:expr) ≫
|
|
|
|
|
[⊢ e ≫ e- (⇒ : τ)]
|
|
|
|
|
#:fail-unless (pure? #'e-) "expression not allowed to have effects"
|
2019-05-31 14:01:36 +00:00
|
|
|
|
#:with τm (mk-Sends- #'(τ))
|
2018-09-12 21:03:19 +00:00
|
|
|
|
--------------------------------------
|
2019-05-31 14:01:36 +00:00
|
|
|
|
[⊢ (#%app- syndicate:send! e-) (⇒ : ★/t)
|
|
|
|
|
(⇒ ν-f (τm))])
|
2018-09-12 21:03:19 +00:00
|
|
|
|
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(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))])
|
|
|
|
|
|
2018-07-31 18:03:15 +00:00
|
|
|
|
(define-typed-syntax (stop facet-name:id cont ...) ≫
|
2018-07-30 18:01:56 +00:00
|
|
|
|
[⊢ facet-name ≫ facet-name- (⇐ : FacetName)]
|
2020-08-17 15:24:06 +00:00
|
|
|
|
[⊢ (block #f cont ...) ≫ cont-
|
2020-05-29 15:15:07 +00:00
|
|
|
|
(⇒ ν-ep (~effs))
|
|
|
|
|
(⇒ ν-s (~effs))
|
|
|
|
|
(⇒ ν-f (~effs τ-f ...))]
|
2020-09-17 19:11:34 +00:00
|
|
|
|
#:with τ #'(Stop facet-name- τ-f ...)
|
2018-07-30 18:01:56 +00:00
|
|
|
|
---------------------------------------------------------------------------------
|
|
|
|
|
[⊢ (syndicate:stop-facet facet-name- cont-) (⇒ : ★/t)
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-f (τ))])
|
2018-07-30 18:01:56 +00:00
|
|
|
|
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(begin-for-syntax
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(define-syntax-class event-cons
|
|
|
|
|
#:attributes (syndicate-kw ty-cons)
|
|
|
|
|
#:datum-literals (asserted retracted message know forget realize)
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(pattern (~or (~and asserted
|
|
|
|
|
(~bind [syndicate-kw #'syndicate:asserted]
|
2019-06-14 15:43:15 +00:00
|
|
|
|
[ty-cons #'Asserted]))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(~and retracted
|
|
|
|
|
(~bind [syndicate-kw #'syndicate:retracted]
|
2019-06-14 15:43:15 +00:00
|
|
|
|
[ty-cons #'Retracted]))
|
2018-09-12 21:03:19 +00:00
|
|
|
|
(~and message
|
|
|
|
|
(~bind [syndicate-kw #'syndicate:message]
|
2019-06-14 15:43:15 +00:00
|
|
|
|
[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])))))
|
2019-05-24 19:06:55 +00:00
|
|
|
|
(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*))
|
|
|
|
|
)
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
|
|
|
|
(define-typed-syntax on
|
2019-06-14 15:43:15 +00:00
|
|
|
|
#:datum-literals (start stop)
|
|
|
|
|
[(on start s ...) ≫
|
2020-08-17 15:24:06 +00:00
|
|
|
|
[⊢ (block s ...) ≫ s- (⇒ ν-ep (~effs))
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-f (~effs τ-f ...))
|
|
|
|
|
(⇒ ν-s (~effs τ-s ...))]
|
2018-08-08 19:20:09 +00:00
|
|
|
|
#:with τ-r (type-eval #'(Reacts OnStart τ-f ... τ-s ...))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
-----------------------------------
|
2018-07-31 19:51:20 +00:00
|
|
|
|
[⊢ (syndicate:on-start s-) (⇒ : ★/t)
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-ep (τ-r))]]
|
2019-06-14 15:43:15 +00:00
|
|
|
|
[(on stop s ...) ≫
|
2020-08-17 15:24:06 +00:00
|
|
|
|
[⊢ (block s ...) ≫ s- (⇒ ν-ep (~effs))
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-f (~effs τ-f ...))
|
|
|
|
|
(⇒ ν-s (~effs τ-s ...))]
|
2018-08-08 19:20:09 +00:00
|
|
|
|
#:with τ-r (type-eval #'(Reacts OnStop τ-f ... τ-s ...))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
-----------------------------------
|
2018-07-31 19:51:20 +00:00
|
|
|
|
[⊢ (syndicate:on-stop s-) (⇒ : ★/t)
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-ep (τ-r))]]
|
2019-06-14 15:43:15 +00:00
|
|
|
|
[(on (evt:event-cons p)
|
2019-05-24 19:06:55 +00:00
|
|
|
|
priority:priority
|
|
|
|
|
s ...) ≫
|
2019-06-14 15:43:15 +00:00
|
|
|
|
#:do [(define msg? (free-identifier=? #'syndicate:message (attribute evt.syndicate-kw)))
|
2019-05-31 14:01:36 +00:00
|
|
|
|
(define elab
|
|
|
|
|
(elaborate-pattern/with-com-ty (if msg? #'(message p) #'p)))]
|
|
|
|
|
#:with p/e (if msg? (stx-cadr elab) elab)
|
2019-05-24 14:05:23 +00:00
|
|
|
|
[⊢ p/e ≫ p-- (⇒ : τp)]
|
2018-07-27 15:37:22 +00:00
|
|
|
|
#:fail-unless (pure? #'p--) "pattern not allowed to have effects"
|
2019-05-24 14:05:23 +00:00
|
|
|
|
#:with ([x:id τ:type] ...) (pat-bindings #'p/e)
|
2020-08-17 15:24:06 +00:00
|
|
|
|
[[x ≫ x- : τ] ... ⊢ (block s ...) ≫ s-
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-ep (~effs))
|
|
|
|
|
(⇒ ν-f (~effs τ-f ...))
|
|
|
|
|
(⇒ ν-s (~effs τ-s ...))]
|
2019-05-24 14:05:23 +00:00
|
|
|
|
#:with p- (substs #'(x- ...) #'(x ...) (compile-syndicate-pattern #'p/e))
|
2019-06-14 15:43:15 +00:00
|
|
|
|
#:with τ-r (type-eval #'(Reacts (evt.ty-cons τp) τ-f ... τ-s ...))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
-----------------------------------
|
2019-06-14 15:43:15 +00:00
|
|
|
|
[⊢ (syndicate:on (evt.syndicate-kw p-)
|
2019-05-24 19:06:55 +00:00
|
|
|
|
#:priority priority.level
|
2018-07-31 18:46:24 +00:00
|
|
|
|
s-)
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(⇒ : ★/t)
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-ep (τ-r))]])
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
2018-08-14 21:02:39 +00:00
|
|
|
|
(define-typed-syntax (begin/dataflow s ...+) ≫
|
2020-08-17 15:24:06 +00:00
|
|
|
|
[⊢ (block s ...) ≫ s-
|
2018-08-14 21:02:39 +00:00
|
|
|
|
(⇒ : _)
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-ep (~effs))
|
|
|
|
|
(⇒ ν-f (~effs τ-f ...))
|
|
|
|
|
(⇒ ν-s (~effs τ-s ...))]
|
2018-08-14 21:02:39 +00:00
|
|
|
|
#:with τ-r (type-eval #'(Reacts OnDataflow τ-f ... τ-s ...))
|
|
|
|
|
--------------------------------------------------
|
|
|
|
|
[⊢ (syndicate:begin/dataflow s-)
|
|
|
|
|
(⇒ : ★/t)
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-ep (τ-r))])
|
2018-08-14 21:02:39 +00:00
|
|
|
|
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(define-for-syntax (compile-syndicate-pattern pat)
|
|
|
|
|
(compile-pattern pat
|
2018-08-01 15:30:25 +00:00
|
|
|
|
#'list-
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(lambda (id) #`($ #,id))
|
|
|
|
|
identity))
|
|
|
|
|
|
2019-05-24 15:12:06 +00:00
|
|
|
|
(define-typed-syntax spawn
|
2020-03-05 15:37:50 +00:00
|
|
|
|
;; TODO - do the lack of #:cut-s cause bad error messages here?
|
2019-05-24 15:12:06 +00:00
|
|
|
|
[(spawn τ-c:type s) ≫
|
2018-07-25 21:26:47 +00:00
|
|
|
|
#:fail-unless (flat-type? #'τ-c.norm) "Communication type must be first-order"
|
2018-07-30 18:01:56 +00:00
|
|
|
|
;; TODO: check that each τ-f is a Role
|
2019-05-24 15:12:06 +00:00
|
|
|
|
#:mode (communication-type-mode #'τ-c.norm)
|
|
|
|
|
[
|
2020-08-17 15:24:06 +00:00
|
|
|
|
[⊢ (block s) ≫ s- (⇒ ν-ep (~effs)) (⇒ ν-s (~effs)) (⇒ ν-f (~effs τ-f ...))]
|
2019-05-24 15:12:06 +00:00
|
|
|
|
]
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;; TODO: s shouldn't refer to facets or fields!
|
2020-11-30 22:47:53 +00:00
|
|
|
|
#:fail-unless (and (stx-andmap Role? #'(τ-f ...))
|
|
|
|
|
(= 1 (length (syntax->list #'(τ-f ...)))))
|
|
|
|
|
"expected exactly one Role for body"
|
2019-06-14 15:43:15 +00:00
|
|
|
|
#:with (τ-i τ-o τ-i/i τ-o/i τ-a) (analyze-roles #'(τ-f ...))
|
2018-07-27 21:16:44 +00:00
|
|
|
|
#:fail-unless (<: #'τ-o #'τ-c.norm)
|
|
|
|
|
(format "Output ~a not valid in dataspace ~a" (type->str #'τ-o) (type->str #'τ-c.norm))
|
2020-11-30 22:47:53 +00:00
|
|
|
|
#:with τ-final #;(mk-Actor- #'(τ-c.norm)) (mk-ActorWithRole- #'(τ-c.norm τ-f ...))
|
2019-05-31 14:01:36 +00:00
|
|
|
|
#:fail-unless (<: #'τ-a #'τ-final)
|
2018-07-31 19:51:20 +00:00
|
|
|
|
"Spawned actors not valid in dataspace"
|
2018-07-27 21:16:44 +00:00
|
|
|
|
#:fail-unless (project-safe? (∩ (strip-? #'τ-o) #'τ-c.norm)
|
|
|
|
|
#'τ-i)
|
2020-02-25 21:14:30 +00:00
|
|
|
|
(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))
|
2018-07-25 21:26:47 +00:00
|
|
|
|
--------------------------------------------------------------------------------------------
|
2018-07-27 15:37:22 +00:00
|
|
|
|
[⊢ (syndicate:spawn (syndicate:on-start s-)) (⇒ : ★/t)
|
2019-05-24 15:12:06 +00:00
|
|
|
|
(⇒ ν-s (τ-final))]]
|
|
|
|
|
[(spawn s) ≫
|
|
|
|
|
#:do [(define τc (current-communication-type))]
|
|
|
|
|
#:when τc
|
|
|
|
|
----------------------------------------
|
|
|
|
|
[≻ (spawn #,τc s)]])
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
2020-02-25 21:14:30 +00:00
|
|
|
|
;; 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)])])))
|
|
|
|
|
|
2018-07-30 15:54:05 +00:00
|
|
|
|
(define-typed-syntax (dataspace τ-c:type s ...) ≫
|
|
|
|
|
#:fail-unless (flat-type? #'τ-c.norm) "Communication type must be first-order"
|
2019-05-24 15:12:06 +00:00
|
|
|
|
#:mode (communication-type-mode #'τ-c.norm)
|
|
|
|
|
[
|
|
|
|
|
[⊢ s ≫ s- (⇒ ν-ep (~effs)) (⇒ ν-s (~effs τ-s ...)) (⇒ ν-f (~effs))] ...
|
|
|
|
|
]
|
2019-05-31 14:01:36 +00:00
|
|
|
|
#:with τ-actor (mk-Actor- #'(τ-c.norm))
|
2018-07-30 15:54:05 +00:00
|
|
|
|
#: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)
|
2018-11-19 22:42:08 +00:00
|
|
|
|
(⇒ ν-s ((Actor (U τ-ds-i τ-ds-o τ-relay))))])
|
2018-07-30 15:54:05 +00:00
|
|
|
|
|
2018-07-25 21:26:47 +00:00
|
|
|
|
(define-typed-syntax (set! x:id e:expr) ≫
|
2018-07-27 15:37:22 +00:00
|
|
|
|
[⊢ e ≫ e- (⇒ : τ)]
|
|
|
|
|
#:fail-unless (pure? #'e-) "expression not allowed to have effects"
|
2018-07-25 21:26:47 +00:00
|
|
|
|
[⊢ x ≫ x- (⇒ : (~Field τ-x:type))]
|
|
|
|
|
#:fail-unless (<: #'τ #'τ-x) "Ill-typed field write"
|
|
|
|
|
----------------------------------------------------
|
2019-05-13 19:35:38 +00:00
|
|
|
|
[⊢ (#%app- x- e-) (⇒ : ★/t)])
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
2018-08-01 15:30:25 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
;; Derived Forms
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(define-typed-syntax during
|
|
|
|
|
#:literals (know)
|
|
|
|
|
[(_ (~or (~and k (know p)) p) s ...) ≫
|
2019-05-24 15:12:06 +00:00
|
|
|
|
#:with p+ (elaborate-pattern/with-com-ty #'p)
|
2019-05-24 14:05:23 +00:00
|
|
|
|
#:with inst-p (instantiate-pattern #'p+)
|
2019-06-14 15:43:15 +00:00
|
|
|
|
#: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 ...))
|
2018-08-01 15:30:25 +00:00
|
|
|
|
----------------------------------------
|
2019-06-14 15:43:15 +00:00
|
|
|
|
[≻ (on (start-e p+)
|
2018-08-01 15:30:25 +00:00
|
|
|
|
(start-facet during-inner
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(on (stop-e inst-p)
|
2018-08-01 15:30:25 +00:00
|
|
|
|
(stop during-inner))
|
2019-06-14 15:43:15 +00:00
|
|
|
|
s ...))]])
|
2018-08-01 15:30:25 +00:00
|
|
|
|
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(define-simple-macro (During (~or (~and K ((~literal Know) τ:type)) τ:type)
|
|
|
|
|
EP ...)
|
2019-06-06 17:48:37 +00:00
|
|
|
|
#:with τ/inst (instantiate-pattern-type #'τ.norm)
|
2019-06-14 15:43:15 +00:00
|
|
|
|
#:with start-e (if (attribute K) #'Know #'Asserted)
|
|
|
|
|
#:with stop-e (if (attribute K) #'Forget #'Retracted)
|
|
|
|
|
(Reacts (start-e τ)
|
2019-06-06 17:48:37 +00:00
|
|
|
|
(Role (during-inner)
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(Reacts (stop-e τ/inst)
|
2019-06-06 17:48:37 +00:00
|
|
|
|
(Stop during-inner))
|
|
|
|
|
EP ...)))
|
|
|
|
|
|
2018-08-01 15:30:25 +00:00
|
|
|
|
;; 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]
|
2018-08-13 23:32:23 +00:00
|
|
|
|
;; not sure about this
|
2018-08-01 15:30:25 +00:00
|
|
|
|
[discard
|
2018-08-13 23:32:23 +00:00
|
|
|
|
#'discard]
|
2018-08-01 15:30:25 +00:00
|
|
|
|
[(~constructor-exp ctor p ...)
|
|
|
|
|
(define/with-syntax uctor (untyped-ctor #'ctor))
|
|
|
|
|
#`(ctor #,@(stx-map loop #'(p ...)))]
|
|
|
|
|
[_
|
|
|
|
|
pat])))
|
|
|
|
|
|
2019-06-06 17:48:37 +00:00
|
|
|
|
;; 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 #'(τ ...)))]
|
2020-09-17 19:11:34 +00:00
|
|
|
|
[(~Any/new τ-cons τ ...)
|
2019-06-06 17:48:37 +00:00
|
|
|
|
#:when (reassemblable? #'τ-cons)
|
|
|
|
|
(define subitems (for/list ([t (in-syntax #'(τ ...))])
|
|
|
|
|
(instantiate-pattern-type t)))
|
|
|
|
|
(reassemble-type #'τ-cons subitems)]
|
|
|
|
|
[_ ty]))
|
|
|
|
|
|
2019-05-24 19:06:55 +00:00
|
|
|
|
(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)) ≫
|
2018-08-14 19:43:51 +00:00
|
|
|
|
[⊢ e0 ≫ e0- (⇒ : τ)]
|
|
|
|
|
#:fail-unless (pure? #'e0-) "expression must be pure"
|
|
|
|
|
----------------------------------------
|
|
|
|
|
[≻ (begin (field [x τ e0-])
|
|
|
|
|
(on (asserted p)
|
2019-05-24 19:06:55 +00:00
|
|
|
|
#:priority *query-priority*
|
|
|
|
|
(set! x e)
|
|
|
|
|
add.expr)
|
2018-08-14 19:43:51 +00:00
|
|
|
|
(on (retracted p)
|
2019-05-24 19:06:55 +00:00
|
|
|
|
#:priority *query-priority-high*
|
|
|
|
|
(set! x e0-)
|
|
|
|
|
remove.expr))])
|
2018-08-14 19:43:51 +00:00
|
|
|
|
|
2019-05-24 19:06:55 +00:00
|
|
|
|
(define-typed-syntax (define/query-set x:id p e
|
|
|
|
|
(~optional add:on-add)
|
|
|
|
|
(~optional remove:on-remove)) ≫
|
2019-05-24 15:12:06 +00:00
|
|
|
|
#:with p+ (elaborate-pattern/with-com-ty #'p)
|
2019-05-24 14:05:23 +00:00
|
|
|
|
#:with ([y τ] ...) (pat-bindings #'p+)
|
2018-08-14 20:35:39 +00:00
|
|
|
|
;; e will be re-expanded :/
|
|
|
|
|
[[y ≫ y- : τ] ... ⊢ e ≫ e- ⇒ τ-e]
|
|
|
|
|
----------------------------------------
|
|
|
|
|
[≻ (begin (field [x (Set τ-e) (set)])
|
2019-05-24 14:05:23 +00:00
|
|
|
|
(on (asserted p+)
|
2019-05-24 19:06:55 +00:00
|
|
|
|
#:priority *query-priority*
|
|
|
|
|
(set! x (set-add (ref x) e))
|
|
|
|
|
add.expr)
|
2019-05-24 14:05:23 +00:00
|
|
|
|
(on (retracted p+)
|
2019-05-24 19:06:55 +00:00
|
|
|
|
#:priority *query-priority-high*
|
|
|
|
|
(set! x (set-remove (ref x) e))
|
|
|
|
|
remove.expr))])
|
2018-08-14 20:35:39 +00:00
|
|
|
|
|
2019-05-24 19:06:55 +00:00
|
|
|
|
(define-typed-syntax (define/query-hash x:id p e-key e-value
|
|
|
|
|
(~optional add:on-add)
|
|
|
|
|
(~optional remove:on-remove)) ≫
|
2019-05-24 15:12:06 +00:00
|
|
|
|
#:with p+ (elaborate-pattern/with-com-ty #'p)
|
2019-05-24 14:05:23 +00:00
|
|
|
|
#:with ([y τ] ...) (pat-bindings #'p+)
|
2019-05-17 14:37:49 +00:00
|
|
|
|
;; 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)])
|
2019-05-24 14:05:23 +00:00
|
|
|
|
(on (asserted p+)
|
2019-05-24 19:06:55 +00:00
|
|
|
|
#:priority *query-priority*
|
|
|
|
|
(set! x (hash-set (ref x) e-key e-value))
|
|
|
|
|
add.expr)
|
2019-05-24 14:05:23 +00:00
|
|
|
|
(on (retracted p+)
|
2019-05-24 19:06:55 +00:00
|
|
|
|
#:priority *query-priority-high*
|
|
|
|
|
(set! x (hash-remove (ref x) e-key))
|
|
|
|
|
remove.expr))])
|
2019-05-17 14:37:49 +00:00
|
|
|
|
|
2019-06-14 15:43:15 +00:00
|
|
|
|
(define-simple-macro (on-start e ...)
|
|
|
|
|
(on start e ...))
|
|
|
|
|
|
|
|
|
|
(define-simple-macro (on-stop e ...)
|
|
|
|
|
(on stop e ...))
|
|
|
|
|
|
2019-10-03 19:24:31 +00:00
|
|
|
|
(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-)]])
|
|
|
|
|
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
;; Expressions
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
|
|
(define-typed-syntax (ref x:id) ≫
|
|
|
|
|
[⊢ x ≫ x- ⇒ (~Field τ)]
|
|
|
|
|
------------------------
|
2019-05-13 19:35:38 +00:00
|
|
|
|
[⊢ (#%app- x-) (⇒ : τ)])
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2019-01-25 15:51:46 +00:00
|
|
|
|
;; 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 ...) ≫
|
2020-08-17 15:24:06 +00:00
|
|
|
|
;;#: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)]
|
|
|
|
|
]
|
2020-10-22 20:46:48 +00:00
|
|
|
|
#:with τ-out (strip-outbound #'τ-c.norm)
|
2019-01-25 15:51:46 +00:00
|
|
|
|
-----------------------------------------------------------------------------------
|
2020-12-14 19:22:32 +00:00
|
|
|
|
[⊢ (#%app- syndicate:run-ground (#%app- syndicate:capture-actor-actions (lambda- () (#%app- list- s- ...))))
|
|
|
|
|
(⇒ : (AssertionSet τ-out))])
|
2019-01-25 15:51:46 +00:00
|
|
|
|
|
2018-07-25 21:26:47 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
;; Utilities
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
|
|
(define-typed-syntax (print-type e) ≫
|
2018-11-19 22:42:08 +00:00
|
|
|
|
[⊢ e ≫ e- (⇒ : τ) (⇒ ν-ep (~effs eps ...)) (⇒ ν-f (~effs fs ...)) (⇒ ν-s (~effs ss ...))]
|
2019-06-06 17:48:37 +00:00
|
|
|
|
#:do [(pretty-display (type->strX #'τ))]
|
2018-07-25 21:26:47 +00:00
|
|
|
|
----------------------------------
|
2018-11-19 22:42:08 +00:00
|
|
|
|
[⊢ e- (⇒ : τ) (⇒ ν-ep (eps ...)) (⇒ ν-f (fs ...)) (⇒ ν-s (ss ...))])
|
2018-07-25 21:26:47 +00:00
|
|
|
|
|
|
|
|
|
(define-typed-syntax (print-role e) ≫
|
2018-11-19 22:42:08 +00:00
|
|
|
|
[⊢ e ≫ e- (⇒ : τ) (⇒ ν-ep (~effs eps ...)) (⇒ ν-f (~effs fs ...)) (⇒ ν-s (~effs ss ...))]
|
2018-08-08 19:20:09 +00:00
|
|
|
|
#:do [(for ([r (in-syntax #'(fs ...))])
|
2019-05-29 15:28:46 +00:00
|
|
|
|
(pretty-display (type->strX r)))]
|
2018-07-25 21:26:47 +00:00
|
|
|
|
----------------------------------
|
2018-11-19 22:42:08 +00:00
|
|
|
|
[⊢ e- (⇒ : τ) (⇒ ν-ep (eps ...)) (⇒ ν-f (fs ...)) (⇒ ν-s (ss ...))])
|
2018-07-27 21:16:44 +00:00
|
|
|
|
|
2019-06-03 15:15:47 +00:00
|
|
|
|
;; 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))])
|
|
|
|
|
|
2021-01-11 16:52:00 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
;; LTL Syntax
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
|
|
(define-type LTL : LTL)
|
|
|
|
|
|
|
|
|
|
(define-type True : LTL)
|
|
|
|
|
(define-type False : LTL)
|
|
|
|
|
(define-type Always : LTL -> LTL)
|
|
|
|
|
(define-type Eventually : LTL -> LTL)
|
|
|
|
|
(define-type Until : LTL LTL -> LTL)
|
|
|
|
|
(define-type WeakUntil : LTL LTL -> LTL)
|
|
|
|
|
(define-type Implies : LTL LTL -> LTL)
|
|
|
|
|
(define-type And : LTL * -> LTL)
|
|
|
|
|
(define-type Or : LTL * -> LTL)
|
|
|
|
|
(define-type Not : LTL -> LTL)
|
|
|
|
|
(define-type A : Type -> LTL)
|
|
|
|
|
|
2020-10-28 18:06:19 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
;; Behavioral Analysis
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
|
|
(begin-for-syntax
|
|
|
|
|
|
|
|
|
|
(define ID-PHASE 0)
|
|
|
|
|
|
|
|
|
|
(define-syntax (build-id-table stx)
|
|
|
|
|
(syntax-parse stx
|
|
|
|
|
[(_ (~seq key val) ...)
|
|
|
|
|
#'(make-free-id-table (hash (~@ #'key val) ...) #:phase ID-PHASE)]))
|
|
|
|
|
|
2020-11-09 19:43:42 +00:00
|
|
|
|
(define (mk-proto:U . args)
|
|
|
|
|
(proto:U args))
|
|
|
|
|
(define (mk-proto:Branch . args)
|
|
|
|
|
(proto:Branch args))
|
|
|
|
|
|
2020-10-28 18:06:19 +00:00
|
|
|
|
(define TRANSLATION#
|
|
|
|
|
(build-id-table Spawns proto:Spawn
|
|
|
|
|
Sends proto:Sends
|
|
|
|
|
Realizes proto:Realizes
|
|
|
|
|
Shares proto:Shares
|
|
|
|
|
Know proto:Know
|
2020-11-09 19:43:42 +00:00
|
|
|
|
Branch mk-proto:Branch
|
|
|
|
|
Effs list
|
2020-10-28 18:06:19 +00:00
|
|
|
|
Asserted proto:Asserted
|
|
|
|
|
Retracted proto:Retracted
|
|
|
|
|
Message proto:Message
|
|
|
|
|
Forget proto:Forget
|
|
|
|
|
Realize proto:Realize
|
2020-11-09 19:43:42 +00:00
|
|
|
|
U* mk-proto:U
|
2020-10-28 18:06:19 +00:00
|
|
|
|
Observe proto:Observe
|
|
|
|
|
List proto:List
|
|
|
|
|
Set proto:Set
|
2020-11-30 22:47:53 +00:00
|
|
|
|
Hash proto:Hash
|
|
|
|
|
OnStart proto:StartEvt
|
|
|
|
|
OnStop proto:StopEvt
|
2021-01-11 16:52:00 +00:00
|
|
|
|
OnDataflow proto:DataflowEvt
|
|
|
|
|
;; LTL
|
|
|
|
|
True #t
|
|
|
|
|
False #f
|
|
|
|
|
Always proto:always
|
|
|
|
|
Eventually proto:eventually
|
|
|
|
|
Until proto:strong-until
|
|
|
|
|
WeakUntil proto:weak-until
|
|
|
|
|
Implies proto:ltl-implies
|
|
|
|
|
And proto:&&
|
|
|
|
|
Or proto:||
|
|
|
|
|
Not proto:ltl-not
|
|
|
|
|
A proto:atomic))
|
2020-10-28 18:06:19 +00:00
|
|
|
|
|
|
|
|
|
(define (double-check)
|
|
|
|
|
(for/first ([id (in-dict-keys TRANSLATION#)]
|
|
|
|
|
#:when (false? (identifier-binding id)))
|
|
|
|
|
(pretty-print id)
|
|
|
|
|
(pretty-print (syntax-debug-info id))))
|
|
|
|
|
|
|
|
|
|
(define (synd->proto ty)
|
|
|
|
|
(let convert ([ty (resugar-type ty)])
|
|
|
|
|
(syntax-parse ty
|
2020-11-30 22:47:53 +00:00
|
|
|
|
#:literals (★/t Bind Discard ∀/internal →/internal Role/internal Stop Reacts Actor ActorWithRole)
|
2020-10-28 18:06:19 +00:00
|
|
|
|
[(ctor:id t ...)
|
|
|
|
|
#:when (dict-has-key? TRANSLATION# #'ctor)
|
|
|
|
|
(apply (dict-ref TRANSLATION# #'ctor) (stx-map convert #'(t ...)))]
|
2020-11-30 22:47:53 +00:00
|
|
|
|
[nm:id
|
|
|
|
|
#:when (dict-has-key? TRANSLATION# #'nm)
|
|
|
|
|
(dict-ref TRANSLATION# #'nm)]
|
|
|
|
|
[(Actor _)
|
|
|
|
|
(error "only able to convert actors with roles")]
|
|
|
|
|
[(ActorWithRole _ r)
|
|
|
|
|
(proto:Spawn (convert #'r))]
|
2020-10-28 18:06:19 +00:00
|
|
|
|
[★/t proto:⋆]
|
2020-11-05 16:09:00 +00:00
|
|
|
|
[(Bind t)
|
|
|
|
|
;; TODO - this is debatable handling
|
|
|
|
|
(convert #'t)]
|
|
|
|
|
[Discard
|
|
|
|
|
;; TODO - should prob have a Discard type in proto
|
|
|
|
|
proto:⋆]
|
2020-10-28 18:06:19 +00:00
|
|
|
|
[(∀/internal (X ...) body)
|
|
|
|
|
;; TODO
|
|
|
|
|
(error "unimplemented")]
|
|
|
|
|
[(→/internal ty-in ... ty-out)
|
|
|
|
|
;; TODO
|
|
|
|
|
(error "unimplemented")]
|
|
|
|
|
[(Role/internal (nm) body ...)
|
|
|
|
|
(proto:Role (syntax-e #'nm) (stx-map convert #'(body ...)))]
|
|
|
|
|
[(Stop nm body ...)
|
2020-11-30 22:47:53 +00:00
|
|
|
|
(proto:Stop (syntax-e #'nm) (stx-map convert #'(body ...)))]
|
2020-10-28 18:06:19 +00:00
|
|
|
|
[(Reacts evt body ...)
|
|
|
|
|
(define converted-body (stx-map convert #'(body ...)))
|
|
|
|
|
(define body+
|
|
|
|
|
(if (= 1 (length converted-body))
|
|
|
|
|
(first converted-body)
|
|
|
|
|
converted-body))
|
|
|
|
|
(proto:Reacts (convert #'evt) body+)]
|
|
|
|
|
[t:id
|
|
|
|
|
(proto:Base (syntax-e #'t))]
|
|
|
|
|
[(ctor:id args ...)
|
|
|
|
|
;; assume it's a struct
|
|
|
|
|
(proto:Struct (syntax-e #'ctor) (stx-map convert #'(args ...)))]
|
|
|
|
|
[unrecognized (error (format "unrecognized type: ~a" #'unrecognized))]))))
|
|
|
|
|
|
|
|
|
|
(define-typed-syntax (export-roles dest:string e:expr) ≫
|
|
|
|
|
[⊢ e ≫ e- (⇒ : τ) (⇒ ν-ep (~effs eps ...)) (⇒ ν-f (~effs fs ...)) (⇒ ν-s (~effs ss ...))]
|
|
|
|
|
#:do [(with-output-to-file (syntax-e #'dest)
|
|
|
|
|
(thunk (for ([f (in-syntax #'(fs ...))])
|
|
|
|
|
(pretty-write (synd->proto f))))
|
|
|
|
|
#:exists 'replace)]
|
|
|
|
|
----------------------------------------
|
|
|
|
|
[⊢ e- (⇒ : τ) (⇒ ν-ep (eps ...)) (⇒ ν-f (fs ...)) (⇒ ν-s (ss ...))])
|
|
|
|
|
|
2020-12-08 15:47:23 +00:00
|
|
|
|
(define-typed-syntax (export-type dest:string τ:type) ≫
|
|
|
|
|
#:do [(with-output-to-file (syntax-e #'dest)
|
|
|
|
|
(thunk (pretty-write (synd->proto #'τ.norm)))
|
|
|
|
|
#:exists 'replace)]
|
|
|
|
|
----------------------------------------
|
|
|
|
|
[⊢ (#%app- void-) (⇒ : ★/t)])
|
|
|
|
|
|
2020-11-05 16:09:00 +00:00
|
|
|
|
(define-typed-syntax (lift+define-role x:id e:expr) ≫
|
|
|
|
|
[⊢ e ≫ e- (⇒ : τ) (⇒ ν-ep (~effs)) (⇒ ν-f ((~and r (~Role (_) _ ...)))) (⇒ ν-s (~effs))]
|
|
|
|
|
;; because turnstile introduces a lot of intdef scopes; ideally, we'd be able to synthesize somethign
|
|
|
|
|
;; with the right module scopes
|
|
|
|
|
#:with x+ (syntax-local-introduce (datum->syntax #f (syntax-e #'x)))
|
2020-12-14 16:50:24 +00:00
|
|
|
|
#:do [(define r- (synd->proto #'r))
|
|
|
|
|
(syntax-local-lift-module-end-declaration #`(define- x+ '#,r-))]
|
2020-11-05 16:09:00 +00:00
|
|
|
|
----------------------------------------
|
|
|
|
|
[⊢ e- (⇒ : τ) (⇒ ν-ep ()) (⇒ ν-f (r)) (⇒ ν-s ())])
|
|
|
|
|
|
2020-11-30 22:47:53 +00:00
|
|
|
|
|
|
|
|
|
;; Type Type -> Bool
|
|
|
|
|
;; (normalized Types)
|
|
|
|
|
(define-for-syntax (simulating-types? ty-impl ty-spec)
|
|
|
|
|
(define ty-impl- (synd->proto ty-impl))
|
|
|
|
|
(define ty-spec- (synd->proto ty-spec))
|
2020-12-01 22:34:32 +00:00
|
|
|
|
(proto:simulates?/report-error ty-impl- ty-spec-))
|
2020-11-30 22:47:53 +00:00
|
|
|
|
|
|
|
|
|
;; Type Type -> Bool
|
|
|
|
|
;; (normalized Types)
|
|
|
|
|
(define-for-syntax (type-has-simulating-subgraphs? ty-impl ty-spec)
|
|
|
|
|
(define ty-impl- (synd->proto ty-impl))
|
|
|
|
|
(define ty-spec- (synd->proto ty-spec))
|
2020-12-01 22:34:32 +00:00
|
|
|
|
(define ans (proto:find-simulating-subgraph/report-error ty-impl- ty-spec-))
|
2020-11-30 22:47:53 +00:00
|
|
|
|
(unless ans
|
|
|
|
|
(pretty-print ty-impl-)
|
|
|
|
|
(pretty-print ty-spec-))
|
|
|
|
|
ans)
|
|
|
|
|
|
2020-12-14 16:50:24 +00:00
|
|
|
|
(define- (ensure-Role! r)
|
|
|
|
|
(unless- (#%app- proto:Role? r)
|
|
|
|
|
(#%app- error- 'check-simulates "expected a Role type, got " r))
|
|
|
|
|
r)
|
|
|
|
|
|
|
|
|
|
(begin-for-syntax
|
|
|
|
|
(define-syntax-class type-or-proto
|
|
|
|
|
#:attributes (role)
|
|
|
|
|
(pattern t:type #:attr role #`(quote- #,(synd->proto #'t.norm)))
|
|
|
|
|
(pattern x:id #:attr role #'(#%app- ensure-Role! x))
|
|
|
|
|
#;(pattern ((~literal quote-) r)
|
|
|
|
|
#:do [(define r- (syntax-e ))]
|
|
|
|
|
#:when (proto:Role? r-)
|
|
|
|
|
#:attr role r-)))
|
2020-10-28 18:06:19 +00:00
|
|
|
|
|
2020-12-14 16:50:24 +00:00
|
|
|
|
(require rackunit)
|
|
|
|
|
|
|
|
|
|
(define-syntax-parser check-simulates
|
|
|
|
|
[(_ τ-impl:type-or-proto τ-spec:type-or-proto)
|
|
|
|
|
(syntax/loc this-syntax
|
2020-12-21 16:07:29 +00:00
|
|
|
|
(check-true (#%app- proto:simulates?/report-error τ-impl.role τ-spec.role)))])
|
2020-12-14 16:50:24 +00:00
|
|
|
|
|
|
|
|
|
(define-syntax-parser check-has-simulating-subgraph
|
|
|
|
|
[(_ τ-impl:type-or-proto τ-spec:type-or-proto)
|
|
|
|
|
(syntax/loc this-syntax
|
|
|
|
|
(check-not-false (#%app- proto:find-simulating-subgraph/report-error τ-impl.role τ-spec.role)))])
|
2020-11-05 16:09:00 +00:00
|
|
|
|
|
2021-01-11 16:52:00 +00:00
|
|
|
|
(define-syntax-parser verify-actors
|
|
|
|
|
[(_ spec actor-ty:type-or-proto ...)
|
|
|
|
|
#:with spec- #`(quote- #,(synd->proto (type-eval #'spec)))
|
|
|
|
|
(syntax/loc this-syntax
|
|
|
|
|
(check-true (#%app- proto:compile+verify spec- (#%app- list- actor-ty.role ...))))])
|
|
|
|
|
|
2018-07-27 21:16:44 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
;; Tests
|
2018-09-12 19:06:08 +00:00
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
2018-09-12 21:03:19 +00:00
|
|
|
|
(module+ test
|
2020-09-17 19:11:34 +00:00
|
|
|
|
(check-type
|
|
|
|
|
(spawn (U (Observe (Tuple Int ★/t)))
|
|
|
|
|
(start-facet echo
|
2020-12-08 15:42:39 +00:00
|
|
|
|
(on (message (tuple 1 $x:Int))
|
2020-09-17 19:11:34 +00:00
|
|
|
|
#f)))
|
|
|
|
|
: ★/t)
|
2018-09-12 21:03:19 +00:00
|
|
|
|
(check-type (spawn (U (Message (Tuple String Int))
|
|
|
|
|
(Observe (Tuple String ★/t)))
|
|
|
|
|
(start-facet echo
|
2019-05-24 15:12:06 +00:00
|
|
|
|
(on (message (tuple "ping" $x))
|
2018-09-12 21:03:19 +00:00
|
|
|
|
(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)))))))
|
|
|
|
|
|
2018-09-12 19:06:08 +00:00
|
|
|
|
;; 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))
|
2018-11-19 22:42:08 +00:00
|
|
|
|
1234))
|