- 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>
211 lines
4.2 KiB
Markdown
211 lines
4.2 KiB
Markdown
# 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
|
|
|
|
```prg
|
|
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
|
|
|
|
```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
|
|
|
|
```prg
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```prg
|
|
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.**
|
|
|
|
```prg
|
|
// 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
|
|
|
|
```prg
|
|
// 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
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
```prg
|
|
// hello.prg
|
|
PROCEDURE Main()
|
|
? "Hello, Five!"
|
|
? f"Today: {Date()}"
|
|
RETURN
|
|
```
|
|
|
|
---
|
|
|
|
**Five — 30 years of xBase heritage, powered by Go's future.**
|