- 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>
4.6 KiB
4.6 KiB
Five — Harbour와 Go의 만남
기존 xBase 코드는 그대로, Go의 힘은 전부.
Five는 Harbour PRG 코드를 Go 네이티브 바이너리로 변환하는 fusion 언어입니다. 30년간 쌓아온 xBase 비즈니스 로직을 버리지 않고, Go의 현대적 기능을 PRG 문법으로 사용합니다.
왜 Five인가
1. 기존 코드를 버리지 않습니다
USE customers NEW
INDEX ON Upper(name) TO cust_name
SEEK "CHARLES"
? customers->name, customers->balance
이 코드가 그대로 실행됩니다. DBF, NTX, CDX 전부 지원. 수천 줄의 기존 PRG 코드를 수정 없이 Five로 빌드할 수 있습니다.
2. Go의 모든 패키지를 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
IMPORT 한 줄이면 Go의 50만개 패키지에 접근합니다.
SQL, HTTP, WebSocket, JSON, 암호화, 정규식 — 전부 PRG 코드로.
#pragma BEGINDUMP가 필요 없습니다.
3. goroutine이 PRG 문법입니다
LOCAL ch := Channel()
SPAWN {|| ch <- HeavyWork() } // goroutine 시작
? "다른 작업 중..."
result := <- ch // 결과 수신
WATCH
CASE msg := <- chServer1
? "서버1 응답:", msg
CASE msg := <- chServer2
? "서버2 응답:", msg
CASE <- chTimeout
? "타임아웃!"
END WATCH
Harbour에서는 불가능한 동시성을 PRG 문법으로 자연스럽게.
SPAWN, <-, WATCH — Go의 goroutine, channel, select가 됩니다.
4. 네이티브 바이너리로 빌드됩니다
five build myapp.prg -o myapp
./myapp # 단일 실행 파일, 의존성 없음
JVM도 없고, 인터프리터도 없습니다. Go 컴파일러가 만드는 네이티브 바이너리. Linux, macOS, Windows 크로스 컴파일.
5. 안전한 코드를 강제합니다
PROCEDURE Main()
LOCAL cName, nAge // 모든 변수는 선언 필수
cName := "Charles"
nAge := 30
? cName, nAge
DEFER db:Close() // 리소스 정리 보장
RETURN
Five 컴파일러가 자동으로 체크합니다:
- 선언 안 된 변수 → 경고
- 사용 안 한 변수 → 힌트
DEFER로 리소스 누수 방지
Harbour 개발자라면
바꿀 것은 없고, 얻는 것만 있습니다.
| 기존 Harbour | Five 추가 |
|---|---|
| DBF/NTX/CDX | + SQLite, PostgreSQL, MySQL |
| 단일 스레드 | + goroutine 병렬 처리 |
| C 라이브러리 의존 | + Go 패키지 50만개 |
| 인터프리터/HRB | + 네이티브 바이너리 |
| Windows 위주 | + Linux, macOS, 클라우드 |
Go 개발자라면
데이터 처리가 10배 빨라집니다.
// 이 코드가 얼마나 간결한지 보세요
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
Go에서 이걸 하려면 CSV 파싱, 구조체 정의, sort 인터페이스, 필터 루프... Five는 xBase 명령어 한 줄이 Go 코드 20줄을 대체합니다.
핵심 숫자
Harbour 호환: 98% (232/236 테스트 파일)
RTL 함수: 351개
Go Interop: FastPath 15M calls/sec
테스트: 13개 패키지 ALL PASS
빌드 결과: 단일 네이티브 바이너리
Five만의 문법
// Multi-return
cName, nAge := GetUserInfo()
// DEFER — 자동 정리
DEFER db:Close()
// 채널 연산자
ch <- "hello"
msg := <- ch
// WATCH — 채널 멀티플렉싱
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]
// Go 패키지 직접 호출
? strings.ToUpper("hello")
? math.Sqrt(144)
? fmt.Sprintf("%.2f", 3.14)
시작하기
# 설치
go install github.com/aspect-build/five@latest
# 실행
five run hello.prg
# 빌드
five build hello.prg -o hello
# 디버그
five debug hello.prg
// hello.prg
PROCEDURE Main()
? "Hello, Five!"
? f"Today: {Date()}"
RETURN
Five — xBase의 30년 유산 위에 Go의 미래를 올립니다.