Introduction Last updated: 2023-08-30

ExMachina is a programming and system-development platform with a visual, dataflow-based, purely functional, array-oriented, event-driven, programming language. It is intended for domain experts or other people who are not full-time programmers who need to implement relatively complex systems or models.

With ExMachina it is simple to make programs that:
  • Are concise, yet readable
  • Are easy to analyze, debug and maintain
  • Can be divided into separate parts and that can then be easily integrated, allowing several people to work on the same project at the same time, or to reuse parts of a project in another one with minimal modifications.
What are the advantages of ExMachina?

Purely functional programming is a great tool that makes it easier to write programs that behave the way they are intended to. Unfortunately, most purely functional programming languages contain a lot of complicated abstractions that can make it difficult to get into them.
ExMachina overcomes this hurdle by using a visual language, which makes function composition simple and makes the way that information flows through the program explicit and clear. Additionally, the fact that all programs are structured as a collection of event-driven actors makes the handling of inputs and outputs, which is another sore point for most functional languages, very straightforward.

Getting Started Last updated: 2023-08-30

Installation

Windows

To install ExMachina in Windows, follow these steps:

  1. Download the latest version of ExMachina.exe here.
  2. Extract the zip file in the desired location.
  3. 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'.
  4. When prompted, accept to Check for updates.
  5. Wait for all files to download.
  6. Once all required files are downloaded, ExMachina will automatically start.
  7. 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:

  1. On Linux, Java 21 or higher should be installed in the computer before installing ExMachina.
  2. Download the latest version of ExMachina.jar here.
  3. Extract the zip file in the desired location.
  4. Run ExMachina.exe
  5. When prompted, accept to Check for updates.
  6. Wait for all files to download.
  7. Once all required files are downloaded, ExMachina will automatically start.
  8. 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.
Programmer
2. Click on the Projects menu, then on New Project.
Programmer
3. The New Project window will appear. Fill all fields as indicated in the image, then press the Create project button.
Programmer
4. Click on the Add block menu, then on Add constant (alternatively, you can type Ctrl+K).
Programmer
The Add constant window will appear. Write "Hello World" in the text area, then press the Add constant button.
Programmer
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").
Programmer
7. Click on the Add block menu, then click on Imported Machines (or press Ctrl+B).
Programmer
8. The Add machine block window will appear. In the Imported Machines tree, click on "ex".
Programmer
9. Click on "actor".
Programmer
10. Click on "println(T%%class;*msg)".
Programmer
11. Press the Add block button.
Programmer
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").
Programmer
13. Click on the Add block menu, then click on Imported Machines (or type Ctrl+B).
Programmer
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.
Programmer
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.
Programmer
16. Click the Add block menu, then click Add machine block, then click Elemental machines (or type Ctrl+L).
Programmer
17. The Add machine block window will appear. Click on "Arrays".
Programmer
18. Click on "bind".
Programmer
19. Press the Add block button.
Programmer
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".
Programmer
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".
Programmer
22. Connect the blue square on the "Hello World" constant block to the yellow area that says "class" on the "println" block.
Programmer
23. Click on the Add block menu, then on Set terminal (or type Ctrl+R).
Programmer
24. The Specify terminal block window will appear. Select "Out", then press the Accept button.
Programmer
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".
Programmer
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.
Programmer
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.
Programmer
28. Click on the Executables tab.
Programmer
29. Double-click on "myname" in the Executable machines tree.
Programmer
30. Double-click on "mylibrary".
Programmer
31. Double-click on "HelloWorld". This will create an executable instance of your helloWorld program.
Programmer
32. The line "Hello World" will be printed to the console, and then the instance of the program will terminate.
Programmer

User Interface Last updated: 2023-08-30

Overview

Overview
#SectionDescription
1Navigation MenuContains the buttons to navigate between different areas of the program.
2Console AreaContains the console, where the program output is displayed.
3Main AreaContains the functionality of the selected section.

Programmer

Programmer
#SectionDescription
1Projects OptionsButton to open the project options. Ex: Save, Open, New, etc.
2Projects Navigation TabsContains the tabs of the projects that are open.
3Project optionsContains the options of the active project internal machines and project settings. Ex: Create new internal machine, Open internal Machine, etc.
4Internal Machine tabsContains the tabs of the internal machines that are open.
5ToolsContains the tools to navigate between the boards of an internal machine and add blocks to the board. Ex: Open board tree, Add machine, etc.
6BoardThis is where you add blocs and connect them to create a program. Main Area

Executables

Executables
#SectionDescription
1Executable MachinesA tree with all executable machines.
2Active ProcessesA list of all currently active processes.
3Start buttonCreates a new process that runs the currently selected executable machine.
4Terminate process buttonTerminates the currently selected processes.

Machines

Machines
#SectionDescription
1Imported Machines treeContains the list of imported machines from the specified folder.
2Imported Directory ActionsContains the actions and details where the imported machines are located.

About

About
#SectionDescription
1About AreaContains the information of the program and the developers.

Console

Console
#SectionDescription
1Console Output AreaContains the output of the program and the errors. From the ExMachine itself and the programs that are running.
2Console Input AreaContains the input of the program. From the ExMachine itself and the programs that are running.

The ExMachina Actor System Last updated: 2024-04-05

A Brief Overview of the Actor Model

The actor model is a paradigm for designing concurrent and distributed systems. The objective is to represent computation as a collection of independent actors communicating through message passing. Each actor encapsulates its state and behavior and can only interact with other actors by sending and receiving messages.

Communication between actors occurs exclusively through message passing. When one actor wants to interact with another actor, it sends a message with specific data. The receiving actor processes the message and may send a response back.

The actor encapsulates its internal state, and only the actor itself can update it. This isolation ensures that actors cannot interfere with other states directly. Any changes to an actor's state must occur through message passing. Each actor operates independently, running on its thread. This concurrency allows the efficient use of resources and can improve system performance.

The actor model proves highly beneficial in dividing tasks suitable for parallel processing. It excels in scenarios where multiple functions can run simultaneously and combine their results before final processing.

The actor model of concurrency is one way to design software that executes several threads at once. Each actor has its process with a single thread that runs independently of the processes of other actors. This model enables efficient utilization of resources, as actors can execute concurrently without blocking each other by distributing actors in multiple processing units. This combination provides a framework for building scalable, responsive, fault-tolerant systems.

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.
Actors Structure
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.

Actors Tree
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'.