Introduction to ACP and SubScript

Algebra of Communicating Processes (ACP) is a mathematical theory that describes processes and their interaction with each other. Vast majority of all the modern applications rely heavily on multithreading and concurrency. Thus, such a mathematical theory is of a great use when applied in practice.

SubScript is an extension for Scala programming language that makes it possible to describe your applications in terms of ACP. The main benefit from this is that your applications become backed by a strong mathematical theory and, hence, are easy to reason about and more resistant to errors.

For more theoretical information on ACP and SubScript, see the Theory section of this website.

SubScript revolves around the concept of scripts. A script is an expression that is composed of SubScript operands and operators (you can see a mapping between ACP and SubScript operators here. You don’t need to fully understand ACP at this point, the majority of its operators that are used in SubScript will be covered later in this tutorial.). Scripts are executed by SubScript Virtual Machine (VM).

SubScript VM shouldn’t be confused with Java VM, they are two different things. SubScript VM is just an ordinary Scala object.

You can define scripts just like ordinary methods, except that you write script right after def:

script scriptName() = // whatever implementation goes here

What kind of implementation should you put after the = sign? As mentioned above, it must be a valid SubScript expression. SubScript expressions can involve lots of kinds operators and operands, most of which will be covered in later topics. The majority of SubScript operands are blocks of ordinary Scala code that are supposed to be executed by SubScript VM. The majority of SubScript operators define the order of execution of the operands (in sequence, in parallel etc). In order to make your first steps in SubScript, it is reasonable to get introduced to the simplest operators and operands.

First, there is a so-called “normal code” operand. A normal code is simply a piece of code to be executed. You can specify a piece of normal code as follows:

{any valid Scala code goes here}

That is, you just put any valid Scala code between curly braces. For example:

script sayHello = {println("Hello")}
script sayHelloTo(who: String) = {println(s"Hello, $who")}

You might be wondering, why is this operand called “normal code”, why the “code” is “normal”. The “normal” word refers to the way this code is treated by SubScript VM: in this case, it is executed “normally”, without any specific sugar. In contrast, a “threaded code” that will be covered in later tutorials makes the VM launch a new thread and execute the code from it.

In order to execute such scripts with SubScript VM, you should import the SubScript DSL with

import subscript.DSL._

Then, invoke

_execute([sayHello()])

Now that you know about the simplest operand, you can learn about the simplest operator to use these operands with. It is a sequential composition operator. A sequential composition simply tells the SubScript VM to execute two its operands in sequence, one after another. You can write it in two different ways:

{println("Hello")} ; {println("World")}

or

{println("Hello")} {println("World")}

That is, you put either a semicolon ; or a space between the two operands. These scripts will first print “Hello” and then “World” to the console.

Here is the full working example of how it looks in practice:

import subscript.DSL._

object Main {
  def main(args: Array[String]): Unit = _execute([sayHelloToTheWorld])

  script sayHelloToTheWorld = {println("Hello")} ; {println("World")}
}

In the next tutorial, you’ll learn about the parallel composition operators.

Leave a Reply