2016年3月15日火曜日

HSPの落とし穴(水玉模様)

hello, セルディアです。

HSP3dishにだって…… わからないことぐらい…ある…


HSP3dishには、残念ながらまだまだ未対応な機能や隠されたバグがあります。

発展途上とも言えれば、まだまだ成長する余地はある、とも言えますが、開発中に突然原因不明のバグが発生して、Androidで画面が真っ暗になり気づいたらホーム画面に戻る…という悪夢は見たくないでしょう。

ここで、HSP3dishの仕様と未対応機能をまとめておきます。

チキチキ不具合ルーレット


まずは、Windows版では動くがAndroid版で落ちるコードの書き方をまとめます。


  • 新規関数登録(#defcfunc)による関数で、他の新規関数や新規命令(#deffunc)を呼び出すと落ちる
#deffunc testfunc
    ...
    return

#defcfunc testcfunc
    ...
    testfunc
    ...
    return
  • 配列への連続代入で落ちる
dim array_var, 5
array_var = 1, 2, 3

  • 新規関数、新規命令内で、別のラベルにgosubしてから引数を使うと落ちる
#deffunc testfunc str testarg
    gosub *testlabel
    return

*testlabel
    mes testarg
    return
  • foreach、forを使うと、Cコードへ変換時にエラーが発生する(コード自体は生成されるが、Androidで動かすと落ちる)


実は、HSP自体にも問題が発生するコードの書き方があるので、まとめます。


  • (1) repeat~loopループ内でgosubラベルによりジャンプする
    (2) ラベル内でrepeat~loopループ内でreturnすると、次のrepeat~loopで予期しない挙動を取る

repeat 4
    gosub *testlabel
    mes "testA"
loop
stop

*testlabel
    repeat 4
        mes "testB"
        return
    loop
    return

(やっかいなのは、gosubがrepeat~loop内でなければ、何の問題も起こさないことです。たまたまループの外でgosubしてうまくいっている経験があると、この仕様に気づきにくいかもしれません)
  • 新規関数、新規命令をreturnで閉じないまま別の新規関数、新規命令の定義文に差し掛かってもエラーが出ない(個人的にこれでよく悩まされます)


#deffunc testfuncA
    a = 0

#deffunc testfuncB
    a = 1
    return

以上です。

ざっと並べましたが、中にはWindows版で全く意識せずやらかしている場合もあるかもしれません。
私もコードを書いているうちに、うっかり上記の条件を満たしてしまってドはまりすることがよくあります。

HSP3dishを使って「Windowsでは動くのにAndroidでは動かない! なぜだ!」となっている人の助けになれば幸いです。

気を付けてもやらかしちゃう 人間だもの


気を付けて書けばバグが減るならこの世にバグはないです。

ということで、自動的にAndroidで落ちてしまうコードを発見するプログラムを作りました。

簡単に言えば「Windowsで動くけどAndroidで落ちるったー」です。

こちらがコードになります。
https://sites.google.com/site/seldiacotton/file/codecheck.rb

驚くなかれ、Rubyで書かれています。Rubyが一番書きやすいんだもん…!(わがまま)
動かすためにはRuby実行環境をインストールする必要があります。
入っていない場合は、以下のサイトからインストールしてください。
https://www.ruby-lang.org/ja/
(Windows版Rubyバイナリのインストーラをダウンロードして実行すればOK. Rubyバージョンは1.9.0以降ならなんでも大丈夫…なはず)

ダウンロードしたRubyコードを、hspファイルと同じディレクトリに置いて、コマンドプロンプトで以下のコマンドで実行してください。

ruby -Ks codecheck.rb

すると、同じディレクトリのhspファイルを検査してくれます。

いきなりRubyとか出てきて、とてもHSPのコードを書く人向けに作ったとは思えない投げ出しっぷりですが、お役に立てれば幸いです(そしてすべてを投げ出す)。

使い方と注意事項


上で述べている、不具合を起こしてしまうコードの書き方はある程度検出できるようになっています。コマンドプロンプト上に出力された文を見て、良しなに判断してください。

Rubyコードの2行目と4行目に、対象に含むファイルと、逆に除外するファイルを記述することができます。指定方法は記入済みの例に倣ってください。

あくまで個人的に検査用に作っただけで、万人の書き方にも耐えうるよう精密な仕様に対応してるわけではありませんのであしからず。一応、せっかくつくるならと、結構作り込んではいますが…。

もし、こういうコードの書き方をすると誤検知するよ! とか、こういう書き方は検知してくれないの? とか、他にもこういう不具合があるんだけど! とかあったら、コメントでくれると対応したり喜んだりするかもしれません。

よろしくお願いいたします。

いじょ。