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


HSPTV!掲示板


未解決 解決 停止 削除要請

2009
1222
木村goto命令含むスクリプトのモジュール化ができません6解決


木村

リンク

2009/12/22(Tue) 20:24:43|NO.29401

 以下のスクリプト部分をモジュール化しようとしたのですが上手く行きません。


*背景取得0 /*----*/ goto *背景取得1 *背景取得1 /*----*/ repeat tbuf2 /*----*/ /*----*/ : button goto "BackGround"+cnt,*背景取得2 loop /*----*/ /*----*/ : button goto "決定",*背景取得6 /*----*/ : button goto "キャンセル",*背景取得5 /*----*/ goto *背景取得3 *背景取得2 /*----*/ goto *背景取得4 *背景取得3 /*----*/ goto *背景取得4 *背景取得4 /*----*/ goto *背景取得4 *背景取得5 /*----*/ goto *基本ループ *背景取得6 /*----*/ if idnum=-1 : /*----*/ : goto *背景取得4 /*----*/ goto *イベント追加 //※『/*----*/』部分は今回の質問に無関係なスクリプト

 『*背景取得0』から始まって、
『*基本ループ』か『*イベント追加』に抜けるスクリプトなので、
『*背景取得0』以降を#deffunc命令の開始地点に、
『*基本ループ』をreturn 0、
『*イベント追加』をreturn 1に変更した形をモジュールにして、


goto *背景取得0 /*----*/ *背景取得0 meirei0 switch stat case 0 : goto *基本ループ : swbreak case 1 : goto *イベント追加 : swbreak swend

 ……と、してやれば上手く行くだろうと書いてみたのですが、
returnが『サブルーチン以外のreturnは無効です』と言われてしまって立ち往生です。

 returnが使えないのなら、return'statを利用せずに直にgotoジャンプしたいのですが、
#deffunc命令にはラベル変数を要素として放り込めません。

 こういう形のスクリプト自体、モジュール化が無理なのでしょうか。
 どうすればモジュール化できるか教えてください。



この記事に返信する


Hatter

リンク

2009/12/22(Tue) 21:26:41|NO.29404

その部分のスクリプトを普通に読み込ませていませんか?

ちゃんと goto を使って# deffuncの部分を実行させないようにさせるか,#module〜#globalで別空間にしてますか?



木村

リンク

2009/12/22(Tue) 22:29:32|NO.29407

>>Hatter様へ

 その部分を詳しく調べてみたところ、少し面白い現象を発見しました。


#module #defcfunc a mes sublev //第2mes button goto "+6",*c mes sublev //第3mes *b wait mes sublev //連続mes goto *b *c mes sublev //ボタンmes return 1 #global gosub *d *d gosub *e *e mes sublev //第1mes mes a()
//※システム変数sublevはサブルーチンネスト(gosub〜return)の深さ

 #deffunc命令(この場合は#defcfunc命令ですが)は一種のサブルーチンネストとして
命令としての動きをします。
 その証拠に、『第1mes』は2、その後の『第2mes』と『第3mes』、『連続mes』では
3とサブルーチンネストの深さはなっています。
 ところが、ボタンを押した後の『ボタンmes』ではサブルーチンネストが0に
なってしまっています。
 0サブルーチンネストでreturn命令をされれば、エラーを起こすのは必然です。結論、


――#deffuncサブルーチンネストはボタンを押した瞬間に初期化される――


 と、いう事なのでしょう。

 そうなると、モジュール内で生成したボタンから発動するスクリプトは、
モジュール外、つまりグローバル空間に帰還できないという事になります。
(goto命令を使ったところでモジュール内にしか移動できないですしそもそも、
モジュール内→モジュール外というスクリプト解析の移動を#deffunc命令以外で
作ってしまってはモジュール構造の意味がありません)
 モジュール内から始まってモジュール外に抜けるスクリプトを作るには、あらかじめ
そのモジュール内にグローバル空間の宛先を投入して


//例 #module #deffunc labelinit label l1 label1=l1 return #deffunc newgoto goto label1 return #global labelinit *ss : newgoto *ss mes "SSに到着しました" : stop //のように

やれば良いのでしょう。
 ところが、#deffunc命令のヘルプにはラベル変数を投入する方法が書いてありません。
(余談ですが、他のモジュール変数でさえarray属性で投入できるというのにです)
 このままでは、モジュール内では一切のグローバル空間に帰還させたいボタンを作れない
という事になります。
 一体どうすれば良いのでしょうか。要約するなら、

Q1,モジュール内でグローバル空間に帰還するボタンは作れるのか? 作れないのか?
Q2,作れるとしたらどうやればそのボタンは作れるのか?

 Q1だけでも回答をお願いします。Q1が無理だというのなら、モジュール分割は諦(アキラ)めて
スクリプトファイル自体を2ファイルに分割して#includeで結合する方式で分割します。



Hatter

リンク

2009/12/23(Wed) 00:24:07|NO.29416

Q1に関しては僕は分かりません。
お力になれなくてすみません。色々調べましたけど、調べ方が不十分だったのか
goto と ネスト関連の情報が全然見つかりませんでした。

あと、補足ですが
――#deffuncサブルーチンネストはボタンを押した瞬間に初期化される――
以下のスクリプトを実行してデバッグウィンドウを見てもらえれば分かると思います。


repeat gosub *A loop *A button goto "B",*B stop *B mes "B" return



窓口

リンク

2009/12/23(Wed) 05:59:08|NO.29418

global空間にジャンプするラベルは、自分の知る限りは作れなかったと思います。
ただ下の方法で代用することはできるかもしれません。


#define global WM_USER $00000400 ; ボタンがクリックされたときに通知するユーザー定義メッセージ #define global WM_P_BUTTON (WM_USER + 0x101) #module ;SetButton int window_id ; 引数1 ボタンクリックを通知するwindowID。 #deffunc SetButton int wid_ IDstok = ginfo_sel gsel wid_ : mainhwnd = hwnd button gosub "雄",*label button gosub "雄2",*label screen 1 : title "1" button gosub "雄",*label button gosub "雄2",*label screen 2 : title "2" button gosub "雄",*label button gosub "雄2",*label gsel IDstok return *label ; ボタンがクリックされた際にジャンプするラベル /*ボタンがクリックされた限り、メッセージを送信*/ ; stat(押されたobjID) , ginfo_act(アクティブに成っているwindowID) sendmsg mainhwnd , WM_P_BUTTON , stat , ginfo_act return #global ;====================================================== ; global空間 gsel 0 : title "0" oncmd gosub *label , WM_P_BUTTON SetButton 0 stop *label gsel 0 mes "windowID["+str(lparam)+"]の、objID["+str(wparam)+"]がクリック!" return

手順としては、ボタンが押された場合、指定したウインドウID に sendmsg でWM_P_BUTTONメッセージ(ユーザー定義)を送信。
global空間に定義された。ラベルでWM_P_BUTTONメッセージを受け取ります。
ついでに、どのウインドウのどのボタンが押されたかもわかるようにしてみました。



shinkun

リンク

2009/12/23(Wed) 20:23:32|NO.29435

Q1の回答だけを述べれば、グローバル空間のラベルにジャンプするボタンをモジュール内で作る事は出来ます。
以下のスクリプトを検証下さい。

#module #deffunc createButton button goto "global jump", *global@ return #global *main createButton stop *global mes "jump to global section" stop
グローバル空間で定義された *global ラベルの本当の名前は *global@ です。
ですから、モジュール内で *global@ へジャンプするボタンを作れば実現出来ます。

ところで、木村さんのQ1の質問は論点がちょっとずれてるように思います。
木村さんがモジュール化したいと考えているスクリプトでは、ボタンの押し下げによって直接グローバル空間にジャンプするのではなく、一旦モジュール内のラベルを介してジャンプする事になるので、どちらかと言えば、「モジュール内からグローバル空間にジャンプする事はできるのか?その方法は?」というのが適切だと思います。
で、そういう質問がなされたとして、それに答えるならば次のようになります。

#module #deffunc createButton button goto "global jump", *temp ; 一旦モジュール内のラベルに飛んで… return *temp goto *global@ ; そこからグローバル空間にジャンプ #global *main createButton stop *global mes "jump to global section" stop
ミソとなる部分はなんら変わりません。また、goto の場合だけでなく gosub に対しても同様に「*ラベル名@」でモジュール内からグローバル空間へジャンプ出来ます。結局、名前の指定の仕方だけの問題なので。
このスクリプトを gosub で書き直した場合、窓口さんの書かれたスクリプトとほぼ同等になります。モジュール内からグローバル空間へジャンプする先のラベルが固定されているので、窓口さんのと違って汎用性はありませんが、改良を加えればそれも可能になります。

という事で、モジュール内からグローバル空間へジャンプする事は出来ます。

-----------------------------------------
以下、余談ですが、今回のスクリプトに関しては無理にモジュール化する程の利点は無い様に思えます。

モジュール化する利点は、私が考えるに、(1) ほとんど処理は同じだが、ほんの少しだけパラメータが異なるスクリプトが何度も必要になる場合 (2) 同じ処理・同じデータ構造をしているが、個々に独立したデータ群が複数必要(= モジュール変数)の 2 点位かと思います。

今回は上記のいずれにも当てはまりません。おそらく、スクリプトが長くなって可読性が悪いので分割しよう、という事だと思います。労力と仕上がったものの出来、どちらを考えても #include でファイル分割するのが最適に思います。

特に、HSP は名前と名前空間に関するルールが非常に複雑っぽいので、無理にモジュール化した所で余計な苦労を背負い込むだけかもしれません。



木村

リンク

2009/12/24(Thu) 00:33:30|NO.29457

 解決しました。おかげさまで、何とかスクリプトの目鼻が立ちそうです。
 Hatter様、窓口様、shinkun様、回答をどうもありがとうございました。



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