Installation
Windows
To install ExMachina in Windows, follow these steps:
- Download the latest version of ExMachina.exe here.
- Extract the zip file in the desired location.
- Run ExMachina.exe. Some Windows versions might try to prevent the app from running, depending on your local configuration. If that is the case, select 'Run Anyway'.
- When prompted, accept to Check for updates.
- Wait for all files to download.
- Once all required files are downloaded, ExMachina will automatically start.
- Check the Quick Start Guide for instructions on how to create and run a basic program.
Linux
To install ExMachina on Linux, follow these steps:
- On Linux, Java 21 or higher should be installed in the computer before installing ExMachina.
- Download the latest version of ExMachina.jar here.
- Extract the zip file in the desired location.
- Run ExMachina.exe
- When prompted, accept to Check for updates.
- Wait for all files to download.
- Once all required files are downloaded, ExMachina will automatically start.
- Check the Quick Start Guide for instructions on how to create and run a basic program.
Note:
macOS is not currently supported.
Quick Start Guide
Hello World
Before you start:
Make sure that ExMachina is correctly installed in your computer and running. If not, follow the steps at Installation.
To create a simple program that prints "Hello World!" to the console, follow these steps:
1. Click on the Programmer tab.
2. Click on the Projects menu, then on New Project.
3. The New Project window will appear. Fill all fields as indicated in the image, then press the Create project button.
4. Click on the Add block menu, then on Add constant (alternatively, you can type Ctrl+K).
The Add constant window will appear. Write "Hello World" in the text area, then press the Add constant button.
6. A constant block will be placed on the board. You can move constant blocks by dragging them with the left mouse button from the left area, where the value of the constant is displayed (in this case, the white area that says "Hello world").
7. Click on the Add block menu, then click on Imported Machines (or press Ctrl+B).
8. The Add machine block window will appear. In the Imported Machines tree, click on "ex".
9. Click on "actor".
10. Click on "println(T%%class;*msg)".
11. Press the Add block button.
12. A machine block will be added to the board. Machine blocks can be moved by dragging them with the left mouse button from the top area where the machine name is displayed (in this case the green area that says "println").
13. Click on the Add block menu, then click on Imported Machines (or type Ctrl+B).
14. On the Imported machines tree of the Add machine block window, click on "ex", then on "actor", then on "stop(;*msg)". Press the Add block button.
15. A new machine block will be placed labeled "stop". If it is not visible, it might have been placed behind the "println" block. In that case, just drag the "println" block out of the way.
16. Click the Add block menu, then click Add machine block, then click Elemental machines (or type Ctrl+L).
17. The Add machine block window will appear. Click on "Arrays".
18. Click on "bind".
19. Press the Add block button.
20. Right-click on the blue square on the right side of the "println" block, and without releasing it drag it to the first yellow area on the left side of the "bind" block that says "*class".
21. In the same manner, connect the blue square on the right of the "stop" block to the second gray area on the left side of the "bind" block that says "*msg".
22. Connect the blue square on the "Hello World" constant block to the yellow area that says "class" on the "println" block.
23. Click on the Add block menu, then on Set terminal (or type Ctrl+R).
24. The Specify terminal block window will appear. Select "Out", then press the Accept button.
25. A terminal block labeled "Out" will appear. Terminal blocks can be moved in the same way as machine blocks. Connect the blue square at the right of the "bind" block with the gray area at the left of the Out block that says "*msg".
26. Click on the Projects menu, then on Save select the project (or press Ctrl+S). The line "Project myname%mylibrary%helloWorld was successfully saved" should appear on the console.
27. Click on the Projects menu, then on Compile selected project (or press Ctrl+P). The lines "Project myname%mylibrary%helloWorld was successfully compiled" and "Project myname%mylibrary%helloWorld was imported" should appear on the console.
28. Click on the Executables tab.
29. Double-click on "myname" in the Executable machines tree.
30. Double-click on "mylibrary".
31. Double-click on "HelloWorld". This will create an executable instance of your helloWorld program.
32. The line "Hello World" will be printed to the console, and then the instance of the program will terminate.
Actors in ExMachina
Actors in ExMachina have the following basic components.
- A message accumulator: messages received by the actor are placed in the message accumulator while they wait their turn to be evaluated. They are evaluated in the order that they were received. A message consists of an id, which can be any arbitrary string, a 'destination', which is the id of the actor that is meant to receive the message, a 'source', a 'type', which should indicate the purpose of the message, and a 'payload', which is a token of an arbitrary type. The source might be the ID of the sending actor, but this is not mandatory and the actual implementation is up to the user. It is strongly recommended that knowing the 'source' and 'type' of a message is enough to determine the type of the 'payload', but this is not mandatory.
- A main machine: any machine can be used as the main machine of an actor as long as its only input is a cx token, and its only output is an array of msg tokens (cx;*msg). Every time that a received message is evaluated, the main machine is executed. This is referred to as an event evaluation cycle (eval-cycle). The message can be accessed from the cx token during its eval cycle.
- A temporary storage (TS). The TS is a look-up table where any token can be associated with a string identifier. The TS can be read from the cx token at any moment, but it can only be modified after each eval cycle.
- A parent actor (unless the actor is the base of the actor tree. See Programs as Actor Trees.).
- A set of child actors: see Programs as Actor Trees.
- A set of connectors: Connectors are pre-established special actors that can communicate with entities external to the system. Connectors are the only way to interact with the console, to create and interact with GUIs, to send and receive HTTP messages, to interact with the serial port, etc. Each actor has one connector of each possible type already instantiated. They cannot be created, nor deleted.
Programs as Actor Trees
Executable programs in ExMachina are structured as actor trees. When an executable machine is selected to be run, an actor with that machine as its main machine is created. That actor is the base node of the program's tree. Actors can create more actors as their children, and can also destroy them. If an actor terminates for any reason, all its descendants will terminate as well. An actor can only send or receive messages from its parent, its children, or its connectors.
Interacting with the TS
The following machines can be used to interact with the temporary storage:
- ex%actor%toTS: writes a message that stores a token in the temporary storage under a given key.
- ex%actor%deleteTS: writes a message that removes the token associated with a given key from the temporary storage.
- ex%actor%rdTS: tries to retrieve a token from the temporary storage.
Managing Actors
The following machines can be used to administrate child actors.
- ex%actor%createChildFromMachine: writes a message that requests the creation of a child actor with a given machine as its main machine. If the child actor is successfully created, the parent actor receives a message of type 'child created' with a string array as payload. The first element of the array is the ID of the original message, and the second element is the ID of the child actor. If the child actor cannot be created, the parent actor receives a message of type 'failure'.
- ex%actor%removeChild: writes a message that requests the termination of a child actor. If the child actor was successfully terminated, the parent actor receives a message of type 'childRemoved' with the id of the original message as payload. If the child actor is not found, the parent actor receives a message of type 'failure'.
- ex%actor%getActorId: returns the id of the actor from which it is called.
Sending Messages to Actors
To send an arbitrary message to an actor, first, the message must be written using the 'writemsg' elemental machine, then the message must be included in the output message array. To send a message to a child actor, the 'destination' input of 'writemsg' should be the id of the child. To send a message to a connector, the 'destination' input of 'writemsg' should be the name of the connector. To send a message to the parent actor, the 'destination' input of 'writemsg' should be 'parent'. For an actor to send a message to itself, the input of 'writemsg' should be 'self'.