diff --git a/OPTIMIZATION_TODO.md b/OPTIMIZATION_TODO.md index b9fdf8a..3686a02 100644 --- a/OPTIMIZATION_TODO.md +++ b/OPTIMIZATION_TODO.md @@ -556,4 +556,79 @@ correctness 라운드(SQL NULL + 대형 버그 감사)가 마무리된 시점의 `check_order`, `test_deep_err`, `test_dbg*`. - `~/tmp/error.log` 이전 에러 덤프 보관. +--- + +## 완료 (2026-04-30: PP / std.ch 라운드 — 9 commits) + +파서가 silent no-op 으로 삼키던 xBase 명령들을 Harbour-style `#command` +규칙으로 옮겼다. 결과: 13개 명령이 시즌 처음으로 *실제* 동작한다. +PP 자체에서는 14건의 결함을 추가로 잡았다. + +### 동작하기 시작한 명령들 + +| 명령 | RTL 백엔드 | 비고 | +|------|-----------|-----| +| `ERASE`/`DELETE FILE`/`RENAME` | `FErase`/`FRename` | 이전엔 silent no-op (파일 안 지움) | +| `CLOSE`/`CLOSE ALL`/`CLOSE DATABASES`/`CLOSE ` | `DbCloseArea`/`DbCloseAll` + alias-arrow | 알리아스 형은 알리아스 무시했었음 | +| `COMMIT`/`UNLOCK`/`UNLOCK ALL` | `DbCommit`/`DbRUnlock`/`DbUnlock` | | +| `LOCATE`/`CONTINUE` | `__dbLocate`/`__dbContinue` | 기존 RTL — 파서 하드코드만 제거 | +| `REINDEX`/`PACK`/`ZAP` | `DbReindex`/`DbPack`/`DbZap` | | +| `KEYBOARD`/`RUN` | `Keyboard`/`hb_Run` | | +| `COUNT`/`SUM`/`AVERAGE` | `dbEval` (`__dbAverage` 만 신규) | Harbour 그대로 dbEval 위에 쌓는 매크로 | +| `COPY TO` `[FIELDS] [FOR/WHILE/NEXT/REC/REST/ALL]` | 신규 `__dbCopy` | DBF→DBF (SDF/DELIMITED 미지원) | +| `SORT TO` `[ON keys/D] [FOR/...]` | 신규 `__dbSort` | 다중 키, `/D` desc, stable insertion sort | +| `LIST`/`DISPLAY` `[fields] [OFF] [FOR/...]` | 신규 `__dbList` | OFF/ALL 차이는 Harbour 그대로 | +| `TOTAL TO` `ON [FIELDS]` | 신규 `__dbTotal` | 연속 동일-키 그룹별 합. memo 필드 제외 | +| `JOIN WITH TO ` | 신규 `__dbJoin` | nested-loop, master-precedence 필드 union | +| `UPDATE FROM [ON ] [RANDOM] REPLACE ...` | 신규 `__dbUpdate` | `_FIELD->` wrapping 으로 dispatch | + +파서의 IDENT-statement no-op switch 에서 16개 키워드 제거 — `parseIdentStmt`/`parseExprStmt` 두 곳 동기화된 상태로. + +### PP 자체 결함 fix 14건 + +1. partial-pattern false-match (literal tail 미검사) — `CLOSE` 가 `CLOSE ALL` 룰에 매치 +2. 미캡쳐 marker tail 우선순위 (`` 가 옵션이 아닌데 옵션처럼 skip) — `CLOSE` 가 `CLOSE ` 룰에 매치 +3. `<{name}>` blockify substitution 미구현 +4. `findMarkerEnd` 가 `{`/`}` prefix/suffix 인식 못함 +5. `<(name)>` 패턴 marker 의 capture 키에 괄호 baked-in (smart-stringify 안 동작) +6. 옵션 절 marker 가 outer pattern 끝까지 greedy 캡처 — `[TO <(f)>] [FOR ]` 에서 file 이 FOR 까지 삼킴 +7. `matchSegment` 가 옵션 절 내 `MarkerList`(``) 미지원 +8. `captureExpression` 이 첫 delimiter 만 사용 — 옵션 절 chain 에서 모든 후속 키워드 stop 못함 +9. `<(name)>` smart-stringify 가 list capture 에 element-별 quote 안 함 — `{ "a , b" }` ←→ `{ "a", "b" }` +10. `<{name}>` blockify 가 list capture 에 element-별 wrap 안 함 — `{|| a , b }` ←→ `{ {|| a }, {|| b } }` +11. `#command` 다중-행 line-continuation `;` 미지원 — std.ch 형식의 멀티라인 룰 자체가 등록 안 됨 +12. `matchSegment` 가 `MarkerWordList` (``) 미지원 +13. List/regular capture stop 경계가 `MarkerWordList` 의 값들을 인식 못함 — `[] []` 에서 v 가 OFF 까지 삼킴 +14. 옵션-반복 loop 가 no-progress iteration 의 빈 capture 를 `\x01` 로 contaminating 후 break — multi-capture mode 로 잘못 들어감 +15. 미캡쳐 `<.name.>` 이 빈 문자열로 정리됨 (Harbour idiom: `.F.` 가 정답) +16. `matchSegment` 가 nested `[...]` 옵션 절 미지원 — `[REPLACE WITH [, WITH ]]` 에서 inner `[` 를 literal 로 매치 시도 + +### 누적 silent 버그 fix +PP/std.ch 라운드 14건 + 시즌 전체 (~62 + 14) = **약 76건**. + +--- + +## 보류 — 아주 먼 미래 (LABEL / REPORT) + +xBase 의 `LABEL FORM` / `REPORT FORM` 명령은 별도 `.lbl` / `.frm` 바이너리 +포맷 파일을 읽어 페이지/컬럼 폭/머리·꼬리/그룹 break 등을 처리하는 +**완전한 출력 포맷팅 엔진**이다. + +* 사용 빈도: 1990년대 dBASE/Clipper 환경에서나 흔했고, 현 시점 신규 코드에서 + 거의 안 쓰임. SQL + 외부 PDF/HTML 라이브러리로 대체된 지 오래. +* 구현 비용: `.lbl`/`.frm` 바이너리 파서 + 페이지네이션/컬럼 폭 계산 + + group break + summary 등 — 예상 ~800~1500 LOC. +* ROI: 매우 낮음. 현존 사용자 거의 없음. + +**결정**: 보류. 향후 실수요 사례가 등장하기 전까지는 파서가 silent no-op +으로 삼키는 현 상태 유지. 파서 IDENT-stmt switch 에 `LABEL`/`REPORT` 가 +남아있고, 두 키워드 다음 토큰을 EOL 까지 소비한다 — Harbour 호환 PRG +파일이 컴파일은 되며 (실행하면 무동작) 다른 동작에 영향 없음. + +재개 시 진입 지점: +* harbour-core/include/std.ch — `#command LABEL FORM`, `#command REPORT FORM` +* harbour-core/src/rdd/dblabel.prg, dbreport.prg, dbrlist.prg +* harbour-core/src/rtl/frlabel.prg (label .lbl reader) +* `.frm` / `.lbl` 바이너리 포맷: dBASE III 시대 문서 (Sybex 등 옛 reference 자료) + 다음 세션 시작 시 `CLAUDE.md` 로드 → 이 파일 읽기 → 위 순서 1번부터 진행.