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

79 lines
2.1 KiB
Go

// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
// All rights reserved.
// Console I/O functions for the Five runtime library.
// Implements Harbour's QOut (?), QQOut (??), and related output functions.
package hbrtl
import (
"five/hbrt"
"fmt"
"strings"
)
// QOut implements the ? command. Prints newline then values separated by space.
// Harbour: QOut() / hb_conOutStd()
func QOut(t *hbrt.Thread) {
t.Frame(0, 0) // variadic — args are already consumed by caller
defer t.EndProc()
// The caller pushes args before calling. We need a different approach:
// In generated code, ? a, b, c becomes:
// PushSymbol(QOUT); PushNil; Push(a); Push(b); Push(c); Function(3)
// But our Frame(0,0) means no locals. We need to accept variadic args.
// For now, this is called directly by the test harness.
t.RetNil()
}
// qoutImpl is the actual implementation called with pre-collected args.
func qoutImpl(args []hbrt.Value) {
parts := make([]string, len(args))
for i, v := range args {
parts[i] = valueToDisplay(v)
}
fmt.Print("\r\n" + strings.Join(parts, " "))
}
// qqoutImpl prints without leading newline (??).
func qqoutImpl(args []hbrt.Value) {
parts := make([]string, len(args))
for i, v := range args {
parts[i] = valueToDisplay(v)
}
fmt.Print(strings.Join(parts, " "))
}
// valueToDisplay converts a Value to its display string.
// Harbour: hb_itemString()
func valueToDisplay(v hbrt.Value) string {
switch {
case v.IsNil():
return "NIL"
case v.IsLogical():
if v.AsBool() {
return ".T."
}
return ".F."
case v.IsInt():
return fmt.Sprintf("%d", v.AsInt())
case v.IsLong():
return fmt.Sprintf("%d", v.AsLong())
case v.IsDouble():
dec := v.Decimal()
if dec == 255 {
return fmt.Sprintf("%g", v.AsDouble())
}
return fmt.Sprintf("%.*f", dec, v.AsDouble())
case v.IsString():
return v.AsString()
case v.IsDate():
return julianToDateStr(v.AsJulian())
case v.IsArray():
return fmt.Sprintf("{Array(%d)}", len(v.AsArray().Items))
default:
return v.String()
}
}
// julianToDateStr and date formatting moved to datetime.go