Files
five/hbrt/call.go
Charles KWON OhJun 59568f3301 Five v0.9 — Harbour + Go fusion language
- Compiler: PP → Lexer → Parser → Analyzer → Gengo pipeline
- Parser: 232/236 (98%) Harbour compatibility, registry-based dispatch
- RTL: 351 Harbour-compatible functions
- RDD: DBF/NTX/CDX engines with Rushmore bitmap optimization
- Go Interop: IMPORT + pkg.Func() + obj:Method() with FastPath (15M calls/sec)
- HB_FUNC API: Full Harbour C API compatible Go bridge
- Concurrency: SPAWN/LAUNCH/GOROUTINE, <-, WATCH, PARALLEL FOR, ASYNC/AWAIT
- Extensions: Multi-return, DEFER, Slice, f-string, Nil-safe ?:, CONST
- Macro Compiler: Runtime AST parsing and evaluation
- Debugger: TUI debugger with source display, breakpoints, stepping
- FRB: Native + Pcode dual mode runtime binary
- Tests: 13 packages ALL PASS

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:41:50 +09:00

73 lines
1.7 KiB
Go

// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
// All rights reserved.
package hbrt
import "strings"
// pendingCall stores the symbol for the next Function/Do call.
// This avoids storing Go pointers in Value.data (which GC can't trace).
// PushSymbol records the function symbol for the next call.
// The actual symbol is stored in Thread, not on the eval stack.
// A marker NIL is pushed to keep stack positions correct.
// Harbour: hb_xvmPushSymbol
func (t *Thread) PushSymbol(sym *Symbol) {
t.pushPendingSym(sym)
t.push(MakeNil()) // placeholder for symbol position
}
// Function calls the function with nArgs arguments.
// Stack layout before: [sym_placeholder] [nil/self] [arg1] ... [argN]
// Stack after: [retval]
// Harbour: hb_xvmFunction
func (t *Thread) Function(nArgs int) {
sym := t.popPendingSym()
if sym == nil {
panic(t.runtimeError("no function symbol for call"))
}
// Resolve function
fn := sym.Func
if fn == nil && t.vm != nil {
found := t.vm.FindSymbol(strings.ToUpper(sym.Name))
if found != nil {
fn = found.Func
}
}
if fn == nil {
panic(t.runtimeError("undefined function: " + sym.Name))
}
// Collect args from stack
args := make([]Value, nArgs)
for i := nArgs - 1; i >= 0; i-- {
args[i] = t.pop()
}
t.pop() // pop NIL/self placeholder
t.pop() // pop symbol placeholder
// Push args back for Frame() to pick up
for _, arg := range args {
t.push(arg)
}
// Set pending params count and symbol for Frame()
t.pendingParams = nArgs
t.pendingCallSym = sym
// Call
fn(t)
// Push return value
t.push(t.retVal)
}
// Do calls the function but discards the return value.
// Harbour: hb_xvmDo
func (t *Thread) Do(nArgs int) {
t.Function(nArgs)
t.pop() // discard return value
}