docs: TODO 와 핸드오프 문서를 추적한다
지난번 에이전트가 handoff1 만 지우라는 지시에 두 문서까지 같이 지웠다. untracked 였기 때문에 git 에 기록이 없어 복구할 수 없었다.
This commit is contained in:
@@ -0,0 +1,115 @@
|
|||||||
|
# TODO
|
||||||
|
|
||||||
|
현재: **150/188** (`uv run python tests/run.py`)
|
||||||
|
|
||||||
|
컴파일러는 프론트엔드뿐이다. IR·lowering·백엔드는 없다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 프론트엔드 마무리
|
||||||
|
|
||||||
|
| # | 일 | 규모 | fixture | 비고 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 1 | cross-unit 이름 해석 | 중 | units 8 | `util.answer()` 가 다른 유닛 선언을 보게. `check.c` 가 import binding 을 심볼로 알아야 함 |
|
||||||
|
| 2 | 가시성 `pub`/private | 중 | units 4 | `privfn` `privfld` `dotpriv` `pubpriv` |
|
||||||
|
| 3 | nominal error identity | 중 | units 3 | `errsame` `errdet` `errnom` |
|
||||||
|
| 4 | **제네릭 실체화** | 대 | generic 25 | worklist 엔진. **IR 설계에 직접 영향 — 분기점** |
|
||||||
|
| 5 | 마커 없는 fixture 37개 판정 | 중 | — | 개당 판단 필요. 아래 참조 |
|
||||||
|
|
||||||
|
## 백엔드
|
||||||
|
|
||||||
|
| # | 일 | 규모 | 비고 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 6 | IR 정의 | 중 | 초안 있음. 4번이 정해져야 확정 |
|
||||||
|
| 7 | **lowering** | 대 | `try`/`catch`/`defer`/drop/`for`/메서드/경계검사 전개. **프로젝트 무게중심** |
|
||||||
|
| 8 | i386 백엔드 | 대 | IR → x86 asm → `wasm` → `wlink`. W11 에서 실행 검증 |
|
||||||
|
| 9 | 런타임 최소 세트 | 소~중 | 시작 스텁, `fe_trap`, `malloc`/`free` |
|
||||||
|
| 10 | `pending-backend/` 3개 복귀 | 소 | bounds trap, `--no-checks` 차등, 소유권 drop |
|
||||||
|
|
||||||
|
## 그 이후
|
||||||
|
|
||||||
|
| # | 일 | 규모 | 비고 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 11 | stdlib | 대 | 현재 49줄, 본문 있는 함수 2개. `List`/`Map` 은 4번에 의존 |
|
||||||
|
| 12 | bits16 백엔드 | 대 | `DX:AX` 32비트 산술, 세그먼트. 제일 어려움. 마지막 |
|
||||||
|
| 13 | 타깃 의존 구문 | 중 | `far` `asm` `interrupt` `atomic` `critical` `shared` — 파싱만 되고 의미 없음. fixture 도 없음 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 미결 결정
|
||||||
|
|
||||||
|
| | 내용 | 언제 |
|
||||||
|
|---|---|---|
|
||||||
|
| 덩어리 전달 규약 | 정함 (전부 주소로). 8번 착수 전 재확인 | 8 전 |
|
||||||
|
| `extern` C 상호운용 | 위 규약이 C ABI 와 안 맞음. 경계 변환 필요 | 8 전 |
|
||||||
|
| 주 타깃 | i386/W11 로 기울었으나 SPEC §1.2 는 아직 "640KB 셀프호스팅" | 아무 때나 |
|
||||||
|
| stdlib 명세 | SPEC §10 이 플레이스홀더. 시그니처·오류·경계 동작 미정 | 11 전 |
|
||||||
|
| `far` 의 거취 | IR 에 안 두기로 함. 언어에서 뺄지 bits16 전용으로 둘지는 미정 | 12 전 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 순서
|
||||||
|
|
||||||
|
```
|
||||||
|
1 → 2 → 3 프론트엔드 유닛 완성
|
||||||
|
4 제네릭. ← 여기서 IR 형태가 결정됨
|
||||||
|
6 → 7 IR + lowering
|
||||||
|
8 → 9 → 10 i386 백엔드, 실행 검증 복귀
|
||||||
|
11 stdlib
|
||||||
|
12 → 13 DOS 고유
|
||||||
|
```
|
||||||
|
|
||||||
|
5번은 독립적이라 아무 때나 끼워 넣는다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 위임 정책
|
||||||
|
|
||||||
|
**위임 가능** — 결과가 자명하고 판단이 없는 것
|
||||||
|
|
||||||
|
- fixture 이름 개선, README 갱신, 문서 정합
|
||||||
|
- 파일 목록을 **명시적으로 열거해서** 줄 것. "찾아서 하라" 는 약함
|
||||||
|
- 기준선 두 숫자(`N/188`, `M pin`)를 주고 **변하면 안 된다**고 못박을 것
|
||||||
|
|
||||||
|
**위임 불가** — 언어 의미론 판단이 섞인 것
|
||||||
|
|
||||||
|
- 마커 판정, cross-unit 해석, 가시성, 제네릭, IR/lowering/백엔드
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5번에 대하여 (마커 없는 fixture 37개)
|
||||||
|
|
||||||
|
거부 fixture 76개 중 **37개에 `// ERROR:` 마커가 없다.** 마커가 없으면 러너는
|
||||||
|
"거부되기만 하면 통과" 로 판정한다. 즉 **엉뚱한 이유로 거부돼도 초록이다.**
|
||||||
|
|
||||||
|
```
|
||||||
|
format 10 own 8 types 19
|
||||||
|
```
|
||||||
|
|
||||||
|
마커를 붙이려면 fixture 마다 "지금 나오는 진단이 옳은가" 를 판정해야 하고,
|
||||||
|
그 판정은 세 갈래로 갈린다. 오늘 5건을 조사했을 때 실제로 셋 다 나왔다:
|
||||||
|
|
||||||
|
| 결론 | 예 | 조치 |
|
||||||
|
|---|---|---|
|
||||||
|
| 마커가 틀렸다 | `badbrmov` 한 줄 밀림 | 마커 수정 |
|
||||||
|
| 마커가 언어를 오해했다 | `badloop` — 루프 안에서 이미 걸림 | 마커 수정 |
|
||||||
|
| **진단이 부실하다** | `badweak` — "type mismatch" 로만 나옴 | **컴파일러 수정** |
|
||||||
|
|
||||||
|
세 번째 때문에 위임이 위험하다. 실제 출력을 마커에 그대로 베끼면 전부 초록이
|
||||||
|
되지만 **컴파일러가 틀린 곳까지 정답으로 굳는다.**
|
||||||
|
|
||||||
|
### 병렬화
|
||||||
|
|
||||||
|
판정 자체는 **fixture 간 독립**이라 병렬 가능하다. 다만 **판정을 위임하면 안 된다.**
|
||||||
|
쓸 수 있는 형태는 증거 수집과 판정을 나누는 것이다:
|
||||||
|
|
||||||
|
```
|
||||||
|
위임: fixture 를 열고 → fec 를 돌리고 → 다음을 보고
|
||||||
|
파일 경로 / 검사하려는 것으로 보이는 규칙 / 실제 진단 전문(줄·문구)
|
||||||
|
마커는 만들지 않는다
|
||||||
|
|
||||||
|
직접: 보고를 읽고 세 갈래 중 무엇인지 판정 → 마커를 쓰거나 컴파일러를 고침
|
||||||
|
```
|
||||||
|
|
||||||
|
이러면 37개를 디렉터리별로 병렬로 뿌려 증거를 모으고, 판정만 직접 하면 된다.
|
||||||
|
느린 부분(파일 읽기·실행·정리)이 병렬화되고 위험한 부분은 남는다.
|
||||||
+244
@@ -0,0 +1,244 @@
|
|||||||
|
# Handoff 2 — 마커 증거 수집과 fixture 이름 짓기
|
||||||
|
|
||||||
|
앞선 시도가 한 번 실패해서 되돌렸다(`7636a41`). 실패 원인부터 읽어라.
|
||||||
|
그게 이 문서의 절반이다.
|
||||||
|
|
||||||
|
## 실패한 방식
|
||||||
|
|
||||||
|
지난번 에이전트는 **파일을 열지 않고 이름 문자열만 변환했다.** 밑줄을 지우고,
|
||||||
|
그 결과 충돌하는 이름에 숫자를 붙였다.
|
||||||
|
|
||||||
|
```
|
||||||
|
bad_loop → badlop1 badweak → badweak2
|
||||||
|
badloop → badlp2 oktry → oktry2
|
||||||
|
```
|
||||||
|
|
||||||
|
결정적 증거는 이것이다. `own/badfld.fe` 는 **구조체 필드에 참조를 둔 것**을 검사하고
|
||||||
|
`types/badfld.fe` 는 **없는 필드에 접근한 것**을 검사한다. 완전히 다른 규칙인데
|
||||||
|
둘 다 `badfmem.fe` 가 됐다. 같은 옛 이름에 같은 치환을 먹였기 때문이다.
|
||||||
|
|
||||||
|
**이 일의 본질은 파일을 읽고 무엇을 검사하는지 판단하는 것이다.** 이름 변환이 아니다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 배경
|
||||||
|
|
||||||
|
`fec` 는 Ferro 언어의 컴파일러이고 현재 **프론트엔드만** 있다. fixture 는 컴파일러가
|
||||||
|
어떤 코드를 받아들이고 어떤 코드를 거부하는지 고정하는 테스트다. 파일 하나가 케이스
|
||||||
|
하나다.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
uv run python tests/run.py # 전체
|
||||||
|
uv run python tests/run.py -k own # 경로에 own 이 들어간 것만
|
||||||
|
```
|
||||||
|
|
||||||
|
러너는 매번 `.build\fec.exe` 를 새로 빌드한다. 진단 전문을 보려면 그걸 직접 부른다.
|
||||||
|
|
||||||
|
```
|
||||||
|
> .build\fec.exe --check fec\tests\types\bad_ari.fe
|
||||||
|
fec/tests/types/bad_ari.fe:8:15: error: wrong number of arguments
|
||||||
|
8 | return add(1);
|
||||||
|
| ^
|
||||||
|
```
|
||||||
|
|
||||||
|
### 러너가 기대를 정하는 방법 — 이걸 정확히 알아야 한다
|
||||||
|
|
||||||
|
`tests/run.py` 의 `expectation()` 을 직접 읽어라. 요약하면:
|
||||||
|
|
||||||
|
| 파일 첫 줄 | 러너의 기대 |
|
||||||
|
|---|---|
|
||||||
|
| `// ERROR:7:borrow` | **거부**되고, 진단이 **7번 줄**, 문구에 **`borrow`** 포함 |
|
||||||
|
| `// ERROR:borrow` | 거부되고 문구에 `borrow` 포함 (줄은 안 봄) |
|
||||||
|
| **마커 없음** | **파일명이 `bad` 로 시작하면 거부**, 아니면 **성공** |
|
||||||
|
|
||||||
|
마지막 줄이 이 작업의 핵심 함정이다.
|
||||||
|
|
||||||
|
> ### 마커가 없는 파일에서는 `bad` 접두사가 기대값 그 자체다
|
||||||
|
>
|
||||||
|
> 마커 없는 `bad_ari.fe` 를 `arity.fe` 로 바꾸면 러너는 그 순간부터
|
||||||
|
> **성공하기를** 기대한다. 그리고 그 fixture 는 실패한다.
|
||||||
|
>
|
||||||
|
> 마커가 **있는** 파일은 마커가 기대를 정하므로 접두사가 아무 의미도 없다.
|
||||||
|
> 마음대로 지어도 된다.
|
||||||
|
|
||||||
|
그래서 이 핸드오프는 마커 없는 37개를 **먼저** 처리한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 착수 전 기준선
|
||||||
|
|
||||||
|
```
|
||||||
|
uv run python tests/run.py
|
||||||
|
→ 150/188 passed (58 pin a line and message)
|
||||||
|
```
|
||||||
|
|
||||||
|
**두 숫자 모두 끝까지 변하면 안 된다.**
|
||||||
|
|
||||||
|
- 줄면 무언가 깨진 것이다
|
||||||
|
- **늘면 검사를 약화시킨 것이다.** 이쪽이 더 나쁘다. 조용히 통과하는 테스트는
|
||||||
|
없는 테스트보다 해롭다
|
||||||
|
|
||||||
|
어느 쪽이든 되돌리고 보고하라.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 1. 마커 없는 fixture 37개 — 증거만 모은다
|
||||||
|
|
||||||
|
이 37개는 마커가 없어서 **"거부되기만 하면 통과"** 다. 엉뚱한 이유로 거부돼도 초록이다.
|
||||||
|
마커를 붙여야 하는데 **그 판정은 네가 하지 않는다.**
|
||||||
|
|
||||||
|
```
|
||||||
|
types/ 19 bad_ari bad_asgn bad_cast bad_cond bad_mlet bad_ret bad_shwr
|
||||||
|
bad_type bad_unit bad_unk bad_void badarr badchar badcycle
|
||||||
|
badfield badfld badindex badmat badstr
|
||||||
|
|
||||||
|
format/ 10 bad_ari bad_bufw bad_cls bad_many bad_open bad_run bad_try
|
||||||
|
bad_type bad_verb bad_writ
|
||||||
|
|
||||||
|
own/ 8 bad_clos bad_cond bad_dbl bad_dest bad_drop bad_loop bad_move
|
||||||
|
bad_proj
|
||||||
|
```
|
||||||
|
|
||||||
|
## 왜 판정을 맡기지 않는가
|
||||||
|
|
||||||
|
판정 결과가 세 갈래로 갈리는데 그중 하나는 **컴파일러를 고쳐야 하는 경우**다.
|
||||||
|
|
||||||
|
| 결론 | 조치 |
|
||||||
|
|---|---|
|
||||||
|
| 마커를 안 붙였을 뿐, 진단은 옳다 | 마커를 쓴다 |
|
||||||
|
| 진단은 나오지만 **다른 이유**로 거부하고 있다 | fixture 를 다시 본다 |
|
||||||
|
| **진단이 부실하다** — 규칙 위반을 못 짚고 뭉뚱그린 오류만 낸다 | **컴파일러를 고친다** |
|
||||||
|
|
||||||
|
세 번째가 실제로 있었다. `own/badweak.fe` 는 mut 대여를 shared 로 약화시키는 것을
|
||||||
|
검사하는데 컴파일러는 `type mismatch` 라고만 했다. 실제 출력을 마커에 그대로
|
||||||
|
베꼈다면 초록이 되면서 **컴파일러의 부실한 진단이 정답으로 굳었을 것이다.**
|
||||||
|
|
||||||
|
그래서 **너는 증거를 모으고 판정은 사람이 한다.**
|
||||||
|
|
||||||
|
## 파일마다 보고할 것
|
||||||
|
|
||||||
|
```
|
||||||
|
파일 fec/tests/types/bad_ari.fe
|
||||||
|
검사 대상 이 코드가 무엇을 위반하려 하는가 — 네가 읽고 판단한 것
|
||||||
|
근거 그렇게 본 이유. 어느 줄의 무엇 때문인지
|
||||||
|
실제 진단 .build\fec.exe --check <경로> 의 출력 전문 (줄·열·문구 그대로)
|
||||||
|
일치 여부 실제 진단이 '검사 대상' 을 짚는가 — 예 / 아니오 / 애매
|
||||||
|
```
|
||||||
|
|
||||||
|
`일치 여부` 가 이 작업의 산출물이다. 나머지는 그 판단의 근거다.
|
||||||
|
**애매하면 애매하다고 써라.** 억지로 '예' 로 만들면 이 작업이 무의미해진다.
|
||||||
|
|
||||||
|
## 절대 금지
|
||||||
|
|
||||||
|
- **`// ERROR:` 마커를 하나도 쓰지 마라.** 이 항목의 산출물은 보고서뿐이다
|
||||||
|
- `fec/src/` 의 어떤 파일도 고치지 마라
|
||||||
|
- `tests/run.py` 를 고치지 마라 (읽는 건 권장)
|
||||||
|
- fixture 의 내용을 고치지 마라
|
||||||
|
- **실제 출력을 그대로 마커로 옮기는 것** — 가장 하기 쉽고 가장 해로운 실수다
|
||||||
|
|
||||||
|
## 산출물
|
||||||
|
|
||||||
|
리포지터리 루트에 `fixture-report.md`. 디렉터리별로 나누고 위 다섯 항목을 담는다.
|
||||||
|
이것만 커밋한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 2. fixture 이름 짓기
|
||||||
|
|
||||||
|
1번을 **끝내고 보고한 뒤에** 시작한다. 1번의 판정 결과가 이름을 바꾸기 때문이다.
|
||||||
|
|
||||||
|
대상은 네 디렉터리의 모든 `.fe` 파일이다.
|
||||||
|
|
||||||
|
```
|
||||||
|
fec/tests/types/ 31
|
||||||
|
fec/tests/format/ 13
|
||||||
|
fec/tests/own/ 50
|
||||||
|
fec/tests/optional/ 28
|
||||||
|
```
|
||||||
|
|
||||||
|
`units/` `generic/` `parse/` `pending-backend/` 는 **제외한다.**
|
||||||
|
(`units/` 와 `generic/` 은 이름이 import 경로의 일부라 구조가 다르다.)
|
||||||
|
|
||||||
|
이미 제대로 된 이름 셋은 손대지 마라.
|
||||||
|
|
||||||
|
```
|
||||||
|
own/globalm.fe own/localesc.fe own/self_fld.fe
|
||||||
|
```
|
||||||
|
|
||||||
|
## 이름 제약 (컴파일러가 강제한다)
|
||||||
|
|
||||||
|
각 `.fe` 는 `unit <이름>;` 을 갖고 **그 이름이 파일명(확장자 제외)과 정확히 같아야 한다.**
|
||||||
|
이름은 소문자로 시작, `a-z0-9_` 만, **최대 8자**. DOS 8.3 에서 온 제약이고
|
||||||
|
`SPEC.md` §8.1 의 일부라 바꿀 수 없다.
|
||||||
|
|
||||||
|
### 디렉터리가 다르면 이름이 겹쳐도 된다
|
||||||
|
|
||||||
|
지금 `types/bad_ari.fe` 와 `format/bad_ari.fe` 가 **동시에 존재하고 테스트는 통과한다.**
|
||||||
|
각 fixture 는 독립된 빌드다. 지난번 실패는 이걸 몰라서 억지로 유일하게 만들려다
|
||||||
|
숫자를 붙인 것이다. **각 디렉터리 안에서만 유일하면 된다.**
|
||||||
|
|
||||||
|
### 접두사
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| **마커가 있는 파일** | `bad`/`ok` 접두사를 **버려도 된다.** 기대는 마커가 정한다. 8자를 접두사에 쓰지 마라 |
|
||||||
|
| **1번의 37개** | 사람이 마커를 붙이기 전까지 **`bad` 접두사를 반드시 유지해야 한다.** 남는 건 5자다 |
|
||||||
|
|
||||||
|
37개는 5자 안에 뜻을 담기 어려우니 **가능한 만큼만 개선하고, 안 되는 건 그대로 두고
|
||||||
|
목록에 적어라.** 마커가 붙으면 그때 다시 짓는다.
|
||||||
|
|
||||||
|
## 절차
|
||||||
|
|
||||||
|
파일 하나마다:
|
||||||
|
|
||||||
|
1. **연다.** 전체를 읽는다. 대개 10줄 미만이다
|
||||||
|
2. **무엇을 검사하는지 판단한다.** 마커가 있으면 강한 단서다
|
||||||
|
3. 그것을 8자 안에 나타내는 이름을 짓는다
|
||||||
|
4. `git mv` 로 옮긴다
|
||||||
|
5. **파일 안 `unit` 선언을 새 이름으로 고친다.** 안 하면 컴파일러가 거부한다
|
||||||
|
6. 그 외에는 파일을 **한 글자도** 건드리지 마라
|
||||||
|
|
||||||
|
## 이름의 기준
|
||||||
|
|
||||||
|
이름은 **"무엇을 검사하는가"** 를 나타낸다.
|
||||||
|
|
||||||
|
```
|
||||||
|
좋음: badgmut → globalm 전역을 mut 로 빌리는 것
|
||||||
|
badlocsl → localesc 지역 변수의 참조가 탈출하는 것
|
||||||
|
badfld → reffield 구조체 필드에 참조를 둔 것 (own/)
|
||||||
|
badfld → nofield 없는 필드에 접근한 것 (types/)
|
||||||
|
|
||||||
|
나쁨: badarr → ba1 아무것도 말하지 않음
|
||||||
|
badweak → badweak2 숫자는 정보가 아님
|
||||||
|
badcatch → badcatc 그냥 자른 것
|
||||||
|
```
|
||||||
|
|
||||||
|
축약은 해도 된다. 다만 **읽어서 짐작이 가야 한다.**
|
||||||
|
|
||||||
|
## 절대 금지
|
||||||
|
|
||||||
|
- **첫 줄 `// ERROR:` 마커를 만들거나 고치거나 지우지 마라**
|
||||||
|
- `unit` 선언 외의 내용 변경
|
||||||
|
- 빈 줄 추가 — 지난번에 119개 파일에 군더더기 빈 줄이 들어갔다
|
||||||
|
|
||||||
|
## 진행 방법
|
||||||
|
|
||||||
|
**디렉터리 하나씩** 끝내고 `-k <디렉터리>` 로 확인한 뒤 커밋해라. 범위가 좁아야
|
||||||
|
문제를 찾는다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 커밋
|
||||||
|
|
||||||
|
1번은 하나, 2번은 디렉터리마다 하나. 메시지는 무엇을 왜 바꿨는지 한국어로.
|
||||||
|
**푸시하지 마라.**
|
||||||
|
|
||||||
|
# 최종 보고
|
||||||
|
|
||||||
|
- 각 커밋 전후의 두 숫자 (`N/188`, `M pin`)
|
||||||
|
- 1번: `fixture-report.md` 경로, 그리고 **`일치 여부: 아니오 / 애매`** 로 판정한 것의 목록.
|
||||||
|
거기가 컴파일러를 고쳐야 할 수도 있는 지점이라 가장 중요하다
|
||||||
|
- 2번: **바꾼 이름 전체 목록** — `디렉터리/이전 → 이후` 와 각각 **한 줄 근거**.
|
||||||
|
근거가 안 써지는 이름은 잘못 지은 것이다
|
||||||
|
- 2번에서 이름을 못 지은 파일 목록과 이유. 억지로 짓지 말고 남겨라
|
||||||
|
- 판단이 필요해서 건너뛴 것
|
||||||
Reference in New Issue
Block a user