HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2006
0502
strategy別スクリプトファイル間のgosub-return9解決


strategy

リンク

2006/5/2(Tue) 16:51:03|NO.562

作業をひとつ行うサブルーチンaをもつスクリプトAと
Aのサブルーチンを繰り返し呼び出してまとまった作業を行うスクリプトB
という2つのファイルを作成しました。
B側でAを#include "A.hsp"と結合し、gosub *aで
飛んだところ、飛ぶことができましたが、スクリプトAのサブルーチンaの
最後のreturnまできたところで「サブルーチン外のreturnは無効」のエラー
となってしまいBに帰ることができません。
gosubで飛んできたのにファイルをまたいだ時点でそのことが
忘れられてしまうようです。
どのような対策があるでしょうか。



この記事に返信する


Irisawa

リンク

2006/5/2(Tue) 17:15:07|NO.566

大丈夫なはずですが...。

main.hsp

#include "sub1.as" gosub *sub1 gosub *sub2 stop #include "sub2.as"
sub1.as

goto *__sub1__end *sub1 dialog "サブルーチン1" return *__sub1__end
sub2.as

*sub2 dialog "サブルーチン2" return
プリプロセスの処理結果

##0 "main.hsp" ##0 "sub1.as" goto@hsp *__sub1__end *sub1 dialog@hsp "サブルーチン1" return@hsp *__sub1__end ##3 "hsptmp" gosub@hsp *sub1 gosub@hsp *sub2 stop@hsp ##0 "sub2.as" *sub2 dialog@hsp "サブルーチン2" return@hsp ##9 "hsptmp"



strategy

リンク

2006/5/2(Tue) 17:31:37|NO.567

レスありがとうございます。
具体的には下記のようなスクリプトですが、
returnのところでエラーになります。

list.hsp

#include "generator.hsp"
     人物数=100
ct=1
while ct<=人物数
gosub *人物作成
ct++
wait 1
wend
end


generator.hsp
//ーーーーーーーーーーーーー キャラクタージェネレータ
*人物作成
return



Irisawa

リンク

2006/5/2(Tue) 17:41:14|NO.568

一応、上記のままでは不親切な上に恐らくどこが問題なのかも分からない可能性があるので
考えられる可能性を指摘します。

メインとなっているスクリプトの上部でサブルーチンファイルをインクルードしようとして
そのサブルーチンファイルの中でサブルーチンの処理をとばしていない(gotoしていない)
のが原因ではないでしょうか。
上記のようにプリプロセス処理後の結果を見てみれば分かるようにsub1.asの上部で
gotoしないと*sub1をそのまま実行してしまおうとしてgosubしていないのにreturnが
あるためエラーになります。
基本的に別ファイルに特定の処理をまとめる場合はサブルーチンよりもモジュール機能を
使用した方がいいでしょう。


; sub1.as #module #deffunc sub1 dialog "サブルーチン1" return #global ; sub2.as #module #deffunc sub2 dialog "サブルーチン2" return #global #include "sub1.as" #include "sub2.as" sub1 sub2 stop

上記はまとめて記述していますが実際には別ファイルで書いてください。
(#includeを消してしまえばそのままでも実行できます)

サブルーチンはスクリプト内の同一モジュール空間ならどこに書いても普通に呼び出せ
ますがモジュール定義命令は呼び出す位置より前で定義されていないといけませんので
ご注意ください。

# なお、サブルーチンやgotoによるラベルジャンプはラベル名にモジュール空間を指定する
# ことで別モジュール空間のラベルにもジャンプできます。



osakana

リンク

2006/5/2(Tue) 17:43:32|NO.569

これを同じフォルダに保存して、
B.hspの方を実行してみて下さい。

スクリプトA
ファイル名:a.as

*sub mes "サブルーチン" return
スクリプトB
ファイル名:b.hsp

mes "メインルーチン" gosub *sub stop #include "a.as"

おそらくstrategyさんは、スクリプトの一番上で
#includeしてるんだと思いますが、
サブルーチン入りのファイルはメインより下に書きます。
トップに書きたい時はこうします。

goto *top #include "a.as" *top mes "メインルーチン" gosub *sub stop
とか書きながら、まとを外してたらすいません。



Irisawa

リンク

2006/5/2(Tue) 17:44:17|NO.570

って、返信きてるし...。
やはり予測したとおりですね。



あんすこえむ

リンク

2006/5/2(Tue) 17:46:59|NO.571

もし、インクルードされる側のスクリプトで、onkey goto や、button goto を使っていたら、
これを button gosub形式に直し、ここから呼ばれる飛び先での処理も、サブルーチンのルール
に従って記述し直してください。
ちなみに onkey *labelは、 onkey goto *labelのように指定したのと同じ意味になります。

現行バージョン3.0〜3.1β3では、onkey gotoのような割り込みで飛ぶと、サブルーチンの
ネストレベルが0にリセットなります。
HSP2.6では割り込みで飛んでもサブルーチンのネストレベルは変りませんでしたが、そのせいで
サブルーチン中に割り込み処理後に普通のgotoで飛んでいると、いつのまにかネスト限界に
達するということが良くありました。
昔β版BBS(今のHSP3掲示板、HTMLのタイトルはbeta-BBSのまま)で議論があり、ネストレベルを
リセットする要望も出ていますので、3.0で仕様として対処されたのだと思われます。
2.6で作った割り込み付きモジュールをHSP3化する際、非常に厄介な制限になりますね。



osakana

リンク

2006/5/2(Tue) 17:53:50|NO.572

書き込みが重なってしまった・・。
しかも解決してるっぽい・・・?。
書き込みの遅さが明るみに・・・・(^^)。



strategy

リンク

2006/5/2(Tue) 21:39:18|NO.576

Irisawaさんosakanaさんありがとうございます。
インクルードした瞬間にその場所にコードが貼り付けられてしまい
そこから実行されてしまうというイメージでしょうか。

あんすこえむさんのいうような制限もあるようなので
気をつけたいと思います。



あんすこえむ

リンク

2006/5/3(Wed) 01:32:37|NO.580

>そこから実行されてしまうというイメージでしょうか。
この考え方はOKです。ただしその前の

>インクルードした瞬間にその場所にコードが貼り付けられてしまい
というのは補足が必要ですね。
「インクルードした瞬間」、それはプログラムの実行時ではありません。
実行時には#Include命令というものは存在しないからです。

#includeはプリプロセッサ命令であることに注意してください。
プリプロセッサ命令は、コンパイル(中間コードへのコンバート)の前に解釈されます。
コンパイルを行う前、#includeのある位置へ、指定したファイルの内容が展開されます。
コンパイルはその後。
コンパイルされた結果のコードが実行されるのは、更にその後。EXEの作成も同様。

No.567の例だと、プリプロセッサ機能が働いた結果、以下のようなスクリプトが
コンパイラに渡されています。

//ーーーーーーーーーーーーー キャラクタージェネレータ *人物作成 return      人物数=100 ct=1 while ct<=人物数 gosub *人物作成 ct++ wait 1 wend end
当然、人物作成のルーチンが、真っ先に実行されます。Gosub呼び出しではありません。

標準エディタのF5キーを押すと、実行まで連続していっぺんでやってしまうのでイメージ
しにくいかもしれませんが、スクリプトが走る前に#include命令は役目を果たしており
インクルード対象ファイルの内容に取って代わられているのです。

なお、大抵のコンパイル言語にいえますが、プリプロセッサ機能には言語本来の仕様とは
別のルールがあったりするので、注意が必要です。



ONION software Copyright 1997-2023(c) All rights reserved.