秀丸マクロにtypeof 実装要望No.09123
天翔記.jp さん 16/10/04 15:02
 
こちら、秀丸マクロへの新関数の要望となります。

秀丸マクロに以下のような関数を実装していだくことはできますか?

typeof( filename ) とすると "string"

typeof(1) とすると、"numer"
typeof(1.3) とすると、"number" (こちらは浮動小数点秀丸用)
typeof( sprintf ) とすると、エラーもしくは"function" // 仕様次第
typeof( #aa ) とすると、"number"
typeof( $aa )とすると、"string"

comobjectなどの場合、悩みますが、"userdata"なり、"object"なりで良いと思います。

それ以外 エラーなり"unknown"

みたいなものです。


各言語で、似たような機能のもの。
typeid // C++
typeof -- C#, javascript
type -- luaやpython  
.class -- ruby

これらは、何通りか使いみちがありますが、

@型によってバラバラな記述となっている関数を、
総称的な記述へとまとめる際に必要です。
(マクロシーンでいえば、「引数が数値でも、文字列でも上手く処理出来る関数」を
作るといった場合に必要)

AC++側から、マクロに変数シンボルを問い合わせて、
 C++側へとコピーしてくる際に、
 必要性が高くなります。
(これも究極的には、「マクロ上のシンボルが数値でも文字列」でもC++層以上の上
層が同一記述で上手く処理できるあらゆるプログラムを作る際に必要ということにな
ります)


ぜひご検討ください

[ ]
RE:09123 秀丸マクロにtypeof 実装要望No.09124
天翔記.jp さん 16/10/04 15:10
 
ちょっと追記

配列の場合も忘れていました。
$a[0] = 1;

typeof($a) ⇒ "array"なり"table"なり

[ ]
RE:09124 秀丸マクロにtypeof 実装要望No.09125
秀丸担当 さん 16/10/04 16:05
 

秀丸マクロは変数名の頭に#や$が付くので、その種類が何かということを調べる
ことはなく、わかってしまうと思います。
また配列はちょっと特殊で、$aaと$aa[n]は別の存在になっています。
aaの種類は何かということを調べることは無く、#aa $aa $aa[n] がそれぞれ別
の値で共存して存在しています。
ちなみにmenuarrayは、menuarray $aa,10;という感じで書きますが、使うのは
$aaじゃなくて$aa[n]のほうを見ていたりします。

[ ]
RE:09125 秀丸マクロにtypeof 実装要望No.09126
天翔記.jp さん 16/10/04 16:29
 
確かに、$a などは(最悪目印がついてるので)わかりますが、
filenameやxやyといったものが、そのシンボル名を受けただけではわかりません。

(今は仮に強引に秀丸マクロを全部を調べ尽くして登録したとしても、
 将増えたものに付いていけないです)

[ ]
RE:09126 秀丸マクロにtypeof 実装要望No.09127
秀丸担当 さん 16/10/04 17:35
 

filenameやxなどは、固定なのであらかじめ知っているということになりますが、
利用されるシーンがちょっとよくわからないです。
マクロ内では、サブルーチンでは##1や$$1になってキーワードが使われるわけで
はないということと、C++側とのやりとりというのは具体的なイメージがちょっ
とわからず、教えていただけると助かります。

[ ]
RE:09127 秀丸マクロにtypeof 実装要望No.09128
天翔記.jp さん 16/10/04 18:38
 
>はないということと、C++側とのやりとりというのは具体的なイメージがちょっ
>とわからず、教えていただけると助かります。
あ、たしかに、typeofがあっても、マクロの層だと総称的に出来ないですね。
(typeofがあっても、数値でも文字列でも両方でいける関数を作れないです、失礼し
ました)


C++でのやりとりが必要というのは、Hideamru_EvalMacroがあるので、
必要性が高くなる(無くても書けるがあると圧倒的にスマートになる)。

秀丸マクロ上の、変数の中身は、C++からは直接読めないので、
何らかの形で、C++で扱うためには、必ず、マクロ⇔C++の変数伝達
が必要となります。

EvalMacro(R("
    // 対象が文字列なら、SetStrVarというdllの関数を使わねばならない
    #_ = dllfuncw( #self, "SetStrVar", "filename", filename);
    // マクロの環境変数内にある内容を、自分自身のdllに伝えて、
  // 何らかの形で、filenameというなまえのハッシュなりなんなりに
    // 移すことになる。

    // 対象が数値なら、SetNumVarというdllの関数を使わねばならない
    #_ = dllfuncw( #self, "SetNumVar", "x", x);
    // 数値だとこうなる。秀丸マクロ⇒dll自分に伝達する度に、
    // StrかNumかの関数の呼び分けが必要になる。
);

これをC++で関数でラップしたとして、

// AUTODYNAMICは何の型でも受け付けられるようなタイプを作成したとする
AUTODYNAMIC GetMacroVar( string var_name) {
    // 連結とか記述すると煩雑なので、以下の%sにvar_nameの内容の文字列が入っ
てるものとします
    // ここでtypeofがあれば、
    hm.EvalMacro("
        if typeof( %s ) == "string" {
            // マクロ⇒dllへの文字列タイプの伝達
            #_ = dllfuncw( #self, "SetStrVar", %s, %s);
        } else typeof( %s ) == "number" {
            // マクロ⇒dllへの数値タイプの伝達
            #_ = dllfuncw( #self, "SetNumVar", %s, %s);
        }
    )

    return AutoDynamicHash[var_name];
}

AUTODYNAMIC myfilename = GetMacroVar( "filename" );
AUTODYNAMIC cpp_xx = GetMacroVar( "$xx" );
AUTODYNAMIC cpp_date = GetMacroVar( "date" );


GetMacroVarとは別に、SetMacroVarも作成し、オブジェクトや演算子多重定義や代入
演算子などでさらに洗練させてゆくと、記述は

// C++上で、macrovarというオブジェクトは、秀丸マクロの変数アクセスオブジェク
トであるかのように利用できる。
auto myfilename = macrovar["filename"];
auto cpp_xx = macrovar["$xx"];
macrovar["$xx"] = "abc";


typeofで一番あるあるな役割がこのパターンだろうと思います。
(実際にはもっととりまわしがし易いAUTODYNAMICとか作る必要がないC#とかで実装す
ると思います)




秀丸マクロの場合ほとんどの場合は、「数値なタイプなの?」「文字列なタイプな
の?」に糾合されるので、

文字列でもそれ以外でもどちらでも(関数の)引数にできるけれども、
(関数)結果から引数が文字列だったか、そうでないか、
判別可能な関数が1つでに既存であるならば、それで概ねは代用できるかもしれませ
ん。

現行の秀丸マクロとして、「引数の型を問わない関数」が難しいようなら、実装しだ
いですが、sprintfあたりに、%tとか加えて、実現できないかな〜とか。


[ ]
RE:09128 秀丸マクロにtypeof 実装要望No.09129
天翔記.jp さん 16/10/05 02:42
 
以下のようなものを秀丸担当さんなら、
どうC++層で実装するか、という観点で考えていただければ
Hidemaru_EvalMacroを使う上で、
何から複数点で使いづらいと実感していただけるかと思います。

(以前別途投稿させていただいた、#mydllの値なりシンボルなりがdll内部から必要な
どといったことも納得いただけるかと…)

■完結されたdllを作成する。

 .mac内容は以下のようなものとする。

   #mydll = loaddll( hidemarudir + @"\test.dll" );
   #_ = dllfuncw( #mydll, "DoFunc" );
   freedll(#mydll);

  ただし、mydllという変数名は、秀丸ユーザーが後日編集するかもしれない。
 また、loaddll関数ではなく、loaddll文を使った形に直してしまうかもしれない。

 又、上記記述の前や後に、別のマクロ記述を秀丸ユーザーが増やすかもしれない。


■C++層(test.dll)

 C++層のDoFuncでは、何か「シンボル名」を秀丸ユーザーによって入力してもらい、
結果を表示する、というところまで行う。

 (あ)何か「シンボル名」を秀丸ユーザーによって入力してもらう。

  この投稿での「シンボル名」の定義:
   「秀丸マクロ上」から見える何らかの変数名(##aaや$bなど)とする
   また、filenameやxやdateなど秀丸専用の変数名全てシンボル名に含む。

  入力方法としては、C++のdll内部から
    (a)秀丸マクロのinput関数をHidemaru_MacroEvalで発行し、ユーザーの入力
結果を利用する。
     (これは、ユーザーにテキストファイルでシンボル名を記載するようなス
クリプトを作ってもらうことと同じことのシュミレーション)

 (い)ユーザーが入力した「シンボル名」に完全一致するものが「秀丸マクロ環境」
にあれば、
   それをC++層からMesssageBoxとして表示する。
   ただし、win32APIとなる、MessageBoxWを使う。(C++から値をコントロールす
るということ)
   その値が、文字列系だったのか、数値系だったのか、
   もメッセージボックスの表示に含むこととする。
   (意味もわからず表示しているのはダメだということ)
   (例えば、ユーザーが、input関数の入力枠に、「filename2」と入力したなら
ば、現在秀丸で開いているファイルのフルパスを
   MessageBoxWを使って表示し、文字列タイプであることも併記する
   ユーザーが、input関数の入力枠に「x」と入力すれば、
   現在の秀丸のカーソルのx位置をMessageBoxWで表示し、
   それが数値タイプだということも添えること。

   現在の秀丸実装に存在する「シンボル名」だけではなく、
   将来の秀丸のシンボル名に対しても原則的に、
   このdll作成時で全部対応すること。


以上です。
(別に上のままのものを実装しているわけではないですが…)


このあたりを実装を試みていただくと、Hidemaru_MacroEval を
現実的に利用する上での、すごい問題点や、クリアは出来ているが
取りまわりが不自然となるポイントがハッキリと認識していただけるかと思います
(多分3点)。

[ ]
RE:09129 秀丸マクロにtypeof 実装要望No.09130
秀丸担当 さん 16/10/05 13:13
 

具体的な例などありがとうございます。
イメージが掴めました。
無いよりかはあったらいいと思いますが、実際に目的を持って何かを作る場合は
マクロ同様あらかじめ知っていることがほとんどだと思うので、マクロで、
  #a=x;
  $b=filename;
のように、知っていて#や$を決めるかのごとく、DLLでも知っているものとして、
  a=GetNumVar("x");
  b=GetStrVar("filename");
というように関数を分けたりすれば、それほど大差無く作れるのではないかと思
います。
デバッグや習得の目的で、どっちかよくわからないものを調べることには使える
とは思います。

作るとしたら、こちらでも実際の動作とは直接繋がりのない一覧を作って、それ
を返すだけのようなものになり、もし一覧を間違えていても気づかないままにな
ると思います。

1つの案として、パラメータの種類などの呼ばれ方を取得する方法があるといい
のではないかと思います。
マクロ内の例の場合、サブルーチンであるといいのは、パラメータの種類を取得
する方法があるといいです。
例えばgetparamtype(1)とか作って、##1を使うべきか$$1を使うべきか判断でき
たらいいです。

同じようにDLLの場合、Hidemaru_GetDllFuncCalledType()のようなものを作って、
マクロで文字列を渡したか数値を渡したかをDLL側で知ることができれば、安全
なDLLを作ることもでき、typeofのような使い方もできると思います。
あとdllfunc/dllfuncstrの違いや、dllfunc/dllfuncwの違いも判断できたらいい
です。
現状、DLLを配布して第三者に使ってもらうような場合、呼び方を間違えると落
ちる危険性がありますが、それを防止することができると思います。
(あくまで1つの案として)

[ ]
RE:09130 秀丸マクロにtypeof 実装要望No.09132
天翔記.jp さん 16/10/05 18:10
 
>作るとしたら、こちらでも実際の動作とは直接繋がりのない一覧を作って、それ
>を返すだけのようなものになり、もし一覧を間違えていても気づかないままにな
>ると思います。
う〜むなるほど、それではちょっとよろしくないですね〜


>同じようにDLLの場合、Hidemaru_GetDllFuncCalledType()のようなものを作って、
>マクロで文字列を渡したか数値を渡したかをDLL側で知ることができれば、安全
>なDLLを作ることもでき、typeofのような使い方もできると思います。
>あとdllfunc/dllfuncstrの違いや、dllfunc/dllfuncwの違いも判断できたらいい
>です。
>現状、DLLを配布して第三者に使ってもらうような場合、呼び方を間違えると落
>ちる危険性がありますが、それを防止することができると思います。
>(あくまで1つの案として)
おー
sizeof(int) == sizeof(TCHAR *) == sizeof(float[浮動小数版秀丸]) だから、
マクロから渡すだけ渡してC++層でHidemaru_GetDllFuncCalledType()の結果に応じて、
処理出来るってことですか?
(dllfuncのwとか結構付け忘れますからねぇ。あれ自分でも頻繁に間違えるので、正
直警告だしたいですし…)



あと、やはり何度考えても、Hidemaru_EvalMacroが出来た限り、
「dllがどのような方法でloaddllされたのか、loaddll関数の場合は、その#dll値は
何か」
dll自身が自分で判別できるような方法があった方が良いと思います。

今だと、dll内からHidemaru_EvalMacroで「loaddllfile」と「getloaddllfile」を順
次呼び出して、
dll自身のフルパスと一致すれば、
「dll自身にその『#dll値』を伝える (loaddll文だった場合は区分けが付く別値)」
というのは
あまりにトリッキーというかなんというか…

[ ]
RE:09132 秀丸マクロにtypeof 実装要望No.09133
秀丸担当 さん 16/10/06 16:04
 

とりあえずHidemaru_GetDllFuncCalledType()でパラメータの種類や、呼ばれ方
を判断できる方向で検討してみます。

自身の#dllが何であるかを知るというのは、それを伝える関数をDLL側に用意し
てもらってもいいですし、EvalMacroで丸投げ状態なので自由にしてもらえばい
という気がします。
EvalMacroとかその中でdllfuncとかしている時点でもう既にトリッキーだらけに
なっていると思います。
Hidemaru_GetDllFuncCalledType(0)でdllfuncの種類、1〜でパラメータの種類に
しようかと考えていますが、例えば-1のときに#dllを返すくらいであればおそら
く簡単だとは思います。
それでトリッキーが軽減されるかというと、たいして変わらない気がします。

[ ]
RE:09133 秀丸マクロにtypeof 実装要望No.09134
天翔記.jp さん 16/10/06 17:41
 
>Hidemaru_GetDllFuncCalledType(0)でdllfuncの種類、1〜でパラメータの種類に
>しようかと考えていますが、例えば-1のときに#dllを返すくらいであればおそら
>く簡単だとは思います。
個人的には、可能であれば、

Hidemaru_GetDllFuncCalledType(-1) などにより、

・対象のdllが、
 #dll = loaddll( "***.dll" );
 みたいに、「loaddll関数」で呼ばれていれば、その#dll値そのものを。

・対象が
 loaddll "***.dll";
 みたいに「loaddll文」で呼ばれていれば、何か別の値(#dll値と被りえない値:-1
とか? など)を
 返していただけると有り難いです。



[ ]
RE:09134 秀丸マクロにtypeof 実装要望No.09136
秀丸担当 さん 16/10/07 11:46
 

Hidemaru_GetDllFuncCalledType(-1) で#dllの値を取得できるようにして、
loadll関数では1から始まる数字で、loaddll文は-1を返すようにしてみます。
0はloadll関数の失敗と同じ値なので、何らかのエラーということにしようと思
います。

[ ]