T.TのHPIndex > UNSAFEモードについて
回数繰り返しとJUMP問題
注意:この項目はバージョン2.5以上を対象に書かれています。

 UNSAFEモードについて説明する前に、この機能と深く関わる問題について説明する必要があります。

 プロロボには回数繰り返し命令を一つのプログラムで10回しか使用できない仕様があります。公式のエディタでも、 繰り返しを10個を超えておくとエラーになりますし、もちろんPrbScriptでもそれは検知されます。また、10回よりも 多い回数の繰り返しを行うコードをプロロボに転送すると、11回目の繰り返しでプロロボはフリーズします。ゆえに 公式エディタなどは不正なプログラムを転送しないようチェックをしています。
 また、回数繰り返しの開始(=REPEAT命令)を読み込む前に回数繰り返しの終了(=RETURN命令)を読み込むとプロロボは フリーズします。そのため、PrbScriptや公式エディタでも回数繰り返しの終了と回数繰り返し開始の数が合うかどうか検知をしています。
 しかし、公式エディタでは「回数繰り返し内でのJUMP/SENSOR/LABEL」が可能です。 これは以下のようなコードが実行可能であることを意味します。

例1
START_UNSAFE '後述します
		REPEAT 10
			STRAIGHT LOW,100
			BACK LOW,100
			JUMP "@TOP" '永遠に繰り返すはずが11回目でフリーズする。
			TURN R,HIGH,1000 '到達不能
		RETURN
FINISH

例2
START_UNSAFE 'UNSAFEモードに設定
		BRAKE LOW,100
		JUMP "INLOOP"
		REPEAT 10
			LABEL "INLOOP"
				STRAIGHT LOW,100 
		RETURN 'ここでフリーズ
FINISH

 例1では、JUMP "@TOP"はプログラムの先頭へプログラムの進行を移動させます。 このコードは永遠に前後運動をし続けるかのように見えますが、実際には10回前後運動をしたあとフリーズします。 これはプログラムがJUMP命令によって先頭に飛び、再びREPEAT命令を処理することが重なり、REPEAT命令が10回より多く 実行されたためです。このような不具合はSENSOR命令でも起こりえます。
 例2では、REPEATを文字どおりJUMPしてINLOOPに飛ぶために、RETURN命令の戻る先が定義されず読み込まれ、 1秒前進後に異常停止します。これは繰り返し内でLABELが使用できるためです。
 上記はPrbScriptでの例ですが、公式エディタ(新Ver/旧Ver問わず)でもこのようなプログラムを作製し、 転送、プロロボを異常停止させることは可能です。これはバグと言っても過言ではないでしょう。
 PrbScript 2.0では、回数繰り返しの中でのJUMPとSENSOR、LABELを制限していました。 (この問題のためではなく美学的な理由です。回数繰り返し中でのジャンプはあまり推奨されず、繰り返し内への ジャンプはプログラミングではご法度です。) 故にPrbScriptでは上記の問題は発生しません。
 しかし、これらの機能を用いないと組めないプログラムは多く存在すると考えます。例えば、 「30秒前進するが、途中で右センサに反応があれば停止する。」と言うものなどは、(変数が利用できないので) 回数繰り返しとその中でのSENSORを用いないと実装できません。 また、公式エディタで組めるものはすべてPrbScriptに置き換えたいという願いもあります。
 公式エディタはさまざまなプログラムを作成できるようにあえて、この問題に対策していないのかもしれません。 それはわかりませんが、この問題のために、回数繰り返しの中でのJUMP/SENSOR/LABELはとても扱いが難しいのです。

UNSAFEモード

 PrbScript 2.5ではこの問題を解決する一つの方法としてUNSAFEモードを実装しました。 UNSAFEモードでは回数繰り返し内でのJUMP命令、SENSOR命令、LABEL命令の使用に制限がかかりませんが、 安全な動作の保証はできません。(また@命令行番号のシステムラベルはこのモードを有効にしないと使用できません)
 UNSAFEモードを有効にするには通常のSTART命令の代わりにSTART_UNSAFE命令を使います。
 以下はサンプルです。

'30秒前進するが、途中で左右センサに反応があれば終了する。
START_UNSAFE 'UNSAFEモードに設定
		REPEAT 30
			STRAIGHT LOW,100
			SENSOR TOUCH_LEFT,"@END","@NEXT"
			SENSOR TOUCH_RIGHT,"@END","@NEXT"
		RETURN
FINISH

 このコードではSENSORのジャンプ先は@ENDですから、異常停止は理論上発生しません。 このように、UNSAFEモード使用時は、コードが理論上異常停止しないかどうかをよく考慮した上、 プログラムを実行してください。(まあ最悪異常停止してもあまり害はないかもしれませんが......)
 また、繰り返し外から繰り返し内へのジャンプを含むコードは転送可能ですがおすすめしませんし、 書く価値がありません。繰り返し内から繰り返し内へジャンプすることを想定しています。

 最後に命令行番号のシステムラベルをご紹介します。この機能はPrbScript 2.0から実装されていましたが、 しかし、これもまた、UNSAFEな機能であるため、 PrbScript 2.5ではUNSAFEモードでのみ使用できるように仕様変更しました。
 詳しくは、このページを読んでいただきたいのですが、 プロロボ内部では基本的に「次はどの命令行番号にジャンプするか」という考え方で、逐次実行、ラベルジャンプ、 条件分岐などが実現されています。 (組み込みの機械語ですから、当たり前ではあります)
 PrbScriptはこの機械語的な言語をBASIC風に、書きやすいようにカバーしているため、命令行番号を指定するジャンプ ではなく、宣言されたラベルへのジャンプなどの機能を備えています。
 @命令行番号のシステムラベルは機械語的に、この命令行番号へのジャンプを使用できます。

'命令行番号へのジャンプ
START_UNSAFE 'UNSAFEモードに設定
		STRAIGHT HIGH,100
		BACK HIGH,100
		TURN R,HIGH,100
		JUMP "@3" 'BACKへ

 3個目の命令はBACK命令であり、ここに延々とジャンプするために1回だけ前進したあと、後進と回転を 繰り返します。

 このような場合なら問題ありませんが、「存在しない命令行へのジャンプ」や上記のような繰り返し内へのジャンプは 異常停止の原因となります。そのため、ラベルを用いたジャンプを強くおすすめします。 この機能は正直使い道ないです。
 また、"@1"にジャンプするのは"@END"と等価です。これは内部処理において、1の命令行には終了が書き込まれているからです。







inserted by FC2 system