固定値(固定式)や決められた文字列をスクリプトに組み込む時、 複数箇所存在する場合に修正が必要となると、実際に使用している場所へ直接記述しているなら面倒です。 かといって、不変であるのに変数を使用するのもどうかという場合は、 変数のようにエイリアスをつけて定義する#define命令を使用してみましょう。
| #define エイリアス 定数 | |||
| エイリアス | 定数を表す別名を指定する。 | ||
| 定数 | 置換元の固定値(固定式)、固定文字列を指定する。 | ||
1 2 3 4 5 6 7 8 9 10 11 12 |
#define softname "SampleName" #define creater "ultimate" #define homepage "http://www.rinku.zaq.ne.jp/ultimate/" title softname syscolor 15 : boxf pos 10, 10 : button gosub "About", *about stop *about dialog "本ソフト名\t" + softname + "\n作者\t" + creater + "\n提供元\t" + homepage return |
上記の感じに定義しておけば、ソフトを新しく作るときに楽チンです。 さて、「置き換え」がメインの#define命令にはもう1つの顔があるので紹介しておきます。 置換元は定数という書き方をしましたが、#define命令で変数やその他の命令による処理も置き換えられます。 どういうことか? 具体的な例を出すと「#define clear color 255, 200, 200 : boxf : color」とすると、 定義以降は、clearと記述することで淡い赤色でウィンドウ内をクリア表示してくれるようになります。
1 2 3 4 5 6 7 |
#define clear color 255, 200, 200 : boxf : color clear pos 10, 10 : mes "イメージつかない場合は実行してみてください" wait 300 clear pos 10, 10 : mes "あたかも「赤色でクリアする1つの命令」のように振舞います" |
HSP3.1からは展開ファイル「hsptmp.i」が出力されなくなりましたが、 処理として、先ほどのサンプルは次のように展開して実行されていました。
1 2 3 4 5 |
color 255, 200, 200 : boxf : color pos 10, 10 : mes "イメージつかない場合は実行してみてください" wait 300 color 255, 200, 200 : boxf : color pos 10, 10 : mes "あたかも「赤色でクリアする1つの命令」のように振舞います" |
このような置き換えをマクロと呼んでいますが、この言葉は以前からも拡張マクロという言い方でありました。 「HSPdir\common\hspdef.as」を開いてみたことはありますか? この中には幾つものマクロが定義されており、for命令やwhile命令等も入っています。 そう、実はこれらの命令はHSPで用意された命令ではなく、単に定義されたマクロ命令だったんですね。 マクロ命令だったとはいえ、for命令にしろ、while命令にしろ、 プログラム実行時には既に展開されてるはずのものに対して、 可変の値を引数(パラメータ)として与えられるのは変な感じですね。 引数を指定できるようなマクロを特殊展開マクロと呼んでおり、 1つ目の引数を%1、2つ目を%2…として最大32個(%32まで)指定可能となってます。 33個以上指定して実行すると、スクリプトエディタがアベンドしてしまうので気をつけてください。 これらの引数を指定するときは、エイリアス(マクロ名)の後にカッコを付け、関数の要領で記述します。 引数付きマクロの引数を省略してマクロ呼び出しすると実行前にエラーとなってしまいますが、 定義するマクロ側に初期値を設定しておくことで、引数を省略してマクロを呼び出すことが可能となります。 書き方は「#define マクロ(%1 = 初期値) マクロ内容」という感じになります。
1 2 3 |
#define macroname(%1, %2) mes "引数には" + %1 + "と" + %2 + "が指定されました" macroname 123, "test" |
引数つきの場合は前述の通りにマクロ定義側をカッコ付きで記述しますが、 マクロ呼出側ではカッコを付けません。カッコ付きで記述したい場合はctypeオプションを使用します。 計算式や文字列に埋め込みむ時にctypeオプションを付けなければうまく動作しなくなるので、 その他の応用範囲は狭いのですがctypeオプションの存在も覚えておきましょう。
1 2 3 4 5 6 7 |
#define tax 1.05 #define addtax1(%1) int(tax * %1) #define ctype addtax2(%1) int(tax * %1) item = 500 mes "" + item + "円の商品の税込価格は" + addtax1 item + "円になります" // 正常に表示されない mes "" + item + "円の商品の税込価格は" + addtax2(item) + "円になります" |
引数以外にも、キーワードを用いて特殊な動作をさせることができます。 「%c」を使うと、1行に書いたマクロを改行して展開してくれますので、 実際には複数行に分けて書く必要があるものもマクロでは1行に書くことができます。 その他のキーワードは異なるマクロでデータを共有させることを目的にしたもので、 マクロを共有させる場合はまず「%t」で共有タグ名をつける必要があります。 共有タグは「%tcommon」という様に、「%t」の後に続けて指定すれば、 同一タグ名を持つ別マクロを共有領域としてこれから紹介するキーワードを使うことができるようになります。 「%n」も「%i」もどちらも、ユニークなラベル文字列を生成するもので、 その違いは、スタックに積む(%i)か積まない(%n)か、だけです。 スタックとはデータを一時的に確保しておく先入れ後出し(後入れ先出し)データ構造の領域のことで、 HSP内部で保持されるものであり、変数のように直接アクセスすることはできません。 スタックに詰まれたデータは「%p」か「%o」で取り出すことが可能で、 「%p」は取り出すもののスタックを降ろしませんので、次回取り出しをしても同一データが取り出されます。 また「%p」には、「%p0」〜「%p9」が用意されており、 「%p0」は数値省略した「%p」と同じ一番目に取り出されるデータを取り出し、 「%p1」は2番目のデータ、「%p2」は3番目のデータ…「%p9」は9番目のデータを取り出します。 当然、スタックを4つしか積んでないと5番目以降は取り出すことができずにエラーとなります。 データを取り出してスタックを降ろすには「%o」を使用しますが、 数値をつけた「%o0」は、スタックを降ろすだけでデータの展開を行いません。 ユニークなラベル文字列ではなくマクロの引数をスタックに積む場合は「%s」を使用します。 スタックに積める引数は1〜9だけで、実際に積む場合は「%s1」〜「%s9」を指定しましょう。 10番目以降の引数を積もうとしてもエラーにはなりませんが正常に積めません。 どうやら、sの後に書いた数字1文字分のみしか見ていないようで、 「%s10」〜「%s19」は「%s1」、「%s20」〜「%s29」は「%s2」として判断されるようです。 もし、仮に15番目の引数を積みたいなら「%i = %15」とすることで同じようにスタックへ積めます。 尚「%s」で積んだスタックの取り出しも「%o」で行います。 以上で特殊キーワードを使ったマクロの説明を終わりますが、使うとすればスタックを扱う上での注意点。 積まれたスタックデータは、必ず降ろさなければならないルール、 言い換えると「%i」と「%o」の個数は「%o」の数と同じでなければならないことを覚えておきましょう。
1 2 3 4 5 6 7 8 9 |
#define push(%1) %tdata %s1 #define pop %tdata %o push 1 push 22 push 333 mes pop mes pop mes pop |
#define命令は置き換えだと書きました。 例えば「#define xxx 1 + 22」と定義して「xxx * 333」を計算させて表示すると、 「1 + 22 * 333」の答えである7327が表示されます。 「#define xxx (1 + 22)」としておくことで「(1 + 22) * 333」の解、7659を得ることができますが、 これから紹介する命令は、計算式の場合に予め計算させた結果を置き換えます。
| #const エイリアス 定数 | |||
| エイリアス | 定数を表す別名を指定する。 | ||
| 定数 | 置換元の固定値(固定式)を指定する。 | ||
1 2 3 4 5 |
#const value1 9876 - 543 #define value2 9876 - 543 mes "const 9876 - 543 / 21 = " + (value1 / 21) // 9333 / 21 mes "define 9876 - 543 / 21 = " + (value2 / 21) // 9876 - (543 / 21) |
さて、次は定義されたものを取り消す命令の紹介です。
| #undef 取消対象 | |||
| 取消対象 | 取り消す対象を指定する。 | ||
1 2 3 4 5 6 7 8 9 10 11 12 |
#undef boxf #define boxf(%1 = 0, %2 = ginfo_winx, %3 = 0, %4 = ginfo_winy) \ line %1 - 1, %2, %3, %2 : line %1, %2, %1, %4 : line %3, %2, %3, %4 : line %1, %4, %3, %4 color 255 boxf 100, 50, 300, 200 color , 255 boxf 200, 100, 400, 300 color , , 255 boxf 350, 200, 500, 400 color 150, 150, 150 boxf@hsp 450, 30, 500, 80 // 元のboxf命令 |
この章の最後にHSP3で新しく追加された、定数を列挙する命令を紹介して終わります。
| #enum エイリアス = 定数 | |||
| エイリアス | 定数を表す別名を指定する。 | ||
| 定数 | 割り当てる定数を指定する。省略した場合は直前に指定した定数+1となる。 | ||
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#enum MAINBOX = 0 #enum LOADBUTTON #enum SAVEBUTTON #enum EXITBUTTON notesel buf mesbox buf, ginfo_winx, ginfo_winy - 20 objsize ginfo_winx / 3, 20 pos ginfo_winx / 3 * 0, ginfo_winy - 20 : button gosub "読込", *proc pos ginfo_winx / 3 * 1, ginfo_winy - 20 : button gosub "保存", *proc pos ginfo_winx / 3 * 2, ginfo_winy - 20 : button gosub "終了", *proc stop *proc if stat = EXITBUTTON : end if stat = LOADBUTTON { dialog "", 16, "読み込むファイル" if stat { noteload refstr objprm MAINBOX, buf } } else { dialog "", 17, "保存名" if stat : notesave refstr } return |