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.

Walks a local expression to pull out/convert function calls.

Types

@type remote_actor_ref() :: {:remote, integer(), binary(), integer()}

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

Link to this function

actor_from_local_exp(actor_alias, env)

View Source

Get the actor name from an expression

iex> Chorex.actor_from_local_exp((quote do: Foo.bar(42)), __ENV__)
{:ok, Foo}
Link to this function

cont_or_return(cont_exp, ret_var, ctx)

View Source
Link to this macro

defchor(actor_list, list)

View Source (macro)

Define a new choreography.

See the documentation for the Chorex module for more details.

Link to this function

do_local_project_wrapper(code, acc, env, label, ctx)

View Source

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.

Link to this function

empty_ctx(caller, actors \\ [])

View Source
Link to this function

make_continue_function(ret_tok, cont, ctx)

View Source
Link to this function

make_var_continue_function(ret_tok, var_expr, cont, ctx)

View Source

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.

Link to this function

project(expr, env, label, ctx)

View Source
@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:

  1. Elixir AST term to project.
  2. Macro environment.
  3. Name of the actor currently under projection. Atom.
  4. 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:

  1. The projected term. Elixir AST.
  2. A list of callback specifications for this actor. (Functions the actor implementer needs to have.)
  3. List of auxiliary functions generated during the projection process.
Link to this function

project_identifier(stx, env, label)

View Source

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.

Link to this function

project_local_expr(stx, env, label, ctx)

View Source

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.

Link to this function

project_sequence(expr, env, label, ctx)

View Source
@spec project_sequence(term(), Macro.Env.t(), atom(), map()) :: WriterMonad.t()

Project a sequence of expressions.

Link to this function

start(chorex_module, actor_impl_map, init_args)

View Source
@spec start(module(), %{required(atom()) => module() | remote_actor_ref()}, [any()]) ::
  any()

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 },
             [])
Link to this function

tron(atom, actor, label, data)

View Source
Link to this function

tron(atom, choice, who, sender, receiver)

View Source
Link to this function

walk_local_expr(code, env, label, ctx)

View Source

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 as 1 + impl.foo() and foo/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 as impl.some_func(&impl.other_local_func/2) and both some_func and other_local_func need to be added to the list of functions for the Alice behaviour.

  • Alice.(1 + Enum.sum(...)) should not be rewritten as impl.….

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.