feat(rtl): add hb_HGetDef and PValue / hb_PValue

Two standard Harbour functions that fivenode-style PRG code (bridge_*.prg
and downstream apps) calls frequently. Without them, every reference
emits an analyzer WARN and resolves to NIL at runtime.

* hb_HGetDef(hHash, xKey, xDefault) — hash lookup with fallback.
* PValue(nIndex[, xDefault]) — read the nth parameter of the calling
  PRG function. Mirrors the PCount pattern: needs the caller frame's
  paramCount and locals, exposed via new hbrt.Thread.CallerLocal helper
  that pairs with the existing CallerParamCount.

Registered under PVALUE and HB_PVALUE (Harbour accepts both forms).

Verified: hb_HGetDef / PValue / HB_PVALUE all return expected values for
present-key, missing-key-with-default, missing-key-no-default, and
out-of-range-param cases. Full regression: go test (18 packages) +
Compat 56/56 + std.ch 17/17 + FRB 7/7 + FiveSql2 43/43 all green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 09:55:19 +09:00
parent 5daba8beec
commit ad6cc0bcee
4 changed files with 53 additions and 0 deletions

View File

@@ -670,6 +670,19 @@ func (t *Thread) CallerParamCount() int {
return 0
}
// CallerLocal returns the n-th parameter of the calling PRG function
// (1-based). Returns NIL if no caller frame exists or n is out of range.
// Pairs with CallerParamCount for implementing the PValue() RTL.
func (t *Thread) CallerLocal(n int) Value {
if t.callSP >= 2 {
caller := &t.calls[t.callSP-2]
if n >= 1 && n <= caller.paramCount {
return caller.GetLocal(n, t.locals)
}
}
return MakeNil()
}
// PendingParams2 sets pending param count for direct block calls (AEval, ASort etc.)
func (t *Thread) PendingParams2(n int) {
t.pendingParams = n