コード生成の概念
TLC は一般的なプログラミング言語であるターゲット言語を解釈し、そのようなものとして使用できます。ただし、TLC は
ファイルを生成コードに変換するという 1 つの目的のために設計されたものであることに留意してください。そのため、ターゲット言語には、そのタスクに便利な機能は多数用意されていますが、C や C++ などの他の言語で提供されている機能の一部は提供されていません。model
.rtw
ここでは、TLC 内で使用される基本的な構成要素について理解するのに役立つ一般的なプログラミング例をいくつか示します。
出力ストリーム
ターゲット言語の簡単な例として、典型的な "Hello World" の例について考えてみます。hello.tlc
という名前のファイルに次のように入力します。
%selectfile STDOUT Hello, World
この TLC プログラムを実行するには、次のように入力します。
tlc hello.tlc
これは MATLAB® プロンプトで行います。
この簡単なスクリプトは、TLC の目的 (つまりは設計) の基となるいくつかの重要な概念を示しています。主要な目的はコードを生成することであるため、TLC は出力 (またはストリーム) 指向です。そのため、テキストのバッファーの扱いが簡単で、それらを簡単に出力できます。上記のスクリプトの %selectfile
命令は、TLC で生成されるか認識されないあらゆる後続のテキストを標準の出力デバイスに送信するように TLC に指示しています。TLC で認識される構文は %
文字で始まります。Hello, World
は認識されないため、出力にそのまま送信されます。出力先をファイルに簡単に変更できます。STDOUT
ストリームは開かないでください。代わりに、コマンド ウィンドウに書き込むように選択します。
%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
バッファーを切り替えてステータス メッセージを表示できます。3 つの命令 %openfile
、%selectfile
、および %closefile
のセマンティクスについては、Target Language Compiler Directivesで説明しています。
変数の型
もう 1 つの特徴として、TLC には変数の明示的な型宣言がありません。変数の暗黙的なデータ型の詳細については、Target Language Compilerを参照してください。
レコード
ファイルからのコード生成に最も関連する構成要素の 1 つにレコードがあります。"レコード" は、C の構造体や Pascal のレコードに似ています。レコードの宣言の構文は次のとおりです。model
.rtw
%createrecord recVar { ... field1 value1 ... field2 value2 ... ... fieldN valueN ... }
ここで、recVar
は宣言するレコードの名前、fieldi
は文字列、valuei
は対応する TLC の値です。
レコード内に入れ子になったレコード (下位レコード) を含めることができます。
ファイルは、本質的には、複数のレベルの下位レコードを含む model
.rtwCompiledModel
という名前の 1 つの大きなレコードです。
MATLAB とは異なり、TLC では同じターゲット ファイル内にない関数定義は明示的に読み込む必要があります。MATLAB では、A = myfunc(B)
の行により、myfunc
という名前の MATLAB ファイルまたは MEX ファイルが MATLAB で自動的に検索されて読み込まれます。TLC では、%addincludepath
命令を使用して、関数を定義するファイルを明確に含める必要があります。
TLC には、レコードを使用する際に便利な %with
命令が用意されています。Target Language Compiler Directivesを参照してください。
メモ:
ファイルのフォーマットや構造は、コード ジェネレーターのリリースごとに変更になる可能性があります。model
.rtw
ファイルから読み取ったレコードは、プログラムで宣言する他のレコードと同様に変更が可能です。レコード CompiledModel
は、コード生成中に何度も変更されます。CompiledModel
は
ファイルにあるグローバル レコードです。model
.rtwNumNonvirtSubsystems
や NumBlocks
など、コード生成に使用される変数が格納されます。また、コード生成中に、多くの新しい変数、オプション、下位レコードが追加されていきます。
LibGetFormattedBlockPath
などの関数は、
(開く) にある TLC ライブラリで提供されています。使用可能な関数の完全な一覧については、Target Language Compilerの「TLC 関数ライブラリ リファレンス」を参照してください。matlabroot
/rtw/c/tlc/lib/*.tlc
レコードのフィールドへの値の代入
レコードのフィールドに値を代入するには、"修飾子付き変数式" を使用する必要があります。修飾子付き変数式では、次のいずれかの形式で変数を参照します。
識別子
修飾子付き変数の後に "
.
" に続けて識別子を指定した次のような形式var[2].b
修飾子付き変数の後にかっこで囲んで式を指定した次のような形式
var[expr]
レコードのエイリアス
TLC では、レコードに対する "エイリアス" を作成できます。エイリアスは、C の構造体へのポインターに似ています。単一のレコードに対して複数のエイリアスを作成できます。エイリアスされたレコードに対する変更は、エイリアスを保持するすべての場所で認識されます。
次のコード フラグメントは、エイリアスの使用法を示しています。
%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
このスクリプトを record_alias.tlc
として保存し、次のように呼び出します。
tlc -v record_alias.tlc
次の出力が生成されます。
ISALIAS(a.foo) = 1 ISALIAS(b.foo) = 1 ISALIAS(c.foo) = 0 a.foo.field = 2 b.foo.field = 2 c.foo.field = 1
関数の内部では、その関数内にあるローカルで作成したレコードに対するエイリアスを作成できます。次の例に示すように、関数からエイリアスが返されると、関数の終了後も有効なままになります。
%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>
このスクリプトを alias_func.tlc
として保存し、次のように呼び出します。
tlc -v alias_func.tlc
次の出力が生成されます。
ISALIAS(a.foo) = 1 ISALIAS(x) = 1 x = { field 2 } x.field = 2
レコードにエイリアスによる何らかの参照がある限り、そのレコードは削除されません。そのため、レコードは関数からの戻り値として使用できます。