<?xml version="1.0" encoding="Shift_JIS" ?>

<doc>
<title>サブルーチンを使おう</title>


<para>
<ptitle>サブルーチンとは</ptitle>
　サブルーチンとは、いくつかの処理のをまとめた物で、ほかの箇所から「呼び出して」つかう物です。サブルーチンの処理が終わると、呼び出した所へ制御が戻ります。<r/>
<r/>
　マクロ <comlink href="Macro"/> と機能は似ていますが、サブルーチンの方がより本格的な処理を行うのに対し、マクロは簡単な処理を行う用途です。<r/>
</para>

<para>
<ptitle>サブルーチンの基本的な使い方</ptitle>
　サブルーチンはラベルによって区別されますので、ラベルを定義します。サブルーチンから呼び出し元に戻るところに <kw>return</kw> タグ、サブルーチンを呼び出すには <kw>call</kw> タグを用います。<r/>
　下の例を見てください。<r/>
<bq>
[wait time=200]<r/>
*start|スタート<r/>
[cm]<r/>
サブルーチンを呼び出します。[l][r]<r/>
<b>[call target=*subroutine]</b><r/>
サブルーチンを呼び出しました。<r/>
[s]<r/>
<r/>
<b>*subroutine</b><r/>
これはサブルーチンです。[l][r]<r/>
クリックをすると呼び出し元に戻ります。[l][r]<r/>
<b>[return]</b><r/>
</bq>
<r/>
　さて、この例を実行させると、「サブルーチンを呼び出します。」のメッセージのあとに「これはサブルーチンです。」と表示され、「クリックをすると呼び出し元に戻ります。」でクリックすると、「サブルーチンを呼び出しました。」と表示されるはずです。<r/>
　つまり、call タグで指定したラベルにジャンプをするのですが、このときに呼び出した位置が自動的に記録され、return タグでは、この記録された呼び出し元に自動的に戻ります ( この自動的に記録されるものを「<kw>コールスタック</kw>」と呼んでいます )。<r/>
　この例では、<tt>*subroutine</tt> から <tt>[return]</tt> までが「サブルーチン」です。<r/>
<r/>
　サブルーチンの中からほかのサブルーチンを呼び出すこともできます。呼び出しの深さ ( return せずにいくつまで call できるか ) に制限はありません。<r/>
<r/>
　ちなみに「選択肢を使ってみよう」の所ではラベルの次には [cm] を書くと書きましたが、セーブの箇所となるような ( | 付きの ) ラベルの次でなければ [cm] を書かなくても OK です。<r/>
<r/>
<r/>
　コールスタックには、シナリオファイル名、シナリオ中の直前のラベルとそれから call タグのある行までの行数、call タグのある行の内容、その行内での位置の情報しか記録されません。シナリオのデバッグ中などで、戻り先のシナリオファイル中の構成が変わるととんでもない位置に戻ってしまう場合があるので注意してください。<r/>
　基本的には、サブルーチンのラベルやサブルーチン中には、セーブ箇所となるラベル ( | 付きのラベル ) を使わない/作らないが吉です。<r/>
</para>

<para>
<ptitle>サブルーチンに関する注意</ptitle>
　call で自分自身を呼びだしてしまったりすると無限ループにはまります。<r/>
　call と return の対応がとれていないと、どんどんコールスタックが増えていったり、あるいは return タグのところで呼び出し元に戻れなくなってエラーになる事がありますので、注意してください。<r/>
<r/>
　それと、次の例のように<r/>
<r/>
<bq>
*subroutine<r/>
・・・<r/>
[if exp="f.flag1"]<b>[jump target=*otherplaces1]</b>[endif]<r/>
[if exp="f.flag2"]<b>[jump target=*otherplaces2]</b>[endif]<r/>
・・・<r/>
[return]<r/>
<r/>
*otherplaces1<r/>
・・・<r/>
[return]<r/>
<r/>
*otherplaces2<r/>
;この先には return タグがない・・・<r/>
</bq>
<r/>
　サブルーチン中で他の場所にジャンプする場合は注意してください。otherplaces1 にジャンプする場合は、ジャンプ先に return があるので call 〜 return のバランスを崩すことはありません。しかし、otherplaces2 にジャンプする場合、ジャンプした先に return が現れないので、そのサブルーチンからは「戻ってない」ことになります。つまり、call 〜 return のバランスを崩してしまいます。<r/>
<r/>
　もし、呼び出し元に戻るのではなく、任意の場所に戻りたい場合は、return タグの storage や target 属性を利用して、任意の場所に戻ることができます。<r/>
</para>
</doc>
