fix: PCount, Break/RECOVER, SET INDEX TO — 3 Harbour compat fixes
Release-blocking compatibility issues discovered during the 258-test
pre-release validation suite (100 syntax + 44 RDD + 114 RTL).
1. PCount() always returned 0 in PRG code
Root cause: ParamCount() returned t.pendingParams, which is
overwritten by every nested Function() call. By the time the
PCount() RTL's Frame() executes, pendingParams is already 0.
Fix: Frame() now stores pendingParams in frame.paramCount.
PCount() RTL uses CallerParamCount() which reads callSP-2
(the PRG caller's frame), while RTL functions still use
ParamCount() (reads pendingParams before their own Frame).
Verified: PCount(1,2,3)=3, PCount(1)=1, PCount()=0
2. Break("string") panicked instead of being caught by RECOVER USING
Root cause: Generated SEQUENCE code only caught *HbError panics.
Break() panics with BreakValue (a different type), which fell
through to EndProc's "runtime error" message and re-panic.
Fix (two parts):
a) gengo emitBeginSequence: recover closure now catches any
panic (interface{}), then dispatches via type switch:
- *HbError → extract .Error() string
- hasValue interface (BreakValue) → extract .GetValue()
- other → static "error" string
b) hbrtl/error.go: BreakValue gets GetValue() method for
duck-type detection without import cycles
c) hbrt/thread.go EndProc: BreakValue type name check added
so it re-panics silently (no stderr noise)
3. SET INDEX TO a, b, c only opened the last file
Root cause: Parser's parseSet() called parseExpr() once for
INDEX setting, stopping at the first comma. Remaining file
names were consumed by the "eat rest of line" loop.
Fix: Parser now collects comma-separated identifiers into a
single string literal "a,b,c". gengo splits on comma and
calls OrderListAdd() for each file.
Verified: SET INDEX TO si_name, si_city → OrdCount=2
All tests pass:
go test ./... 14 packages OK
FiveSql2 43/43 100%
compat_harbour 51/51
Syntax test 100/100
RDD test 44/44
RTL test 114/114
Windows cross-compile OK
Linux cross-compile OK
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -103,6 +103,12 @@ type BreakValue struct {
|
||||
Value hbrt.Value
|
||||
}
|
||||
|
||||
// GetValue returns the Break() argument. Used by RECOVER USING via duck typing
|
||||
// (the generated code checks for a `hasValue` interface to avoid import cycles).
|
||||
func (bv BreakValue) GetValue() hbrt.Value {
|
||||
return bv.Value
|
||||
}
|
||||
|
||||
// Break(xValue) → panics with BreakValue, caught by BEGIN SEQUENCE/RECOVER.
|
||||
func Break(t *hbrt.Thread) {
|
||||
nParams := t.ParamCount()
|
||||
|
||||
@@ -269,11 +269,12 @@ func TypeFunc(t *hbrt.Thread) {
|
||||
t.RetValue()
|
||||
}
|
||||
|
||||
// PCount returns number of parameters passed.
|
||||
// PCount returns number of parameters passed to the calling PRG function.
|
||||
// Harbour: hb_pcount() — returns the CALLER's param count, not PCount's own.
|
||||
func PCount(t *hbrt.Thread) {
|
||||
t.Frame(0, 0)
|
||||
defer t.EndProcFast()
|
||||
t.RetInt(int64(t.ParamCount()))
|
||||
t.RetInt(int64(t.CallerParamCount()))
|
||||
}
|
||||
|
||||
// Break moved to error.go — full implementation with BreakValue type.
|
||||
|
||||
Reference in New Issue
Block a user