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


HSPTV!掲示板


未解決 解決 停止 削除要請

2022
0211
ネットヤンキーまみmoduleを使いこなす方法11未解決


ネットヤンキーまみ

リンク

2022/2/11(Fri) 13:11:52|NO.95378

こちらのソースなのですが、何故エラーになるんでしょうか。
特に間違っていない認識なのですが、もしかしてmoduleの内部に干渉するにはdeffuncやmodinit等でアクセスするほかないのでしょうか。


#module test *a b=1000 stop #global goto *a@test end


また、HSPプログラミングマニュアルの4.1の項を見ると
HSPモジュールを使いこなすためには、モジュール指定命令、ユーザー拡張命令 などについて覚える必要があります。

こちらはどの命令文法の事を指しているのでしょうか。 初歩的な質問で申し訳ありませんが、教えてくださると幸いです。 よろしくお願いいたします。



この記事に返信する


GENKI

リンク

2022/2/11(Fri) 16:38:55|NO.95379

「#ラベルの定義が存在しません [a@test]」
エラーメッセージでも出ている通り、動かないのはgotoで指定したラベルが存在しないからです。


#module test *a mes "module" stop #global goto *a@test end *a@test mes "test" stop


> もしかしてmoduleの内部に干渉するにはdeffuncやmodinit等でアクセスするほかないのでしょうか。

基本的にはその認識で利用してください。
極めて特殊でアクロバティックな使い方として、モジュールの外からモジュール内の変数に直接アクセスするために「変数名@モジュール名」という書式を使うことができます。(プログラミング・マニュアル 4.5.モジュール定義命令)
この方法が使えるのは変数名であり、ラベルには適用されません。ラベルは変数ではありません。
またマニュアルにも書いてありますが、この方法は使うべきではありません。この書式の存在は、忘れてしまったほうがいいでしょう。

モジュールの内側である #module 〜 #global の間は特殊な空間になっています。
モジュールの内側と外側は切り離されていて、例えば内と外とではラベルや変数を共用しません。
共用しないので、内と外とで同じ変数名を異なる用途で使用しても全く問題がありません。(@を使えばアクセスできますが、切り離された空間という保証がなくなるので後でメンテが大変になります。)
切り離された空間との出入り口を定義しているのが #deffunc 等の命令です。



MIZUSHIKI

リンク

2022/2/12(Sat) 01:12:51|NO.95384

>>もしかしてmoduleの内部に干渉するにはdeffuncやmodinit等でアクセスするほかないのでしょうか。
>
>>GENKI さん
>基本的にはその認識で利用してください。
>「変数名@モジュール名」という書式
>マニュアルにも書いてありますが、この方法は使うべきではありません。この書式の存在は、忘れてしまったほうがいいでしょう。
>(@を使えばアクセスできますが、切り離された空間という保証がなくなるので後でメンテが大変になります。)

私もその通りだと思います。

・・・ただ、それを踏まえたうえで、、、チョットだけ・・・そこを何とか・・・ユルシテ-
という思いで以下を紹介させてください。

#module test #deffunc 私を認識して! return *a ;error //「;」だけ消すと「*a@test」になってることを確認できます(エラーレポート) mes "module" stop #global 私を認識して! goto *a@test end
実は、一度も使われていないモジュールは丸ごと無かったことにされてしまいます。
(実行ファイルサイズを抑える最適化の為と思われます。)
なので、ネットヤンキーまみさんのスクリプトの場合、適当な命令を定義して実行してあげなくてはなりません。

testモジュール内で「*a@test」になっているかは、上記スクリプトの「;」を消すとエラーレポートから確認できます。



zrs90(5さい)

リンク

2022/2/12(Sat) 03:05:21|NO.95385

スレッド主さんの質問には
GENKI さん、MIZUSHIKI さんが
丁寧に解説されてますので...


(※他人様の立てたスレッドに、乱入してすみません)
別件の質問を、MIZUSHIKI さんに、したいのですが...

『一度も、使用されていないモジュールは
丸ごと無かった事にされてしまいます』
...と、ありますが

例えば、現在非推奨の llmod3 等の
外部モジュール等 にも
適用されるのでしょうか?

こういった最適化等が
コンパイル時?に行われている事
自体、初めて知りました。



MIZUSHIKI

リンク

2022/2/12(Sat) 11:40:20|NO.95386

zrs90(5さい)さん
>『一度も、使用されていないモジュールは丸ごと無かった事にされてしまいます』
>...と、ありますが
>例えば、現在非推奨の llmod3 等の外部モジュール等 にも適用されるのでしょうか?
(※ llmod3 : hsp3.51まで標準で付属。hsp3.6からは除外されているモジュール。)

どんなモジュールであれ例外はありません。
ただ、検証をしてみたら llmod3 自体は特殊な状況にあり、最適化では無かったことにされないようです。

llmod3.hsp は、スクリプト末尾にモジュール外から『_init_llmod』という初期化命令を実行しているため、
#include "llmod3.hsp"した時点で モジュールは使われた判定されます。

なら『_init_llmod』を消せば最適化されるのかというと、そういう訳でも無いようでして・・・


話が途中で変わりますが、先に下記のスクリプトを見てみてください。

#module test #deffunc 私を認識して! return 私を認識して! //モジュール内で書いただけでも「使われた」判定されるみたい *a ;error mes "module" stop #global goto *a@test end
このスクリプトは、エラーなく実行できます。

私は前回「適当な命令を定義して実行してあげなくてはなりません。」と言いましたが、実は『私を認識して!』命令をモジュール内にただ書いだけでもこのモジュールは「使われた」扱いになります。

それを踏まえて llmod3.hsp を見てみると、モジュール内で『#deffunc dllproc』という命令が定義されており、別の『#deffunc setwndlong』命令の中でこの『dllproc』が「使われて」います。

上記のような事情があり、llmod3 は #include した時点で最適化では消されない存在であるようです。



zrs90(5さい)

リンク

2022/2/12(Sat) 15:02:24|NO.95391

MIZUSHIKI さんへ

実は、llmod3 、個人的に作っている物で
3.5(書籍版)と、3.6でも、コッソリ使用しています。

(※内容、ソース、処理が雑すぎて、人前に出せませんけど。
まだ、3.5を使っているのは、mod_fontdlg.as の問題
があるのも、理由の1つです。

この件は、去年8月末頃、投稿があり
BMSCR構造体、絡みの処理を、自分で修正すれば
使えるようになる...とは思います。多分。)


ご返信の上、丁寧な解説に、動作検証まで...
お手数をおかけしてすみません。
ありがとうございました。



ネットヤンキーまみ

リンク

2022/2/12(Sat) 22:54:22|NO.95398

GENKI様
MIZUSHIKI様
ご教示頂き有難うございます。

私が載せたスクリプトについてGENKI様の教えを解釈すると
モジュール内の変数には@を付加してアクセス出来るものの
ラベルについては出来ない、という理解をしたのですが、
MIZUSHIKI様のスクリプトを参照すると
goto *a@test
でアクセス出来ている様に見えるのは
私の理解が足りていないのでしょうか。。 >またマニュアルにも書いてありますが、この方法は使うべきではありません。この書式の存在は、忘れてしまったほうがいいでしょう。 少々余談になりますが、私は数万行に及ぶスクリプトをいつも作成しており その場合どうしてもmoduleでパーツ毎に作っていく方が 管理がしやすいので、使うべきではない、と思えていなかったりしています… またMIZUSHIKI様のスクリプトから「;」を消して実行すると下記のエラーが表示されました。
#HSP script preprocessor ver3.5 / onion software 1997-2017(c)
#Use file [hspdef.as]
#HSP code generator ver3.5 / onion software 1997-2017(c)
???(6) : error 2 : 文法が間違っています (6行目)
--> *a@test error@test 

消さない場合は実行できるので、実際はmodule内のラベルにa@testとする事でアクセスは出来るのものの
最適化されてしまっているが為にアクセス出来ない、という事なのでしょうか。

また、最適化されてしまっている可能性も考慮し

mes "module" stop
という命令も追加していたのですが、不十分でしたでしょうか( ;∀;)

以前から最適化に苦しめられる場面が多く、最適化の仕様自体もマニュアル等には記載がなく
最適化を切る事も非推奨とされている様なので、申し訳ないのですがご教示くださりますと有難いです。


ちなみに6行目には
*a@test error@test
というラベルも記述もないので
エラーレポートでこの様な表示になるのも不思議です。 まるで@testというモジュールの中に@test errorというモジュールの中にaというラベルがあるかの様なレポートで、少し謎が深まりました。 重ね重ね申し訳ありません。 何とか理解したい所存でございますので宜しくお願い致します。



GENKI

リンク

2022/2/13(Sun) 01:40:42|NO.95400

> でアクセス出来ている様に見えるのは
> 私の理解が足りていないのでしょうか。。

なんと、アクセスできていますね…。これ知らなかった。
同様の方法でラベルにもアクセスできたんですね。マニュアルの記載漏れまたは、ごめんなさい私のマニュアル見落としです。


> この書式の存在は、忘れてしまったほうがいいでしょう。

@を使ったモジュール内へのアクセス方法を指しています。

モジュール機能は、スクリプトを整理するためにも積極的な活用をおすすめします。
ただし@を使って変数やラベルにアクセスしていると、修正が困難な思わぬ不具合に遭遇する可能性があります。モジュールの管理も複雑化します。
モジュールの外と内とのやり取りは、必ず#deffuncや#defcfuncを使うことをおすすめします。


> 消さない場合は実行できるので、実際はmodule内のラベルにa@testとする事でアクセスは出来るのものの
> 最適化されてしまっているが為にアクセス出来ない、という事なのでしょうか。

「;」だけ消す事によって意図的に「*a」の行でエラーを発生させて、ここで動作を強制的に停止させています。
このようにすると、エラーメッセージに「*a」がモジュール外からどう見えているかを表示させることが出来ます。
エラーメッセージの最後の行にエラー行が表示されています。

--> *a@test error@test
スクリプトでは「*a error」ですが、ラベル「*a」と変数「error」の直後にそれぞれ「@test」がくっついています。
つまりモジュールの外からは、モジュール内のラベル「*a」は「*a@test」、変数「error」は「error@test」として見えているということです。

意図的にエラーを発生させて動作を止めているのは、「*a」はモジュール外からは「*a@test」に見えているということを確認することが目的です。
最適化の話はここでは関係ありません。


> 以前から最適化に苦しめられる場面が多く、最適化の仕様自体もマニュアル等には記載がなく

モジュールを使うにしても、普通に使ってれば影響を受けることはまずありません。影響ないのでマニュアルへの記載もないのだと思います。
推奨されない機能(@によるアクセス)を使うなら、影響を受けないような対策は自分で実施しなければいけません。
苦しめられるのを避けたかったら「推奨されない機能」を「使わない」ようにすることをおすすめします。

「最適化」の機能については、HSP3をずっと追いかけてる人じゃないと知る機会もないと思います。
マニュアルの記載を探してみましたが、これかな?さすがにこれで「記載あり」とは言えないですね。

history.txt
2006/03/09 3.1b2
不必要なモジュール、DLLインポート情報をオブジェクトファイルから破棄する最適化機能を追加。



ネットヤンキーまみ

リンク

2022/2/13(Sun) 13:52:19|NO.95407

> モジュール機能は、スクリプトを整理するためにも積極的な活用をおすすめします。

以前モジュール機能を使いすぎてフローチャートを追いかけて脳内で記憶するのが難しく、
スクリプトを最小限まで削っても解明できなかったのですが、
最近になって最小限まで削った結果最適化で別の問題に巻き込まれていた事がわかり数百時間を無駄にしてしまいました。

きっと私の経験不足という事ですね。今後は改めて推奨の方法で挑戦してみたいと思います!

> 最適化の話はここでは関係ありません。

そうなると私のスクリプトで
goto *a@test
でモジュール内にアクセス出来ず
MIZUSHIKI様のスクリプトでは
goto *a@test
でモジュール内にアクセス出来たのは何故なのでしょうか。
> 実は、一度も使われていないモジュールは丸ごと無かったことにされてしまいます。
> (実行ファイルサイズを抑える最適化の為と思われます。)
> なので、ネットヤンキーまみさんのスクリプトの場合、適当な命令を定義して実行してあげなくてはなりません。

MIZUSHIKI様の話をくみ取ると関係がある様に見えるのですが…
アクロバティックな方法は控えるとしても、理解していないまま解決にするのは失礼かつ後続の方にとっても不利益になってしまう気がするので
お聞かせいただければ幸いです。



ネットヤンキーまみ

リンク

2022/2/15(Tue) 16:09:49|NO.95428

どうしても気になって下記のスクリプト組んでみました。

#module test #deffunc emp_deffunc return *a mes "module" return #global #module test2 *a return #global #module test3 #deffunc emp_deffunc2 return *a return #global ; emp_deffunc ; gosub *a@test ; gosub *a@test2 ; gosub *a@test3

上記の結果から、emp_deffuncを実行する場合のみa@testが存在する様にみえます。
その為、
・a@test2 及びa@test3 はコンパイル時に破棄されている
・moduleはdeffunc、defcfunc及びnewmodでglobalからアクセスをしないと実行できない(コンパイルされない)
とおもったのですが

>極めて特殊でアクロバティックな使い方として、モジュールの外からモジュール内の変数に直接アクセスするために「変数名@モジュール名」という書式を使うことができます。(プログラミング・マニュアル 4.5.モジュール定義命令)
>この方法が使えるのは変数名であり、ラベルには適用されません。ラベルは変数ではありません。


上記のご教示を下記スクリプトで試してみたところエラーにはなりませんでした(@_@)

#module test b=100 #global v=b@test mes v

これはb@testは存在しないものの、HSPが動的言語であるためエラーが回避されており、
実際は moduleはdeffunc、defcfunc及びnewmodでglobalからアクセスをしないと実行できない(コンパイルされない) という理解であっていますでしょうか。
またそれはいわゆる最適化とは違うのでしょうか。

引き続きご教示賜りますと幸いです。



usagi

リンク

2022/2/15(Tue) 17:54:31|NO.95429

こんにちわ
プリプロセスの段階な気がしますね。

#cmpopt optinfo 1 を追加いただくとコンパイル時に
"#未使用のモジュールを削除しました test"のメッセージが出ますので、
モジュール内の命令、関数呼び出しが無いから使ってと判断され
削除したという事で動作的には合っているのかと思いました。

特にスクリプトの容量が気にならなければ、
#cmpopt optcode 0 を追加して削除しないのも
運用によっては回避方法かもしれません。

削除しない状態でコンパイルするとプリプロセス後の実態は以下になります。
※#cmpopt ppout 1 で出力した一部

#module test goto@hsp *_test_exit ;ここは使ってないからスキップされる *a@test ;でも消さない設定にしてるので、ラベルが残る b@test=1000 stop@hsp *_test_exit ;ここまでスキップ #global goto@hsp *a@test ;ラベルが残ってるのでジャンプできる end@hsp

あとは何かしらの理由で基本最適はしたいけど、
このモジュールだけは最適化したくない等であれば、ダミーで以下のように回避もありかもしれません。

#module test #deffunc non_optimization non_optimization *labe b=100 return #global

おそらく、モジュールはネームスペースみたいなものですから、
スクリプトが長くなってきて変数名は干渉したくないけど、
ラベルはグローバルにアクセスしたい。みたいなことがやりたいのかと思いました。
いかがでしょうか。
※モジュール内のラベルにgotoするより命令に置き換えてgosub的な運用の方が管理は楽かもですね。



usagi

リンク

2022/2/16(Wed) 20:44:14|NO.95443

>これはb@testは存在しないものの
これのコメント忘れてました。
内部的にはプリプロセス時にグローバル領域との干渉を防ぐため
変数に@マークが自動でつくのが仕様です。(置換される)

例えばhogeと宣言した場合

グローバル領域 : hoge ※hoge@でモジュールからアクセスできる。
モジュール領域(名前なし) : hoge@_m* ※*は自動で数字が付く
モジュール領域(名前あり) : hoge@test ※testと名前を付けた場合

ですから、v=b@test の部分はモジュール外で@testと付けた変数を
用意しただけ(存在している)と言えばよいでしょうか。
※ラベルではないですから、エラーはでないです。

デバックウインドウでは@付きはモジュール扱いの表示になりますので、
モジュールにチェック入れれば、変数として確保されている事が分かると思います。

一例で、こういったスクリプトも動きます。
※ただマニュアルで推奨はされてないですし、私もこのようなコードデザインは避けます。
いかがでしょうか。

・グローバルで@付きを宣言した。

a@test = 10 b@test = a@test a = 5 mes a@test ;10になる mes b@test mes a; 5になる

・モジュール内からグローバル変数へアクセス

#module test #deffunc tes mes a@ ; 0ではなく10と表示される stop #global a = 10 tes



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