##expression
説明
このマクロ・プリプロセッサ関数は、コンパイル時に ObjectScript 式を評価します。以下の形式をとります。
##expression(content)
ここで、content は、引用符で囲まれた文字列または他のプリプロセッサ指示文を含まない、有効な ObjectScript コードです (下記の入れ子にされた ##expression を除く)。
プリプロセッサは、コンパイル時にこの関数の引数の値を評価し、ObjectScript .int コードの評価で ##expression(content) を置き換えます。##expression 内では変数を引用符で囲んで記述する必要があります。そうしない場合、その変数がコンパイル時に評価されます。
以下の例では、簡単な式をいくつか示します。
#define NumFunc ##expression(1+2*3)
#define StringFunc ##expression("""This is"_" a concatenated string""")
WRITE $$$NumFunc,!
WRITE $$$StringFunc,!
以下の例は、現在のルーチンのコンパイル・タイムスタンプを含む式を定義しています。
#define CompTS ##expression("""Compiled: " _ $ZDATETIME($HOROLOG) _ """,!")
WRITE $$$CompTS
ここで、##expression の引数は、3 か所で解析され、_ 演算子を使用して連結されます。
-
最初の文字列、"""Compiled: "。これは、二重引用符で区切られています。その中で、二重引用符のペアは、1 つの二重引用符が評価の後に表示されるように指定しています。
-
値、$ZDATETIME($HOROLOG)。$ZDATETIME 関数により変換および書式設定された、コンパイル時の $HOROLOG 特殊変数の値。
-
最後の文字列、""",!"。これも、二重引用符で区切られています。その中に、二重引用符が 1 組みあります (評価後、1 つの二重引用符となります)。定義される値は WRITE コマンドに渡されるので、WRITE コマンドに改行が含まれるように、最後の文字列には ,! が含まれています。
ルーチンの中間 (.int) コードには、以下のような行が含まれることになります。
WRITE "Compiled: 05/29/2018 07:49:30",!
##expression とリテラル文字列
##expression で解析しても、リテラル文字列は認識されません。引用符内で文字を括弧で囲っても、特別に扱われません。例えば、以下の指示文を考えます。
#define MyMacro ##expression(^abc(")",1))
引用符が付いた右側の括弧は、引数を指定するための閉じ括弧であるかのように扱われます。
##expression の入れ子
InterSystems IRIS では、入れ子にした ##expression を使用できます。他の ##expression に展開するマクロを含む ##expression は、その展開が ObjectScript レベルで評価可能 (つまり、プリプロセッサ指示文がない) であって、ObjectScript 変数に格納可能であれば、定義可能です。入れ子にした ##expression では、##expression 式を持つマクロが最初に展開された後、入れ子にした ##expression が展開されます。
##expression では、以下のマクロ関数を入れ子にすることもできます。##BeginLit...##EndLit、##function、##lit、##quote、##SafeExpression、##stripq、##unique。
##expression、サブクラス、および ##SafeExpression
メソッドが ##expression を含んでいる場合、クラスのコンパイル時にこれが検出されます。コンパイラでは ##expression の内容を解析しないため、この ##expression によってサブクラスで本来とは異なるコードが生成される可能性があります。これを回避するために、InterSystems IRIS では、サブクラスごとにコンパイラでメソッド・コードを再生成するようにしています。例えば、##expression(%classname) では現在のクラス名を挿入しますが、サブクラスのコンパイル時には、サブクラスのクラス名が挿入されている必要があります。InterSystems IRIS では、メソッドを強制的にサブクラス内で再生成することで、この状態が確実に発生するようになっています。
サブクラス内のコードが別のものにならないことがわかっている場合は、サブクラスごとのメソッドの再生成を回避してもかまいません。そのためには、##SafeExpression プリプロセッサ関数を ##expression の代わりに使用します。それ以外の場合、これら 2 つのプリプロセッサ関数は同じ機能となります。
##expression の動作
以下に示すように ##expression への引数には、ObjectScript XECUTE コマンドで値を設定します。
SET value="Set value="_expression XECUTE value
ここで、expression は、value の値を決定する ObjectScript 式です。この式には、マクロや ##expression プリプロセッサ関数は使用できません。
ただし、XECUTE value の結果には、マクロや別の ##expression を使用できます。この例のように、ObjectScript プリプロセッサは、これらのどれであってもさらに展開を進めます。
ルーチン A.mac に次の式が記述されているとします。
#define BB ##expression(10_"_"_$$aa^B())
SET CC = $$$BB
QUIT
また、ルーチン B.mac には次の式が記述されているとします。
aa()
QUIT "##expression(10+10+10)"
この結果、A.int の内容は次のようになります。
SET CC = 10_30
QUIT