Files
five/docs/five-intro-en.md
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

4.2 KiB

Five — Where Harbour Meets Go

Keep your xBase code. Gain all of Go.

Five is a fusion language that transpiles Harbour PRG code to Go native binaries. Don't throw away 30 years of xBase business logic — use Go's modern power with PRG syntax.

Why Five

1. Your existing code just works

USE customers NEW
INDEX ON Upper(name) TO cust_name
SEEK "CHARLES"
? customers->name, customers->balance

This runs as-is. DBF, NTX, CDX — all supported. Thousands of lines of existing PRG code build with Five unchanged.

2. Every Go package, directly from PRG

IMPORT "strings"
IMPORT "database/sql"
IMPORT _ "modernc.org/sqlite"

PROCEDURE Main()
   LOCAL db, aRows, i

   ? strings.ToUpper("hello five!")

   db := sql.Open("sqlite", ":memory:")
   db:Exec("CREATE TABLE users (id INTEGER, name TEXT)")
   db:Exec("INSERT INTO users VALUES (1, 'Charles')")

   aRows := SqlScan(db, "SELECT * FROM users")
   FOR i := 1 TO Len(aRows)
      ? aRows[i]["name"]
   NEXT
   db:Close()

   RETURN

One IMPORT line gives you access to 500,000+ Go packages. SQL, HTTP, WebSocket, JSON, crypto, regex — all from PRG code. No #pragma BEGINDUMP needed.

3. Goroutines are PRG syntax

LOCAL ch := Channel()

SPAWN {|| ch <- HeavyWork() }    // launch goroutine
? "doing other work..."
result := <- ch                   // receive result

WATCH
CASE msg := <- chServer1
   ? "Server 1 replied:", msg
CASE msg := <- chServer2
   ? "Server 2 replied:", msg
CASE <- chTimeout
   ? "Timeout!"
END WATCH

Concurrency that's impossible in Harbour — natural in Five. SPAWN, <-, WATCH — these ARE Go's goroutine, channel, select.

4. Builds to native binary

five build myapp.prg -o myapp
./myapp    # single executable, zero dependencies

No JVM. No interpreter. No runtime. Go compiler produces native binary. Cross-compile to Linux, macOS, Windows.

5. Safe code by default

PROCEDURE Main()
   LOCAL cName, nAge        // all variables must be declared
   cName := "Charles"
   nAge := 30
   ? cName, nAge
   DEFER db:Close()         // guaranteed resource cleanup
   RETURN

Five's compiler checks automatically:

  • Undeclared variable → warning
  • Unused variable → hint
  • DEFER prevents resource leaks

For Harbour Developers

Nothing to change. Everything to gain.

Existing Harbour Five adds
DBF/NTX/CDX + SQLite, PostgreSQL, MySQL
Single thread + goroutine parallelism
C library dependency + 500K Go packages
Interpreter/HRB + native binary
Windows focused + Linux, macOS, cloud

For Go Developers

Data processing, 10x faster to write.

// Look how concise this is
USE sales NEW
INDEX ON DToS(date) + Str(amount) TO sales_idx
SET FILTER TO amount > 1000
GO TOP
DO WHILE !Eof()
   ? date, customer, amount
   SKIP
ENDDO

In Go, this requires CSV parsing, struct definitions, sort interfaces, filter loops... One xBase command replaces 20 lines of Go code.

Key Numbers

Harbour compat:    98% (232/236 test files)
RTL functions:     351
Go interop:        FastPath 15M calls/sec
Tests:             13 packages ALL PASS
Build output:      single native binary

Five-Only Syntax

// Multi-return
cName, nAge := GetUserInfo()

// DEFER — automatic cleanup
DEFER db:Close()

// Channel operators
ch <- "hello"
msg := <- ch

// WATCH — channel multiplexing
WATCH
CASE msg := <- ch1
CASE <- chTimeout
END WATCH

// Parallel FOR
PARALLEL FOR i := 1 TO 100000
   aResult[i] := Process(aData[i])
NEXT

// ASYNC/AWAIT
future := ASYNC HeavyQuery()
result := AWAIT future

// Nil-safe
? customer?:address?:city

// f-string
? f"Name: {cName}, Age: {nAge}"

// Slice
aSub := aData[2:5]

// Direct Go package calls
? strings.ToUpper("hello")
? math.Sqrt(144)
? fmt.Sprintf("%.2f", 3.14)

Getting Started

# Install
go install github.com/aspect-build/five@latest

# Run
five run hello.prg

# Build
five build hello.prg -o hello

# Debug
five debug hello.prg
// hello.prg
PROCEDURE Main()
   ? "Hello, Five!"
   ? f"Today: {Date()}"
   RETURN

Five — 30 years of xBase heritage, powered by Go's future.