マクロとインクルード・ファイルの使用
ここでは、マクロと (マクロが含まれる) インクルード・ファイルを定義して使用する方法について説明します。InterSystems IRIS® データ・プラットフォームには、システム・マクロが用意されており、こちらも使用できます。
インクルード・ファイルというフレーズは、これまでの経緯から使用されていますが、残念ながらいくらかの混乱も生じさせています。InterSystems IRIS では、インクルード・ファイルは、実際にはファイル (オペレーティング・システム内の個別のスタンドアロンのファイル) ではありません。クラスやルーチンと同じように、インクルード・ファイルは、InterSystems IRIS データベース内に保存されるコード・ユニットです。
その他のコード要素の場合と同様に、適切な IDE により、インクルード・ファイルを作成するオプションが提供され、コードがデータベースに正しく保存されます。同様に、IDE がソース・コントロール・システムに接続されている場合、各コード要素は、ソース・コントロールを介して管理される外部ファイルに投影されます。
マクロの基本情報
マクロは、便利な置換表現として以下のように定義して使用できます。
-
マクロは特殊な構文、通常は #define 指示文を介して定義します。以下に例を示します。
#define StringMacro "Hello, World!"
この構文は、StringMacro と呼ばれるマクロを定義します。このマクロ名の大文字と小文字は区別されます。
-
後で、このマクロを構文 $$$macroname を使用して呼び出せます。
write $$$StringMacro
前述した構文は、以下と等価です。
write "Hello, World!"
この置換は、コード (クラスまたはルーチン) のコンパイル時に行われます。特に、クラスまたはルーチン自体が変更されていなくても .INT コードが生成されている場合は、置換が行われたことを示しています (コードがどのようにコンパイルされるかについての詳細は、"これらのコード要素がどのように連携しているか" を参照してください)。
マクロはテキスト置換であることに注意してください。置換が実行されたら、結果として生成される文は、構文的に正しいものである必要があります。したがって、式を定義するマクロは、式を必要とするコンテキスト内で呼び出される必要があります。また、コマンドとその引数に対するマクロは、ObjectScript の独立した行として置くことができます。
インクルード・ファイルの基本情報
通常、マクロはインクルード・ファイル内で定義します。その後、このインクルード・ファイルをその他のコード内に含めて、そのコードがマクロを参照できるようにします。これは、以下のように機能します。
-
インクルード・ファイルは、データベース内に格納される特殊な種類のコード・ユニットです。以下は、部分的な例です。
#; Optional comment lines #define RELEASEID $GET(^MyGlobal("ReleaseID"),"") #define RELEASENUMBER $GET(^MyGlobal("ReleaseNumber"),"") #define PRODUCT $GET(^MyGlobal("Product"),"") #define LOCALE $GET(^MyGlobal("Locale"),"en-us")
各行はコメント行であるか、#define 指示文で開始することに注意してください。空白行も許可されます。より複雑なマクロを定義できる #define の代替手段もありますが、それらについては別の場所でより詳しく説明します。
一般的なシナリオでは、IDE でインクルード・ファイルを作成し、それを MyMacros のような特定の名前で保存します。
-
マクロを使用する必要のあるクラスまたはルーチン内に、インクルード・ファイルを含めます。以下に例を示します。
include MyMacros Class MyPackage.MyClass { // }
この例では、インクルード・ファイルの名前は MyMacros です。
この手順により、MyMacros のマクロがクラスまたはルーチン内で使用できるようになります。
ルーチンごとに異なる構文のすべてのバリエーションについては、"インクルード・ファイルを含める方法" を参照してください。
-
同じクラスまたはルーチン内で、構文 $$$macroname を使用してマクロを参照します。以下に例を示します。
set title=$$$PRODUCT_" "_$$$RELEASENUMBER
実行されるテキストでは、インクルード・ファイル名に通常 .inc を追加します。例えば、一連の有用なシステム・マクロは %occStatus.inc および %occMessages.inc インクルード・ファイルで定義されています。
マクロの定義
最も基本的な形式では、"マクロの基本情報" で示したように、マクロは #define 指示文を使用して作成されます。
引数を受け入れ、より複雑なシナリオをサポートするマクロを定義できるようにする、追加の指示文もあります。また、##continue を使用して、#define 指示文を次の行に継続することもできます。詳細は、"システム・プリプロセッサ・コマンド・リファレンス" を参照してください。
ここでは、マクロを定義できる場所、マクロ定義に含めることができる内容、マクロ名のルール、マクロ内での空白の使用、およびマクロのコメントに関する情報を提供します。
マクロを定義する場所
マクロは以下の場所で定義できます。各場所が、マクロの可用性に影響を及ぼします。
-
インクルード・ファイル内でマクロを定義できます。この場合、マクロは必要なインクルード・ファイルを含む任意のコード内で利用できます。
クラスにインクルード・ファイルが含まれる場合、そのクラスのサブクラスには自動的に同じインクルード・ファイルが含まれます。
-
メソッド内でマクロを定義できます。この場合、マクロはそのメソッド内で利用できます。
-
ルーチン内でマクロを定義できます。この場合、マクロはそのルーチン内で利用できます。
許可されるマクロ定義
以下はサポート対象の機能です。
-
上記の例のような文字列置換
-
数値置換
#define NumberMacro 22
#define 25M ##expression(25*1000*1000)
通常、ObjectScript のマクロ定義では、文字列には引用符が必要ですが、数値には必要ありません。
-
変数置換
#define VariableMacro Variable
マクロ名は、既に定義済みの変数名に置換されます。変数が未定義の場合、<UNDEFINED> エラーが発生します。
-
コマンドと引数の呼び出し
#define CommandArgumentMacro(%Arg) WRITE %Arg,!
マクロ引数名は、上記の %Arg 引数のように、% 文字で始まる必要があります。このマクロは、%Arg 引数を使用する WRITE コマンドを呼び出します。
-
関数、式、演算子の使用
#define FunctionExpressionOperatorMacro ($ZDate(+$Horolog))
ここでは、マクロ全体が式で、その値は、$ZDate 関数の返り値になります。$ZDate は、システム変数 $Horolog に格納されているシステム時刻に + 演算子を付けた演算の結果として生じる式を処理します。上記のように、式を括弧で囲むことをお勧めします。これにより、式が使用されている文とのやり取りが最小限に抑えられます。
-
他のマクロの参照
#define ReferenceOtherMacroMacro WRITE $$$ReferencedMacro
このマクロは、WRITE コマンドへの引数として、他のマクロの式の値を使用します。
Note:1 つのマクロが別のマクロを参照する場合、参照先のマクロは、参照元のマクロの前にコンパイル済みのコード行に表示されている必要があります。
マクロの名前付け規約
-
最初の文字は、英数字またはパーセント記号 (%) でなくてはならない。
-
2 番目以降の文字は英数字でなくてはならない。マクロ名には、スペース、アンダースコア、ハイフンなどの記号文字を含めることはできません。
-
マクロ名では大文字と小文字が区別される。
-
マクロ名は最長 500 文字。
-
マクロ名には日本語の全角文字および半角かな文字を使用可能。詳細は、"パターン・マッチ演算子 (?)" にある "パターン・コード" のテーブルを参照してください。
-
ISCname.inc ファイルがシステム用に予約されているため、マクロ名を ISC で開始することはできません。
マクロの空白規約
-
規約では、マクロ指示文をインデントさせずに、列 1 にて記述することになっています。しかし、マクロ指示文はインデントさせても構いません。
-
1 つ以上のスペースをマクロ指示文に続けることができます。マクロ内では、任意数のスペースをマクロ指示文、マクロ名、マクロ値の間に入れることができます。
-
マクロ指示文は単一行の文となります。マクロ指示文、マクロ名、およびマクロ値はすべて同一行で記述する必要があります。##continue を使用すると、マクロ指示文を次の行に継続できます。
-
#if 指示文と #elseIf 指示文はテスト式の形をとります。テスト式にはスペースを含めることはできません。
-
#if 式、#elseIf 式、#else 指示文、および #endif 指示文はすべて、それぞれの独立した行に記述します。同一行にてこれらの指示文のいずれかに続くものはコメントと見なされるので、解析はされません。
マクロ・コメントとスタジオ・アシスト
マクロには、その定義の一部として渡すコメントを記述できます。/* と */、//、#;、;、および ;; で区切ったコメントは、すべて通常どおりに機能します。"コメント" を参照してください。
/// で始まるコメントには特別な機能があります。インクルード・ファイルにあるマクロでスタジオ・アシストを使用する場合、マクロの定義の直前の行に /// コメントを記述します。これにより、そのマクロの名前がスタジオ・アシストのポップアップに表示されます (現在のファイルにあるすべてのマクロがスタジオ・アシストのポップアップに表示されます)。例えば、以下のコードを #include 指示文で参照する場合、最初のマクロの名前はスタジオ・アシストのポップアップに表示されますが、2 番目のマクロの名前は表示されません。
/// A macro that is visible with Studio Assist
#define MyAssistMacro 100
//
// ...
//
// A macro that is not visible with Studio Assist
#define MyOtherMacro -100
インクルード・ファイルでマクロを使用可能にする方法については、"インクルード・ファイルを含める方法" を参照してください。
インクルード・ファイルを含める方法
ここでは、コードにインクルード・ファイルを含める方法について説明します。
-
クラス内またはルーチンの開始部にインクルード・ファイルを含めるには、以下の形式で指示文を使用します。
#include MacroIncFile
ここで、MacroIncFile は、MacroIncFile.inc と呼ばれるマクロを含むインクルード・ファイルを参照しています。参照先ファイルが #include の引数となっている場合には、.inc 接尾語が参照先ファイルの名前に含まれないことに注意してください。#include 指示文では大文字と小文字は区別されません。
クラスにインクルード・ファイルが含まれる場合、そのクラスのサブクラスには自動的に同じインクルード・ファイルが含まれます。
例えば、MyMacros.inc というファイルに 1 つ以上のマクロがある場合、以下の呼び出しに組み込むことができます。
#include MyMacros
-
1 つのルーチン内に複数のインクルード・ファイルを含めるには、同じ形式の複数の指示文を使用します。以下に例を示します。
#include MyMacros #include YourMacros
-
クラス定義の開始部に複数のインクルード・ファイルを組み込むには、構文を以下の形式とします。
include (MyMacros, YourMacros)
この include 構文には、先頭にシャープ記号がないことに注意してください。この構文は #include には使用できません。
#include のリファレンス・セクションを参照してください。
クラス定義をコンパイルすると、そのプロセスによってさまざまな方法で (空白の削除など) クラス定義が正規化されることに注意してください。このような正規化の一環として、include 指示文の大文字と小文字が変換されます。
ObjectScript コンパイラは、外部マクロを含めることを許可する /defines 修飾子を提供します。詳細は、"$SYSTEM" リファレンス・ページの "コンパイラ修飾子" を参照してください。
マクロが拡張される条件
前述のように、クラスやルーチンをコンパイルする際は、システムにより INT コード (中間 ObjectScript) コードが生成されます。この INT コードを表示し、読み取ることで、ある種のトラブルシューティングの実行に役立ちます。
プリプロセッサは、ObjectScript パーサによって埋め込み SQL が処理される前にマクロを拡張します。プリプロセッサは、埋め込みまたは遅延いずれかのコンパイル・モードの埋め込み SQL をサポートしています。プリプロセッサは、ダイナミック SQL でのマクロ拡張は行いません。
ObjectScript パーサは、プリプロセッサ指示文を解析する前に、複数の行から成るコメントを削除します。そのため、/* と */ で囲んで記述した複数行コメントの中で指定したマクロ・プリプロセッサ指示文は、実行されません。
また以下のグローバルには MAC コード (元のソース・コード) が含まれます。これらのグローバルとその添え字を表示するには、ZWRITE を使用します。
-
^rINDEX(routinename,"MAC") には、MAC コードが変更後に最後に保存された日時を表すタイムスタンプと、この MAC コード・ファイルの文字数が含まれます。文字数には、コメントおよび空白行が含まれます。MAC コードが最後に保存された日時を表すタイムスタンプ、コンパイルされた日時を表すタイムスタンプ、および使用された #include ファイルに関する情報は、.INT コードの ^ROUTINE グローバルに記録されます。.INT コードの詳細は、"ZLOAD" コマンドを参照してください。
-
^rMAC(routinename) には、MAC ルーチンの各コード行の添え字ノードが含まれます。また、^rMAC(routinename,0,0) には行数、^rMAC(routinename,0) には MAC ルーチンが最後に保存された日時のタイムスタンプ、^rMAC(routinename,0,"SIZE") には文字数がそれぞれ含まれます。
-
^rMACSAVE(routinename) には、MAC ルーチンの履歴が含まれます。ここには、保存された過去の MAC ルーチン・バージョン 5 つ分の ^rMAC(routinename) と同じ情報が含まれます。現在の MAC バージョンに関する情報は含まれません。