diff options
| author | eunhhu <[email protected]> | 2026-10-19 00:40:55 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-19 00:40:55 +0100 |
| commit | e9f53dc8a56ddca0855213da4355f39a69306c07 (patch) | |
| tree | 81f76bc1dfabcc63f928523c945c7d64eea0de88 /docs | |
| parent | 3cc6bc3d8a1d8827519decbf7e084e89110c93f9 (diff) | |
| download | pure-e9f53dc8a56ddca0855213da4355f39a69306c07.tar.gz pure-e9f53dc8a56ddca0855213da4355f39a69306c07.zip | |
027's 4f-4: loops nested to any depth: the load counts a module's deepest nesting (nesting), a run keeping PURE_MODULE_NESTING (8) on its stack as before and a module nesting deeper running in the executor that calls, its loops in its app's room (PureApp.deep, grown to it), so run()'s hot path is as it was; the JIT compiles modules nesting 8 at most; a function's nesting counted without a cap (u32), its frame sized to it; unit test: 40 loops nested, run to their end (2^20 rounds) and stopped by the work budget (2^40), 8 still on the stack; counts: b42 against b41 with batches BFS -0.12%, without BFS +0.09%, the rest within 0.001%; the bank's queries (s41 and s42 in turns, six each) in_credit +1.04%, per_branch +0.60%, ranks +0.36%, the rest within 0.01% (their spread: the bank has no functions, so none runs the changed executor, and s42's in_credit is within s41's own earlier six); 008 and 027
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/design/008-module-format.md | 4 | ||||
| -rw-r--r-- | docs/design/027-computation-core.md | 14 |
2 files changed, 16 insertions, 2 deletions
diff --git a/docs/design/008-module-format.md b/docs/design/008-module-format.md index fa59692..dde292e 100644 --- a/docs/design/008-module-format.md +++ b/docs/design/008-module-format.md @@ -153,7 +153,7 @@ v7은 027의 4단계(패턴 모으기)의 판이다. 4b로 **키별 문서**를 | 60 | MOD | n n → n | 나눗셈을 내림한 나머지. 결과는 나누는 수의 부호를 따른다(0도). 0으로 나누면 `divide` | | 61 | SEND | f… → | 출력 `인자`의 필드 값을 필드 순서대로 받아(u32·수는 n, bool은 bool, 바이트는 b, text는 t) 메시지 페이로드(접두부와 가변 필드)로 만들고 이벤트의 일부로 보낸다. u32 필드의 값이 0–2³²−1의 정수가 아니면 `limit`. 핸들러 전용 | | 62 | OUTER_ROW | → i | 열 안의 집계 블록에서 그 열의 행(집계의 항목은 ROW). 걷기 안의 집계에서는 걷는 항목 | -| 63 | EACH | | 걷기. `인자`의 비트 8–15는 리스트 상태, 16–31은 뒤따르는 블록의 길이 L. 그 L개 명령이 리스트가 시작할 때 가진 항목마다 차례로 핸들러의 코드로 돈다(`ROW`가 항목). 블록은 상태, 그 리스트의 항목(필드 바꾸기, 지우기), 다른 리스트를 바꿀 수 있지만 걷는 리스트에 넣을 수는 없다. 걷는 항목이나 그 앞의 항목을 지우면 걷기가 따라가 다음 항목을 건너뛰지 않는다. 걷기와 LOOP는 서로 안에 8겹까지 둔다. 안쪽의 코드는 바깥 걷기가 도는 리스트에 넣거나 지우지 못한다. 핸들러 전용 | +| 63 | EACH | | 걷기. `인자`의 비트 8–15는 리스트 상태, 16–31은 뒤따르는 블록의 길이 L. 그 L개 명령이 리스트가 시작할 때 가진 항목마다 차례로 핸들러의 코드로 돈다(`ROW`가 항목). 블록은 상태, 그 리스트의 항목(필드 바꾸기, 지우기), 다른 리스트를 바꿀 수 있지만 걷는 리스트에 넣을 수는 없다. 걷는 항목이나 그 앞의 항목을 지우면 걷기가 따라가 다음 항목을 건너뛰지 않는다. 걷기와 LOOP는 서로 안에 몇 겹이든 둔다(027의 4f-4: 8겹보다 깊은 모듈은 부르는 실행기가 앱의 칸으로 돈다). 안쪽의 코드는 바깥 걷기가 도는 리스트에 넣거나 지우지 못한다. 핸들러 전용 | | 64 | LOCAL_LOAD | → n, bool 또는 i | 이벤트의 지역 칸. `인자`의 비트 0–7은 칸(64개), 8–15는 담는 것(0 수, 1 인덱스, 2 bool), 16–31은 인덱스의 리스트. 칸은 이벤트가 시작할 때 0이고 저장되지 않는다. 핸들러와 그 안의 걷기, 그 안의 집계에서 읽는다 | | 65 | LOCAL_STORE | n, bool, i64 또는 i → | 그 칸에 넣는다. 핸들러와 그 안의 걷기에서. 담는 것 3은 i64. 한 핸들러는 한 칸을 한 가지(수, bool, i64, 또는 한 리스트의 인덱스)로만 쓴다 | | 66–68 | I64_ADD I64_SUB I64_MUL | i64 i64 → i64 | 범위를 넘으면 `overflow` | @@ -227,7 +227,7 @@ bool은 실행 중에 수의 칸에 든 0이나 1이고, i64는 같은 8바이� 걷는 리스트에 넣지(LIST_APPEND·LIST_INSERT) 못하며, 응답(REPLY)하지 않는다(응답은 이벤트에 하나다). 안의 집계는 걷는 항목을 OUTER_ROW로 읽는다. 둘레의 블록은 EACH와 그 블록을 명령 하나로 보고, 앞의 분기가 블록 안으로 들어오지 못한다. 걷는 리스트는 줄기만 하므로 한 걷기는 시작할 때의 항목 수 × 블록 길이를 넘지 않는다. -- 반복(EACH와 LOOP, [018](018-lifetimes-and-computation.md))은 서로 안에 8겹까지 둔다. 검증기는 둘레의 걷기들이 도는 리스트의 +- 반복(EACH와 LOOP, [018](018-lifetimes-and-computation.md))은 서로 안에 몇 겹이든 둔다(4f-4 전에는 8겹). 검증기는 둘레의 걷기들이 도는 리스트의 집합을 들고 내려가, 안의 코드가 그 가운데 어느 것에 넣는 것과, 가장 안쪽 걷기의 것이 아닌 것에서 지우는 것을 거절한다. 그래서 실행기는 가장 안쪽 걷기의 자리만 고친다. LOOP의 블록은 둘레 블록과 같은 자리(핸들러나 걷기)의 코드로 검증하고 둘레는 LOOP와 그 블록을 명령 하나로 본다. LOOP는 수 둘이나 i64 둘을 꺼내고 그 칸을 그 타입의 지역 칸으로 쓴다(한 핸들러에서 한 칸은 한 diff --git a/docs/design/027-computation-core.md b/docs/design/027-computation-core.md index 06bfe02..687a51f 100644 --- a/docs/design/027-computation-core.md +++ b/docs/design/027-computation-core.md @@ -479,6 +479,20 @@ - 명령 수(b41 대 b40): 묶음과 함께 BFS +0.12%, 실행기만 BFS −0.09%, 나머지 ±0.001% 안이다. 은행 질의(s40과 s41을 한 번에 번갈아 여섯 번)는 in_credit +0.09%, per_branch +0.05%, ranks +0.03%, 나머지 ±0.01% 안이다. 처음 세 번의 in_credit +1.16%는 그 질의의 흔들림이었다(같은 빌드의 여섯 번 사이 2.75%). + - **4f-4 만듦(2026-10-19).** + - Pure: 반복은 몇 겹이든 둔다(검증기의 8겹 거절이 없어졌다). 로드가 모듈의 가장 깊은 겹을 센다(`nesting`). 8겹까지는 전처럼 실행의 + 스택에 겹 칸을 두고, 더 깊은 모듈은 부르는 실행기(runner 2)가 앱의 칸(`PureApp.deep`, 그 겹만큼 자람)으로 돈다. 그래서 `run()`의 + 뜨거운 길은 그대로다. JIT은 8겹까지인 모듈만 컴파일한다. 함수의 겹(호출 프레임의 크기)도 막지 않고 센다(u32). + - aup: 소스의 32 KB가 없어졌다(파일과 표준 입력을 크기대로 읽는다). 컴파일러의 표는 고정 배열 그대로이되 Pure의 너비에 맞춰 + 올렸다(상태 4,096, 입력 1,024, 보기 4,096, 핸들러 4,096, 레코드 1,024, 레코드 필드 16,384): 컴파일러는 15 MB를 calloc으로 + 잡고, 쓰지 않는 칸은 메모리에 올라오지 않는다. 진단은 그 수를 말한다. 출력은 255까지(Pure의 저장 너비), 걷기와 집계가 도는 + 리스트는 상태 번호 256 아래(그 인자의 바이트)라고 aup가 미리 말한다. 표를 정말 모듈에 맞춰 자라게 하는 것은 컴파일러의 표 + 전체를 바꾸는 일이라 남겼다. + - 시험: 단위 시험이 40겹의 반복을 로드해 끝까지(2^20번) 돌리고, 2^40번은 일의 예산에서 멈추게 한다(8겹은 스택에서 돈다). aup의 + 시험이 상태 301, 입력 40, 보기 70, 레코드 20인 48 KB 소스를 짓고 pure-run으로 마지막 것들까지 돌린다. + - 명령 수(b42 대 b41): 묶음과 함께 BFS −0.12%, 실행기만 BFS +0.09%, 나머지 ±0.001% 안이다. 은행 질의(s41과 s42를 한 번에 번갈아 + 여섯 번)는 in_credit +1.04%, per_branch +0.60%, ranks +0.36%, 나머지 ±0.01% 안이다. 그 셋은 흔들림이다: 은행 앱에는 함수가 없어 + 바뀐 길(부르는 실행기)을 지나지 않고, s42의 in_credit 여섯(3.51M–3.55M)은 같은 s41 빌드가 앞서 낸 여섯(3.49M–3.59M) 안에 있다. - **차례의 까닭.** - 4a는 작고, 3단계의 끝을 맺는다. - 4b는 가장 많이 지운다. 키 있는 메시지와 기준 리비전이 사라지면 4d가 단순해진다. |
