[なでしこv1] PHiValue型で変数の詳細を覗いてみよう

## まえがき
`なでしこv1` が来年でいよいよ20周年を迎えることになります。
Windowsアプリケーションを作る用途としては痒いところに手が届かない部分も多々あるものの、
インストールが非常に容易であり、簡単な文字列処理などを行うスクリプト言語として活用する機会はまだ十分にあると言えます。

## ところで、PHiValue型って…？
`PHiValue` 型とは、なでしこ内部で使われている型です。
整数、実数、文字列、グループなどの変数はこの型で管理されています。
厳密に言えばポインタ型というメモリの番地が入った型であり、実際のデータはその指し示す先に格納されています。
通常は意識することがないものですが、せっかくなのでちょっと中身を覗いてみましょう。
デバッグにも活用できるかもしれません。

## THiValue型
`PHiValue` が指し示す先にある実際のデータ `THiValue` 型について説明します。

THiValue型は `hi_unit\hima_variable.pas` で次のように定義されています。
```pascal:hi_unit\hima_variable.pas
  THiValue = packed record
    VType       : THiVType; // 値の型
    Size        : Integer;  // 値の大きさ
    VarID       : DWORD;    // 変数名
    RefCount    : Integer;  // 参照カウント
    Setter      : PHiValue; // Setter
    Getter      : PHiValue; // Getter
    ReadOnly    : Byte;     // 定数なら 1 変数なら 0
    Registered  : Byte;     // 変数として登録した場合は1, 自動解放は0 // 配列やグループでも後々自動的に解放されるものは 1 に設定される
    Designer    : Byte;     // 誰が定義した変数か(0..User/1..System)
    Flag1       : Byte;     //
    case Byte of
    0:( int     : Longint   ); // varInt
    1:( ptr     : Pointer   ); // other...
    2:( ptr_s   : PAnsiChar ); // varStr
    3:( link    : PHiValue  ); // varLink
  end;
```
何やら色々と書かれていますが、とりあえず変数にはこれだけの情報を持っているということがわかります。

## 実行環境
> AMD E2-7110 APU with AMD Radeon R2 Graphics 1.80 GHz RAM 8.00 GB
> Windows 10 Home 22H2
> なでしこ v1.550

## PHiValue型から変数情報を取得してみよう
シンタックスハイライトになでしこの色分けがないので、なでしこエディタにコピー＆ペーストして読むことをおすすめします。
```:hv_utils.nako
●変数詳細取得({参照渡し}Vの)
　ADDR(V)からPHiValue詳細取得

●変数名詳細取得({文字列}vNameの|vNameから)
　pとは整数 = nako_getVariable(vName)
　もしp > 0なら
　　pからPHiValue詳細取得
　違えば
　　_ = "変数「{vName}」が見つかりません。{~}"

●PHiValue詳細取得({整数}Pから)
　resultとは文字列
　hiValueとはTHiValue
　varNameとは文字列
　varNameに1KBを確保
　UNPACK(UNPOINTER(P, 29), hiValue, `byte,int,long,int,int,int,byte,byte,byte,byte,int`)
　hiValueについて
　　nako_id2tango(VarID, POINTER(varName), varNameのバイト数)
　　result = "変数名：{varNameをトリム}{~}型とサイズ：{VTypes[VType]} ({Size}バイト){~}" &
　　　"変数名ID：{VarID}{~}参照カウント：{RefCount}{~}" &
　　　"セッター：{FORMAT(Setter, `0x%.8x`)}{~}ゲッター：{FORMAT(Getter, `0x%.8x`)}{~}" &
　　　"定数：{YesNoStr[ReadOnly]}{~}変数として登録：{YesNoStr[Registered]}{~}" &
　　　"システムとして定義：{YesNoStr[Designer]}{~}データ：{FORMAT(Data, `0x%.8x`)} "

　　VTypeで条件分岐
　　　varIntなら、resultに"(整数: {Data})"を追加
　　　varFloatなら、resultに"(実数: {nako_var2double(P)})"を追加
　　　varStrなら、resultに"(文字列: {UNPOINTER(Data, Size)をトリム})"を追加
　　_ = result & "{~}"

■THiValue
　・VType
　・Size
　・VarID
　・RefCount
　・Setter
　・Getter
　・ReadOnly
　・Registered
　・Designer
　・Flag1
　・Data

!YesNoStr = "いいえ{~}はい"
!VTypes   = "NIL{~}整数{~}実数{~}文字列{~}ポインタ{~}関数{~}配列{~}ハッシュ{~}グループ{~}リンク"

!varNil     = 0
!varInt     = 1
!varFloat   = 2
!varStr     = 3
!varPointer = 4
!varFunc    = 5
!varArray   = 6
!varHash    = 7
!varGroup   = 8
!varLink    = 9

# 変数IDから単語を取得したり、変数名からPHiValueを求めたりするためのなでしこAPI
●nako_id2tango(id,tango,maxLen) = DLL(`dnako.dll`, `DWORD nako_id2tango(DWORD,char*,DWORD)`)
●nako_getVariable(vName) = DLL(`dnako.dll`, `PHiValue nako_getVariable(char*)`)
●nako_var2double(hiValue) = DLL(`dnako.dll`, `double nako_var2double(PHiValue)`)
```
上記のコードを `hv_utils.nako` で保存してください。

## 使ってみる！
```:hv_usage.nako
!『hv_utils.nako』を取り込む
!πとは実数 = 3.141592653589

リンゴとは数値
ミカンとは文字列

リンゴは5個
リンゴの変数詳細取得して表示
ミカンは『おいしい』
ミカンの変数詳細取得して表示

πの変数詳細取得して表示

『あ』の変数名詳細取得して表示
『作業フォルダ』の変数名詳細取得して表示
待機
```
先ほど保存した `hv_utils.nako` と同じフォルダで実行してください。

```:実行結果
変数名：リンゴ
型とサイズ：整数 (0バイト)
変数名ID：100095
参照カウント：1
セッター：0x00000000
ゲッター：0x00000000
定数：いいえ
変数として登録：はい
システムとして定義：いいえ
データ：0x00000005 (整数: 5)

変数名：ミカン
型とサイズ：文字列 (9バイト)
変数名ID：100096
参照カウント：1
セッター：0x00000000
ゲッター：0x00000000
定数：いいえ
変数として登録：はい
システムとして定義：いいえ
データ：0x02386F60 (文字列: おいしい)

変数名：π
型とサイズ：実数 (10バイト)
変数名ID：100094
参照カウント：1
セッター：0x00000000
ゲッター：0x00000000
定数：はい
変数として登録：はい
システムとして定義：いいえ
データ：0x02386DA0 (実数: 3.141592653589)

変数「あ」が見つかりません。

変数名：作業フォルダ
型とサイズ：NIL (0バイト)
変数名ID：537
参照カウント：0
セッター：0x01EC1F10
ゲッター：0x01EC1F60
定数：いいえ
変数として登録：はい
システムとして定義：はい
データ：0x00000000
```

## 最後に
なでしこユーザー歴が長い自分でもまだよく知らない機能や発見があったりして面白いな～と思います。
v3の方は実はあまり触っていないのですが、そっちも沼が深いかもしれませんね。