Files
five/hbrtl/register.go
CharlesKWON d2ed140273 feat(FiveSql2): SqlEach block callback — beats raw RDD on end-to-end timing
The structural 1.38x gap vs raw RDD for no-WHERE full scans wasn't
a limit of our engine — it was a limit of the result shape. SqlScan
materializes N rows as HbArray wrappers over a flat Value buffer,
then the PRG caller iterates that materialized array. Two passes
over the data. Raw RDD is one pass.

SqlEach folds both passes into one. The caller supplies a code block
that receives the selected column values as positional parameters;
SqlEach invokes it per matching row. No result array is ever built.

Usage (drop-in replacement for the common "scan + process" idiom):

    five_SQLEach( "SELECT id, name, salary FROM emp WHERE salary > 50000",
                  {|nID, cName, nSalary| Process(nID, cName, nSalary) } )

API shape borrows Harbour's AEval/ASort block-callback convention,
so there's nothing new to learn. Positional params also sidestep
the `SELECT COUNT(*)` naming problem — no need to invent names for
anonymous expressions.

Implementation notes:
  - 4-way loop specialization ({DBF, generic Area} × {WHERE, none}),
    matching SqlScan. Each path is zero-allocation in the steady state.
  - Block invocation uses the direct pendingParams + blk.Fn(t) protocol
    rather than EvalBlock, which would allocate a temporary args slice
    on every call (50k scans × small slice adds up).
  - FastFieldGetter is installed the same way as SqlScan so PcOpFieldGet
    in the WHERE predicate skips the PushSymbol + Function dispatch.

Bench (50k rows, end-to-end including user-code loop, steady state):

  Path                           Time     vs raw RDD
  ─────────────────────────────────────────────────────
  Raw PRG loop, WHERE + sum      8.7ms    1.00x
  SqlScan + PRG FOR, WHERE       5.1ms    0.59x
  SqlEach block, WHERE           4.1ms    0.47x  ← beats raw
  ─────────────────────────────────────────────────────
  Raw PRG loop, no WHERE         6.1ms    1.00x
  SqlEach block, no WHERE        3.8ms    0.62x  ← beats raw

SqlEach is faster than a hand-rolled `DO WHILE !Eof()` loop because
the per-row FieldGet in raw PRG still goes through a full Frame +
RTL dispatch, whereas SqlEach's FastFieldGetter captures the concrete
*dbf.DBFArea directly. The SQL abstraction now costs nothing — it
pays you to use it.

Validation:
  - FiveSql2 43/43
  - Harbour compat 51/51
  - go test ./... ALL PASS

Next step (not in this commit): FiveSql2 TSqlExecutor integration —
detect when five_SQL is called with a block argument and route to
SqlEach instead of SqlScan + array build.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:16:36 +09:00

695 lines
27 KiB
Go

// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
// All rights reserved.
// RTL registration for the Five runtime library.
// Centralized registration following tsgo's NodeFactory pattern.
package hbrtl
import (
"five/hbrt"
"five/hbrdd"
)
// RegisterRTL registers all standard library functions with the VM.
func RegisterRTL(vm *hbrt.VM) {
// Auto-create WorkAreaManager for each thread
vm.SetWAFactory(func() interface{} {
return hbrdd.NewWorkAreaManager()
})
// Restore terminal on exit
vm.SetOnExit(func() {
RestoreTerminal()
})
mod := hbrt.NewModule("_RTL",
// Console
hbrt.Sym("QOUT", hbrt.FsPublic, rtlQOut),
hbrt.Sym("QQOUT", hbrt.FsPublic, rtlQQOut),
hbrt.Sym("OUTSTD", hbrt.FsPublic, rtlOutStd),
hbrt.Sym("OUTERR", hbrt.FsPublic, rtlOutErr),
// Strings / Conversion
hbrt.Sym("STR", hbrt.FsPublic, Str),
hbrt.Sym("VAL", hbrt.FsPublic, Val),
hbrt.Sym("LEN", hbrt.FsPublic, Len),
hbrt.Sym("SUBSTR", hbrt.FsPublic, SubStr),
hbrt.Sym("UPPER", hbrt.FsPublic, Upper),
hbrt.Sym("LOWER", hbrt.FsPublic, Lower),
hbrt.Sym("ALLTRIM", hbrt.FsPublic, AllTrim),
hbrt.Sym("LTRIM", hbrt.FsPublic, LTrim),
hbrt.Sym("RTRIM", hbrt.FsPublic, RTrim),
hbrt.Sym("TRIM", hbrt.FsPublic, RTrim), // TRIM = RTRIM in Harbour
hbrt.Sym("SPACE", hbrt.FsPublic, Space),
hbrt.Sym("PADR", hbrt.FsPublic, PadR),
hbrt.Sym("PADL", hbrt.FsPublic, PadL),
hbrt.Sym("REPLICATE", hbrt.FsPublic, Replicate),
// Type / Conversion
hbrt.Sym("VALTYPE", hbrt.FsPublic, ValType),
hbrt.Sym("EMPTY", hbrt.FsPublic, Empty),
hbrt.Sym("ABS", hbrt.FsPublic, Abs),
hbrt.Sym("INT", hbrt.FsPublic, Int),
// Array
hbrt.Sym("AADD", hbrt.FsPublic, AAdd),
hbrt.Sym("ADEL", hbrt.FsPublic, ADel),
hbrt.Sym("AINS", hbrt.FsPublic, AIns),
hbrt.Sym("ASIZE", hbrt.FsPublic, ASize),
hbrt.Sym("ACLONE", hbrt.FsPublic, AClone),
hbrt.Sym("ACOPY", hbrt.FsPublic, ACopy),
hbrt.Sym("AFILL", hbrt.FsPublic, AFill),
hbrt.Sym("ASORT", hbrt.FsPublic, ASort),
hbrt.Sym("AEVAL", hbrt.FsPublic, AEval),
hbrt.Sym("ASCAN", hbrt.FsPublic, AScan),
hbrt.Sym("ATAIL", hbrt.FsPublic, ATail),
// Hash
hbrt.Sym("HB_HASH", hbrt.FsPublic, HbHash),
hbrt.Sym("HB_HGET", hbrt.FsPublic, HbHGet),
hbrt.Sym("HB_HSET", hbrt.FsPublic, HbHSet),
hbrt.Sym("HB_HDEL", hbrt.FsPublic, HbHDel),
hbrt.Sym("HB_HHASKEY", hbrt.FsPublic, HbHHasKey),
hbrt.Sym("HB_HKEYS", hbrt.FsPublic, HbHKeys),
hbrt.Sym("HB_HVALUES", hbrt.FsPublic, HbHValues),
// Date / Time
hbrt.Sym("DATE", hbrt.FsPublic, Date),
hbrt.Sym("TIME", hbrt.FsPublic, Time),
hbrt.Sym("YEAR", hbrt.FsPublic, Year),
hbrt.Sym("MONTH", hbrt.FsPublic, Month),
hbrt.Sym("DAY", hbrt.FsPublic, Day),
hbrt.Sym("DOW", hbrt.FsPublic, DOW),
hbrt.Sym("SECONDS", hbrt.FsPublic, Seconds),
hbrt.Sym("DTOC", hbrt.FsPublic, DToC),
hbrt.Sym("DTOS", hbrt.FsPublic, DToS),
hbrt.Sym("STOD", hbrt.FsPublic, SToD),
// Eval
hbrt.Sym("EVAL", hbrt.FsPublic, rtlEval),
// String (new)
hbrt.Sym("AT", hbrt.FsPublic, At),
hbrt.Sym("LEFT", hbrt.FsPublic, Left),
hbrt.Sym("RIGHT", hbrt.FsPublic, Right),
hbrt.Sym("ASC", hbrt.FsPublic, Asc),
hbrt.Sym("CHR", hbrt.FsPublic, Chr),
hbrt.Sym("STRTRAN", hbrt.FsPublic, StrTran),
hbrt.Sym("STUFF", hbrt.FsPublic, Stuff),
hbrt.Sym("PADC", hbrt.FsPublic, PadC),
hbrt.Sym("HB_STRREPLACE", hbrt.FsPublic, HbStrReplace),
hbrt.Sym("HB_NTOS", hbrt.FsPublic, HbNToS),
// Math (new)
hbrt.Sym("ROUND", hbrt.FsPublic, Round),
hbrt.Sym("MAX", hbrt.FsPublic, Max),
hbrt.Sym("MIN", hbrt.FsPublic, Min),
hbrt.Sym("SQRT", hbrt.FsPublic, Sqrt),
hbrt.Sym("LOG", hbrt.FsPublic, Log),
hbrt.Sym("EXP", hbrt.FsPublic, Exp),
hbrt.Sym("MOD", hbrt.FsPublic, Mod),
// Date (new)
hbrt.Sym("CTOD", hbrt.FsPublic, CToD),
hbrt.Sym("CDOW", hbrt.FsPublic, CDoW),
hbrt.Sym("CMONTH", hbrt.FsPublic, CMonth),
// Misc (new)
hbrt.Sym("TYPE", hbrt.FsPublic, TypeFunc),
hbrt.Sym("PCOUNT", hbrt.FsPublic, PCount),
hbrt.Sym("BREAK", hbrt.FsPublic, Break),
hbrt.Sym("ARRAY", hbrt.FsPublic, ArrayFunc),
hbrt.Sym("FCOUNT", hbrt.FsPublic, FCount),
hbrt.Sym("FIELDNAME", hbrt.FsPublic, FieldName),
hbrt.Sym("SELECT", hbrt.FsPublic, SelectFunc),
hbrt.Sym("FILE", hbrt.FsPublic, FileFunc),
hbrt.Sym("INKEY", hbrt.FsPublic, Inkey),
hbrt.Sym("TRANSFORM", hbrt.FsPublic, Transform),
hbrt.Sym("SETDATEFORMAT", hbrt.FsPublic, rtlSetDateFormat),
hbrt.Sym("SETEPOCH", hbrt.FsPublic, rtlSetEpoch),
hbrt.Sym("SETCENTURY", hbrt.FsPublic, rtlSetCentury),
// Terminal
hbrt.Sym("SETPOS", hbrt.FsPublic, SetPos),
hbrt.Sym("ROW", hbrt.FsPublic, Row),
hbrt.Sym("COL", hbrt.FsPublic, Col),
hbrt.Sym("DEVPOS", hbrt.FsPublic, DevPos),
hbrt.Sym("DEVOUT", hbrt.FsPublic, DevOut),
hbrt.Sym("DISPOUT", hbrt.FsPublic, DispOut),
hbrt.Sym("DEVOUTPICT", hbrt.FsPublic, DevOutPict),
hbrt.Sym("DISPBOX", hbrt.FsPublic, DispBox),
hbrt.Sym("CLS", hbrt.FsPublic, Cls),
hbrt.Sym("SCROLL", hbrt.FsPublic, Scroll),
hbrt.Sym("SETCOLOR", hbrt.FsPublic, SetColor),
hbrt.Sym("SETCURSOR", hbrt.FsPublic, SetCursor),
hbrt.Sym("MAXROW", hbrt.FsPublic, MaxRow),
hbrt.Sym("MAXCOL", hbrt.FsPublic, MaxCol),
// dbEdit / Browse / TBrowse
hbrt.Sym("DBEDIT", hbrt.FsPublic, DbEdit),
hbrt.Sym("TBROWSEDB", hbrt.FsPublic, rtlTBrowseDB),
hbrt.Sym("TBROWSENEW", hbrt.FsPublic, rtlTBrowseNew),
hbrt.Sym("TBCOLUMNNEW", hbrt.FsPublic, rtlTBColumnNew),
// RDD functions
hbrt.Sym("EOF", hbrt.FsPublic, rtlEOF),
hbrt.Sym("BOF", hbrt.FsPublic, rtlBOF),
hbrt.Sym("FOUND", hbrt.FsPublic, rtlFound),
hbrt.Sym("RECNO", hbrt.FsPublic, rtlRecNo),
hbrt.Sym("RECCOUNT", hbrt.FsPublic, rtlRecCount),
hbrt.Sym("LASTREC", hbrt.FsPublic, rtlRecCount), // alias
hbrt.Sym("DELETED", hbrt.FsPublic, rtlDeleted),
hbrt.Sym("FIELDGET", hbrt.FsPublic, rtlFieldGet),
// Database callable functions
hbrt.Sym("FIELDPUT", hbrt.FsPublic, rtlFieldPut),
hbrt.Sym("ALIAS", hbrt.FsPublic, rtlAlias),
hbrt.Sym("DBEVAL", hbrt.FsPublic, rtlDbEval),
hbrt.Sym("USED", hbrt.FsPublic, Used),
hbrt.Sym("DBUSEAREA", hbrt.FsPublic, rtlDbUseArea),
hbrt.Sym("DBCLOSEAREA", hbrt.FsPublic, rtlDbCloseArea),
hbrt.Sym("DBCLOSEALL", hbrt.FsPublic, rtlDbCloseAll),
hbrt.Sym("DBGOTO", hbrt.FsPublic, rtlDbGoTo),
hbrt.Sym("DBSKIP", hbrt.FsPublic, rtlDbSkip),
hbrt.Sym("DBGOTOP", hbrt.FsPublic, rtlDbGoTop),
hbrt.Sym("DBGOBOTTOM", hbrt.FsPublic, rtlDbGoBottom),
hbrt.Sym("DBAPPEND", hbrt.FsPublic, rtlDbAppend),
hbrt.Sym("DBDELETE", hbrt.FsPublic, rtlDbDelete),
hbrt.Sym("DBRECALL", hbrt.FsPublic, rtlDbRecall),
hbrt.Sym("DBCOMMIT", hbrt.FsPublic, rtlDbCommit),
hbrt.Sym("DBRLOCK", hbrt.FsPublic, rtlDbRLock),
hbrt.Sym("DBRUNLOCK", hbrt.FsPublic, rtlDbRUnlock),
hbrt.Sym("FLOCK", hbrt.FsPublic, rtlFLock),
hbrt.Sym("DBUNLOCK", hbrt.FsPublic, rtlDbUnlock),
hbrt.Sym("DBSEEK", hbrt.FsPublic, rtlDbSeek),
hbrt.Sym("DBSELECTAREA", hbrt.FsPublic, rtlDbSelectArea),
hbrt.Sym("DBPACK", hbrt.FsPublic, rtlDbPack),
hbrt.Sym("DBZAP", hbrt.FsPublic, rtlDbZap),
hbrt.Sym("RECALL", hbrt.FsPublic, rtlDbRecall),
hbrt.Sym("PACK", hbrt.FsPublic, rtlDbPack),
hbrt.Sym("ZAP", hbrt.FsPublic, rtlDbZap),
hbrt.Sym("__DBPACK", hbrt.FsPublic, rtlDbPack),
hbrt.Sym("__DBZAP", hbrt.FsPublic, rtlDbZap),
hbrt.Sym("DBRECALL", hbrt.FsPublic, rtlDbRecall),
// Locate / Filter
hbrt.Sym("DBLOCATE", hbrt.FsPublic, rtlDbLocate),
hbrt.Sym("__DBLOCATE", hbrt.FsPublic, rtlDbLocate),
hbrt.Sym("__DBCONTINUE", hbrt.FsPublic, rtlDbContinue),
hbrt.Sym("DBSETFILTER", hbrt.FsPublic, rtlDbSetFilter),
hbrt.Sym("DBCLEARFILTER", hbrt.FsPublic, rtlDbClearFilter),
hbrt.Sym("DBFILTER", hbrt.FsPublic, rtlDbFilter),
// Encoding / Hashing (Go stdlib)
hbrt.Sym("HB_MD5", hbrt.FsPublic, HbMD5),
hbrt.Sym("HB_SHA256", hbrt.FsPublic, HbSHA256),
hbrt.Sym("HB_BASE64ENCODE", hbrt.FsPublic, HbBase64Encode),
hbrt.Sym("HB_BASE64DECODE", hbrt.FsPublic, HbBase64Decode),
hbrt.Sym("HB_CRC32", hbrt.FsPublic, HbCRC32),
// Bit operations (Go native)
hbrt.Sym("HB_BITAND", hbrt.FsPublic, HbBitAnd),
hbrt.Sym("HB_BITOR", hbrt.FsPublic, HbBitOr),
hbrt.Sym("HB_BITXOR", hbrt.FsPublic, HbBitXor),
hbrt.Sym("HB_BITNOT", hbrt.FsPublic, HbBitNot),
hbrt.Sym("HB_BITSHIFT", hbrt.FsPublic, HbBitShift),
hbrt.Sym("HB_BITTEST", hbrt.FsPublic, HbBitTest),
hbrt.Sym("HB_BITSET", hbrt.FsPublic, HbBitSet),
hbrt.Sym("HB_BITRESET", hbrt.FsPublic, HbBitReset),
// Regex (Go regexp)
hbrt.Sym("HB_REGEXCOMP", hbrt.FsPublic, HbRegexComp),
hbrt.Sym("HB_REGEXMATCH", hbrt.FsPublic, HbRegexMatch),
hbrt.Sym("HB_REGEXSPLIT", hbrt.FsPublic, HbRegexSplit),
hbrt.Sym("HB_REGEXALL", hbrt.FsPublic, HbRegexAll),
hbrt.Sym("HB_REGEXREPLACE", hbrt.FsPublic, HbRegexReplace),
// String (additional)
hbrt.Sym("RAT", hbrt.FsPublic, Rat),
hbrt.Sym("STRZERO", hbrt.FsPublic, StrZero),
hbrt.Sym("DESCEND", hbrt.FsPublic, Descend),
hbrt.Sym("HB_VALTOSTR", hbrt.FsPublic, HbValToStr),
hbrt.Sym("HB_VALTOEXP", hbrt.FsPublic, HbValToExp),
hbrt.Sym("HB_CSTR", hbrt.FsPublic, HbCStr),
hbrt.Sym("HB_NTOS", hbrt.FsPublic, HbNtos),
hbrt.Sym("MEMOREAD", hbrt.FsPublic, MemoRead),
hbrt.Sym("MEMOWRIT", hbrt.FsPublic, MemoWrit),
hbrt.Sym("MEMOTRAN", hbrt.FsPublic, MemoTran),
// Binary conversion
hbrt.Sym("BIN2I", hbrt.FsPublic, Bin2I),
hbrt.Sym("BIN2L", hbrt.FsPublic, Bin2L),
hbrt.Sym("BIN2W", hbrt.FsPublic, Bin2W),
hbrt.Sym("I2BIN", hbrt.FsPublic, I2Bin),
hbrt.Sym("L2BIN", hbrt.FsPublic, L2Bin),
hbrt.Sym("W2BIN", hbrt.FsPublic, W2Bin),
// Keyboard
hbrt.Sym("LASTKEY", hbrt.FsPublic, LastKey),
hbrt.Sym("NEXTKEY", hbrt.FsPublic, NextKey),
hbrt.Sym("READKEY", hbrt.FsPublic, ReadKeyFunc),
hbrt.Sym("SETKEY", hbrt.FsPublic, SetKeyFunc),
hbrt.Sym("KEYBOARD", hbrt.FsPublic, Keyboard),
hbrt.Sym("HB_KEYPUT", hbrt.FsPublic, HbKeyPut),
// Display
hbrt.Sym("DISPBEGIN", hbrt.FsPublic, DispBegin),
hbrt.Sym("DISPEND", hbrt.FsPublic, DispEnd),
hbrt.Sym("DISPCOUNT", hbrt.FsPublic, DispCount),
hbrt.Sym("SAVESCREEN", hbrt.FsPublic, SaveScreen),
hbrt.Sym("RESTSCREEN", hbrt.FsPublic, RestScreen),
hbrt.Sym("ALERT", hbrt.FsPublic, Alert),
// Error handling
hbrt.Sym("ERRORBLOCK", hbrt.FsPublic, ErrorBlock),
hbrt.Sym("ERRORNEW", hbrt.FsPublic, ErrorNew),
hbrt.Sym("DOSERROR", hbrt.FsPublic, DosError),
hbrt.Sym("FERROR", hbrt.FsPublic, FError),
// SET commands
hbrt.Sym("SET", hbrt.FsPublic, SetFunc),
hbrt.Sym("__SETDATEFORMAT", hbrt.FsPublic, SetDateFunc),
hbrt.Sym("__SETDECIMALS", hbrt.FsPublic, SetDecimalsFunc),
hbrt.Sym("__SETEPOCH", hbrt.FsPublic, SetEpochFunc),
// SET toggle functions
hbrt.Sym("SETDELETED", hbrt.FsPublic, SetDeletedFunc),
hbrt.Sym("SETEXACT", hbrt.FsPublic, SetExactFunc),
hbrt.Sym("SETSOFTSEEK", hbrt.FsPublic, SetSoftSeekFunc),
hbrt.Sym("SETEXCLUSIVE", hbrt.FsPublic, SetExclusiveFunc),
hbrt.Sym("SETFIXED", hbrt.FsPublic, SetFixedFunc),
hbrt.Sym("SETCANCEL", hbrt.FsPublic, SetCancelFunc),
hbrt.Sym("SETBELL", hbrt.FsPublic, SetBellFunc),
hbrt.Sym("SETCONFIRM", hbrt.FsPublic, SetConfirmFunc),
hbrt.Sym("SETINSERT", hbrt.FsPublic, SetInsertFunc),
hbrt.Sym("SETESCAPE", hbrt.FsPublic, SetEscapeFunc),
hbrt.Sym("SETWRAP", hbrt.FsPublic, SetWrapFunc),
// SET constants
hbrt.Sym("_SET_EXACT", hbrt.FsPublic, SetConstExact),
hbrt.Sym("_SET_DELETED", hbrt.FsPublic, SetConstDeleted),
hbrt.Sym("_SET_SOFTSEEK", hbrt.FsPublic, SetConstSoftSeek),
hbrt.Sym("_SET_EXCLUSIVE", hbrt.FsPublic, SetConstExclusive),
hbrt.Sym("_SET_DATEFORMAT", hbrt.FsPublic, SetConstDateFmt),
hbrt.Sym("_SET_DECIMALS", hbrt.FsPublic, SetConstDecimals),
hbrt.Sym("_SET_EPOCH", hbrt.FsPublic, SetConstEpoch),
// Error handling
hbrt.Sym("ERRORBLOCK", hbrt.FsPublic, ErrorBlock),
hbrt.Sym("ERRORNEW", hbrt.FsPublic, ErrorNew),
hbrt.Sym("DOSERROR", hbrt.FsPublic, DosError),
hbrt.Sym("FERROR", hbrt.FsPublic, FError),
hbrt.Sym("BREAK", hbrt.FsPublic, Break),
// File I/O
hbrt.Sym("FOPEN", hbrt.FsPublic, FOpen),
hbrt.Sym("FCREATE", hbrt.FsPublic, FCreate),
hbrt.Sym("FCLOSE", hbrt.FsPublic, FClose),
hbrt.Sym("FREAD", hbrt.FsPublic, FRead),
hbrt.Sym("FWRITE", hbrt.FsPublic, FWrite),
hbrt.Sym("FSEEK", hbrt.FsPublic, FSeek),
hbrt.Sym("FERASE", hbrt.FsPublic, FErase),
hbrt.Sym("FRENAME", hbrt.FsPublic, FRename),
hbrt.Sym("HB_FILEEXISTS", hbrt.FsPublic, HbFileExists),
// Directory/Disk
hbrt.Sym("CURDIR", hbrt.FsPublic, CurDir),
hbrt.Sym("DIRCHANGE", hbrt.FsPublic, DirChange),
hbrt.Sym("DIRECTORY", hbrt.FsPublic, Directory),
hbrt.Sym("DIRMAKE", hbrt.FsPublic, DirMake),
hbrt.Sym("DIRREMOVE", hbrt.FsPublic, DirRemove),
// Type checking (HB_IS*)
hbrt.Sym("HB_ISARRAY", hbrt.FsPublic, HbIsArray),
hbrt.Sym("HB_ISBLOCK", hbrt.FsPublic, HbIsBlock),
hbrt.Sym("HB_ISCHAR", hbrt.FsPublic, HbIsChar),
hbrt.Sym("HB_ISSTRING", hbrt.FsPublic, HbIsString),
hbrt.Sym("HB_ISDATE", hbrt.FsPublic, HbIsDate),
hbrt.Sym("HB_ISDATETIME", hbrt.FsPublic, HbIsDateTime),
hbrt.Sym("HB_ISLOGICAL", hbrt.FsPublic, HbIsLogical),
hbrt.Sym("HB_ISNUMERIC", hbrt.FsPublic, HbIsNumeric),
hbrt.Sym("HB_ISOBJECT", hbrt.FsPublic, HbIsObject),
hbrt.Sym("HB_ISHASH", hbrt.FsPublic, HbIsHash),
hbrt.Sym("HB_ISNIL", hbrt.FsPublic, HbIsNil),
hbrt.Sym("HB_ISPOINTER", hbrt.FsPublic, HbIsPointer),
// OS/Environment
hbrt.Sym("GETENV", hbrt.FsPublic, GetEnv),
hbrt.Sym("HB_GETENV", hbrt.FsPublic, HbGetEnv),
hbrt.Sym("SETENV", hbrt.FsPublic, SetEnvFunc),
hbrt.Sym("OS", hbrt.FsPublic, OSFunc),
hbrt.Sym("VERSION", hbrt.FsPublic, VersionFunc),
hbrt.Sym("HB_RUN", hbrt.FsPublic, HbRun),
hbrt.Sym("HB_FNAMEDIR", hbrt.FsPublic, HbFNameDir),
hbrt.Sym("HB_FNAMEEXT", hbrt.FsPublic, HbFNameExt),
hbrt.Sym("HB_FNAMENAME", hbrt.FsPublic, HbFNameName),
hbrt.Sym("HB_FNAMEMERGE", hbrt.FsPublic, HbFNameMerge),
// Character classification
hbrt.Sym("ISDIGIT", hbrt.FsPublic, IsDigit),
hbrt.Sym("ISALPHA", hbrt.FsPublic, IsAlpha),
hbrt.Sym("ISALNUM", hbrt.FsPublic, IsAlnum),
hbrt.Sym("ISUPPER", hbrt.FsPublic, IsUpper),
hbrt.Sym("ISLOWER", hbrt.FsPublic, IsLower),
hbrt.Sym("ISSPACE", hbrt.FsPublic, IsSpace),
// Harbour extension functions
hbrt.Sym("HB_ISEVALITEM", hbrt.FsPublic, HbIsEvalItem),
hbrt.Sym("HB_ASCIIUPPER", hbrt.FsPublic, HbAsciiUpper),
hbrt.Sym("HB_ASCIILOWER", hbrt.FsPublic, HbAsciiLower),
hbrt.Sym("HB_DEFAULT", hbrt.FsPublic, HbDefault),
hbrt.Sym("HB_DEFAULTVALUE", hbrt.FsPublic, HbDefaultValue),
hbrt.Sym("HB_DISPOUTAT", hbrt.FsPublic, HbDispOutAt),
hbrt.Sym("HB_COLORINDEX", hbrt.FsPublic, HbColorIndex),
hbrt.Sym("HB_LEFTEQ", hbrt.FsPublic, HbLeftEq),
hbrt.Sym("HB_VAL", hbrt.FsPublic, HbVal),
hbrt.Sym("HB_KEYCHAR", hbrt.FsPublic, HbKeyChar),
hbrt.Sym("HB_KEYINS", hbrt.FsPublic, HbKeyIns),
hbrt.Sym("FIELDWBLOCK", hbrt.FsPublic, FieldWBlock),
hbrt.Sym("MEMVARBLOCK", hbrt.FsPublic, MemVarBlock),
hbrt.Sym("__DEFAULTNIL", hbrt.FsPublic, DefaultNIL),
hbrt.Sym("HB_DISPOUTATBOX", hbrt.FsPublic, HbDispOutAtBox),
hbrt.Sym("HB_DISPBOX", hbrt.FsPublic, HbDispBox),
hbrt.Sym("HB_TOKENGET", hbrt.FsPublic, HbTokenGet),
hbrt.Sym("HB_TOKENCOUNT", hbrt.FsPublic, HbTokenCount),
// Bitmap/Rushmore
hbrt.Sym("BM_DBSETFILTER", hbrt.FsPublic, BmDbSetFilter),
hbrt.Sym("BM_DBSEEKWILD", hbrt.FsPublic, BmDbSeekWild),
hbrt.Sym("BM_TURBO", hbrt.FsPublic, BmTurbo),
hbrt.Sym("BM_DBGETFILTERARRAY", hbrt.FsPublic, BmDbGetFilterArray),
hbrt.Sym("BM_DBSETFILTERARRAY", hbrt.FsPublic, BmDbSetFilterArray),
hbrt.Sym("BM_DBSETFILTERARRAYADD", hbrt.FsPublic, BmDbSetFilterArrayAdd),
hbrt.Sym("BM_DBSETFILTERARRAYDEL", hbrt.FsPublic, BmDbSetFilterArrayDel),
// HBSIX compatibility
hbrt.Sym("SX_SETTAG", hbrt.FsPublic, SxSetTag),
hbrt.Sym("SX_INDEXTAG", hbrt.FsPublic, SxIndexTag),
hbrt.Sym("SX_TAGORDER", hbrt.FsPublic, SxTagOrder),
hbrt.Sym("SX_TAGCOUNT", hbrt.FsPublic, SxTagCount),
hbrt.Sym("SX_TAGS", hbrt.FsPublic, SxTags),
hbrt.Sym("SX_SETFILEORD", hbrt.FsPublic, SxSetFileOrd),
hbrt.Sym("SX_ISDBT", hbrt.FsPublic, SxIsDBT),
hbrt.Sym("SX_ISFPT", hbrt.FsPublic, SxIsFPT),
hbrt.Sym("SX_ISSMT", hbrt.FsPublic, SxIsSMT),
hbrt.Sym("SX_AUTOOPEN", hbrt.FsPublic, SxAutoOpen),
hbrt.Sym("SX_AUTOSHARE", hbrt.FsPublic, SxAutoShare),
hbrt.Sym("SX_BLOB2FILE", hbrt.FsPublic, SxBlob2File),
hbrt.Sym("SX_FILE2BLOB", hbrt.FsPublic, SxFile2Blob),
hbrt.Sym("SX_SETTRIGGER", hbrt.FsPublic, SxSetTrigger),
hbrt.Sym("SX_VFGET", hbrt.FsPublic, SxVFGet),
hbrt.Sym("SX_DBFENCRYPT", hbrt.FsPublic, SxDbfEncrypt),
hbrt.Sym("SX_DBFDECRYPT", hbrt.FsPublic, SxDbfDecrypt),
hbrt.Sym("SX_COMPRESS", hbrt.FsPublic, SxCompress),
hbrt.Sym("SX_DECOMPRESS", hbrt.FsPublic, SxDecompress),
hbrt.Sym("RDDINFO", hbrt.FsPublic, RddInfo),
hbrt.Sym("RDDNAME", hbrt.FsPublic, RddName),
hbrt.Sym("RDDLIST", hbrt.FsPublic, RddList),
// Timestamp
hbrt.Sym("HB_DATETIME", hbrt.FsPublic, HbDateTime),
hbrt.Sym("HB_HOUR", hbrt.FsPublic, HbHour),
hbrt.Sym("HB_MINUTE", hbrt.FsPublic, HbMinute),
hbrt.Sym("HB_SEC", hbrt.FsPublic, HbSec),
hbrt.Sym("HB_TTOC", hbrt.FsPublic, HbTToC),
hbrt.Sym("HB_CTOT", hbrt.FsPublic, HbCToT),
hbrt.Sym("HB_SECOND", hbrt.FsPublic, HbSecond),
hbrt.Sym("HB_ATOKENS", hbrt.FsPublic, HbATokens),
hbrt.Sym("HB_CDPSELECT", hbrt.FsPublic, HbCdpSelect),
hbrt.Sym("DBSETINDEX", hbrt.FsPublic, rtlDbSetIndex),
hbrt.Sym("HB_TTOS", hbrt.FsPublic, HbTToS),
hbrt.Sym("HB_STOT", hbrt.FsPublic, HbSToT),
hbrt.Sym("HB_MILLISECONDS", hbrt.FsPublic, HbMilliseconds),
// Index / DB introspection
hbrt.Sym("INDEXORD", hbrt.FsPublic, IndexOrd),
hbrt.Sym("INDEXKEY", hbrt.FsPublic, IndexKey),
hbrt.Sym("ORDSETFOCUS", hbrt.FsPublic, OrdSetFocus),
hbrt.Sym("ORDCREATE", hbrt.FsPublic, OrdCreate),
hbrt.Sym("DBCREATEINDEX", hbrt.FsPublic, DbCreateIndex),
hbrt.Sym("DBCLEARINDEX", hbrt.FsPublic, DbClearIndex),
hbrt.Sym("FIELDTYPE", hbrt.FsPublic, FieldType),
hbrt.Sym("FIELDLEN", hbrt.FsPublic, FieldLen),
hbrt.Sym("FIELDDEC", hbrt.FsPublic, FieldDec),
hbrt.Sym("ORDCOUNT", hbrt.FsPublic, OrdCount),
hbrt.Sym("ORDNAME", hbrt.FsPublic, OrdName),
hbrt.Sym("ORDKEY", hbrt.FsPublic, OrdKey),
hbrt.Sym("ORDFOR", hbrt.FsPublic, OrdFor),
hbrt.Sym("DBINFO", hbrt.FsPublic, DbInfo),
hbrt.Sym("ORDINFO", hbrt.FsPublic, OrdInfo),
hbrt.Sym("ORDSCOPE", hbrt.FsPublic, OrdScope),
hbrt.Sym("DBORDERINFO", hbrt.FsPublic, DbOrderInfo),
hbrt.Sym("RDDSETDEFAULT", hbrt.FsPublic, RddSetDefault),
hbrt.Sym("DBCREATE", hbrt.FsPublic, DbCreate),
// Directory / Temp file (session 1)
hbrt.Sym("HB_DIREXISTS", hbrt.FsPublic, HbDirExists),
hbrt.Sym("HB_DIRCREATE", hbrt.FsPublic, HbDirCreate),
hbrt.Sym("HB_FTEMPCREATE", hbrt.FsPublic, HbFTempCreate),
hbrt.Sym("HB_FNAMESPLIT", hbrt.FsPublic, HbFNameSplit),
// File extended (session 2)
hbrt.Sym("HB_FSIZE", hbrt.FsPublic, HbFSize),
hbrt.Sym("HB_FCOPY", hbrt.FsPublic, HbFCopy),
hbrt.Sym("HB_FEOF", hbrt.FsPublic, HbFEof),
hbrt.Sym("HB_FCOMMIT", hbrt.FsPublic, HbFCommit),
hbrt.Sym("HB_FREADLEN", hbrt.FsPublic, HbFReadLen),
hbrt.Sym("HB_FGETATTR", hbrt.FsPublic, HbFGetAttr),
hbrt.Sym("HB_FSETATTR", hbrt.FsPublic, HbFSetAttr),
hbrt.Sym("HB_FGETDATETIME", hbrt.FsPublic, HbFGetDateTime),
hbrt.Sym("HB_FSETDATETIME", hbrt.FsPublic, HbFSetDateTime),
hbrt.Sym("HB_FLOCK", hbrt.FsPublic, HbFLock),
hbrt.Sym("HB_FUNLOCK", hbrt.FsPublic, HbFUnlock),
hbrt.Sym("HB_FILEDELETE", hbrt.FsPublic, HbFileDelete),
hbrt.Sym("HB_FILEMATCH", hbrt.FsPublic, HbFileMatch),
hbrt.Sym("HB_FNAMEEXISTS", hbrt.FsPublic, HbFNameExists),
hbrt.Sym("HB_FNAMEEXTSET", hbrt.FsPublic, HbFNameExtSet),
hbrt.Sym("HB_FNAMENAMEEXT", hbrt.FsPublic, HbFNameNameExt),
hbrt.Sym("HB_MEMOREAD", hbrt.FsPublic, HbMemoRead),
hbrt.Sym("HB_MEMOWRIT", hbrt.FsPublic, HbMemoWrit),
hbrt.Sym("HB_DIRTEMP", hbrt.FsPublic, HbDirTemp),
hbrt.Sym("HB_DISKSPACE", hbrt.FsPublic, HbDiskSpace),
hbrt.Sym("DISKSPACE", hbrt.FsPublic, DiskSpaceFunc),
// String extended (session 2)
hbrt.Sym("HB_AT", hbrt.FsPublic, HbAt),
hbrt.Sym("HB_RAT", hbrt.FsPublic, HbRat),
hbrt.Sym("HB_ATI", hbrt.FsPublic, HbAtI),
hbrt.Sym("HB_ATX", hbrt.FsPublic, HbAtX),
hbrt.Sym("HB_LEFTEQI", hbrt.FsPublic, HbLeftEqI),
hbrt.Sym("HB_ASCIIISALPHA", hbrt.FsPublic, HbAsciiIsAlpha),
hbrt.Sym("HB_ASCIIISDIGIT", hbrt.FsPublic, HbAsciiIsDigit),
hbrt.Sym("HB_ASCIIISLOWER", hbrt.FsPublic, HbAsciiIsLower),
hbrt.Sym("HB_ASCIIISUPPER", hbrt.FsPublic, HbAsciiIsUpper),
hbrt.Sym("HB_STRISUTF8", hbrt.FsPublic, HbStrIsUtf8),
hbrt.Sym("HB_STRDECODESCAPE", hbrt.FsPublic, HbStrDecodeEscape),
hbrt.Sym("HB_STRXOR", hbrt.FsPublic, HbStrXor),
hbrt.Sym("HB_WILDMATCH", hbrt.FsPublic, HbWildMatch),
hbrt.Sym("HB_WILDMATCHI", hbrt.FsPublic, HbWildMatchI),
hbrt.Sym("HARDCR", hbrt.FsPublic, HardCR),
// DateTime extended (session 2)
hbrt.Sym("HB_DATE", hbrt.FsPublic, HbDate),
hbrt.Sym("HB_CTOD", hbrt.FsPublic, HbCToD),
hbrt.Sym("HB_DTOC", hbrt.FsPublic, HbDToC),
hbrt.Sym("HB_STOD", hbrt.FsPublic, HbSToD),
hbrt.Sym("HB_DTOT", hbrt.FsPublic, HbDToT),
hbrt.Sym("HB_TTOD", hbrt.FsPublic, HbTToD),
hbrt.Sym("HB_TTOHOUR", hbrt.FsPublic, HbTToHour),
hbrt.Sym("HB_TTOMIN", hbrt.FsPublic, HbTToMin),
hbrt.Sym("HB_TTOSEC", hbrt.FsPublic, HbTToSec),
hbrt.Sym("HB_TTOMSEC", hbrt.FsPublic, HbTToMsec),
hbrt.Sym("HB_TTON", hbrt.FsPublic, HbTToN),
hbrt.Sym("HB_NTOT", hbrt.FsPublic, HbNToT),
hbrt.Sym("HB_NTOHOUR", hbrt.FsPublic, HbNToHour),
hbrt.Sym("HB_NTOMIN", hbrt.FsPublic, HbNToMin),
hbrt.Sym("HB_NTOSEC", hbrt.FsPublic, HbNToSec),
hbrt.Sym("HB_WEEK", hbrt.FsPublic, HbWeek),
hbrt.Sym("HB_CDAY", hbrt.FsPublic, HbCDay),
hbrt.Sym("DAYS", hbrt.FsPublic, Days),
hbrt.Sym("ELAPTIME", hbrt.FsPublic, ElapTime),
hbrt.Sym("AMPM", hbrt.FsPublic, AMPM),
hbrt.Sym("SECS", hbrt.FsPublic, Secs),
// Utilities (session 2)
hbrt.Sym("HB_SETENV", hbrt.FsPublic, HbSetEnv),
hbrt.Sym("HB_PS", hbrt.FsPublic, HbPS),
hbrt.Sym("HB_EOL", hbrt.FsPublic, HbEOL),
hbrt.Sym("HB_ISNULL", hbrt.FsPublic, HbIsNull),
hbrt.Sym("ERRORSYS", hbrt.FsPublic, ErrorSys),
// Token
hbrt.Sym("TOKEN", hbrt.FsPublic, Token),
hbrt.Sym("NUMTOKEN", hbrt.FsPublic, NumToken),
// Hex conversion
hbrt.Sym("HB_NUMTOHEX", hbrt.FsPublic, HbNumToHex),
hbrt.Sym("HB_HEXTONUM", hbrt.FsPublic, HbHexToNum),
// Hash position access
hbrt.Sym("HB_HPOS", hbrt.FsPublic, HbHPos),
hbrt.Sym("HB_HKEYAT", hbrt.FsPublic, HbHKeyAt),
hbrt.Sym("HB_HVALUEAT", hbrt.FsPublic, HbHValueAt),
hbrt.Sym("HB_HCLONE", hbrt.FsPublic, HbHClone),
// Sleep
hbrt.Sym("HB_IDLESLEEP", hbrt.FsPublic, HbIdleSleep),
// UTF-8
hbrt.Sym("HB_UTF8TOSTR", hbrt.FsPublic, HbUTF8ToStr),
hbrt.Sym("HB_STRTOUTF8", hbrt.FsPublic, HbStrToUTF8),
hbrt.Sym("HB_UTF8LEN", hbrt.FsPublic, HbUTF8Len),
hbrt.Sym("HB_UTF8SUBSTR", hbrt.FsPublic, HbUTF8SubStr),
// Stack introspection
hbrt.Sym("PROCNAME", hbrt.FsPublic, ProcName),
hbrt.Sym("PROCLINE", hbrt.FsPublic, ProcLine),
hbrt.Sym("PROCFILE", hbrt.FsPublic, ProcFile),
hbrt.Sym("ERRORLEVEL", hbrt.FsPublic, ErrorLevel),
// Field/DB introspection
hbrt.Sym("FIELDPOS", hbrt.FsPublic, FieldPos),
hbrt.Sym("FIELDBLOCK", hbrt.FsPublic, FieldBlockFunc),
hbrt.Sym("FIELDNAME", hbrt.FsPublic, FieldNameFunc),
hbrt.Sym("AFIELDS", hbrt.FsPublic, AFields),
hbrt.Sym("DBSTRUCT", hbrt.FsPublic, DbStruct),
// Misc
hbrt.Sym("TONE", hbrt.FsPublic, Tone),
hbrt.Sym("CENTER", hbrt.FsPublic, Center),
hbrt.Sym("SOUNDEX", hbrt.FsPublic, Soundex),
// JSON — Harbour compatible
hbrt.Sym("HB_JSONENCODE", hbrt.FsPublic, HbJsonEncode),
hbrt.Sym("HB_JSONDECODE", hbrt.FsPublic, HbJsonDecode),
// JSON — Five extensions (Go-native)
hbrt.Sym("JSONPRETTY", hbrt.FsPublic, JsonPretty),
hbrt.Sym("JSONTO", hbrt.FsPublic, JsonTo),
hbrt.Sym("JSONFROM", hbrt.FsPublic, JsonFrom),
hbrt.Sym("JSONPATH", hbrt.FsPublic, JsonPath),
hbrt.Sym("JSONMERGE", hbrt.FsPublic, JsonMerge),
hbrt.Sym("JSONTYPE", hbrt.FsPublic, JsonType),
hbrt.Sym("JSONVALID", hbrt.FsPublic, JsonValid),
hbrt.Sym("JSONHTTPGET", hbrt.FsPublic, JsonHttpGet),
hbrt.Sym("JSONHTTPPOST", hbrt.FsPublic, JsonHttpPost),
// Random
hbrt.Sym("HB_RANDOM", hbrt.FsPublic, HbRandom),
hbrt.Sym("HB_RANDOMINT", hbrt.FsPublic, HbRandomInt),
hbrt.Sym("HB_RANDOMSEED", hbrt.FsPublic, HbRandomSeed),
hbrt.Sym("HB_RANDSTR", hbrt.FsPublic, HbRandStr),
// OS Info
hbrt.Sym("HB_VERSION", hbrt.FsPublic, HbVersion),
hbrt.Sym("HB_COMPILER", hbrt.FsPublic, HbCompiler),
hbrt.Sym("HB_OSNEWLINE", hbrt.FsPublic, HbOsNewLine),
hbrt.Sym("HB_OSPATHSEPARATOR", hbrt.FsPublic, HbOsPathSeparator),
hbrt.Sym("HB_CWD", hbrt.FsPublic, HbCwd),
hbrt.Sym("HB_DIRBASE", hbrt.FsPublic, HbDirBase),
hbrt.Sym("HB_PROGNAME", hbrt.FsPublic, HbProgName),
hbrt.Sym("HB_USERNAME", hbrt.FsPublic, HbUserName),
hbrt.Sym("HB_GETHOSTNAME", hbrt.FsPublic, HbGetHostName),
// Process
hbrt.Sym("HB_PROCESSRUN", hbrt.FsPublic, HbProcessRun),
hbrt.Sym("WAIT", hbrt.FsPublic, WaitCmd),
// UTF-8 String
hbrt.Sym("HB_UTF8LEN", hbrt.FsPublic, HbUtf8Len),
hbrt.Sym("HB_UTF8SUBSTR", hbrt.FsPublic, HbUtf8Substr),
hbrt.Sym("HB_UTF8LEFT", hbrt.FsPublic, HbUtf8Left),
hbrt.Sym("HB_UTF8RIGHT", hbrt.FsPublic, HbUtf8Right),
hbrt.Sym("HB_UTF8AT", hbrt.FsPublic, HbUtf8At),
hbrt.Sym("HB_STRTOHEX", hbrt.FsPublic, HbStrToHex),
hbrt.Sym("HB_HEXTOSTR", hbrt.FsPublic, HbHexToStr),
hbrt.Sym("HB_STRFORMAT", hbrt.FsPublic, HbStrFormat),
// Memo line
hbrt.Sym("MEMOLINE", hbrt.FsPublic, MemoLine),
hbrt.Sym("MLCOUNT", hbrt.FsPublic, MlCount),
// FRB (Five Runtime Binary)
hbrt.Sym("FRBLOAD", hbrt.FsPublic, FrbLoadFunc),
hbrt.Sym("FRBDO", hbrt.FsPublic, FrbDoFunc),
hbrt.Sym("FRBUNLOAD", hbrt.FsPublic, FrbUnloadFunc),
hbrt.Sym("FRBRUN", hbrt.FsPublic, FrbRunFunc),
hbrt.Sym("FRBCOMPILE", hbrt.FsPublic, FrbCompileFunc),
hbrt.Sym("FRBEXEC", hbrt.FsPublic, FrbExecFunc),
// Expression bytecode compilation (FiveSql2 hot-path optimization)
hbrt.Sym("PCCOMPILE", hbrt.FsPublic, PcCompile),
hbrt.Sym("PCEVAL", hbrt.FsPublic, PcEval),
// Go-native SQL scan loop (bypasses PRG interpreter for hot path)
hbrt.Sym("SQLSCAN", hbrt.FsPublic, SqlScan),
hbrt.Sym("SQLEACH", hbrt.FsPublic, SqlEach),
// Goroutine / Concurrency
hbrt.Sym("GO", hbrt.FsPublic, GoFunc),
hbrt.Sym("CHANNEL", hbrt.FsPublic, ChannelFunc),
hbrt.Sym("CHSEND", hbrt.FsPublic, ChSend),
hbrt.Sym("CHRECEIVE", hbrt.FsPublic, ChReceive),
hbrt.Sym("CHCLOSE", hbrt.FsPublic, ChClose),
hbrt.Sym("WAITGROUP", hbrt.FsPublic, WaitGroupFunc),
hbrt.Sym("WGDONE", hbrt.FsPublic, WgDone),
hbrt.Sym("WGWAIT", hbrt.FsPublic, WgWait),
hbrt.Sym("WGADD", hbrt.FsPublic, WgAdd),
hbrt.Sym("MUTEX", hbrt.FsPublic, MutexFunc),
hbrt.Sym("LOCK", hbrt.FsPublic, LockFunc),
hbrt.Sym("UNLOCK", hbrt.FsPublic, UnlockFunc),
hbrt.Sym("SLEEP", hbrt.FsPublic, SleepFunc),
)
vm.RegisterModule(mod)
}
// rtlQOut implements ? command as a variadic function.
func rtlQOut(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
args := make([]hbrt.Value, nParams)
for i := 0; i < nParams; i++ {
args[i] = t.Local(i + 1)
}
qoutImpl(args)
t.RetNil()
}
// rtlQQOut implements ?? command.
func rtlQQOut(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
args := make([]hbrt.Value, nParams)
for i := 0; i < nParams; i++ {
args[i] = t.Local(i + 1)
}
qqoutImpl(args)
t.RetNil()
}
// rtlEval evaluates a code block.
// Harbour: Eval(bBlock, [xArg1, ...]) → xResult
func rtlEval(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
blkVal := t.Local(1)
if !blkVal.IsBlock() {
t.RetNil()
return
}
blk := blkVal.AsBlock()
// Push block args onto stack for the block's Frame() to pick up
blockArgs := nParams - 1
for i := 2; i <= nParams; i++ {
t.PushValue(t.Local(i))
}
// Call block function — it will call Frame(N, 0) internally
t.PendingParams2(blockArgs)
blk.Fn(t)
// Return block's result
t.PushValue(t.GetRetValue())
t.RetValue()
}