diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/design/008-module-format.md | 11 | ||||
| -rw-r--r-- | docs/design/018-lifetimes-and-computation.md | 7 |
2 files changed, 13 insertions, 5 deletions
diff --git a/docs/design/008-module-format.md b/docs/design/008-module-format.md index de5849a..e9fe3ca 100644 --- a/docs/design/008-module-format.md +++ b/docs/design/008-module-format.md @@ -33,7 +33,7 @@ v6에는 뒤에 **i64**가 더해졌다([016](016-bool-and-i64.md)의 2단계): | 16 | u32 명령 수, u32 문자열 바이트 수 | | 24 | u16 필드, u16 컬렉션, u16 상수, u16 레코드 | | 32 | u32 상수 블롭 바이트 수, u16 레코드 필드, u16 0 | -| 40 | 상태 × 16 B: u32 이름, u32 타입(0 수, 1 text, 2 커서, 3 리스트, 4 인덱스, 5 bool, 6 i64), 8 B 값: 수와 bool은 f64 초기값(bool은 0이나 1), i64는 초기값(부호 있는 little-endian), text는 u32 초기 상수, 커서는 u32 대상 text 상태와 u32 플래그(1이면 마크: 그 자리에 넣은 글 앞에 남는다), 리스트는 u32 레코드와 u32 키(0이면 없음, 아니면 키 필드 + 1, 256이면 메시지의 행 목록: 이름은 그 필드의 경로 `입력.필드`이고 키가 없다), 인덱스는 u32 대상 리스트 상태 | +| 40 | 상태 × 16 B: u32 이름, u32 타입(비트 0–7: 0 수, 1 text, 2 커서, 3 리스트, 4 인덱스, 5 bool, 6 i64. 비트 8: 저장하지 않는 상태(transient, [018](018-lifetimes-and-computation.md)), 그 위는 0. 메시지의 행 목록은 transient가 아니고, transient text나 리스트를 가리키는 커서와 인덱스는 transient다), 8 B 값: 수와 bool은 f64 초기값(bool은 0이나 1), i64는 초기값(부호 있는 little-endian), text는 u32 초기 상수, 커서는 u32 대상 text 상태와 u32 플래그(1이면 마크: 그 자리에 넣은 글 앞에 남는다), 리스트는 u32 레코드와 u32 키(0이면 없음, 아니면 키 필드 + 1, 256이면 메시지의 행 목록: 이름은 그 필드의 경로 `입력.필드`이고 키가 없다), 인덱스는 u32 대상 리스트 상태 | | | 컬렉션 × 12 B: u32 이름, u32 1(바이트), u32 1(키별) | | | 입력 × 16 B: u32 이름, u8 종류(1 키, 2 메시지, 3 text, 4 타이머, 5 출력: 앱이 보내는 메시지, 모양은 메시지와 같고 핸들러가 없다, 6 인자: 한 보기가 받는 인자, 모양은 메시지와 같고 핸들러가 없으며 이름은 `보기.args`), u8 키별 여부, u16 0, u32 키 이름(키 입력)·주기(타이머, 1 ms–24시간을 ms로)·보기 번호(인자) 또는 0, u16 첫 필드, u16 필드 수 | | | 필드 × 8 B: u32 이름(식별자, 또는 그룹 안의 필드면 점으로 이은 경로 `user.name`), u32 타입(1 u32le, 2 바이트, 3 수(binary64), 4 text, 5 행: 비트 8–23에 그 행이 채우는 행 목록 상태, 6 bool: 1바이트 0이나 1, 7 i64: 8바이트 부호 있는 little-endian). 페이로드는 접두부와 가변 필드의 바이트다. 접두부에는 선언 순서로 고정 필드의 값과 가변 필드(바이트·text)의 u32 길이가 들어가는데, 마지막 가변 필드는 길이 없이 나머지를 차지한다. 가변 필드의 바이트는 접두부 뒤에 선언 순서로 이어진다(가변 필드가 하나면 예전의 "바이트 꼬리"와 같다) | @@ -275,7 +275,10 @@ text·리스트가 남을 때만 위치를 유지한다. ## 상태 영속 데이터 호스트가 상태를 맡으면(`PureData`의 `state`·`save`, 트리 저장소에서는 `pure_tree_data`) 앱의 모든 상태가 -저장소에 산다. 앱에 저장 코드가 없다. 선언한 상태가 곧 영속 상태다. +저장소에 산다. 앱에 저장 코드가 없다. 선언한 상태가 곧 영속 상태다. 다만 transient 상태(타입 워드의 비트 8, 018)는 앱이 +도는 동안만 있다: 저장층은 그것을 열지도 쓰지도 않고(값 묶음, text 초안, 리스트의 이미지와 로그 모두), 시작할 때마다 초기값이다. +실패한 이벤트는 그것도 되돌린다. 그것만 바꾼 이벤트의 저장은 아무것도 쓰지 않는다. 스냅숏은 transient text를 복사한다(저장소에 +없으니 매핑을 나눌 수 없다). | 상태 | 저장 형태 (런타임 이름공간, 문서 키와 겹치지 않음) | |---|---| @@ -323,7 +326,9 @@ text·리스트가 남을 때만 위치를 유지한다. Pi 5의 SD(ext4)에서 이벤트 600개: 이벤트마다 저장 6,282 ms(10.47 ms/이벤트), 8개씩 973 ms, 64개씩 341 ms, 한 번에 194 ms. `pure-run --store 경로 --batch N`으로 잰다. - **교체.** 모듈을 바꾸면 새 상태는 저장된 값이 있으면 그것으로 시작하고, 버린 상태의 저장본은 그대로 남는다. - 새 모듈의 상태는 다음 이벤트나 저장에서 공개된다. + 새 모듈의 상태는 다음 이벤트나 저장에서 공개된다. 이어지는 상태가 transient가 되면 저장소에는 버린 상태처럼 남는다 + (로그에만 있던 리스트의 변경은 이미지로 쓴다). transient였던 상태가 저장되는 상태가 되면 리스트는 교체 때 이미지를 쓰고, + 수와 text는 다음 저장에서 쓰인다. - **스냅숏(다른 스레드의 읽기).** 저장 직후 `pure_app_snapshot`은 저장된 상태의 읽기 전용 스냅숏을 만든다. 수·커서· 인덱스는 복사하고, text 상태는 저장소 매핑의 그 버전을 가리키는 얼린 draft(`pure_draft_freeze`, 복사 없음)로, 리스트는 항목을 공유하는 사본(항목 포인터 배열만 복사, 바뀌지 않은 리스트는 앞 스냅숏의 사본)으로 둔다. 공유된 항목은 diff --git a/docs/design/018-lifetimes-and-computation.md b/docs/design/018-lifetimes-and-computation.md index 901ab08..fab6d96 100644 --- a/docs/design/018-lifetimes-and-computation.md +++ b/docs/design/018-lifetimes-and-computation.md @@ -1,6 +1,6 @@ # 018 — 상태의 수명과 메모리 안의 계산 -작성일: 2026-10-04. 상태: 설계와 착수 기준(구현 전). +작성일: 2026-10-04. 상태: 설계와 착수 기준. 1단계(transient) 구현, 검사로 고정했다. [외부 리뷰 005](../outside-feedback/feedback-005.md)의 (1) "순수 인메모리 연산 및 알고리즘의 단절"과, 상태의 영속성과 상태성을 aup 안에서 정할 수단이 필요하다는 요청에서 시작한다. @@ -81,7 +81,10 @@ view distance(from: u32, to: u32) = { # 보기의 본문(3단계): 스냅숏� (위의 `picked`). - 모듈을 바꿀 때 저장되던 상태가 transient가 되면 그 값은 메모리에서 이어지고, 저장소의 옛 값은 모듈이 버린 상태의 값처럼 남는다(지금도 버린 상태는 지우지 않는다). 다시 저장되는 상태가 되면 그때 시작하는 앱은 저장소의 그 값을 받는다(버렸던 - 상태를 다시 들인 것과 같다). transient였던 것이 저장되는 상태가 되면 바꾸는 그 저장에서 지금의 값이 쓰인다. + 상태를 다시 들인 것과 같다). transient였던 것이 저장되는 상태가 되면 리스트는 바꿀 때 이미지를 쓰고, 수와 text는 바꾼 뒤의 + 첫 저장에서 쓰인다. +- 스냅숏(다른 스레드의 읽기)은 저장되는 text를 저장소의 매핑으로 나누지만 transient text는 저장소에 없으니 스냅숏마다 복사한다. + 큰 text를 transient로 두면 그만큼 든다. - **`let 이름: list of 레코드 [by 필드]`** 는 이벤트의 리스트다. 핸들러(3단계부터는 보기 본문)의 맨 바깥 블록에만 둔다. 저장되는 리스트가 하는 것을 모두 한다(`add`, `append`, `remove`, `[키]`, `has`, `count`, `first`, `last`, `+ n`, 집계, 걷기). 이벤트가 시작할 때 비어 있고, 끝나면(성공이든 실패든) 비워진다. 되돌리기를 기록하지 않는다. |
