Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions docs/HOST_ABI.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,23 @@ int ml_module_set_host_fn(MlModule*, const char* name, void* fn);
> 지키고 있었다.
4. **인코딩은 호스트 계약이다.** 모듈은 **바이트만** 본다 — `==`는 NUL까지의 바이트 동등성이고,
대소문자를 구분하며 정규화하지 않는다(DP-S2). 호스트가 넘기는 바이트와 `.mls` 소스에 쓴
리터럴의 바이트가 같은 인코딩이어야 한다. 소스 리터럴은 **ASCII만** 허용하므로, ASCII 범위에서는
UTF-8·Latin-1·대부분의 코드 페이지가 일치한다.
리터럴의 바이트가 같은 인코딩이어야 한다. **비교하는** 소스 리터럴은 **ASCII만** 허용하므로(비ASCII
리터럴은 반환에만 — 위 "현재 구현된 경계"), ASCII 범위에서는 UTF-8·Latin-1·대부분의 코드 페이지가 일치한다.
- **⚠ ASCII 밖에서는 같은 모듈이 호스트의 코드 페이지에 따라 다른 답을 status `0`으로 낸다**
(2026-09-26, `HISTORY.md` §9-69.3). 한국어 ANSI 기계(`GetACP() = 949`)에서 로드한 모듈에 CP949
바이트를 넣어 잰 값:
- `byte_len`으로 쓴 길이 제한 — `가`×34는 UTF-8로 102바이트, CP949로 68바이트다. 100바이트 한도가
UTF-8 호스트에서는 거부하고 CP949 호스트에서는 **통과**한다.
- 입력에 비ASCII **반환 리터럴**을 이으면 결과는 **호스트의 CP949 바이트 + 리터럴의 UTF-8 바이트**다.
생성 `.h`·`.pas`의 *"This module RETURNS UTF-8 bytes"* 는 **입력이 UTF-8일 때만** 참이고, 그
결과는 어느 코드 페이지로 읽어도 한쪽이 깨진다(측정한 바이트: UTF-8로 읽으면 입력 이름이, CP949로
읽으면 리터럴이 깨진다).
모듈의 답은 E2이고, Delphi의 `AnsiString(S)`가 시스템 ANSI 코드 페이지로 바꾸는 단계는 E1이다 —
아래 5번 표의 "맞다"는 **ASCII 값(`"UPSN"`)으로만** 잰 것이다.
- **반대 방향의 규칙도 같은 표본에서 나왔다**: SMS·LMS 경계처럼 **EUC-KR 바이트로 정의된 업무 규칙**은
CP949로 보낼 때만 맞는다(측정). 그래서 이 계약은 인코딩을 하나로 정하지 않는다(`OPEN_QUESTIONS.md` Q17 (A)).
- **호스트 규칙: 모듈의 바이트 규칙이 어느 인코딩을 전제하는지 모듈 저자와 맞추고, 모든 호출에서 그
인코딩 하나로 보낸다.** 헤더는 그것을 말해 주지 않는다.
5. **⚠ Delphi 함정 (E2 — 2026-09-10 실측, Delphi CE 37.0 Win64).** Delphi의 기본 `string`은
UTF-16 `UnicodeString`이다. **어떤 캐스트를 쓰느냐가 결과를 가른다.** `"UPSN"`을 이 ABI로
실제로 보내며 잰 것이다(`hosts/delphi-host/host.dpr`, `MATHLESS_GATE_DELPHI`):
Expand Down
3 changes: 2 additions & 1 deletion docs/OPEN_QUESTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ ABI 정수 상태코드+out-param, 표면 Result는 sugar. 남은 하위 → Q13
| (C) 파라미터별 코드 페이지 선언 | 두 부류의 규칙을 다 쓸 수 있다 | 표면이 는다. 혼합 바이트(CP949 이름에 UTF-8 리터럴을 잇기)는 모듈 쪽 변환 없이 여전히 틀린다 — 할당자가 없다 |

**권고 (A) — 재검토 조건**: 비ASCII **비교**나 **문자 단위 길이**가 필요한 슬라이스를 고를 때 이 표로 돌아온다.
⏳ **사용자 확인 대기(2026-09-26).**
✅ **2026-09-26 사용자 확인: (A).** 결정이 아니라 **열어 두는 것**이므로 `DECISIONS.md`도 DP-S2도
바뀌지 않는다. 위험은 `HOST_ABI.md` "문자열 파라미터 계약" 4번에 적었다.
- Q12. 반환 값 소유권 규약 — **닫힘(2026-08-31)**: 사용자 확정으로 **(a) caller-allocates out-buffer**.
가변 길이 데이터는 **호스트가 버퍼와 용량을 주고, 모듈이 채우고, 필요한 길이를 돌려준다**.
절단은 **D17의 음수 예약 status**로 보고한다 — "성공했는데 짧다"가 아니라 명시적 실패다.
Expand Down
1 change: 0 additions & 1 deletion docs/STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@
> 1. **체크드 정수 산술 — 구현 중.** DP-O1~O9 전부 사용자 확인(2026-09-26). `docs/slices/SPEC-checked-arithmetic.md`
> §6의 작업 1(codegen·바인딩·오라클 값·문서)이 들어갔고, **작업 2가 남았다** — 실제 C 호스트가 `-3`을 받는 수용 D,
> §9-69의 161행 재측정, 크기 변화, 그리고 슬라이스 닫기.
> 같은 날 인코딩 질문은 `OPEN_QUESTIONS.md` **Q17**로 올렸다(권고 (A) — 사용자 확인 대기).
> 2. **작은 항목**: C# 호스트(Phase 4) · LSP(Phase 3, 큰 일).
> 3. **외부**: `X1`·`X2` — Delphi가 있는 CI 러너. 이 저장소 안에서는 닫히지 않는다.
>
Expand Down
8 changes: 8 additions & 0 deletions docs/history/9-69.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ A+as에도 남는 60행: 무한(`-> i32`) 헬퍼 16 · 무한 export 본문 4(
조건은 *대소문자 무시·정규화*다 — 이번 근거는 그 조건과 다르므로, 재개하려면 그 사실부터 적어야 한다. 또 *UTF-8 전용*
으로 정하면 EUC-KR 바이트 단위 규칙(SMS 길이)이 모든 준수 호스트에서 틀린다는 반례가 같은 도메인에서 나왔다.

규칙과 잰 값(Q17 (A)가 `HOST_ABI.md` 문자열 파라미터 계약 4번에 옮긴 것의 근거 — 같은 날 덧붙였다):

| 규칙 | UTF-8 입력(mlprobe) | CP949 입력(ctypes, `GetACP() = 949`) |
|---|---|---|
| NA-R1 상세주소 — **UTF-8 100바이트** 이하면 바이트 수, 넘으면 `E_TOO_LONG` | 가×33(99B) → 99 · 가×34(102B) → status 1 | 가×34(68B) → **status 0** |
| NA-R3 SMS/LMS — **EUC-KR 90바이트**(한글 45자) 이하 SMS, 2000바이트 이하 LMS | 가×45 → LMS(**틀림**) | 가×45 → SMS · 가×46 → LMS · 가×1001 → `E_TOO_LONG`(전부 맞음) |
| NA-R5 인사말 = 이름 + 반환 리터럴 `" 고객님"` | 홍길동 → 맞음 | 출력 = CP949 이름 바이트 + UTF-8 리터럴 바이트 — UTF-8로 읽으면 이름이, CP949로 읽으면 리터럴이 깨진다 |

#### 9-69.4. 고친 것 — PR 셋

| PR | 결함(전부 E2로 재현) |
Expand Down
2 changes: 1 addition & 1 deletion docs/slices/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ TDD 구현 → Grok 검증 → PR** 순서를 따른다(`CLAUDE.md` "개발 방
**인터페이스 정의 파일**(설계부터)과 **개발/배포 빌드 분리**(D13, `SECURITY.md` P1).
*(2026-09-25 로드맵 검토에서 더했다 — Phase 2의 다섯 항목 중 이 둘이 이 목록에 없었다.)*
§7(§9-69, 12개 도메인 72규칙과 귀속 대조)이 더한 후보: **체크드 정수 산술**(가장 강한 근거 — 확정되어
구현 중이다, 위 색인), **i64**, **입력 문자열의 인코딩 계약**(닫힌 DP-S2의 재개 — 설계 질문, §9-69.3), 비트 연산자,
구현 중이다, 위 색인), **i64**, **입력 문자열의 인코딩 계약**(닫힌 DP-S2의 재개 — `OPEN_QUESTIONS.md` Q17이 (A)로 열어 두었고 재검토 조건은 거기 있다), 비트 연산자,
지역 작업 배열, 수학 내장 함수, 문자 단위 길이.
**struct는 §9-1이 강제되지 않는다고 결론냈다** — 고르려면 그 절을 먼저 읽는다(§9-69도 귀속 0으로 다시 확인했다).
배열도 같은 결론이었고(§9-9가 다섯 번째로), **입력은 그 사실을 SPEC 첫 절에 적은 채로 열렸다**.
Expand Down
Loading