View Source Chorex (Chorex v0.8.6)
Main projector for choreographies.
Summary
Types
A tuple describing where to find a remote host. The Chorex.start/3
function takes this and spins up proxies as needed to manage the connection.
Functions
Get the actor name from an expression
Define a new choreography.
True if the continuation for the given code is empty. This can be from an empty block, or because the projection of block does nothing meaningful.
Perform the control merge function.
Perform endpoint projection in the context of node label
.
Project an expression like Actor.var
to either var
or _
.
Project local expressions of the form ActorName.(something)
.
Project a sequence of expressions.
Start a choreography.
Walks a local expression to pull out/convert function calls.
Types
A tuple describing where to find a remote host. The Chorex.start/3
function takes this and spins up proxies as needed to manage the connection.
{:remote, listen_socket :: integer(), remote_host :: binary(), remote_port :: integer()}
Functions
Get the actor name from an expression
iex> Chorex.actor_from_local_exp((quote do: Foo.bar(42)), __ENV__)
{:ok, Foo}
Define a new choreography.
See the documentation for the Chorex
module for more details.
True if the continuation for the given code is empty. This can be from an empty block, or because the projection of block does nothing meaningful.
Perform the control merge function.
Flatten block expressions at each step: sometimes auxiliary blocks get created around bits of the projection; trim these out at this step so equivalent expressions look equivalent.
@spec project(term :: term(), env :: Macro.Env.t(), label :: atom(), ctx :: map()) :: WriterMonad.t()
Perform endpoint projection in the context of node label
.
This returns a pair of a projection for the label, and a list of behaviors that an implementer of the label must implement.
Arguments:
- Elixir AST term to project.
- Macro environment.
- Name of the actor currently under projection. Atom.
- Extra information about the expansion. Map. Contains:
- vars :: set of live variables
- actors :: list of all actor names
Returns an instance of the WriterMonad
, which is just a 3-tuple
containing:
- The projected term. Elixir AST.
- A list of callback specifications for this actor. (Functions the actor implementer needs to have.)
- List of auxiliary functions generated during the projection process.
Project an expression like Actor.var
to either var
or _
.
Project to var
when Actor
matches the label we're projecting to,
or _
so that whatever data flows to that point can't be captured.
Project local expressions of the form ActorName.(something)
.
Like project/4
, but focus on handling ActorName.(local_var)
,
ActorName.local_func()
or ActorName.(local_exp)
. Handles walking
the local expression to gather list of functions needed for the
behaviour to implement.
@spec project_sequence(term(), Macro.Env.t(), atom(), map()) :: WriterMonad.t()
Project a sequence of expressions.
Start a choreography.
Takes a choreography module like MyCoolThing.Chorex
, a map from
actor names to implementing modules, and a list of arguments to pass
to the run
function.
Values in the map are either modules or remote_actor_ref()
tuples.
Example
Chorex.start(ThreePartySeller.Chorex,
%{ Buyer1 => MyBuyer1, Buyer2 => MyBuyer2, Seller => MySeller },
[])
Walks a local expression to pull out/convert function calls.
The expr
in Alice.(expr)
can almost be dropped directly into
the projection for the Alice
node. Here's where that almost
comes in:
Alice.(1 + foo())
needs to be rewritten as1 + impl.foo()
andfoo/0
needs to be added to the list of functions for the Alice behaviour.Alice.some_func(&other_local_func/2)
needs to be rewritten asimpl.some_func(&impl.other_local_func/2)
and bothsome_func
andother_local_func
need to be added to the list of functions for the Alice behaviour.Alice.(1 + Enum.sum(...))
should not be rewritten asimpl.…
.
There is some subtlety around tuples and function calls. Consider how these expressions and their quoted representations compare:
{:ok, foo}
→{:ok, {:foo, [], …}}
{:ok, foo, bar}
→{:{}, [], [:ok, {:foo, [], …}, {:bar, [], …}]}
ok(bar)
→{:ok, [], [{:bar, [], …}]}
It seems that 2-tuples have some special representation, which is frustrating.