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:
@@ -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
|
||||
|
||||
@@ -40,6 +40,22 @@ func HbHGet(t *hbrt.Thread) {
|
||||
t.RetValue()
|
||||
}
|
||||
|
||||
// HbHGetDef gets a value from a hash by key, returning a default if missing.
|
||||
// Harbour: hb_HGetDef(hHash, xKey, xDefault) → xValue
|
||||
func HbHGetDef(t *hbrt.Thread) {
|
||||
t.Frame(3, 0)
|
||||
defer t.EndProc()
|
||||
if hh := t.Local(1).AsHash(); hh != nil {
|
||||
if i := hh.Lookup(t.Local(2)); i >= 0 {
|
||||
t.PushValue(hh.Values[i])
|
||||
t.RetValue()
|
||||
return
|
||||
}
|
||||
}
|
||||
t.PushValue(t.Local(3))
|
||||
t.RetValue()
|
||||
}
|
||||
|
||||
// HbHSet sets a value in hash by key.
|
||||
// Harbour: hb_HSet(hHash, xKey, xValue) → hHash
|
||||
func HbHSet(t *hbrt.Thread) {
|
||||
|
||||
@@ -278,6 +278,27 @@ func PCount(t *hbrt.Thread) {
|
||||
t.RetInt(int64(t.CallerParamCount()))
|
||||
}
|
||||
|
||||
// PValue returns the nth parameter of the calling PRG function.
|
||||
// Harbour: PValue(nIndex[, xDefault]) → xValue
|
||||
// Returns xDefault when n is out of range, or NIL if no default was given.
|
||||
func PValue(t *hbrt.Thread) {
|
||||
nParams := t.ParamCount()
|
||||
t.Frame(nParams, 0)
|
||||
defer t.EndProc()
|
||||
n := int(t.Local(1).AsNumInt())
|
||||
if n >= 1 && n <= t.CallerParamCount() {
|
||||
t.PushValue(t.CallerLocal(n))
|
||||
t.RetValue()
|
||||
return
|
||||
}
|
||||
if nParams >= 2 {
|
||||
t.PushValue(t.Local(2))
|
||||
} else {
|
||||
t.PushNil()
|
||||
}
|
||||
t.RetValue()
|
||||
}
|
||||
|
||||
// Break moved to error.go — full implementation with BreakValue type.
|
||||
|
||||
// Array creates array of given size.
|
||||
|
||||
@@ -69,6 +69,7 @@ func RegisterRTL(vm *hbrt.VM) {
|
||||
// Hash
|
||||
hbrt.Sym("HB_HASH", hbrt.FsPublic, HbHash),
|
||||
hbrt.Sym("HB_HGET", hbrt.FsPublic, HbHGet),
|
||||
hbrt.Sym("HB_HGETDEF", hbrt.FsPublic, HbHGetDef),
|
||||
hbrt.Sym("HB_HSET", hbrt.FsPublic, HbHSet),
|
||||
hbrt.Sym("HB_HDEL", hbrt.FsPublic, HbHDel),
|
||||
hbrt.Sym("HB_HHASKEY", hbrt.FsPublic, HbHHasKey),
|
||||
@@ -120,6 +121,8 @@ func RegisterRTL(vm *hbrt.VM) {
|
||||
// Misc (new)
|
||||
hbrt.Sym("TYPE", hbrt.FsPublic, TypeFunc),
|
||||
hbrt.Sym("PCOUNT", hbrt.FsPublic, PCount),
|
||||
hbrt.Sym("PVALUE", hbrt.FsPublic, PValue),
|
||||
hbrt.Sym("HB_PVALUE", hbrt.FsPublic, PValue),
|
||||
hbrt.Sym("BREAK", hbrt.FsPublic, Break),
|
||||
hbrt.Sym("ARRAY", hbrt.FsPublic, ArrayFunc),
|
||||
hbrt.Sym("FCOUNT", hbrt.FsPublic, FCount),
|
||||
|
||||
Reference in New Issue
Block a user