aboutsummaryrefslogtreecommitdiffstats
path: root/docs/design
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-18 17:23:37 +0100
committereunhhu <[email protected]>2026-10-18 17:23:37 +0100
commitd8e297452d8e0896d4733e09b70fdc3e6ce08a55 (patch)
treeb7502c598faf2fe54f49dc7e40ebfe54f94bb910 /docs/design
parent241016b0fc3139414089619f0ef8cb7237722c6c (diff)
downloadpure-d8e297452d8e0896d4733e09b70fdc3e6ce08a55.tar.gz
pure-d8e297452d8e0896d4733e09b70fdc3e6ce08a55.zip
Module format and executor: 027's stage 3, nested stored state: a stored or a transient list's records may hold lists (a message's rows not, nor as a key); such a list's cell holds the value in its items' stored form (PURE_CELL_LIST, held as bytes are: each item's fields in order, 8 bytes a number, bool or i64, a u32le length and bytes a text or a list, a list's in this form again), read into one of the event's lists by ITEM_GET (counted in the event's room) and written from one by LIST_APPEND, LIST_INSERT and ITEM_SET, APPEND_IN reading, appending and writing back (undone with the event): images, the log, undoing, readers' shares and commits hold it as a text's bytes, so nothing new is stored or recovered; a list image's header names its record graph (a list field's items' record by its number, the graph's other records after the fields: a record holds itself through a list), and starting or replacing moves the items of the lists in fields by field name down the graph (PureLayout, pure_list_migrate); an event's lists keep the event's lists' numbers; a view lets go the lists a view before it read in; no FIND joined to a list field's read; pure-run shows a kept list's lists; unit tests (an event changing a number and a stored item's list, the process dying at the tree's four stages and the log's two, failed commits changing nothing; a replacement moving a stored and a transient list's lists, their items' record gaining a field and the board's fields changing places; under ASan and UBSan too)
Diffstat (limited to 'docs/design')
-rw-r--r--docs/design/008-module-format.md16
1 files changed, 13 insertions, 3 deletions
diff --git a/docs/design/008-module-format.md b/docs/design/008-module-format.md
index 84c8e18..a23f140 100644
--- a/docs/design/008-module-format.md
+++ b/docs/design/008-module-format.md
@@ -25,13 +25,20 @@ v6에는 뒤에 **i64**가 더해졌다([016](016-bool-and-i64.md)의 2단계):
넷, 90–93). 2a로 **바이트 자르기, 한 바이트, 이름으로 담은 바이트와 text**(94–97), CONCAT의 바이트, NUM_TEXT의 형식이 더해졌다. 2b로
**레코드 안의 리스트**(레코드 필드의 타입 4, 98–100), 레지스터(리스트 상태의 플래그 512), 경로 이름의 레코드 필드, **수 읽기**(101)가
더해졌다. 2c로 **함수**(CALL·RETURN, 102–103, 머리말의 함수 수와 함수 표)와 **글자**(CHAR_AT·CHAR, 104–105)가 더해졌다. 판은
-그대로다(0이던 머리말 자리에 함수 수, 함수가 없는 모듈은 배치가 같다).
+그대로다(0이던 머리말 자리에 함수 수, 함수가 없는 모듈은 배치가 같다). 3단계로 **저장과 transient 리스트의 레코드도 리스트를 담는다**
+(아래 "레코드 안의 리스트"). 모듈의 형식은 바뀌지 않고, 리스트의 이미지 머리가 레코드 그래프를 적는다.
**레코드 안의 리스트**(027의 2b).
- 레코드 필드의 타입 4(LIST)는 항목들의 레코드를 기본값 자리(i64)에 둔다.
- 칸의 값은 이벤트가 만든 리스트의 번호(0은 빈 리스트)다. 정수처럼 옮겨지고 ITEM_GET으로 읽힌다. 스택의 타입은 리스트이고, 그
레코드를 가진다.
-- 그런 레코드는 이벤트의 리스트(let의 것)에만 둔다. 저장 상태, transient, 메시지의 행은 받지 않고, 리스트 필드는 키가 되지 않는다.
+- 3단계부터 저장 상태와 transient의 리스트도 그런 레코드를 받는다. 메시지의 행은 받지 않고, 리스트 필드는 키가 되지 않는다.
+- 이벤트를 넘어 사는 리스트(저장, transient)의 칸은 리스트 값을 그 항목들의 저장 형태로 담는다(칸의 종류 5, 바이트처럼). 항목마다
+ 필드의 차례로, 수·bool·i64는 8바이트 little-endian, text와 리스트는 u32le 길이와 바이트(리스트는 다시 이 형태)다.
+ - ITEM_GET은 그것을 이벤트의 리스트 하나로 읽어 그 번호를 놓는다(읽은 바이트를 이벤트의 몫에 센다).
+ - LIST_APPEND·LIST_INSERT·ITEM_SET은 이벤트의 리스트를 그 형태로 써 넣는다. APPEND_IN은 읽고, 덧붙이고, 다시 쓴다.
+ - 그래서 저장(이미지와 로그), 되돌리기, 읽는 쪽과의 나눔은 text의 바이트를 다루듯 그것을 다룬다. 바꿀 때마다 그 리스트 값
+ 전체를 쓴다(비용은 바뀐 것이 아니라 그 값의 크기에 비례한다). 구조를 나누는 표현은 뜻을 바꾸지 않는 구현의 선택으로 남는다.
- 값으로서의 리스트는 나눠 가질 수 있다. 다른 칸에 담으면 나눠 가지고, 나눠 가지거나 레지스터에 묶인 리스트는 바뀌기 전에
복사된다.
- 이벤트(그리고 보기의 본문)가 시작할 때 그 리스트들은 모두 사라진다. 담은 바이트는 이벤트의 몫에 센다.
@@ -376,7 +383,9 @@ text·리스트가 남을 때만 위치를 유지한다.
| 수·bool·커서·인덱스 | `values`: `PVS1`, 상태마다 종류·이름·binary64(bool은 0이나 1). 바뀐 이벤트에서만 다시 쓴다 |
- **리스트: 이미지와 로그.** 리스트는 저장소 디렉터리의 두 곳에 산다. **이미지** `image-이름`(파일 하나)은
- `PLI1`, 레코드 필드 수, 필드마다 종류(0 수, 1 text, 3 bool)·이름, 그것이 담은 저장의 번호(u64), 항목(수와 bool은 binary64, text는 u32 길이와
+ `PLI1`, 레코드 필드 수, 필드마다 종류(0 수, 1 text, 3 bool, 4 i64, 5 리스트)·이름(리스트는 그 뒤에 u8: 항목들의 레코드 번호), 리스트
+ 필드가 있으면 레코드 그래프의 나머지(u8 수, 레코드마다 u8 필드 수와 필드들, 번호는 그래프에서의 자리: 0이 이 리스트의 레코드,
+ 나머지는 리스트 필드가 처음 만나는 차례), 그것이 담은 저장의 번호(u64), 항목(수와 bool은 binary64, text와 리스트는 u32 길이와
바이트)이고, 통째로 옆에 써서 동기화한 뒤 이름을 바꿔 끼운다(파일 전체의 다이제스트로 잘림·손상을 거부).
**로그**(`log-0`, `log-1`, ... 구간, `core/log.h`)는 리스트를 바꾼 저장마다 항목 하나다. 항목은 저장 번호, 앞 항목의
번호와 다이제스트, 트리도 커밋했는지, 페이로드(바뀐 리스트마다 이름과 변경 기록, 모두 그 리스트 이미지의 필드로)다.
@@ -399,6 +408,7 @@ text·리스트가 남을 때만 위치를 유지한다.
- **시작.** 저장된 상태를 이름과 종류로 불러온다. 리스트는 이미지를 읽고 로그에서 그 이미지가 담은 저장 뒤의 변경을
차례로 다시 한다. 없는 상태는 초기값으로 시작한다. 레코드가 달라진 리스트는
이름·종류가 같은 필드를 옮기고(수와 bool은 교체처럼 서로 옮긴다) 새 필드는 기본값을 쓴 뒤 다시 저장한다(교체와 같은 규칙, 마이그레이션 스크립트 없음).
+ 리스트 필드의 항목도 그래프의 레코드를 따라 같은 규칙으로 옮겨진다(3단계).
커서가 text 범위나 글자 경계를 벗어나거나, 인덱스가 리스트 밖이면 0이 된다. 깨진 리스트·text(형식 오류, UTF-8
아님)는 시작을 `store_error`로 멈춘다. 조용히 버리지 않는다.
- **저장은 묶음이다.** 저장 한 번이 마지막 저장 이후 메시지가 고친 문서들과 바뀐 상태 문서들을 저장소의