Major changes since last commit: - FiveSql2 SQL:1999 engine (10,458 LOC) — 43/43 ALL PASS - 21 compiler/runtime bugs fixed (short-circuit AND/OR, FOR LOOP, etc.) - @byref pass-by-reference via RefCell pattern - Mutable closure capture (EnsureLocalRef + RefCell sharing) - RTL: 400 → 479 functions (+79: file, string, datetime, hash, UTF-8) - DateTime/Timestamp fully working (hb_DateTime, hb_Hour/Min/Sec, display) - Reserved word guard (39 keywords blocked from function calls) - AEval arg order fix (element before index) - Closure capture redecl fix (unique _cap_ names per block) - Hash/string indexing in ArrayPush/ArrayPop - Harbour compat test suite: 51/51 - 4 docs: Porting Report, Implementation Plan, Optimization Plan, Commercialization Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
148 lines
3.4 KiB
Go
148 lines
3.4 KiB
Go
// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
|
|
// All rights reserved.
|
|
|
|
// BaseArea provides default implementations for the Area interface.
|
|
// Harbour equivalent: WAAREA (workarea.c) — ~25 real + ~76 stub methods.
|
|
// Concrete drivers (DBFArea, etc.) embed BaseArea and override as needed.
|
|
package hbrdd
|
|
|
|
import "five/hbrt"
|
|
|
|
// BaseArea is the base workarea with default flag management.
|
|
// Harbour: struct _AREA in hbapirdd.h
|
|
type BaseArea struct {
|
|
driver Driver
|
|
alias string
|
|
fields []FieldInfo
|
|
fieldMap map[string]int // field name → index (0-based)
|
|
|
|
// Cursor state flags — Harbour: fBof, fEof, fFound, fTop, fBottom
|
|
FBof bool
|
|
FEof bool
|
|
FFound bool
|
|
FTop bool
|
|
FBottom bool
|
|
|
|
// Filter
|
|
filterExpr string
|
|
filterBlock func(*hbrt.Thread) bool
|
|
|
|
// Locate
|
|
locateExpr string
|
|
locateBlock func(*hbrt.Thread) bool
|
|
|
|
// Relations
|
|
relations []*Relation
|
|
}
|
|
|
|
// Relation holds a parent→child relationship.
|
|
type Relation struct {
|
|
Child Area
|
|
KeyExpr func(*hbrt.Thread) hbrt.Value
|
|
Scoped bool
|
|
}
|
|
|
|
// --- BaseArea default implementations ---
|
|
|
|
func (a *BaseArea) Driver() Driver { return a.driver }
|
|
func (a *BaseArea) Alias() string { return a.alias }
|
|
func (a *BaseArea) SetAlias(s string) { a.alias = s }
|
|
func (a *BaseArea) BOF() bool { return a.FBof }
|
|
func (a *BaseArea) EOF() bool { return a.FEof }
|
|
func (a *BaseArea) Found() bool { return a.FFound }
|
|
func (a *BaseArea) SetFound(b bool) { a.FFound = b }
|
|
func (a *BaseArea) FieldCount() int { return len(a.fields) }
|
|
|
|
func (a *BaseArea) GetFieldInfo(index int) FieldInfo {
|
|
if index >= 0 && index < len(a.fields) {
|
|
return a.fields[index]
|
|
}
|
|
return FieldInfo{}
|
|
}
|
|
|
|
// FieldIndex returns the 0-based field index by name, or -1 if not found.
|
|
func (a *BaseArea) FieldIndex(name string) int {
|
|
if a.fieldMap == nil {
|
|
return -1
|
|
}
|
|
if idx, ok := a.fieldMap[name]; ok {
|
|
return idx
|
|
}
|
|
return -1
|
|
}
|
|
|
|
// InitFields sets up the field array and name→index map.
|
|
func (a *BaseArea) InitFields(fields []FieldInfo) {
|
|
a.fields = fields
|
|
a.fieldMap = make(map[string]int, len(fields))
|
|
for i, f := range fields {
|
|
a.fieldMap[f.Name] = i
|
|
}
|
|
}
|
|
|
|
// Close provides the base close behavior (reset flags).
|
|
// Harbour: hb_waClose
|
|
func (a *BaseArea) Close() error {
|
|
a.FBof = true
|
|
a.FEof = true
|
|
a.FFound = false
|
|
a.fields = nil
|
|
a.fieldMap = nil
|
|
a.relations = nil
|
|
return nil
|
|
}
|
|
|
|
// --- Filter support ---
|
|
|
|
func (a *BaseArea) SetFilter(expr string, block func(*hbrt.Thread) bool) error {
|
|
a.filterExpr = expr
|
|
a.filterBlock = block
|
|
return nil
|
|
}
|
|
|
|
func (a *BaseArea) ClearFilter() error {
|
|
a.filterExpr = ""
|
|
a.filterBlock = nil
|
|
return nil
|
|
}
|
|
|
|
func (a *BaseArea) HasFilter() bool {
|
|
return a.filterBlock != nil
|
|
}
|
|
|
|
// --- Relation support ---
|
|
|
|
func (a *BaseArea) SetRelation(child Area, keyExpr func(*hbrt.Thread) hbrt.Value, scoped bool) error {
|
|
a.relations = append(a.relations, &Relation{
|
|
Child: child,
|
|
KeyExpr: keyExpr,
|
|
Scoped: scoped,
|
|
})
|
|
return nil
|
|
}
|
|
|
|
func (a *BaseArea) ClearRelation() error {
|
|
a.relations = nil
|
|
return nil
|
|
}
|
|
|
|
// --- Locate support ---
|
|
|
|
func (a *BaseArea) SetLocate(expr string, block func(*hbrt.Thread) bool) {
|
|
a.locateExpr = expr
|
|
a.locateBlock = block
|
|
}
|
|
|
|
func (a *BaseArea) LocateBlock() func(*hbrt.Thread) bool {
|
|
return a.locateBlock
|
|
}
|
|
|
|
// --- Global RDD configuration callbacks ---
|
|
// These are set by hbrtl to avoid circular imports.
|
|
|
|
var (
|
|
// IsSetDeleted returns true when SET DELETED is ON.
|
|
// Set by hbrtl.init() to hbrtl.GetSetDeleted.
|
|
IsSetDeleted func() bool
|
|
)
|