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:
@@ -1781,6 +1781,35 @@ func (p *Parser) parseSet() *ast.SetCmd {
|
||||
if upperSetting == "FILTER" || upperSetting == "RELATION" || upperSetting == "ORDER" || upperSetting == "INDEX" {
|
||||
if p.current.Kind != token.NEWLINE && p.current.Kind != token.EOF {
|
||||
expr = p.parseExpr()
|
||||
// SET INDEX TO a, b, c — collect comma-separated file names
|
||||
// into a single string literal "a,b,c" for gengo to split.
|
||||
if upperSetting == "INDEX" {
|
||||
getName := func(e ast.Expr) string {
|
||||
switch v := e.(type) {
|
||||
case *ast.IdentExpr:
|
||||
return v.Name
|
||||
case *ast.LiteralExpr:
|
||||
return v.Value
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
combined := getName(expr)
|
||||
for p.current.Kind == token.COMMA {
|
||||
p.advance()
|
||||
if p.current.Kind != token.NEWLINE && p.current.Kind != token.EOF {
|
||||
next := p.parseExpr()
|
||||
combined += "," + getName(next)
|
||||
}
|
||||
}
|
||||
if strings.Contains(combined, ",") {
|
||||
expr = &ast.LiteralExpr{
|
||||
Value: combined,
|
||||
Kind: token.STRING,
|
||||
ValuePos: expr.Pos(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if p.current.Kind == token.INTO {
|
||||
p.advance()
|
||||
|
||||
Reference in New Issue
Block a user