Target Language Compiler    

Anatomy of a TLC Script

Let's dissect the script we just ran. Each "paragraph" of output from guide.tlc is discussed in sequence in the following brief sections:

Coding Conventions

These are some basic TLC syntax and coding conventions.

%% Comment
TLC comment, which will not be output
/* comment */
Comment, to be output
%keyword
TLC directives start with "%"
 . (period)
Scoping operator, e.g., Top.Lev2.Lev3
... (at end-of-line)
Statement continuation (no line break output)
\ (at end-of-line)
Statement continuation (line break is output)
localvarIdentifier
Local variables start in lowercase
GlobalvarIdentifier
Global variables start in uppercase
RecordIdentifier
Record identifiers start in uppercase
EXISTS()
TLC built-in functions are named in uppercase
Note: All TLC identifiers are case-sensitive.

For further information, see TLC Coding Conventions.

File Header

read-guide.tlc begins with

The first three lines are comments. All text on a line following the characters "%%" is treated as a comment (ignored, not interpreted or output).

The fourth line, as explained in the third line, is the TLC directive (keyword) %realformat, which controls how subsequent floating-point numbers will be formatted when output. Here we want to minimize the digits displayed.

Token Expansion

The first section of output is produced by the script lines:

The first two lines (and any line that contains no TLC directives or tokens) are simply echoed to the output stream, including leading and trailing spaces.

The third and fourth lines will be explained momentarily.

The last line evaluates (expands) the record Top.Date. More precisely, it evaluates the field called Date existing in the scope called Top. The syntax %<expr> causes expression expr (which can be a record, a variable, or a function) to be evaluated. This operation is sometimes referred to as an eval.

The third line creates a variable named td and assigns a string value to it. The %assign directive creates new and modifies existing variables. Its general syntax is:

The optional double colon prefix specifies that the variable being assigned to is a global variable. In its absence, a local variable in the current scope is created or modified.

The fourth line prints out as

In order to enable the TLC to print "%<Top.Date>" without expanding it beforehand, the preceding line was needed to construct that string by pasting together two literals:

As discussed under "String Processing Plus" below, the plus operator concatenates strings as well as adds numbers.

General Assignment

The second section of output is produced by the script lines:

The first line is simply echoed to output. The second line is an assignment of a field called FirstName in the Top.Employee record scope to a new local variable called worker.

As the second line does not produce output, it was necessary to add a line to show what it is. The third line, therefore, repeats the previous statement, making it visible by enclosing it in quotation marks.

The fourth line then indicates what the assignment caused to happen, and illustrates the token expansion that took place.

String Processing Plus

The next section of the script illustrates string concatenation, one of the uses of the overloaded "+" operator:

The second line performs the concatenation, the third line echoes it, and the fourth line describes the operation, in which a variable is concatenated to a field separated by a space character. An alternative way to do this, without using the + operator, is

The alternative method uses evals of fields and is equally efficient.

The + operator, which is associative, also works for numeric types, vectors, matrices, and records:

Arithmetic Operations

The TLC provides a full complement of arithmetic operators for numeric data. In the next portion of our TLC script, two numeric fields are multiplied:

Again, the second line is the %assign statement that computes the value, which is stored in local variable wageCost, and the third line echoes the operation. Note that the fourth and fifth lines compose a single statement. The ellipsis ("...", typed as three consecutive periods) signals that a statement is continued on the following line, but if the statement has output no line break will be inserted. To continue a statement and insert a line break, use a backslash ("\") in place of "...".

Modifying Records

Once read into memory, records in record files can be modified and manipulated just like variables created by assignment. The next segment of read-guide.tlc replaces the value of record field Top.Employee.GrossRate:

Such changes to records are nonpersistent (because record files are inputs to the TLC; other file types, such as C source code, are the outputs), but can be useful.

Several TLC directives beside %assign may be used to modify records:

  • %createrecord
Creates new top-level records, and may also specify subrecords within them, including name/value pairs.
  • %addtorecord
Adds fields to an existing record. The new fields may be name/value pairs or aliases to existing records.
  • %mergerecord
Combines one or more records. The first record will contain itself plus copies of the contents of all the other records specified by the command, in sequence.
  • %copyrecord
Creates a new record like %createrecord does, except the components of the record come from the existing record specified.
  • %undef var
Removes (deletes) var (a variable or a record) from scope. If var is a field in a record, field is removed from the record. If var is a record array (list), removes the first element of the array; remaining elements remain accessible. Only records created via %createrecord or %copyrecord can be removed.

See Compiler Directives for further details on these related directives.

Traversing Lists

Record files can contain lists, or sequences of records having the same identifier. Our example contains a list of three records identified as Project within the Top scope. List references are indexed, numbered from 0 in the order in which they appear in the record file. Here is TLC code that compiles data from the Name field of the Project list:

The Scope.Record[n].Field syntax is similar to that used in C to reference elements in an array of structs.

While explicit indexing such as the above is perfectly acceptable, it is often preferable to use a loop construct when traversing entire lists, as shown next.

Looping over Lists

By convention, the section of a record file that a list occupies is preceded by a record that indicates how many list elements are present. In model.rtw files such parameters are declared as NumIdent, where Ident is the identifier used for records in the list that follows. In guide.rtw, the Project list looks like this:

Thus the value of NumProject describes how many Project records occur.

The last segment of read-guide.tlc uses a %foreach loop, controlled by the NumProject parameter, to iterate the Project list and manipulate its values. As you recall, the TLC output looks like this:

The TLC statements which generated this output are

After initializing the summation variable diffSum, a %foreach loop is entered, with variable i declared as the loop counter, iterating up to NumProject. The scope of the loop is all statements encountered until the corresponding %endforeach is reached (%foreach loops may be nested).


  Interpreting Records Modify read-guide.tlc