Code Generation Concepts
TLC interprets a target language, which is a general programming language, and you can use
it as such. It is important, however, to remember that TLC was designed for one purpose: to
convert a
file to generated code.
Thus, the target language provides many features that are useful for this task but does not
provide some of the features that other languages like C and C++ provide.model
.rtw
You might find some of the following general programming examples useful to familiarize yourself with the basic constructs used within TLC.
Output Streams
The typical “Hello World” example is rather simple in the target language.
Type the following in a file named hello.tlc
:
%selectfile STDOUT Hello, World
To run this TLC program, type
tlc hello.tlc
at the MATLAB® prompt.
This simple script illustrates some important concepts underlying the purpose (and hence
the design) of TLC. Since the primary purpose of TLC is to generate code, it is output (or
stream) oriented. It makes it easy to handle buffers of text and output them easily. In the
above script, the %selectfile
directive tells TLC to send
any following text that it generates or does not recognize to
the standard output device. Syntax that TLC recognizes begins with the %
character. Because Hello, World
is not recognized, it is sent directly to
the output. You could easily change the output destination to be a file. Do not open the
STDOUT
stream, but select to write to the Command Window.
%openfile foo = "foo.txt" %openfile bar = "bar.txt" %selectfile foo This line is in foo. %selectfile STDOUT Line has been output to foo. %selectfile bar This line is in bar. %selectfile NULL_FILE This line will not show up anywhere. %selectfile STDOUT About to close bar. %closefile bar %closefile foo
You can switch between buffers to display status messages. The semantics of the three
directives %openfile
, %selectfile
, and
%closefile
are given in Target Language Compiler Directives.
Variable Types
The absence of explicit type declarations for variables is another feature of TLC. See Target Language Compiler for more information on the implicit data types of variables.
Records
One of the constructs most relevant to generating code from the
file is a record. A
record is similar to a structure in C or a record in Pascal. The syntax of a record
declaration ismodel
.rtw
%createrecord recVar { ... field1 value1 ... field2 value2 ... ... fieldN valueN ... }
where recVar
is the name of the record being declared,
fieldi
is a string, and valuei
is the corresponding
TLC value.
Records can have nested records, or subrecords, within them. The
file is essentially one large
record, named model
.rtwCompiledModel
, containing levels of subrecords.
Unlike MATLAB, TLC requires that you explicitly load function definitions not located in the
same target file. In MATLAB, the line A = myfunc(B)
causes MATLAB to automatically search for and load a MATLAB file or MEX-file named myfunc
. TLC requires that you
specifically include the file that defines the function using the
%addincludepath
directive.
TLC provides a %with
directive that facilitates using records. See
Target Language Compiler Directives.
Note
The format and structure of the
file are subject to change from
one release of the code generator to another.model
.rtw
A record read in from a file is changeable, like other records that you declare in a
program. The record CompiledModel
is modified many times during code
generation. CompiledModel
is the global record in the
file. It contains variables used
for code generation, such as model
.rtwNumNonvirtSubsystems
,
NumBlocks
. It is also appended during code generation with many new
variables, options, and subrecords.
Functions such as LibGetFormattedBlockPath
are provided in TLC
libraries located in
(open). For a complete
list of available functions, refer to TLC Function Library Reference on Target Language Compiler.matlabroot
/rtw/c/tlc/lib/*.tlc
Assign Values to Fields of Records
To assign a value to a field of a record, you must use a qualified variable expression. A qualified variable expression references a variable in one of the following forms:
An identifier
A qualified variable followed by “
.
” followed by an identifier, such asvar[2].b
A qualified variable followed by a bracketed expression such as
var[expr]
Record Aliases
In TLC, it is possible to create what is called an alias to a record. Aliases are similar to pointers to structures in C. You can create multiple aliases to a single record. Modifications to the aliased record are visible to every place that holds an alias.
The following code fragment illustrates the use of aliases:
%createrecord foo { field 1 } %createrecord a { } %createrecord b { } %createrecord c { } %addtorecord a foo foo %addtorecord b foo foo %addtorecord c foo { field 1 } %% notice we are not changing field through a or b. %assign foo.field = 2 ISALIAS(a.foo) = %<ISALIAS(a.foo)> ISALIAS(b.foo) = %<ISALIAS(b.foo)> ISALIAS(c.foo) = %<ISALIAS(c.foo)> a.foo.field = %<a.foo.field> b.foo.field = %<b.foo.field> c.foo.field = %<c.foo.field> %% note that c.foo.field is unchanged
Saving this script as record_alias.tlc
and invoking it with
tlc -v record_alias.tlc
produces the output
ISALIAS(a.foo) = 1 ISALIAS(b.foo) = 1 ISALIAS(c.foo) = 0 a.foo.field = 2 b.foo.field = 2 c.foo.field = 1
When inside a function, it is possible to create an alias to a locally created record that is within the function. If the alias is returned from the function, it remains valid even after exiting the function, as in the following example:
%function func(value) Output %createrecord foo { field value } %createrecord a { foo foo } ISALIAS(a.foo) = %<ISALIAS(a.foo)> %return a.foo %endfunction %assign x = func(2) ISALIAS(x) = %<ISALIAS(x)> x = %<x> x.field = %<x.field>
Saving this script as alias_func.tlc
and invoking it with
tlc -v alias_func.tlc
produces the output
ISALIAS(a.foo) = 1 ISALIAS(x) = 1 x = { field 2 } x.field = 2
As long as there is some reference to a record through an alias, that record is not deleted. This allows records to be used as return values from functions.