- 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>
788 lines
23 KiB
Markdown
788 lines
23 KiB
Markdown
# Five Development Plan
|
||
|
||
> Harbour + Go 융합 플랫폼 "Five" 개발 계획
|
||
> 4개 설계 문서 기반 실행 계획
|
||
>
|
||
> Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
|
||
> All rights reserved.
|
||
|
||
---
|
||
|
||
## 관련 문서
|
||
|
||
| 문서 | 내용 |
|
||
|------|------|
|
||
| harbour-type-system-analysis.md | HB_ITEM 타입 시스템 분석, Tagged Value 16B 설계 |
|
||
| harbour-prg-to-go-transpiler.md | PRG→Go 트랜스파일러, gencc.c 패턴 분석 |
|
||
| harbour-go-evolution-strategy.md | 융합 전략, 언어 진화, Go 생태계 연동 |
|
||
| harbour-go-compiler-design-review.md | 컴파일러 설계 관점 분석, DBF/Index 이식 전략 |
|
||
|
||
---
|
||
|
||
## 프로젝트 구조
|
||
|
||
```
|
||
five/
|
||
├── docs/ ← 설계 문서 (현재)
|
||
├── cmd/
|
||
│ └── five/ ← CLI 엔트리포인트
|
||
│ └── main.go five build, five run, five fmt
|
||
├── compiler/ ← PRG → Go 컴파일러
|
||
│ ├── token/ 토큰 정의
|
||
│ │ └── token.go
|
||
│ ├── lexer/ 렉서
|
||
│ │ ├── lexer.go
|
||
│ │ └── lexer_test.go
|
||
│ ├── ast/ AST 노드
|
||
│ │ └── ast.go
|
||
│ ├── parser/ 파서 (recursive descent)
|
||
│ │ ├── parser.go
|
||
│ │ ├── parser_expr.go
|
||
│ │ ├── parser_stmt.go
|
||
│ │ ├── parser_cmd.go xBase 명령어 파싱
|
||
│ │ └── parser_test.go
|
||
│ ├── analyzer/ 의미 분석
|
||
│ │ ├── scope.go
|
||
│ │ ├── types.go
|
||
│ │ └── analyzer.go
|
||
│ └── gengo/ Go 코드 생성
|
||
│ ├── gengo.go
|
||
│ ├── gen_expr.go
|
||
│ ├── gen_stmt.go
|
||
│ ├── gen_symbol.go
|
||
│ └── gengo_test.go
|
||
├── hbrt/ ← 핵심 런타임
|
||
│ ├── value.go Tagged Value 16B
|
||
│ ├── value_test.go
|
||
│ ├── thread.go 실행 컨텍스트
|
||
│ ├── stack.go eval 스택
|
||
│ ├── symbol.go 심볼 테이블
|
||
│ ├── class.go CLASS 시스템
|
||
│ ├── error.go 에러/SEQUENCE
|
||
│ ├── macro.go 매크로 컴파일러
|
||
│ ├── ops_arith.go 산술 연산
|
||
│ ├── ops_compare.go 비교 연산
|
||
│ ├── ops_string.go 문자열 연산
|
||
│ ├── bridge.go Go ↔ Five 타입 변환
|
||
│ └── vm.go VM 초기화/관리
|
||
├── hbrtl/ ← 표준 라이브러리 (Harbour RTL 호환)
|
||
│ ├── strings.go SUBSTR, ALLTRIM, UPPER, PAD, ...
|
||
│ ├── numeric.go STR, VAL, INT, ROUND, MOD, ...
|
||
│ ├── datetime.go DATE, TIME, CTOD, DTOC, YEAR, ...
|
||
│ ├── array.go AADD, ADEL, AINS, ASORT, AEVAL, ...
|
||
│ ├── hash.go HB_HASH, HB_HGET, HB_HSET, ...
|
||
│ ├── console.go QOUT, QQOUT, ACCEPT, INKEY, ...
|
||
│ ├── file.go FOPEN, FCLOSE, FREAD, FWRITE, ...
|
||
│ ├── convert.go ASC, CHR, CTOD, DTOC, STOD, ...
|
||
│ └── misc.go TYPE, VALTYPE, EMPTY, ...
|
||
├── hbrdd/ ← RDD 엔진 (DBF/Index)
|
||
│ ├── driver.go Driver/Area interface 정의
|
||
│ ├── workarea.go WorkArea 관리
|
||
│ ├── alias.go ALIAS 시스템
|
||
│ ├── dbf/ DBF 드라이버
|
||
│ │ ├── header.go 헤더/필드 디스크립터
|
||
│ │ ├── record.go 레코드 읽기/쓰기
|
||
│ │ ├── field.go 필드 타입 변환
|
||
│ │ ├── lock.go 6종 락 스키마
|
||
│ │ ├── memo.go FPT 메모 필드
|
||
│ │ └── dbf.go DBF Area 구현
|
||
│ ├── ntx/ NTX 인덱스
|
||
│ │ ├── header.go NTX 헤더 (512B)
|
||
│ │ ├── page.go B-tree 페이지 (1024B)
|
||
│ │ ├── search.go SEEK 알고리즘
|
||
│ │ ├── update.go 삽입/삭제/밸런싱
|
||
│ │ ├── build.go INDEX ON (병렬 빌드)
|
||
│ │ └── ntx.go NTX Indexer 구현
|
||
│ ├── cdx/ CDX 인덱스
|
||
│ │ ├── header.go CDX 헤더 (1024B)
|
||
│ │ ├── tag.go 태그 관리
|
||
│ │ ├── page.go 페이지 (512-8192B)
|
||
│ │ ├── compress.go 비트 패킹 압축/해제
|
||
│ │ ├── search.go SEEK 알고리즘
|
||
│ │ ├── update.go 삽입/삭제
|
||
│ │ └── cdx.go CDX Indexer 구현
|
||
│ └── filter.go SET FILTER / SET RELATION
|
||
├── hbsql/ ← SQL RDD (Phase 5)
|
||
│ └── sqldriver.go
|
||
├── hbweb/ ← HTTP 프레임워크 (Phase 5)
|
||
│ └── server.go
|
||
├── go.mod
|
||
├── go.sum
|
||
└── README.md
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 0: 프로젝트 기반 (1주)
|
||
|
||
### 목표
|
||
|
||
Go 모듈 초기화, 기본 구조 확립, Tagged Value 16B 구현 및 검증
|
||
|
||
### 작업
|
||
|
||
```
|
||
0.1 Go 모듈 초기화
|
||
- go mod init github.com/anthropics/five (또는 개인 레포)
|
||
- 디렉토리 구조 생성
|
||
- .gitignore, LICENSE, README.md
|
||
|
||
0.2 Tagged Value 16B 구현 (hbrt/value.go)
|
||
- Value struct { data uint64; info uint64 }
|
||
- 타입 상수 정의 (tNil, tLogical, tInt, tLong, tDouble, ...)
|
||
- 생성 함수 (MakeNil, MakeBool, MakeInt, MakeLong, MakeDouble, ...)
|
||
- 접근 함수 (Type, IsNil, IsNumeric, AsInt, AsDouble, ...)
|
||
- 포인터 타입 (MakeString, MakeArray, MakeHash, MakeBlock)
|
||
- HbString, HbArray, HbHash, HbBlock 보조 구조체
|
||
|
||
0.3 Value 테스트
|
||
- 모든 타입의 생성/접근 왕복 테스트
|
||
- 타입 체크 매크로 검증
|
||
- 메모리 레이아웃 검증 (unsafe.Sizeof == 16)
|
||
- 벤치마크: Value 연산 vs interface{} 비교
|
||
```
|
||
|
||
### 완료 기준
|
||
|
||
```
|
||
go test ./hbrt/ -v -run TestValue -bench BenchmarkValue
|
||
✓ 14개 타입 생성/접근 테스트 통과
|
||
✓ sizeof(Value) == 16 확인
|
||
✓ 정수 연산 벤치마크: interface{} 대비 2배+ 빠름
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 1: 최소 런타임 (2주)
|
||
|
||
### 목표
|
||
|
||
수동으로 작성한 Go 코드에서 `? "Hello World"`, `? 1 + 2`가 실행되는 것
|
||
|
||
### 작업
|
||
|
||
```
|
||
1.1 Thread + Stack (hbrt/thread.go, stack.go)
|
||
- Thread 구조체 (stack, sp, locals, calls)
|
||
- Frame / EndProc (defer + recover)
|
||
- Push / Pop / Peek / SetTop
|
||
- PushLocal / PopLocal / PushStatic / PopStatic
|
||
|
||
1.2 산술 연산 (hbrt/ops_arith.go)
|
||
- Plus, Minus, Mult, Divide, Modulus, Power
|
||
- Negate, Inc, Dec
|
||
- 타입 승격 규칙 (Int+Int→오버플로우→Double)
|
||
- 소수점 전파 규칙 (decimal 메타)
|
||
- AddInt, MultByInt 최적화 함수
|
||
|
||
1.3 비교 연산 (hbrt/ops_compare.go)
|
||
- Equal, ExactEqual, NotEqual
|
||
- Less, LessEqual, Greater, GreaterEqual
|
||
- Not, And, Or
|
||
- PopLogical (bool 추출)
|
||
|
||
1.4 문자열 연산 (hbrt/ops_string.go)
|
||
- 문자열 연결 (Plus에서 분기)
|
||
- 문자열 비교 (Harbour 의미론: SET EXACT 고려)
|
||
|
||
1.5 심볼 테이블 (hbrt/symbol.go)
|
||
- Symbol 구조체
|
||
- Module (심볼 배열 + 이름)
|
||
- Registry (전역 심볼 테이블, sync.RWMutex)
|
||
- Find, Register, At
|
||
|
||
1.6 함수 호출 (hbrt/thread.go 확장)
|
||
- PushSymbol, PushNil
|
||
- Function(nArgs), Do(nArgs)
|
||
- RetValue, RetInt, RetNil
|
||
- CallFrame 저장/복원
|
||
|
||
1.7 기본 RTL (hbrtl/console.go, strings.go, numeric.go)
|
||
- QOut (?) / QQOut (??)
|
||
- Str, Val, Len, Type, ValType
|
||
- SubStr, Upper, Lower, AllTrim, PadR, PadL, PadC
|
||
- Empty, Space, Replicate
|
||
|
||
1.8 VM 초기화 (hbrt/vm.go)
|
||
- NewVM, RegisterModule, RegisterRTL
|
||
- Run(funcName)
|
||
```
|
||
|
||
### 완료 기준
|
||
|
||
```go
|
||
// 이 Go 코드가 동작해야 함 (컴파일러 없이 수동 작성)
|
||
func HB_MAIN(t *hbrt.Thread) {
|
||
t.Frame(0, 1)
|
||
defer t.EndProc()
|
||
|
||
// ? "Hello World"
|
||
t.PushSymbol(sym_QOUT)
|
||
t.PushNil()
|
||
t.PushString("Hello World")
|
||
t.Function(1)
|
||
|
||
// LOCAL n := 10 + 20
|
||
t.PushInt(10)
|
||
t.AddInt(20)
|
||
t.PopLocal(1)
|
||
|
||
// ? "Result:", Str(n)
|
||
t.PushSymbol(sym_QOUT)
|
||
t.PushNil()
|
||
t.PushString("Result: ")
|
||
t.PushSymbol(sym_STR)
|
||
t.PushNil()
|
||
t.PushLocal(1)
|
||
t.Function(1)
|
||
t.Plus()
|
||
t.Function(1)
|
||
}
|
||
|
||
// 실행 결과:
|
||
// Hello World
|
||
// Result: 30
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 2: 파서 (3주)
|
||
|
||
### 목표
|
||
|
||
PRG 파일을 파싱하여 AST를 생성
|
||
|
||
### 작업
|
||
|
||
```
|
||
2.1 토큰 정의 (compiler/token/token.go)
|
||
- 키워드: FUNCTION, PROCEDURE, LOCAL, STATIC, PRIVATE, PUBLIC
|
||
- 키워드: IF, ELSEIF, ELSE, ENDIF, DO, WHILE, ENDDO
|
||
- 키워드: FOR, NEXT, RETURN, EXIT, LOOP
|
||
- 키워드: BEGIN, SEQUENCE, RECOVER, END
|
||
- 키워드: CLASS, ENDCLASS, DATA, METHOD, INHERIT
|
||
- xBase: USE, SEEK, REPLACE, APPEND, INDEX, SET, GO, SKIP
|
||
- 연산자: +, -, *, /, %, **, :=, ==, !=, <, >, <=, >=
|
||
- 연산자: .AND., .OR., .NOT., .T., .F.
|
||
- 특수: &, @, ::, ->, {|, |}
|
||
|
||
2.2 렉서 (compiler/lexer/lexer.go)
|
||
- UTF-8 소스 처리
|
||
- Harbour 키워드 대소문자 무시
|
||
- 문자열 리터럴 ("...", '...')
|
||
- 숫자 리터럴 (정수, 소수, 16진수)
|
||
- 날짜 리터럴 (CTOD("YYYYMMDD"))
|
||
- 줄 바꿈 = 문장 구분자
|
||
- 세미콜론 (;) = 줄 계속
|
||
- 주석 (// 또는 && 또는 /* */)
|
||
|
||
2.3 AST 정의 (compiler/ast/ast.go)
|
||
- Node, Expr, Stmt, Decl 인터페이스
|
||
- 식: BinaryExpr, UnaryExpr, CallExpr, SendExpr, IndexExpr
|
||
- 식: LiteralExpr (Int, Double, String, Bool, Date, Nil, Array, Hash)
|
||
- 식: IdentExpr, FieldExpr, AliasExpr, MacroExpr, BlockExpr
|
||
- 문: AssignStmt, ReturnStmt, ExprStmt
|
||
- 문: IfStmt, DoWhileStmt, ForStmt, ForEachStmt, SwitchStmt
|
||
- 문: SeqStmt (BEGIN SEQUENCE)
|
||
- 선언: FuncDecl, VarDecl (LOCAL/STATIC/PRIVATE/PUBLIC)
|
||
- 선언: ClassDecl, DataDecl, MethodDecl
|
||
- xBase: UseCmd, SeekCmd, ReplaceCmd, AppendCmd, IndexCmd
|
||
- xBase: GoCmd, SkipCmd, SetCmd, SelectCmd
|
||
|
||
2.4 파서 (compiler/parser/)
|
||
- parser.go: Parser 구조체, advance, expect, match
|
||
- parser_expr.go: 식 파싱 (연산자 우선순위, Pratt 파서)
|
||
- parser_stmt.go: 문 파싱 (IF, DO WHILE, FOR, ...)
|
||
- parser_cmd.go: xBase 명령어 파싱 (USE, SEEK, REPLACE, ...)
|
||
- 에러 복구: synchronize() (LSP 대비)
|
||
|
||
2.5 파서 테스트
|
||
- 기본 식: 1 + 2 * 3
|
||
- 함수 호출: Func(a, b, c)
|
||
- 메서드: obj:Method(args)
|
||
- xBase: USE customers VIA DBFCDX
|
||
- 코드 블록: {|x,y| x + y}
|
||
- 매크로: &cVariable
|
||
- 제어 흐름: IF/ELSEIF/ELSE/ENDIF
|
||
- CLASS: CLASS Person ... ENDCLASS
|
||
```
|
||
|
||
### 완료 기준
|
||
|
||
```
|
||
five parse test.prg --dump-ast
|
||
|
||
입력: FUNCTION Main()
|
||
LOCAL n := 10
|
||
? n + 5
|
||
RETURN n
|
||
|
||
출력: FuncDecl{
|
||
Name: "Main"
|
||
Params: []
|
||
Body: [
|
||
VarDecl{Scope:LOCAL, Name:"n", Init: Literal{Int:10}}
|
||
ExprStmt{Call{Func:"QOUT", Args:[Binary{+, Ident{"n"}, Literal{Int:5}}]}}
|
||
ReturnStmt{Expr: Ident{"n"}}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 3: 코드 생성기 (3주)
|
||
|
||
### 목표
|
||
|
||
PRG → Go 소스 생성 → go build → 실행
|
||
|
||
### 작업
|
||
|
||
```
|
||
3.1 의미 분석 (compiler/analyzer/)
|
||
- 스코프 해석: LOCAL, STATIC, PRIVATE, PUBLIC 구분
|
||
- 심볼 수집: 함수, 변수, 클래스
|
||
- 상수 폴딩: 1 + 2 → 3
|
||
- 미사용 변수 경고
|
||
|
||
3.2 Go 코드 생성 (compiler/gengo/)
|
||
- gengo.go: 파일 헤더, import, main() 생성
|
||
- gen_expr.go: 식 → t.Push*() / t.Plus() 등
|
||
- gen_stmt.go: 문 → 제어 흐름 (goto 또는 for/if)
|
||
- gen_symbol.go: 심볼 테이블, STATIC 초기화 생성
|
||
|
||
3.3 CLI 통합 (cmd/five/main.go)
|
||
- five build <file.prg> [-o output]
|
||
- five run <file.prg>
|
||
- 내부: PRG → 임시 Go → go build → 실행
|
||
|
||
3.4 END-TO-END 테스트
|
||
- hello.prg → hello 바이너리
|
||
- 산술 테스트: 오버플로우, 소수점 전파
|
||
- 문자열 테스트: 연결, 비교
|
||
- 제어 흐름: IF, DO WHILE, FOR, FOR EACH
|
||
- 함수: 재귀, 다중 파라미터, STATIC 변수
|
||
- BEGIN SEQUENCE / RECOVER
|
||
```
|
||
|
||
### 완료 기준
|
||
|
||
```
|
||
five run hello.prg
|
||
|
||
// hello.prg:
|
||
FUNCTION Main()
|
||
LOCAL cName := "World"
|
||
LOCAL n := 0
|
||
|
||
FOR i := 1 TO 10
|
||
n += i
|
||
NEXT
|
||
|
||
? "Hello, " + cName + "!"
|
||
? "Sum 1..10 =", n
|
||
|
||
IF n > 50
|
||
? "Greater than 50"
|
||
ELSE
|
||
? "Not greater than 50"
|
||
ENDIF
|
||
|
||
RETURN NIL
|
||
|
||
// 출력:
|
||
// Hello, World!
|
||
// Sum 1..10 = 55
|
||
// Greater than 50
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 4: RTL 확장 + 코드 블록 (3주)
|
||
|
||
### 목표
|
||
|
||
Harbour 핵심 RTL 함수 100개 + 코드 블록 + 배열/해시 연산
|
||
|
||
### 작업
|
||
|
||
```
|
||
4.1 배열 연산 (hbrtl/array.go)
|
||
- AAdd, ADel, AIns, ASize, AClone, ACopy
|
||
- ASort, AEval, AScan, ATail
|
||
- Array(), ALen (= Len)
|
||
|
||
4.2 해시 연산 (hbrtl/hash.go)
|
||
- hb_Hash, hb_HGet, hb_HSet, hb_HDel
|
||
- hb_HHasKey, hb_HKeys, hb_HValues
|
||
- hb_HPos, hb_HLen
|
||
|
||
4.3 코드 블록 (hbrt/thread.go 확장)
|
||
- PushBlock(func, capturedLocals)
|
||
- EvalBlock(nArgs)
|
||
- 디태치된 로컬 (클로저 캡처)
|
||
|
||
4.4 추가 RTL 함수
|
||
- 문자열: At, Rat, Stuff, StrTran, hb_StrReplace
|
||
- 수치: Abs, Max, Min, Sqrt, Log, Exp, Round, Int
|
||
- 날짜: Date, Time, Year, Month, Day, CToD, DToC, DToS, SToD
|
||
- 변환: Asc, Chr, Bin2I, I2Bin, hb_NumToHex
|
||
- 파일: File, FErase, FRename, DirChange, CurDir
|
||
- 기타: Seconds, OS, GetEnv, hb_Run
|
||
|
||
4.5 Harbour 호환 테스트
|
||
- Harbour 테스트 스위트에서 RTL 관련 테스트 이식
|
||
- 엣지 케이스: 빈 배열, NIL 파라미터, 타입 변환
|
||
```
|
||
|
||
### 완료 기준
|
||
|
||
```harbour
|
||
// 이 코드가 동작해야 함
|
||
FUNCTION Main()
|
||
LOCAL aData := { {"Kim", 30}, {"Lee", 25}, {"Park", 35} }
|
||
|
||
// 정렬
|
||
ASort(aData, {|a,b| a[2] < b[2]})
|
||
|
||
// 출력
|
||
AEval(aData, {|x| QOut(x[1] + " age:" + Str(x[2])) })
|
||
|
||
// 해시
|
||
LOCAL hConfig := { "host" => "localhost", "port" => 8080 }
|
||
? hConfig["host"] + ":" + Str(hConfig["port"])
|
||
|
||
RETURN NIL
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 5: RDD — DBF 엔진 (4주)
|
||
|
||
### 목표
|
||
|
||
기존 DBF/NTX/CDX 파일을 읽고 쓸 수 있는 RDD 엔진.
|
||
**기존 Harbour/Clipper와 포맷 100% 호환.**
|
||
|
||
### 작업
|
||
|
||
```
|
||
5.1 RDD Interface (hbrdd/driver.go)
|
||
- Driver, Area, Indexer, Locker 등 인터페이스 정의
|
||
|
||
5.2 WorkArea 관리 (hbrdd/workarea.go, alias.go)
|
||
- WorkAreaManager (Thread-local)
|
||
- ALIAS 등록/해제/전환
|
||
|
||
5.3 DBF 코어 (hbrdd/dbf/)
|
||
- header.go: DBF 헤더 읽기/쓰기 (32B, 바이트 동일)
|
||
- field.go: 필드 디스크립터 (32B×N)
|
||
- record.go: 레코드 읽기/쓰기 (고정 폭)
|
||
- lock.go: 6종 락 스키마 (Clipper/VFP/HB64)
|
||
- memo.go: FPT 메모 블록 읽기/쓰기
|
||
- dbf.go: DBFArea 구현 (Open/Create/Close/GoTo/Skip/...)
|
||
|
||
5.4 NTX 인덱스 (hbrdd/ntx/)
|
||
- header.go: NTX 헤더 (512B)
|
||
- page.go: B-tree 페이지 (1024B)
|
||
- search.go: SEEK (이진 검색 + 스택 탐색)
|
||
- update.go: 삽입/삭제/페이지 분할/밸런싱
|
||
- build.go: INDEX ON (병렬 정렬 + 바텀업 빌드)
|
||
|
||
5.5 CDX 인덱스 (hbrdd/cdx/)
|
||
- header.go: CDX 파일 헤더 (1024B)
|
||
- tag.go: 태그 헤더 (512B) + 다중 태그 관리
|
||
- compress.go: 비트 패킹 압축/해제 (DupBits/TrlBits/RecBits)
|
||
- page.go: 내부/리프 노드
|
||
- search.go: SEEK
|
||
- update.go: 삽입/삭제
|
||
|
||
5.6 xBase 명령어 연동 (컴파일러 + 런타임)
|
||
- USE path [VIA driver] [ALIAS name]
|
||
- GO TOP / GO BOTTOM / GO recno
|
||
- SKIP [n]
|
||
- SEEK value [SOFTSEEK]
|
||
- REPLACE field WITH value [, ...]
|
||
- APPEND BLANK
|
||
- DELETE / RECALL / PACK / ZAP
|
||
- INDEX ON expr TO file [FOR cond] [UNIQUE]
|
||
- SET INDEX TO file
|
||
- SET FILTER TO expr
|
||
- SET RELATION TO expr INTO alias
|
||
- SELECT alias
|
||
- FIELD->name / alias->name
|
||
|
||
5.7 호환성 테스트
|
||
- Harbour로 생성한 DBF → Five로 읽기
|
||
- Five로 생성한 DBF → Harbour로 읽기
|
||
- NTX/CDX 인덱스 교차 읽기
|
||
- 락 동시 접근 테스트 (Five + Harbour 프로세스)
|
||
```
|
||
|
||
### 완료 기준
|
||
|
||
```harbour
|
||
// 기존 Harbour DBF 파일을 Five로 그대로 사용
|
||
FUNCTION Main()
|
||
USE customers VIA DBFCDX
|
||
SET INDEX TO cust_name
|
||
|
||
// 검색
|
||
SEEK "SMITH"
|
||
IF Found()
|
||
? FIELD->name, FIELD->salary
|
||
REPLACE salary WITH salary * 1.1
|
||
ENDIF
|
||
|
||
// 순회
|
||
GO TOP
|
||
DO WHILE !EOF()
|
||
IF FIELD->country == "KR"
|
||
? FIELD->name
|
||
ENDIF
|
||
SKIP
|
||
ENDDO
|
||
|
||
// 인덱스 생성
|
||
INDEX ON UPPER(name) TO temp_idx
|
||
|
||
USE
|
||
RETURN NIL
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 6: OOP + 매크로 (3주)
|
||
|
||
### 목표
|
||
|
||
CLASS 문법과 매크로 시스템 동작
|
||
|
||
### 작업
|
||
|
||
```
|
||
6.1 CLASS 시스템 (hbrt/class.go)
|
||
- ClassDef 구조체 (이름, DATA 목록, METHOD 목록)
|
||
- ClassRegistry (sync.RWMutex)
|
||
- 인스턴스 생성 (New)
|
||
- 메서드 디스패치 (Send)
|
||
- 상속 (INHERIT FROM)
|
||
- 연산자 오버로딩
|
||
|
||
6.2 CLASS 파서/코드 생성
|
||
- CLASS ... ENDCLASS 파싱
|
||
- DATA 선언 → Go struct 필드
|
||
- METHOD 선언 → Go 메서드
|
||
- INHERIT FROM → Go 임베딩
|
||
- :: (Self 접근) → Go receiver
|
||
|
||
6.3 매크로 컴파일러 (hbrt/macro.go)
|
||
- 미니 렉서 + 파서 (식 전용)
|
||
- &variable → 런타임 파싱 + 실행
|
||
- &(expression) → 런타임 파싱 + 실행
|
||
|
||
6.4 PP 전처리기 (compiler/pp/)
|
||
- #include, #define, #ifdef/#endif
|
||
- #command / #translate (xBase 명령어 정의)
|
||
- #pragma compatibility(...)
|
||
```
|
||
|
||
### 완료 기준
|
||
|
||
```harbour
|
||
CLASS Person
|
||
DATA cName INIT ""
|
||
DATA nAge INIT 0
|
||
METHOD New(cName, nAge) CONSTRUCTOR
|
||
METHOD Greet()
|
||
ENDCLASS
|
||
|
||
METHOD New(cName, nAge) CLASS Person
|
||
::cName := cName
|
||
::nAge := nAge
|
||
RETURN Self
|
||
|
||
METHOD Greet() CLASS Person
|
||
? "Hello, I'm " + ::cName + " (" + Str(::nAge) + ")"
|
||
RETURN Self
|
||
|
||
FUNCTION Main()
|
||
LOCAL oPerson := Person():New("Kim", 30)
|
||
oPerson:Greet()
|
||
|
||
// 매크로
|
||
LOCAL cField := "cName"
|
||
? oPerson:&cField // "Kim"
|
||
|
||
RETURN NIL
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 7: Go 생태계 연동 (3주)
|
||
|
||
### 목표
|
||
|
||
IMPORT 문으로 Go 패키지를 PRG에서 직접 사용
|
||
|
||
### 작업
|
||
|
||
```
|
||
7.1 IMPORT 문법 (컴파일러)
|
||
- IMPORT "net/http"
|
||
- IMPORT "encoding/json"
|
||
- IMPORT "github.com/..."
|
||
- Go 타입을 Five에서 사용하는 브릿지 생성
|
||
|
||
7.2 타입 브릿지 (hbrt/bridge.go)
|
||
- ToGoValue(Value) interface{}
|
||
- FromGoValue(interface{}) Value
|
||
- Marshal / Unmarshal (구조체 ↔ Hash)
|
||
|
||
7.3 동시성 프리미티브
|
||
- GO 키워드 → goroutine
|
||
- CHANNEL(n) → make(chan Value, n)
|
||
- SEND(ch, val) → ch <- val
|
||
- RECEIVE(ch) → <-ch
|
||
- WAITGROUP → sync.WaitGroup wrapper
|
||
|
||
7.4 HTTP 프레임워크 (hbweb/)
|
||
- hbweb.New() → 라우터
|
||
- GET/POST/PUT/DELETE 라우팅
|
||
- JSON 응답
|
||
- 미들웨어
|
||
|
||
7.5 SQL RDD (hbsql/)
|
||
- database/sql 기반
|
||
- PostgreSQL, MySQL, SQLite 드라이버
|
||
- xBase 명령어로 SQL 테이블 조작
|
||
```
|
||
|
||
### 완료 기준
|
||
|
||
```harbour
|
||
IMPORT "encoding/json"
|
||
|
||
FUNCTION Main()
|
||
// HTTP 서버
|
||
LOCAL oApp := hbweb.New()
|
||
|
||
oApp:GET("/api/customers", {|ctx|
|
||
USE customers VIA DBFCDX
|
||
LOCAL aResult := {}
|
||
GO TOP
|
||
DO WHILE !EOF()
|
||
AAdd(aResult, { "name" => FIELD->name, "city" => FIELD->city })
|
||
SKIP
|
||
ENDDO
|
||
USE
|
||
ctx:JSON(200, aResult)
|
||
})
|
||
|
||
// goroutine으로 병렬 처리
|
||
LOCAL ch := CHANNEL(10)
|
||
GO BackgroundTask(ch)
|
||
|
||
? "Server starting on :8080"
|
||
oApp:Listen(":8080")
|
||
RETURN NIL
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 8: 개발 도구 (2주)
|
||
|
||
### 목표
|
||
|
||
개발자 경험 완성: 포매터, LSP, 테스트 프레임워크
|
||
|
||
### 작업
|
||
|
||
```
|
||
8.1 five fmt — 코드 포매터
|
||
- 들여쓰기 정규화
|
||
- 키워드 대소문자 통일
|
||
- 줄 바꿈 규칙
|
||
|
||
8.2 five lsp — Language Server
|
||
- textDocument/completion (자동 완성)
|
||
- textDocument/definition (정의로 이동)
|
||
- textDocument/hover (타입 정보)
|
||
- textDocument/diagnostics (에러 표시)
|
||
- 증분 파싱 (파일 변경 시 부분 재파싱)
|
||
|
||
8.3 five test — 테스트 프레임워크
|
||
- ASSERT 함수
|
||
- 테스트 파일 자동 발견 (*_test.prg)
|
||
- 벤치마크 지원
|
||
|
||
8.4 VSCode 확장
|
||
- 구문 강조 (TextMate grammar)
|
||
- LSP 클라이언트 연결
|
||
- 스니펫
|
||
- 빌드 태스크
|
||
|
||
8.5 five migrate — 마이그레이션 도구
|
||
- 기존 PRG 분석
|
||
- 자동 수정 가능 항목 변환
|
||
- 수동 수정 필요 항목 보고
|
||
```
|
||
|
||
---
|
||
|
||
## 일정 요약
|
||
|
||
```
|
||
Phase 0: 프로젝트 기반 ·········· 1주 ██
|
||
Phase 1: 최소 런타임 ··········· 2주 ████
|
||
Phase 2: 파서 ················· 3주 ██████
|
||
Phase 3: 코드 생성기 ··········· 3주 ██████
|
||
Phase 4: RTL + 코드 블록 ······· 3주 ██████
|
||
Phase 5: RDD (DBF/NTX/CDX) ···· 4주 ████████
|
||
Phase 6: OOP + 매크로 ·········· 3주 ██████
|
||
Phase 7: Go 생태계 연동 ········ 3주 ██████
|
||
Phase 8: 개발 도구 ············ 2주 ████
|
||
────
|
||
합계 24주 (약 6개월)
|
||
```
|
||
|
||
```
|
||
마일스톤:
|
||
|
||
Month 1 끝: "Hello World" 실행 (Phase 0-1)
|
||
Month 2 끝: PRG 파싱 완료 (Phase 2)
|
||
Month 3 끝: PRG → 실행 가능한 바이너리 (Phase 3)
|
||
Month 4 끝: 실용적 프로그래밍 가능 (Phase 4)
|
||
Month 5 끝: DBF 완전 호환 (Phase 5) ← 핵심 마일스톤
|
||
Month 6 끝: 전체 기능 + 도구 (Phase 6-8)
|
||
```
|
||
|
||
---
|
||
|
||
## 우선순위 원칙
|
||
|
||
```
|
||
1. Phase 5 (DBF/Index)가 가장 중요하다.
|
||
→ 이것이 없으면 Five는 Harbour 대체가 될 수 없다.
|
||
→ 포맷 호환이 깨지면 기존 사용자가 올 수 없다.
|
||
|
||
2. Phase 1-3은 Phase 5의 토대이다.
|
||
→ 런타임과 컴파일러가 있어야 DBF를 테스트할 수 있다.
|
||
→ 최소한의 기능으로 빠르게 통과한다.
|
||
|
||
3. Phase 7 (Go 연동)이 Five의 미래를 결정한다.
|
||
→ DBF만 있으면 "Go로 만든 Harbour"일 뿐
|
||
→ Go 생태계 직접 접근이 있어야 "새로운 플랫폼"
|
||
|
||
4. Phase 8 (도구)이 개발자를 데려온다.
|
||
→ 기능이 아무리 좋아도 도구가 없으면 사용하지 않는다.
|
||
```
|
||
|
||
---
|
||
|
||
## 변경 이력
|
||
|
||
| 날짜 | 변경 내용 |
|
||
|------|----------|
|
||
| 2026-03-27 | 초기 작성. 8 Phase, 24주 개발 계획 |
|