前処理指令

この記事では、AliceScriptにおける前処理指令(プリプロセッサディレクティブ)


taiseiue | 2024-11-21

AliceScriptはインタプリタ言語なので、Aliceの実装ごとに個別のプリプロセッサはありませんが、この記事で説明する前処理指令は多くのコンパイル式言語のそれと同じように処理されます。 これらを使用すると、インタプリタに設定を指示したり、シバンとして使用したり、条件付きパースを実行するなどに役立ちます。前処理指令はインタプリタにスクリプトが渡される前のパーサーで実行されます。 この機能はCやC++言語の前処理指令とは異なり、マクロを作成するために使用することはできません。この機能はAlice2.2以降で使用できます。

基本

前処理指令は、#で始まり;で終わるステートメントです。また、;で終了する代わりに改行文字を終端として扱うこともできます。スクリプトの後端に記述することはできません。 さらに、指令には引数を付加できます。指令と引数は(空白文字)を使用して区切ります。 これは通常、次のような形式です。

AliceScript
#<指令> <引数>

また、パーサーが未知の指令に遭遇した場合でもエラーが発生することはありません。未知の指令は無視されます。

シバン

シバンとは、Unix環境でOSにスクリプトを実行するべき処理系を指定する機能のことを指します。 つまり、macOSとLinux環境ではシバンを持つスクリプトは実行権限を与えてやればあたかも実行ファイルかのように実行できるのです。 Aliceの実装でシバンに対する処理は実装されていません。また、未知の指令をパーサーが無視するのもこのためです。

スクリプトでシバンを定義するには次のように記述します。

script.alice
#!/usr/local/bin/alice
print("Hello,World!");

これは次のように実行できます。

シェル
./script.alice

条件付きパース

次の前処理指令を使用して、パースする部分を制御できます。

  • #if 条件付きパースを開始します。コードは、指定されたシンボルが定義されている場合にのみパースされます。
  • #else 前の部分を閉じ、前に指定されたシンボルが定義されていない場合は、コードをパースします。
  • #endif 前の部分を閉じます。

次の例ではシンボルTESTを指定しています。print("Hello,TEST");は実行されますがprint("Hello,MAIN");は実行されません。

AliceScript
#define TEST
#if MAIN
print("Hello,MAIN");
#endif
#if TEST
print("Hello,TEST");
#endif

次の例ではTESTが定義されていない場合にのみ実行されます。

AliceScript
#if !TEST
print("TEST is not defined");
#endif

シンボルの定義

次の前処理指令を使用して、シンボルを定義します。シンボルは条件付きパースのほか、インタプリタの挙動を制御する時にも使用します。シンボルは大文字小文字を区別しません。

  • #define シンボルを定義します。
  • #undef シンボルの定義を解除します。

#undef

#undefを使用するとシンボルの定義が解除されます。これは、スクリプトがインタプリタに渡された時にはすでに定義を解除されているので、インタプリタに渡されることはありません。 インタプリタを制御するときは#undefを使用しないでください。

Cとの違い

#defineを使用して、CやC++で行うような定数値を宣言することはできません。AliceScriptの定数はpublic constの変数として定義できます。

シンボルを使用して、インタプリタの挙動を制御できます。どのようなシンボルを設定するとどのような挙動をするかについては次の表を参照してください。

シンボル 挙動
UNNEED_VAR 変数の宣言が不要になります
FOLLOW_INCLUDE 自分のスクリプトでincludeしたファイルにもシンボルを引継ぎます
DISABLE_USING usingが使用できなくなります。

たとえば、現在のスクリプトで変数の宣言を不要にするには次のようにします。この方法を使用したからと言って未定義の変数が使用できるようになるわけではありません。

AliceScript
#define unneed_var
a = 1; // 通常はvar a = 1;が必要
print(a); // 出力例 : 1

ファイルの挿入

#include指令を使用して、ファイルを現在のスクリプトに挿入できます。include関数と異なる点は、現在のスクリプトの中にそのまま挿入しスクリプトに親子関係を発生させないことです。次に例を示します。

AliceScript
#include sub.alice

エラーの発生

#error指令を使用して、0x019ユーザー定義のエラーを起こすことができます。次に例を示します。

AliceScript
#error ユーザー定義のエラーです

情報の出力

#print指令を使用して、プログラムがパースされる前に情報を出力できます。次に例を示します。

AliceScript
#print 実行前に表示されます