From http://www.agorics.com/Library/Joule/quickref.html: This document provides reference information for the existing Joule implementation. 1. Basic ConceptsJoule embodies a new computational model for building distributed systems. A running Joule system consists of many servers concurrently and asynchronously sending messages to each other. Picture a Joule computation not as a sequence of instructions ordered in time, but as a dataflow diagram spread out in space; focus not on what happens when, but on what is connected to what else. Every object in a Joule system, from complex databases and bank accounts down to simple arrays and numbers, is a server. To get a server to do work (that is, to make use of its service), you send a message to it. (For example, you could send a get: message to an array server to obtain one of its elements.) Joule channels provide the "message plumbing" that interconnects servers into complex systems; they are unidirectional pipelines through which messages are conveyed. A channel is (of course) itself a server, with two facets: an acceptor and a distributor. (A server's facets represent subsets of its behavior.) Messages sent to the acceptor are carried through the channel to be delivered eventually to other servers. Messages sent to the distributor control to which other servers the channel delivers its messages. When a channel is forwarded to (i.e., delivers to) only a single server, messages to the acceptor of the channel act just like messages sent directly to the server. Thus, channels are transparent to message sending. This is the typical case because it is used to get results back from requests. All servers to which a channel forwards are guaranteed to receive all messages (ever) sent to the channel's acceptor. Again, the important thing is not when things happen, but how things are connected. When executing, a server can refer only to servers that it already knows, that it creates, or that are handed to it by other servers. It can send messages to these servers, pass these servers as arguments in such messages, create new servers, and change which servers it remembers. 2. Techniques and Idioms2.1 Message SendingSending a message, the core activity in a Joule program, takes the form
. Typically, the message contains an operation and arguments. By convention,
for operations that produce a value, the last argument is a distributor
which will be forwarded to that value. For example:
2.2 Server-Creating ProcedureWhen multiple instances of a server are needed, nest the server definition inside a procedure for creating instances of that server. The procedure accepts values for initializing the instance. Its result port must be forwarded to the nested server. For example:
|
module | The basic unit of Joule code that can be loaded into a system. |
export | A server explicitly exported by a module, making it accessible to any importing module. |
import | A module that supplies facilities required by the current module; or, a server supplied by an imported module. |
server | An object in a Joule program, so named because it supplies services to other servers. |
composite | Applies to a server whose behavior is provided by Joule code. Such a server builds upon the services of more primitive servers. |
primitive | Applies to a server that is built into the Joule implementation, such as a number, or that is supplied externally. |
facet | Access to a subset of the server's methods, called the facet's behavior. All facets of a server share the server's state, so messages to different facets of the same server are serialized. |
instance variable | A variable that holds a piece of the server's state. All state in Joule is held in this way. |
method | A block of code defining the action that a server takes in response to a message. |
methodical | Applies to a facet that provides a fixed set of services, which it will perform separately in response to specific messages. This is the usual type of facet, and is like an object in a traditional object-oriented language. |
non-methodical | Applies to a facet that provides a single generic service in response to any message, regardless of the particulars of the message, such as transparently forwarding the message. |
port | A reference to a server facet. Messages sent to a port are ultimately delivered to the corresponding facet. |
procedural server | A methodical server that provides a single service, in response to a '::' message. |
signature | The set of operations supported by a server facet,defining its contract with clients. |
message | The object sent by one server when communicating with another server. A message is typically an envelope,containing an operation and arguments. |
activation | The reception of a message by a server and the ensuing computation in response to that message. |
argument | The value supplied for an operation parameter. |
envelope | A server that acts as a sealed container for an operation and a set of arguments. |
operation | A sealer/unsealer pair, typically corresponding to the name of a method. |
reveal | To communicate the result of a computation. The result is typically revealed to the result distributor. Used instead of "return" because "reveal" does not mislead by implying a return of control to the message sender. |
sealer | The operation facet that seals arguments into a newly created Envelope. The Envelope created by a sealer can be opened only by the unsealer of the same operation. |
unsealer | The operation facet that unseals an envelope to extract its arguments. |
channel | A message pipeline that starts at an acceptor and ends at a distributor. A channel is transparent: senders cannot distinguish between sending through a channel to a server and sending directly to that server. |
acceptor | The channel facet that accepts messages for delivery through the channel. Each such message is forwarded to all servers to which the channel is ever forwarded. Thus, sending messages to the acceptor and forwarding the channel with the distributor can be performed in any order. |
distributor | The channel facet that controls delivery of messages. Sending a forward (--> server) message to a distributor causes the channel to deliver to server all messages, past and future, sent to the acceptor of the channel. |
forward | To direct a message or a distributor to a receiver. Thus, forward has two distinct meanings, comparable to forwarding a single letter versus forwarding a mailbox. |
Production | Production Definition |
---|---|
module | Module Identifier {import | export}* block endModule |
import | importModule {Identifier},+ |
export | export {Identifier},+ |
block | {form}* |
form | send | define | scoping | signal | server | type | branch | loop |
send | · simpleExpr {opExpr};+ |
define | Def {param | param = nestExpr},+ | Define {param | param = nestExpr},* blockendDefine |
scoping | Expose {Identifier},*
blockendExpose |
signal | Signal nestExpr |
branch | If nestExpr
block{orIf nestExpr block}*{elseIf nestExpr block{orIf nestExpr block}* }*{else block}?endIf | Switch nestExpr {case pattern {or pattern}*> block}* {otherwise param block}?endSwitch |
server | Server param {method}?
{var}* ops {facet}*endServer |
var | var {param | param = nestExpr},+
block |
ops | {implements Identifier}? {{op | do} method}* {otherwise param block}? |
method | pattern
block {change block}* |
change | to Identifier {opExpr};+ | set {Identifier = nestExpr},+ |
facet | facet param ops |
type | Type param
{super Identifier}? {{op | do} pattern block {to Identifier {opExpr};+ block}*}*endType |
loop | ForAll param {f param}?
blockendForAll |
opExpr | simpleExpr | simpleExpr Operator opExpr |
simpleExpr | Identifier | Literal | envelope | '(' nestExpr ')' |
nestExpr | simpleExpr | simpleExpr opExpr |
envelope | {Operator | Label} {opExpr}* |
pattern | {Operator | Label} {param}* |
param | Identifier |
Module
FundImpl export FundType, makeFund Type FundType super Basic op balance: balance> op withdraw: amount flag> op deposit: amount flag> endType Server makeFund :: fund> . fund> -> theFund Server theFund var myBalance = 0 implements FundType op balance: balance> . balance> -> myBalance op withdraw: amount flag> Def newBalance If amount > myBalance . newBalance> -> myBalance . flag> -> false orIf amount 0 . newBalance> -> myBalance . flag> ->false else . newBalance> -> myBalance - amount . flag> -> true endIf set myBalance = newBalance op deposit: amount flag> Def newBalance If amount 0 . newBalance> -> myBalance . flag> -> false else . newBalance> -> myBalance + amount . flag> -> true endIf set myBalance = newBalance endServer endServer endModule
|
|
report bug (including invalid html) |