Getting started

The best way to learn a new programming language is to write programs in it. But to write programs, you need to know how to compile and run programs because you frequently want to test whether what you wrote does what you expect.

This tutorial starts with a simple program, whose purpose is less to illustrate the language features than to try working with the compiler. Here is the code:

composite HelloWorld {                                                   
  graph                                                                  
    stream<rstring message> Hi = Beacon() {                              
      param iterations : 1u;                                             
      output Hi : message = "Hello, world!";                             
    }                                                                    
    () as Sink = Custom(Hi) {                                            
      logic onTuple Hi : printStringLn(message);                         
    }                                                                    
}                                                                         

First, focus on getting the program that is compiled and defer the description on how the code works. You get the most out of this tutorial if you try out things as you go along. Therefore, the tutorial frequently has information like the following instructions: make sure that you use a computer on which Teracloud® Streams is installed, and the SPL compiler that is named sc is available. Create a directory that is called HelloWorld on that computer. Create a file in the directory that is called HelloWorld.spl. Enter the sample program text, and then save it. Make sure that you are in that directory, and run the compiler, by entering the following command:

sc -M HelloWorld

This command creates a stand-alone executable file, that is, a program that can run as a single process on a single computer, without requiring a running Teracloud® Streams instance. The -M HelloWorld command-line option specifies that the main composite is called HelloWorld. Each SPL program has one main composite operator. A composite operator is an operator that encapsulates a stream graph, and the stream graph of a main composite can be run as a program. If you ran the compiler as described, and there were no compiler errors, then it created the executable file ./output/bin/standalone. Run the executable file. It prints Hello, world! to the console.

Second, focus on how the code works. Line 1 declares a composite operator: composite HelloWorld { ... }. Line 2 starts a graph clause, which means that Lines 3-9 describe a stream graph. The graph consists of two operator invocations. Line 3 is the head of the first operator invocation: stream<rstring message> Hi = Beacon() invokes operator Beacon to produce a stream Hi whose tuples have one attribute rstring message. Line 7 is the head of the second operator invocation: () as Sink = Custom(Hi) invokes operator Custom, which reads from stream Hi. The () as Sink part indicates that this operator invocation produces no stream (( )), and has the name Sink. Here is a visual representation of this stream graph:

Figure 1. Stream graph of the HelloWorld program

This figure is described in the surrounding text.

The operator invocations are shown as circles, and the stream is shown as an arrow. The operator invocations are decorated at the lower right with little scratch-paper icons that indicate internal state: both Beacon and Sink are stateful in this program. The Beacon operator produces data. In this invocation, Line 4, param iterations : 1u;, tells it to produce just one tuple; the u suffix on the number 1 makes it an unsigned integer, since it would not make sense to have a negative number of iterations. In SPL, users or library writers define operators (like Beacon) and their parameters (like iterations) using a common framework; they are not built into the language. Line 5, output Hi : message = "Hello, world!";, assigns the string "Hello, world!" to attribute message of output stream Hi. Moving on to the second operator invocation, the Custom operator provides a clean slate for custom user logic. Line 8, logic onTuple Hi : printStringLn(message), specifies that upon arrival of a tuple on stream Hi, the program prints the string attribute message from the tuple, followed by a newline character \n.

At this point, you compiled and run a first SPL program, and you understand what it does. This program illustrates only a tiny fraction of SPL, but before you move on to more interesting examples, here is a look at the compiled code. Besides the stand-alone executable file, the compiler also generated several other artifacts. Recall that this example started out from just one directory HelloWorld and with just one file HelloWorld.spl. If you look at the directory after you compile, you will find something like the following structure:

/+ HelloWorld
  /+ HelloWorld.spl   # SPL source code
  /* toolkit.xml      # toolkit index
  /* data             # directory for data read/written by the program
  /* output           # directory for artifacts generated by the compiler
    /* HelloWorld.sab # application bundle file
    /* HelloWorld.adl # ADL (application description language) file
    /* bin            # compiled binaries
      /* standalone   # the standalone executable from earlier
    /* src            # generated C++ source code
      /* operator     # source code for operator invocations
      /* pe           # source code for PEs (processing elements)
      /* standalone   # source code for the standalone file
      /* type         # source code for types

In this listing, authored files (files that are written by hand) are annotated with /+ and generated files (files that are written automatically by the compiler) are annotated with /*. For now, all the generated artifacts are not covered in detail, but you are encouraged to look at a few of them to get a feeling for what they look like.

The purpose of this tutorial is to provide an introduction to SPL. To focus on the essentials, it intentionally omits details that you do not immediately need to know, but can look up at your leisure in the reference documentation. This example gives an example for using the sc command, the SPL compiler. For more information about using the SPL compiler, see the Compiler documentation. This example also uses the toolkit operators Beacon and Custom, and the toolkit function printString. For more information about library operators and functions, see the SPL standard toolkit documentation.