diff options
Diffstat (limited to 'docs/design/027-computation-core.md')
| -rw-r--r-- | docs/design/027-computation-core.md | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/docs/design/027-computation-core.md b/docs/design/027-computation-core.md new file mode 100644 index 0000000..4df67f9 --- /dev/null +++ b/docs/design/027-computation-core.md @@ -0,0 +1,189 @@ +# 027 — 계산의 핵: 상태는 값 하나, 값은 몇 가지로 짓는다 + +작성일: 2026-10-13. 상태: 설계와 단계. [026](026-app-contract.md)이 얼릴 계약 안에서 계산의 언어를 다시 세운다. 잴 도구는 +[140](../research/140-spec-suite.md)의 명세 묶음이다. 1.0 전이라 호환은 챙기지 않는다. 사용자의 말: "진행해" (2026-10-13). + +## 쉬운 말로 + +- **지금의 꼴.** aup와 Pure는 패턴마다 종류와 명령을 둔다. 커서, 인덱스, 문서, 표 보기, 메시지의 행이 각각 따로다. 그래서 세상의 + 명세를 담지 못하고(140), 새 패턴마다 형식과 세 실행 길이 함께 자란다. +- **이 설계의 꼴.** 그것을 "값 몇 가지와, 그 값들이 서로를 담는 법"으로 바꾼다. + - 상태는 타입 있는 값 하나다. + - 값은 수(정수, 실수, bool), 바이트(text는 UTF-8인 바이트), 레코드, 갈래, 리스트(키가 있으면 맵)다. +- **계산.** 함수(재귀 포함)와 접기다. 끝남은 문법이 아니라 예산이 보증한다. 이더리움의 가스와 같은 생각이다. 가스가 다하면 그 + 호출의 상태 변경이 모두 되돌아가는데, 이것이 026의 원자성과 같다. +- **빠름.** 뜻이 아니라 구현에서 온다. 열로 담기, B+트리, 묶음 실행, 같은 답일 때만 차례 바꾸기가 그 수단이다. +- **단계.** 다섯이다. + - 1단계(바이트, 비트, 수의 리스트)로 SHA-256을 쓴다. + - 2단계(중첩, 갈래, 재귀, 글자)로 JSON을 쓴다. + - 3단계에서 중첩된 상태를 저장한다. + - 4단계에서 패턴을 모은다. + - 5단계에서 수의 모델을 정한다. +- **근거.** + - 140의 탐침 + - 지금의 구현: 값의 칸 `Slot`, 열로 담은 B+트리 `PureList`, aup의 타입 여덟 + - 선행 기술: 아래 "선행" 절 +- **다음 결정.** 1단계를 만든다. + +## 핵 + +### 값 + +| 값 | 뜻 | 지금 | 바뀌는 것 | +|---|---|---|---| +| `bool` | 참, 거짓 | 같음 | — | +| `i64` | 정확한 정수, −2^63 … 2^63−1, 넘치면 `overflow` | 같음 | 비트 연산(1단계). 이름과 리터럴의 기본은 5단계 | +| `number` | 유한한 binary64 | 같음 | 5단계(수의 모델) | +| `bytes` | 바이트의 열, 불변 | 길이와 text 변환뿐 | 자리로 읽기, 자르기, 잇기, 짓기(1단계) | +| `text` | UTF-8로 검사한 바이트 | 같은 표현 | 글자로 읽기는 그 위의 견해(2단계) | +| 레코드 | 이름 있는 필드의 곱 | 필드는 수, text, bool, i64 | 필드에 아무 값(2단계) | +| 갈래 | 태그 붙은 경우의 합 | 없음 | 새로. `match`가 모든 경우를 다룬다(2단계) | +| `list of T [by k]` | 차례 있는 열. `by k`면 k의 차례이고 키마다 하나다 | 레코드만, 상태와 이벤트와 메시지의 행으로 따로 | 아무 T(1단계 수, 2단계 전부). 키 없는 리스트의 키는 자리다 | +| 앵커 | 편집을 따라가는 위치 | 커서와 인덱스(상태의 종류 둘) | 하나로(4단계) | + +### 계산 + +- **그대로 두는 것.** 식, `let`, `if`, `for`(세기와 걷기), `break`. +- **함수.** + - 자신을 부를 수 있다(2단계). + - 인라인은 구현의 선택이다. 작은 fn은 지금처럼 인라인하고, 재귀하는 fn은 부른다. + - 매개변수에 타입을 적지 않는 것은 그대로다. 부르는 타입마다 한 벌을 만든다(단형화). +- **`match`.** 갈래의 모든 경우를 다룬다. 빠진 경우는 컴파일 오류다(2단계). +- **끝을 모르는 반복.** `while`을 둔다(2단계). 세기의 상한은 뜻에서 필요하지 않다. 묶음 실행이 시작할 때의 횟수를 쓰는 것은 구현이 + 상한을 알아볼 수 있을 때다. +- **접기.** 뜻은 차례대로의 왼쪽 접기다. 구현은 같은 답과 같은 실패를 낼 때만 차례를 바꾼다. 묶음 실행기의 차례 없는 모으기가 이미 + 이 규칙을 따른다. +- **비트 연산.** 정수를 무한한 2의 보수로 보고 정한다. 파이썬의 정수와 같은 뜻이다. + - `&`, `|`, `^`, `~`: 비트마다의 연산이다. + - `x << n`은 x·2^n이다. i64를 넘으면 `overflow`다. + - `x >> n`은 floor(x / 2^n)이다. + - n은 0부터 63까지다. 밖이면 `limit`이다. + - 어느 기계에서나 같은 뜻이고, C의 정의되지 않은 동작이 없다. +- **끝남과 결정성.** + - 모든 걸음은 실행량을 쓰고, 부름의 깊이는 프레임의 바이트로 메모리 몫에 센다. 넘으면 `work`나 `memory`로 끝나고, 이벤트는 + 통째로 되돌아간다. + - 결정성의 단위는 모듈이다. 같은 모듈과 같은 이벤트열이면 실패의 자리까지 같다. + - 소스는 컴파일러의 판에 묶인다. EVM의 바이트코드와 가스표가 그렇다. 이것이 026의 의심 6(예산의 단위)에 대한 답이다. + +### 효과 + +026 그대로다. 상태에 쓰기, 보내기, 답하기, `require`. + +### 상태는 값 하나 + +- 앱의 상태는 레코드 값 하나다. 선언한 상태들이 그 필드이고, 수명(저장, transient)은 필드의 성질이다. +- 저장은 바뀐 부분만 쓴다. 지금 리스트가 이미지와 로그로 하는 그대로다. 중첩된 리스트도 제 이미지와 로그를 가진다(경로로 이름을 + 붙인다, 3단계). +- 값은 불변이라 스냅숏은 나누기만 한다. 지금 리스트의 공유 사본이 그 구현이다. + +### 뜻과 표현 + +| 뜻 | 표현(구현이 고른다) | +|---|---| +| 레코드의 리스트 | 열로 담은 B+트리, 값만큼 좁힌 열, HASHED(지금) | +| 수의 리스트 | 필드 하나인 레코드의 리스트(1단계), 나중에 배열 | +| 바이트 짓기(`out = out + byte(x)`의 반복) | 왼쪽이 이벤트 공간의 끝에 있으면 제자리 덧붙이기 | +| 표 보기 | 물을 때 칸 계산 | +| 접기 | 묶음 실행, 차례 없는 모으기(같은 답일 때만) | +| 작은 fn | 인라인 | + +## 026의 의심에 대한 답 + +| 의심 | 답 | 단계 | +|---|---|---| +| 1. 입력의 종류 | 입력은 메시지 하나다. 키, 글자, 틱은 표면과 호스트가 만드는 메시지다 | 4 | +| 2. 보기의 종류 | 보기는 아무 값을 낸다 | 4 | +| 3. 커서와 인덱스 | 앵커 하나로 모은다. 다만 키가 있는 리스트에서 인덱스는 키와 같을 수 있다. 4단계에서 앵커가 text에만 필요한지 본다 | 4 | +| 4. 키별 문서 | 없앤다. 키 있는 리스트가 한다 | 4 | +| 5. 수의 모델 | 정할 것: 정수 리터럴의 기본, `/`와 `//`, 돈을 위한 십진수 | 5 | +| 6. 예산의 단위 | 모듈로 정한다(위) | 이 문서 | +| 7. 고정 한도 | 뜻에는 예산(실행량, 메모리)과 모듈의 크기만 남긴다. 상태 32, 입력 32, 레코드 16, 필드 16, 컬렉션 1, 중첩 8, aup 소스 32 KB는 뺀다 | 4 | +| 8. 교체의 세부 | 수의 모델 뒤에 다시 본다 | 5 | +| 9. 메시지의 행 | 메시지의 필드가 아무 값을 가지면 따로 둘 까닭이 없다 | 2 | + +## 단계 + +### 1단계: 바이트, 비트, 수의 리스트 (SHA-256) + +- **Pure.** + - 바이트를 자리로 읽기(`b[i]` → i64, 밖이면 `limit`), 자르기, 잇기, 한 바이트로 짓기 + - i64의 비트 연산 여섯 + - 이벤트의 지역 칸이 바이트를 담는다 +- **aup.** + - `b[i]`, `b[a .. c]`, `b + c`, `byte(n)` + - i64의 `& | ^ ~ << >>`, 16진 리터럴 `0x…` + - `list of i64`와 `list of number`(안에서는 필드 하나인 레코드), 리스트 리터럴 `[ … ]` + - 키 없는 리스트를 자리로 읽고 쓰기 `xs[i]` +- **막대.** + - aup로 쓴 SHA-256이 NIST의 짧은 메시지 벡터와 긴 메시지 벡터를 모두 지난다(Pure의 검사 안에서). + - 줄 수가 같은 일을 하는 파이썬 참조 이하다. + - C 대비 시간은 재고 기록하되 막대는 두지 않는다. 바이트와 비트의 일은 실행기로 돈다. 빠르게 하는 것은 핵이 선 뒤다. + - 실행기만의 길에서 다섯 일(041)의 명령 수가 ±0.1%, 은행 질의의 명령 수가 ±1% 안이다. 새 명령은 기존 길을 바꾸지 않는다. +- **검증.** 새 명령마다 경계(밖의 자리, 음수 시프트, 넘침)를 단위 시험으로 본다. 무작위 입력의 다이제스트는 파이썬 `hashlib`와 같아야 + 한다. + +### 2단계: 중첩, 갈래, 재귀, 글자 (JSON) + +- 레코드의 필드와 리스트의 원소가 아무 값을 가진다. +- 갈래와 `match`를 둔다. +- 재귀하는 fn과 `while`을 둔다. Pure에는 부르기와 돌아가기, 함수마다의 검증이 생긴다. +- `for c in t`로 글자(코드 포인트)를 읽는다. +- 메시지의 필드가 아무 값을 가진다. JSON의 배열과 객체가 곧 리스트와 레코드다. +- 먼저 이벤트와 보기의 값(메모리 안)에서 한다. 상태는 3단계다. +- **막대.** + - JSON 파서가 JSONTestSuite의 `y_`를 모두 받고 `n_`을 모두 거절한다. `i_`는 정한 쪽을 적는다. + - 줄 수가 파이썬 참조 이하다. + - 시간을 기록한다. + - TPC-C와 은행 질의가 그대로다(026의 중단 기준). + +### 3단계: 중첩된 상태의 저장 + +- 중첩된 리스트의 이미지와 로그를 경로로 이름 붙인다. +- 스냅숏의 나누기와 교체의 이름 잇기가 깊이에서도 그대로 성립해야 한다. +- **막대.** 메모리 앱과 수시로 재시작하는 저장 앱이 매 단계 비트까지 같다(지금의 대조를 중첩으로 넓힌다). 커밋의 모든 단계에서 + 죽여도 전부 아니면 없음이다. + +### 4단계: 패턴 모으기 + +- 앵커, 메시지 하나인 입력, 아무 값인 보기를 둔다. +- 키별 문서와 고정 한도를 없애고, 메시지의 행을 중첩으로 옮긴다. +- **막대.** + - Pure, aup, Vega의 모든 검사를 옮긴 뒤 초록이다. + - 명령과 상태 종류의 수, 코어의 줄 수가 줄었다(세어 적는다). + - TPC-C와 은행 질의가 그대로다. + +### 5단계: 수의 모델 + +- 정수 리터럴의 기본, `/`와 `//`, 돈의 십진수, 묶음 실행기의 2^53 검사를 정한다. +- **막대.** TPC-C가 SQLite와 행마다 같은 상태를 남기는 것이 그대로다. + +**순서의 까닭.** +- 1과 2가 묶음의 명세 대부분을 연다. 가장 값이 크다. +- 3은 중첩을 상태까지 넓힌다. +- 4는 쌓인 것을 줄인다. 2 뒤에 해야 모을 곳(중첩, 갈래)이 생긴다. +- 5는 모든 앱의 수를 건드리므로 마지막이다. + +## 선행 + +- **EVM의 가스.** 끝없는 반복과 재귀를 허락하고, 끝남과 결정성을 가스로 얻는다. 가스가 다하면 그 호출의 상태 변경이 되돌아간다. 가스는 + 명령마다 명세의 표로 정한다. 모든 노드가 같은 가스를 센다. Pure의 예산, 원자성, "모듈이 단위"와 같은 꼴이다. +- **파이썬의 정수 비트 연산.** 무한한 2의 보수 위의 뜻이다. Pure는 i64 안에서 같은 뜻을 쓰고, 넘으면 실패한다. +- **Elm.** 모델, 업데이트, 뷰와 레코드, 커스텀 타입(갈래)이다. aup 앱의 모양과 같다. 영속, 트랜잭션, 전달은 없다. +- **영속 자료 구조**(Clojure의 벡터와 맵). 구조를 나눠 스냅숏을 싸게 한다. Pure의 공유 리스트 사본이 그 한 예다(B+트리). + +## 의심 (이 설계 안의) + +- **바이트와 text를 따로 둘 것인가?** 표현은 하나이고 타입만 둘이다. 불변식(UTF-8)이 보기와 경계에 필요해서 타입은 남긴다. +- **앵커가 필요한가?** 항목에 키가 있으면 인덱스는 키다. text의 커서는 편집에 따라 옮겨야 하므로 남는다. 4단계에서 정한다. +- **`number`(binary64)는 앱 런타임에 필요한가?** 물리와 그래픽에는 필요하다. 돈에는 맞지 않는다(5단계). +- **세는 `for`가 필요한가?** 뜻으로는 `while`과 예산이면 된다. 다만 세기는 읽기 쉽고, 상한을 구현에 알려 준다. 남긴다. + +## 1단계의 착수 기준 + +- **바꿀 결정.** 바이트, 비트, 수의 리스트로 SHA-256을 얇게 쓸 수 있으면 받아들이고, 2단계로 간다. +- **남은 질문.** + - 새 명령이 실행기, 묶음 실행기, JIT의 기존 길을 바꾸지 않는가? + - 한 블록에 드는 명령 수와 시간은 얼마인가? +- **최소 확인.** aup로 쓴 SHA-256, NIST 벡터, 파이썬 참조의 줄 수, C 대비 시간, 다섯 일과 은행 질의의 명령 수. +- **중단 기준.** 기존 일의 명령 수가 막대를 넘으면 멈추고, 새 명령이 기존 길을 건드린 곳을 찾는다. SHA-256이 파이썬보다 길면, 무엇이 + 길게 했는지 적고 그것을 1단계에서 고칠지 정한다. |
