Files
five/hbrtl/goroutine.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

205 lines
3.8 KiB
Go
Raw Permalink Blame History

// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
// All rights reserved.
// RTL goroutine functions for PRG code:
// GO(bBlock|cFunc, ...) — launch goroutine
// CHANNEL([nSize]) — create channel
// CHSEND(ch, xValue) — send to channel
// CHRECEIVE(ch) <20><><EFBFBD> receive from channel
// CHCLOSE(ch) — close channel
// WAITGROUP(nCount) — create WaitGroup
// WGDONE(wg) — WaitGroup.Done()
// WGWAIT(wg) — WaitGroup.Wait()
// WGADD(wg, n) — WaitGroup.Add(n)
// MUTEX() — create Mutex
// LOCK(mtx) — Mutex.Lock()
// UNLOCK(mtx) — Mutex.Unlock()
// SLEEP(nSeconds) — time.Sleep
package hbrtl
import (
"five/hbrt"
"time"
)
// GO(bBlock [, args...]) — launch goroutine with code block or function
// Returns NIL immediately (goroutine runs in background).
func GoFunc(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
first := t.Local(1)
// Collect args
args := make([]hbrt.Value, 0, nParams-1)
for i := 2; i <= nParams; i++ {
args = append(args, t.Local(i))
}
vm := t.VM()
if first.IsBlock() {
blk := first.AsBlock()
vm.GoLaunchBlock(blk, args)
} else if first.IsString() {
// Function name as string — find symbol and launch
sym := vm.FindSymbol(first.AsString())
if sym != nil && sym.Func != nil {
vm.GoLaunch(sym.Func, args)
}
}
t.RetNil()
}
// CHANNEL([nBufferSize]) → pChannel
func ChannelFunc(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
size := 0
if nParams >= 1 && !t.Local(1).IsNil() {
size = t.Local(1).AsInt()
}
t.RetVal(hbrt.MakeChannel(size))
}
// CHSEND(pChannel, xValue) → NIL
func ChSend(t *hbrt.Thread) {
t.Frame(2, 0)
defer t.EndProc()
ch := t.Local(1).AsChannel()
if ch == nil {
t.RetNil()
return
}
ch.Send(t.Local(2))
t.RetNil()
}
// CHRECEIVE(pChannel) → xValue
func ChReceive(t *hbrt.Thread) {
t.Frame(1, 0)
defer t.EndProc()
ch := t.Local(1).AsChannel()
if ch == nil {
t.RetNil()
return
}
t.RetVal(ch.Receive())
}
// CHCLOSE(pChannel) → NIL
func ChClose(t *hbrt.Thread) {
t.Frame(1, 0)
defer t.EndProc()
ch := t.Local(1).AsChannel()
if ch != nil {
ch.Close()
}
t.RetNil()
}
// WAITGROUP([nCount]) → pWaitGroup
func WaitGroupFunc(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
n := 0
if nParams >= 1 && !t.Local(1).IsNil() {
n = t.Local(1).AsInt()
}
t.RetVal(hbrt.MakeWaitGroup(n))
}
// WGDONE(pWaitGroup) <20><> NIL
func WgDone(t *hbrt.Thread) {
t.Frame(1, 0)
defer t.EndProc()
wg := t.Local(1).AsWaitGroup()
if wg != nil {
wg.WG.Done()
}
t.RetNil()
}
// WGWAIT(pWaitGroup) → NIL
func WgWait(t *hbrt.Thread) {
t.Frame(1, 0)
defer t.EndProc()
wg := t.Local(1).AsWaitGroup()
if wg != nil {
wg.WG.Wait()
}
t.RetNil()
}
// WGADD(pWaitGroup, nDelta) → NIL
func WgAdd(t *hbrt.Thread) {
t.Frame(2, 0)
defer t.EndProc()
wg := t.Local(1).AsWaitGroup()
if wg != nil {
wg.WG.Add(t.Local(2).AsInt())
}
t.RetNil()
}
// MUTEX() → pMutex
func MutexFunc(t *hbrt.Thread) {
t.Frame(0, 0)
defer t.EndProc()
t.RetVal(hbrt.MakeMutex())
}
// LOCK(pMutex) → NIL
func LockFunc(t *hbrt.Thread) {
t.Frame(1, 0)
defer t.EndProc()
mu := t.Local(1).AsMutex()
if mu != nil {
mu.Mu.Lock()
}
t.RetNil()
}
// UNLOCK(pMutex) → NIL
func UnlockFunc(t *hbrt.Thread) {
t.Frame(1, 0)
defer t.EndProc()
mu := t.Local(1).AsMutex()
if mu != nil {
mu.Mu.Unlock()
}
t.RetNil()
}
// SLEEP(nSeconds) → NIL
// Supports fractional seconds: Sleep(0.1) = 100ms
func SleepFunc(t *hbrt.Thread) {
t.Frame(1, 0)
defer t.EndProc()
val := t.Local(1)
var dur time.Duration
if val.IsNumInt() {
dur = time.Duration(val.AsLong()) * time.Second
} else {
dur = time.Duration(val.AsNumDouble() * float64(time.Second))
}
time.Sleep(dur)
t.RetNil()
}