asoma

An anarchic society of machines.

Connecting machines is easy; getting them to behave as one is the work. Asoma is a small virtual machine and a language for it, built so that the boundary between machines matters less.

Anything with the machine in it — a laptop, a browser, a board, a Python process — offers what it can do as addresses, and what it does is a program: written anywhere, sent to it, composed from several machines at once, replaced without a compiler. A program is a bundle of OpenSoundControl (OSC) messages, and so is the running machine itself — its values, its names, the rest of its program — so a running program can be sent too, and carry on where it lands.

The language

Each box below holds a live machine, compiled to WebAssembly. Every line you write is a message to a local OSC server: the machine inside the box, on this page. Edit the program and press Run.

A message is an address and a value. Parentheses gather messages into a bundle, a colon binds a value to a name, and /o/get reads a message back out of a bundle by its address:

# a bundle of messages, bound to a name
/voice : (/freq : 440, /amp : 0.5),
/voice,
(/voice, "/freq") /o/get

Each line answers with a message of its own; the leading colon marks one with no address. Commas separate the lines of a program, and # starts a comment.

A call puts the arguments first and the function after them, as if the bundle of arguments were sent to the machine and then the function to apply to it:

/freq : 440,
# arguments first, then the function
/octave : (/freq, 2) /o/mul,
(/freq, /octave)

A function is a body in curly braces — a bundle kept for later rather than run now — and the names of its parameters. /o/defn puts them together, and the result is called like anything built in:

# a body kept for later, and its parameter
/octave/up : ({ (/hz, 2) /o/mul }, "/hz") /o/defn,
(/freq : 220, /octave : (/freq) /octave/up)

That function is itself a bundle of messages: the body’s instructions and the parameter list. /o/inspect shows them:

/octave/up : ({ (/hz, 2) /o/mul }, "/hz") /o/defn,
/octave/up,
# the function, as the messages it is made of
(/octave/up) /o/inspect

And so is the machine’s own memory. />/_e puts the environment on the table: every name this program has bound, as one bundle. This is what would travel if the program moved to another machine. (The two empty bundles are scope markers; the tour explains them.)

/freq : 440,
/octave/up : ({ (/hz, 2) /o/mul }, "/hz") /o/defn,
# the machine's memory: everything bound so far
/>/_e

The guided tour of osen goes on from here — choosing, lists, folding, and how names are found.

Where it runs

The same machine runs in each of these, a program written for one runs on the others, and any of them can send a program to any other, and most can send a running one.


Try it · Start · Overview · Hosts · Examples