Initial hacking on the documentation to make it untyped only.

This commit is contained in:
Tony Garnock-Jones 2014-08-06 17:20:42 -07:00
parent da7851d451
commit 391243e3cb
5 changed files with 74 additions and 147 deletions

View File

@ -82,8 +82,9 @@ actions the process wishes to perform. See @secref{Actions} for the
possible actions a process can take. possible actions a process can take.
Note that the result of an event handler function is actually a Note that the result of an event handler function is actually a
@racket[Transition] structure; the actual Typed Racket type of event @racket[transition] structure containing a new state and a sequence of
handlers is @racket[TrapK], defined in @secref{handler-functions}. actions, rather than the explicit pair shown in the approximate type
above. See @secref{handler-functions} for more on handler functions.
@section{What is a VM?} @section{What is a VM?}

View File

@ -34,10 +34,9 @@ the subscription at the meta-level as well.
@defmodule[marketplace/drivers/tcp-bare]{ @defmodule[marketplace/drivers/tcp-bare]{
This module is only available for use by untyped Racket processes. It This module is included by default in programs using @tt{#lang
is included by default in programs using @tt{#lang marketplace}; see marketplace}; see @secref{hashlang-variations} for information on
@secref{hashlang-variations} for information on other language other language variants.
variants.
@defproc[(tcp-driver) Spawn]{ @defproc[(tcp-driver) Spawn]{
@ -57,9 +56,9 @@ A pre-made @racket[spawn] action equivalent to @racket[(tcp-driver)].
@subsection{TCP channels} @subsection{TCP channels}
@defstruct*[tcp-channel ([source TcpAddress] @defstruct*[tcp-channel ([source (or/c tcp-address? tcp-handle? tcp-listener?)]
[destination TcpAddress] [destination (or/c tcp-address? tcp-handle? tcp-listener?)]
[subpacket TcpSubPacket]) #:prefab]{ [subpacket (or/c eof-object? bytes?)]) #:prefab]{
A TCP channel represents a section of a unidirectional TCP flow A TCP channel represents a section of a unidirectional TCP flow
appearing on our local "subnet" of the full TCP network, complete with appearing on our local "subnet" of the full TCP network, complete with
@ -67,10 +66,6 @@ source, destination and subpacket. Each TCP connection has two such
flows: one inbound (remote-to-local) bytestream, and one outbound flows: one inbound (remote-to-local) bytestream, and one outbound
(local-to-remote) bytestream. (local-to-remote) bytestream.
}
@deftype[TcpSubPacket (or/c eof-object? bytes?)]{
Packets carried by @racket[tcp-channel] structures are either Packets carried by @racket[tcp-channel] structures are either
end-of-file objects or raw binary data represented as Racket byte end-of-file objects or raw binary data represented as Racket byte
vectors. vectors.
@ -79,8 +74,6 @@ vectors.
@subsection{TCP addresses} @subsection{TCP addresses}
@deftype[TcpAddress (or/c tcp-address? tcp-handle? tcp-listener?)]{
A TCP address describes one end of a TCP connection. It can be either A TCP address describes one end of a TCP connection. It can be either
@itemlist[ @itemlist[
@ -89,8 +82,6 @@ A TCP address describes one end of a TCP connection. It can be either
@item{a @racket[tcp-listener], representing a local socket on a user-assigned port.} @item{a @racket[tcp-listener], representing a local socket on a user-assigned port.}
] ]
}
@defstruct*[tcp-address ([host string?] @defstruct*[tcp-address ([host string?]
[port (integer-in 0 65535)]) #:prefab]{ [port (integer-in 0 65535)]) #:prefab]{
@ -109,7 +100,7 @@ a local name for whichever underlying port number ends up being used.
The @racket[id] must be chosen carefully: it is scoped to the local The @racket[id] must be chosen carefully: it is scoped to the local
VM, i.e. shared between processes in that VM, so processes must make VM, i.e. shared between processes in that VM, so processes must make
sure not to accidentally clash in handle ID selection. They are also sure not to accidentally clash in handle ID selection. They are also
used in TcpChannel to mean a specific @emph{instance} of a TCP used in @racket[tcp-channel] to mean a specific @emph{instance} of a TCP
connection, so if you are likely to want to reconnect individual connection, so if you are likely to want to reconnect individual
flows, use different values for @racket[id]. flows, use different values for @racket[id].
@ -203,14 +194,14 @@ where, as for receiving data, the @racket[subpacket] is either
Not yet documented. Not yet documented.
} }
@section{timer (typed and untyped)} @section{timer}
For examples of the use of the timer driver, see uses of For examples of the use of the timer driver, see uses of
@racket[set-timer] and @racket[timer-expired] in @racket[set-timer] and @racket[timer-expired] in
@hyperlink["https://github.com/tonyg/marketplace-dns/blob/master/network-query.rkt"]{the @hyperlink["https://github.com/tonyg/marketplace-dns/blob/master/network-query.rkt"]{the
Marketplace-based DNS resolver}. Marketplace-based DNS resolver}.
@section{udp (typed and untyped)} @section{udp}
For examples of the use of the UDP driver, see uses of For examples of the use of the UDP driver, see uses of
@racket[udp-packet] etc. in @racket[udp-packet] etc. in

View File

@ -15,9 +15,7 @@ interface} of a Unix-like operating system.
@;{ @;{
@defmodulelang*[(marketplace @defmodulelang*[(marketplace
marketplace/flow-control marketplace/flow-control)]
marketplace/typed
marketplace/typed/flow-control)]
} }
@defmodulelang[marketplace] @defmodulelang[marketplace]
@ -31,28 +29,19 @@ actions spawn application processes and nested VMs, which in turn
subscribe to sources of events from the outside world. subscribe to sources of events from the outside world.
At present, there's just @tt{#lang marketplace}. In future, there will At present, there's just @tt{#lang marketplace}. In future, there will
be a variation for Typed Racket, and languages providing greater be languages providing greater support for flow control,
support for flow control, responsibility transfer, and other responsibility transfer, and other networking concepts.
networking concepts. For now, Typed Racket programs must be written as
@tt{#lang typed/racket} programs using @racket[(require marketplace)]
and @racket[ground-vm:] explicitly.
@;{ @;{
@itemlist[ @itemlist[
@item{@racket[marketplace] is for @emph{untyped} programs, and uses @item{@racket[marketplace] is for ordinary Racket programs, and uses
the @secref{tcp-bare} TCP driver;} the @secref{tcp-bare} TCP driver;}
@item{@racket[marketplace/flow-control] is like @item{@racket[marketplace/flow-control] is like
@racket[marketplace], but uses the flow-controlled @secref{tcp} @racket[marketplace], but uses the flow-controlled @secref{tcp}
driver;} driver;}
@item{@racket[marketplace/typed] is like @racket[marketplace], but
for @emph{typed} programs;}
@item{@racket[marketplace/typed/flow-control] is like
@racket[marketplace/flow-control], but for typed programs.}
] ]
} }
@ -65,7 +54,7 @@ Instead of using Racket's @tt{#lang} feature, ordinary Racket programs
can use Marketplace features by requiring Marketplace modules can use Marketplace features by requiring Marketplace modules
directly. directly.
Such programs need to use @racket[ground-vm]/@racket[ground-vm:] to Such programs need to use @racket[ground-vm] to
start the ground-level VM explicitly. They also need to explicitly start the ground-level VM explicitly. They also need to explicitly
start any drivers they need; for example, the file start any drivers they need; for example, the file
@filepath{examples/echo-plain.rkt} uses @racket[ground-vm] along with @filepath{examples/echo-plain.rkt} uses @racket[ground-vm] along with
@ -78,27 +67,20 @@ start any drivers they need; for example, the file
(on-presence (spawn (echoer from to)))))) (on-presence (spawn (echoer from to))))))
] ]
@deftogether[( @defform[(ground-vm maybe-boot-pid-binding maybe-initial-state initial-action ...)
@defform[(ground-vm maybe-boot-pid-binding maybe-initial-state initial-action ...)]
@defform[(ground-vm: maybe-boot-pid-binding maybe-typed-initial-state initial-action ...)
#:grammar #:grammar
[(maybe-boot-pid-binding (code:line) [(maybe-boot-pid-binding (code:line)
(code:line #:boot-pid id)) (code:line #:boot-pid id))
(maybe-initial-state (code:line) (maybe-initial-state (code:line)
(code:line #:initial-state expr)) (code:line #:initial-state expr))
(maybe-typed-initial-state (code:line) (initial-action expr)]]{
(code:line #:initial-state expr : type))
(initial-action expr)]]
)]{
Starts the ground VM, in untyped and typed programs, respectively. If Starts the ground VM. If @racket[#:boot-pid] is specified, the given
@racket[#:boot-pid] is specified, the given identifier is bound within identifier is bound within the form to the PID of the @emph{primordial
the form to the PID of the @emph{primordial process} that performs the process} that performs the initial actions. If
initial actions. If @racket[#:initial-state] is specified (with a @racket[#:initial-state] is specified, it is used as the initial state
type, for @racket[ground-vm:]), it is used as the initial state for for the primordial process; if it is not supplied, the primordial
the primordial process; if it is not supplied, the primordial process process is given @racket[(void)] as its initial state.
is given @racket[(void)] as its initial state (and @racket[Void] as
its state type).
} }
@ -109,32 +91,24 @@ its state type).
@deftogether[( @deftogether[(
@defform[(transition new-state action-tree ...)] @defform[(transition new-state action-tree ...)]
@defform[(transition: new-state : State action-tree ...)]
@defform[(transition/no-state action-tree ...)] @defform[(transition/no-state action-tree ...)]
)]{ )]{
Each of these forms produces a @racket[Transition] structure. The Each of these forms produces a @racket[transition] structure.
first is for untyped code, the second for typed code (where the
mandatory @racket[State] is the type of the transitioning process's
private state), and the third for either.
Each @racket[action-tree] must be an @racket[(ActionTree State)]. Each @racket[action-tree] must be an @tech{action tree}.
It's fine to include @emph{no} action trees, in which case the
It's fine to include @emph{no} action-trees, in which case the
transition merely updates the state of the process without taking any transition merely updates the state of the process without taking any
actions. actions.
In the case of @racket[transition/no-state], the type @racket[Void] In the case of @racket[transition/no-state], the value @racket[(void)]
and value @racket[(void)] is used for the process state. is used for the process state. @racket[transition/no-state] is useful
@racket[transition/no-state] is useful for processes that are for processes that are stateless other than the implicit state of
stateless other than the implicit state of their endpoints. their endpoints.
} }
@deftogether[( @defstruct*[transition ([state State] [actions action-tree?]) #:transparent]{
@defstruct*[transition ([state State] [actions (ActionTree State)]) #:transparent]
@deftype[(Transition State) (transition State)]
)]{
A transition structure. The @racket[transition-state] field is the new A transition structure. The @racket[transition-state] field is the new
private state the process will have after the transition is applied, private state the process will have after the transition is applied,
@ -143,16 +117,23 @@ performed by the VM in order to apply the transition.
} }
@deftogether[( @defproc[(action-tree? [value any/c]) boolean?]{
@deftype[(ActionTree State) (Constreeof (Action State))]
@deftype[(Constreeof X) (Rec CT (U X (Pairof CT CT) False Void Null))]
)]{
An action-tree is a @deftech{cons-tree} of @racket[Action]s. When Predicate that recognises an @deftech{action tree}. An action tree is
performing actions, a VM will traverse an action-tree in left-to-right either
order.
@racket['()], @racket[(void)], and @racket[#f] may also be present in @itemlist[
@item{@racket['()];}
@item{@racket[#f];}
@item{@racket[(void)];}
@item{a pair of action trees; or}
@item{an @tech{action}.}
]
When performing actions, a VM will traverse an action-tree in
left-to-right order.
@racket['()], @racket[(void)], and @racket[#f] may be present in
action-trees: when the VM reaches such a value, it ignores it and action-trees: when the VM reaches such a value, it ignores it and
continues with the next leaf in the tree. continues with the next leaf in the tree.
@ -194,10 +175,9 @@ at all" in a transition:
} }
@defproc[(sequence-actions [initial-transition (Transition State)] @defproc[(sequence-actions [initial-transition transition?]
[item (U (ActionTree State) [item (or/c action-tree? (any/c -> transition?))]
(State -> (Transition State)))] ...) transition?]{
...) (Transition State)]{
Returns a transition formed from the @racket[initial-transition] Returns a transition formed from the @racket[initial-transition]
extended with new actions, possibly updating its carried state. Each extended with new actions, possibly updating its carried state. Each
@ -238,44 +218,30 @@ collection of macros helps streamline endpoint setup.
@deftogether[( @deftogether[(
@defform[(publisher topic handler ...)] @defform[(publisher topic handler ...)]
@defform[(publisher: State topic handler ...)]
@defform[(subscriber topic handler ...)] @defform[(subscriber topic handler ...)]
@defform[(subscriber: State topic handler ...)]
@defform[(observe-subscribers topic handler ...)] @defform[(observe-subscribers topic handler ...)]
@defform[(observe-subscribers: State topic handler ...)]
@defform[(observe-publishers topic handler ...)] @defform[(observe-publishers topic handler ...)]
@defform[(observe-publishers: State topic handler ...)]
@defform[(observe-subscribers/everything topic handler ...)] @defform[(observe-subscribers/everything topic handler ...)]
@defform[(observe-subscribers/everything: State topic handler ...)]
@defform[(observe-publishers/everything topic handler ...)] @defform[(observe-publishers/everything topic handler ...)]
@defform[(observe-publishers/everything: State topic handler ...)]
@defform[(build-endpoint pre-eid role handler ...)] @defform[(build-endpoint pre-eid role handler ...)]
@defform[(build-endpoint: State pre-eid role handler ...)]
)]{ )]{
The many variations on the core The many variations on the core
@racket[build-endpoint]/@racket[build-endpoint:] form exist to give @racket[build-endpoint] form exist to give
good control over @racket[InterestType] in the endpoint under good control over @racket[InterestType] in the endpoint under
construction; construction;
see @secref{participating-vs-observing}. see @secref{participating-vs-observing}.
Almost everything is optional in an endpoint definition. The only Almost everything is optional in an endpoint definition. The only
mandatory part is the topic, unless you're using Typed Racket, in mandatory part is the topic.
which case the process state type must also be specified.
For example, a minimal endpoint subscribing to all messages would be: For example, a minimal endpoint subscribing to all messages would be:
@racketblock[(subscriber ?)] @racketblock[(subscriber ?)]
or in Typed Racket, for a process with @racket[Integer] as its process
state type,
@racketblock[(subscriber: Integer ?)]
A minimal publishing endpoint would be: A minimal publishing endpoint would be:
@racketblock[(publisher ?) @racketblock[(publisher ?)]
(publisher: Integer ?)]
While topic patterns are ordinary Racket data with embedded @racket[?] While topic patterns are ordinary Racket data with embedded @racket[?]
wildcards (see @secref{messages-and-topics}), all the other patterns wildcards (see @secref{messages-and-topics}), all the other patterns
@ -313,7 +279,7 @@ the wrapped handlers are expected to return
@seclink["constructing-transitions"]{transition structures}. @seclink["constructing-transitions"]{transition structures}.
If not, however, the handler expressions are expected to return plain If not, however, the handler expressions are expected to return plain
@racket[ActionTree]s. @tech{action tree}s.
This way, simple handlers that do not need to examine the process This way, simple handlers that do not need to examine the process
state, and simply act in response to whichever event triggered them, state, and simply act in response to whichever event triggered them,
@ -476,9 +442,8 @@ dynamically:
@itemlist[ @itemlist[
@item{@racket[publisher] and @racket[subscriber] (and typed @item{@racket[publisher] and @racket[subscriber] are for ordinary
variations ending in @tt{:}) are for ordinary @emph{participation} in @emph{participation} in conversations;}
conversations;}
@item{@racket[observe-subscribers] and @racket[observe-publishers] @item{@racket[observe-subscribers] and @racket[observe-publishers]
are for @emph{observing} conversations without participating in them; and} are for @emph{observing} conversations without participating in them; and}
@ -503,7 +468,7 @@ but as an observer, the code should declare the roles being observed.
Endpoint names can be used to @seclink["updating-endpoints"]{update} Endpoint names can be used to @seclink["updating-endpoints"]{update}
or @seclink["deleting-endpoints"]{delete} endpoints. or @seclink["deleting-endpoints"]{delete} endpoints.
@defproc[(name-endpoint [id Any] [add-endpoint-action AddEndpoint]) AddEndpoint]{ @defproc[(name-endpoint [id any/c] [add-endpoint-action AddEndpoint]) AddEndpoint]{
Returns a copy of the passed-in @racket[add-endpoint] action Returns a copy of the passed-in @racket[add-endpoint] action
structure, with the @racket[id] field set to the passed-in identifying structure, with the @racket[id] field set to the passed-in identifying
@ -565,15 +530,7 @@ Equivalent to @racket[(send-message body 'subscriber)].
@defform[(spawn maybe-pid-binding boot-expr)] @defform[(spawn maybe-pid-binding boot-expr)]
@defform[(spawn/continue maybe-pid-binding @defform[(spawn/continue maybe-pid-binding
#:parent parent-state-pattern k-expr #:parent parent-state-pattern k-expr
#:child boot-expr)] #:child boot-expr)
@defform[#:literals (:)
(spawn: maybe-pid-binding
#:parent : ParentStateType
#:child : ChildStateType boot-expr)]
@defform[#:literals (:)
(spawn/continue: maybe-pid-binding
#:parent parent-state-pattern : ParentStateType k-expr
#:child : ChildStateType boot-expr)
#:grammar #:grammar
[(maybe-pid-binding (code:line) [(maybe-pid-binding (code:line)
(code:line #:pid identifier)) (code:line #:pid identifier))
@ -589,15 +546,11 @@ If @racket[#:pid] is supplied, the associated identifier is bound to
the child process's PID in both @racket[boot-expr] and the parent's the child process's PID in both @racket[boot-expr] and the parent's
@racket[k-expr]. @racket[k-expr].
The @racket[spawn/continue] and @racket[spawn/continue:] variations The @racket[spawn/continue] variation includes a @racket[k-expr],
include a @racket[k-expr], which will run in the parent process after which will run in the parent process after the child process has been
the child process has been created. Note that @racket[k-expr] must created. Note that @racket[k-expr] must return a @racket[transition],
return a @racket[Transition], since @racket[parent-state-pattern] is since @racket[parent-state-pattern] is always supplied for these
always supplied for these variations. variations.
In Typed Racket, for type system reasons, @racket[spawn:] and
@racket[spawn/continue:] require @racket[ParentStateType] to be
supplied as well as @racket[ChildStateType].
} }
@ -634,11 +587,7 @@ itself.
@section{Cooperative scheduling} @section{Cooperative scheduling}
@deftogether[( @defform[(yield state-pattern k-expr)]{
@defform[(yield state-pattern k-expr)]
@defform[#:literals (:)
(yield: state-pattern : State k-expr)]
)]{
Lets other processes in the system run for a step, returning to Lets other processes in the system run for a step, returning to
evaluate @racket[k-expr] only after doing a complete round of the evaluate @racket[k-expr] only after doing a complete round of the
@ -646,23 +595,16 @@ scheduler.
The state of the yielding process will be matched against The state of the yielding process will be matched against
@racket[state-pattern] when the process is resumed, and @racket[state-pattern] when the process is resumed, and
@racket[k-expr] must evaluate to a @racket[Transition]. @racket[k-expr] must evaluate to a @racket[transition].
} }
@section{Creating nested VMs} @section{Creating nested VMs}
@deftogether[(
@defform[(spawn-vm maybe-vm-pid-binding maybe-boot-pid-binding @defform[(spawn-vm maybe-vm-pid-binding maybe-boot-pid-binding
maybe-initial-state maybe-initial-state
maybe-debug-name maybe-debug-name
boot-action-expr ...)] boot-action-expr ...)
@defform[#:literals (:)
(spawn-vm: : ParentStateType
maybe-vm-pid-binding maybe-boot-pid-binding
maybe-typed-initial-state
maybe-debug-name
boot-action-expr ...)
#:grammar #:grammar
[(maybe-vm-pid-binding (code:line) [(maybe-vm-pid-binding (code:line)
(code:line #:vm-pid identifier)) (code:line #:vm-pid identifier))
@ -670,12 +612,9 @@ The state of the yielding process will be matched against
(code:line #:boot-pid identifier)) (code:line #:boot-pid identifier))
(maybe-initial-state (code:line) (maybe-initial-state (code:line)
(code:line #:initial-state expr)) (code:line #:initial-state expr))
(maybe-typed-initial-state (code:line)
(code:line #:initial-state expr : StateType))
(maybe-debug-name (code:line) (maybe-debug-name (code:line)
(code:line #:debug-name expr)) (code:line #:debug-name expr))
(boot-action-expr expr)]] (boot-action-expr expr)]]{
)]{
Results in a @racket[spawn] action that starts a nested VM. The Results in a @racket[spawn] action that starts a nested VM. The
primordial process in the new VM executes the boot-actions with the primordial process in the new VM executes the boot-actions with the
@ -692,10 +631,7 @@ primordial process in the new VM.
@section{Relaying across layers} @section{Relaying across layers}
@deftogether[( @defproc[(at-meta-level [preaction (PreAction State)] ...) (Action StateType)]{
@defform[(at-meta-level: StateType preaction ...)]
@defproc[(at-meta-level [preaction (PreAction State)] ...) (Action StateType)]
)]{
Each VM gives its processes access to two distinct IPC facilities: the Each VM gives its processes access to two distinct IPC facilities: the
@emph{internal} one, provided for the VM's processes to talk amongst @emph{internal} one, provided for the VM's processes to talk amongst
@ -704,9 +640,9 @@ itself is a process within.
Marketplace's actions can apply to either of those two networks. By Marketplace's actions can apply to either of those two networks. By
default, actions apply to the VM of the acting process directly, but default, actions apply to the VM of the acting process directly, but
using @racket[at-meta-level] (or @racket[at-meta-level:] in typed using @racket[at-meta-level] to wrap an action @emph{level-shifts} the
code) to wrap an action @emph{level-shifts} the action to make it action to make it apply at the level of the acting process's VM's
apply at the level of the acting process's VM's container instead. container instead.
For example, wrapping an @racket[endpoint] in @racket[at-meta-level] For example, wrapping an @racket[endpoint] in @racket[at-meta-level]
adds a subscription to the VM's container's network. Instead of adds a subscription to the VM's container's network. Instead of

View File

@ -20,7 +20,7 @@ interface} of a Unix-like operating system.
Each @deftech{handler function} is always associated with a particular Each @deftech{handler function} is always associated with a particular
@tech{endpoint}, registered with the VM via @tech{endpoint}, registered with the VM via
@racket[endpoint]/@racket[endpoint:]/@racket[add-endpoint]. A handler @racket[endpoint]/@racket[add-endpoint]. A handler
function for a given process with state type @racket[State] has type: function for a given process with state type @racket[State] has type:
@racketblock[(EndpointEvent -> State -> (Transition State))] @racketblock[(EndpointEvent -> State -> (Transition State))]

View File

@ -28,8 +28,7 @@ each @racket['publisher] message sent to the VM's network.
@section[#:tag "logging"]{logging (MARKETPLACE_LOG)} @section[#:tag "logging"]{logging (MARKETPLACE_LOG)}
@defmodule*[(marketplace/log-untyped @defmodule*[(marketplace/log)]{
marketplace/log-typed)]{
@defform[#:kind "environment variable" #:id MARKETPLACE_LOG MARKETPLACE_LOG]{ @defform[#:kind "environment variable" #:id MARKETPLACE_LOG MARKETPLACE_LOG]{