Operator invocation head
The head of an operator invocation lists the output and input streams and the name of the operator that processes the data.

All the other information that pertains to the operator invocation is in the operator invocation body, making it possible for users to quickly scan a program's topology. The following SPL code is an example of the more advanced features of operator invocation heads:
composite Main {
graph
stream<list<int32> n, float64 i> SomeLongNameForAnInputStream = Beacon() {}
stream<float64 i> FirstStreamInSecondPort = Beacon() {}
stream<FirstStreamInSecondPort> SecondStreamInSecondPort = Beacon() {}
( stream<int32 a1, int32 a2> SomeLongNameForAnOutputStream as A;
stream<float64 b> AnotherLongNameForAnOutputStream as B
) = MyOperator(
SomeLongNameForAnInputStream as C;
stream<float64 i> FirstStreamInSecondPort, SecondStreamInSecondPort as D
) {
output A: a1=1, a2=max(n);
B: b = C.i + D.i;
}
}
opInvokeHead ::= opOutputs ( 'as' ID )? '=' ID opInputs
opOutputs ::= opOutput | '(' opOutput*; ‘)'
opOutput ::= streamTypeID ( ‘as' ID )?
opInputs ::= '(' portInputs*; ')'
portInputs ::= streamType? ID+, ( 'as' ID )?
A port is a point at which streams connect to an operator invocation. The figure shows ports as little triangles. Each output port produces exactly one output stream, but an input port can combine more than one input stream. When there is exactly one output port, the parentheses around the outputs can be omitted.
The syntax allows as-clauses in three places. The top-level as-clause gives an operator instance name; an as-clause on an output port gives an output port alias; and an as-clause on an input port gives an input port alias. When there are zero output ports, the empty parentheses and the top-level as-clause with the operator instance name are mandatory, for example, () as A = B(). The as-clauses with port aliases, however, are always optional, and are useful to make the operator invocation body more readable by providing a local short name.
Types on input streams are redundant because they also occur when those streams are defined as outputs of other operator invocations. Nevertheless, you can optionally specify these types when you feel that they make code more readable. This specification can also lead to more understandable compiler error messages when there is a type mismatch. When there are multiple streams on the same input port, tuples that are coming from different streams are interleaved. The order of the interleaving is non-deterministic in the sense that no particular order is imposed by the run time.
streamType ::= 'stream' '<' tupleBody '>'
If there are multiple input streams on the same port, they must all have the same type. If the type of an input port is explicitly specified, it must be equivalent to the type of the streams that are connecting to it. The tupleBody component of the stream type can be either a list of attributes, or a list of tuple types (extension), where identifiers can refer to types of other streams by their stream names. For details, see Tuples.