BART is an implementation of an Actor Assignment Machine using the Blockly web-based visual programming editor. BART programs can be represented in JSON/CRLF as follows:
{
"lang": "BART",
"ast": [
<sponsor>,
...
]
}
The ast
represents a list of sponsors, which encapsulate actor configurations.
An actor's behavior can be described using a sequential model of variable assignments. This is essentially the model of contemporary processor cores. However, in order to avoid the pitfalls of shared mutable state, we only allow assignment to actor-local (private) variables. All visible effects are captured in the asynchronous messages between actors.
A sponsor plays the role of a processor core, mediating access to computational resources and executing the instructions in an actor's behavior script (the program). Each message delivery event is handled as if it was an atomic transaction. No effects are visible outside the actor until message handling is completed. Message handling may be aborted by an exception, in which case the message is effectively ignored.
A dictionary mapping names to values is the primary conceptual data structure. Each actor maintains a persistent dictionary of local variables, representing it's private state. Each message is a read-only dictionary from which values may be retrieved by the actor's behavior script. Information derived from the message may be assigned to the actor's local persistent state.
The following is a compact summary of BART program elements:
// Containers
{ "kind":"actor_sponsor", "actors":<number>, "events":<number>, "script":[<action>, ...] }
// Actions
{ "kind":"actor_send", "message":<dictionary>, "actor":<address> }
{ "kind":"actor_send_after", "delay":<number>, "message":<dictionary>, "actor":<address> }
{ "kind":"actor_become", "behavior":<behavior> }
{ "kind":"actor_ignore" }
{ "kind":"actor_assign", "name":<string>, "value":<expression> }
{ "kind":"actor_fail", "error":<expression> }
// Address Expressions
{ "kind":"actor_create", "state":<dictionary>, "behavior":<behavior> }
{ "kind":"actor_self" }
// Behavior Expressions
{ "kind":"actor_behavior", "name":<string>, "script":[<action>, ...] }
// Value Expressions
{ "kind":"actor_state", "name":<string> }
{ "kind":"dict_get", "name":<string>, "in":<dictionary> }
{ "kind":"expr_literal", "const":<value> }
{ "kind":"expr_operation", "name":<string>, "args":[<expression>, ...] }
// Boolean Expressions
{ "kind":"actor_has_state", "name":<string> }
{ "kind":"dict_has", "name":<string>, "in":<dictionary> }
// Dictionary Expressions
{ "kind":"actor_message" }
{ "kind":"dict_empty" }
{ "kind":"dict_bind", "name":<string>, "value":<expression>, "with":<dictionary> }
// Number Expressions
{ "kind":"device_now" }
Now we describe each BART program element in detail.
An actor configuration executing a script, with limits on actors and events.
{
"kind": "actor_sponsor",
"actors": <number>,
"events": <number>,
"script": [
<action>,
...
]
}
The actions in the sponsor's script initialize the actor configuration, creating initial actors and sending initial messages.
This action constructs a new send-event to deliver a specific message to a target actor.
{
"kind": "actor_send",
"message": <dictionary>,
"actor": <address>
}
This expression constructs a new actor with an initial state and behavior, and returns it's address.
{
"kind": "actor_create",
"state": <dictionary>,
"behavior": <behavior>
}
The actor's behavior script may retrieve and update bindings in the private state of this actor.
This expression constructs an actor behavior with an optional name.
{
"kind": "actor_behavior",
"name": <string>,
"script": [
<action>,
...
]
}
Actor behavior scripts can be shared between actors, and each actor may use different scripts over time.
This action specifies the behavior this actor will use to process subsequent messages.
{
"kind": "actor_become",
"behavior": <behavior>
}
NOTE: Changing an actor's behavior script has no effect on how it handles the current message.
This action updates the private state of an actor (or sponsor), binding a new value to name.
{
"kind": "actor_assign",
"name": <string>,
"value": <expression>
}
The updated local-state dictionary is used for subsequent actions in the current actor's script.
This expression retrieves the current value bound to name in the current actor (or sponsor).
{
"kind": "actor_state",
"name": <string>
}
Since the actor's local state is mutable, the value retrieved may be affected by previous assignment actions in the same script.
This expression evaluates to true
if name is bound to a value in the current actor (or sponsor), or false
otherwise.
{
"kind": "actor_has_state",
"name": <string>
}
This expression retrieves the (immutable) dictionary representing the current message being processed.
{
"kind": "actor_message"
}
This expression evaluates to the address of the current actor.
{
"kind": "actor_self"
}
This action has no effect.
{
"kind": "actor_ignore"
}
This action aborts processing the current message and reverts all accumulated effects.
{
"kind": "actor_fail",
"error": <expression>
}
This action constructs a new send-event to deliver a specific message to a target actor after a delay.
{
"kind": "actor_send_after",
"delay": <number>,
"message": <dictionary>,
"actor": <address>
}
This expression evaluates to the current time.
{
"kind": "device_now"
}
This expression evaluates to an (immutable) empty dictionary.
{
"kind": "dict_empty"
}
This expression evaluates to an immutable dictionary where, value is bound to name, extending or overriding bindings in with.
{
"kind": "dict_bind",
"name": <string>,
"value": <expression>,
"with": <dictionary>
}
NOTE: The with dictionary is not mutated. A new dictionary is created with the added/modified binding.
This expression retrieves the current value bound to name in this dictionary.
{
"kind": "dict_get",
"name": <string>,
"in": <dictionary>
}
This expression evaluates to true
if name is bound to a value in this dictionary, or false
otherwise.
{
"kind": "dict_has",
"name": <string>,
"in": <dictionary>
}
This expression evaluates to a constant value (with an optional type).
{
"kind": "expr_literal",
"type": <type>,
"const": <value>
}
This expression evaluates to the result (with an optional type) of calling operation name with args.
{
"kind": "expr_operation",
"type": <type>,
"name": <string>,
"args": [
<expression>,
...
]
}