From 8d0901ba060165ad0622a3be09b09e3acd4a8899 Mon Sep 17 00:00:00 2001 From: eunhhu Date: Sun, 4 Oct 2026 14:43:11 +0100 Subject: Let a view compute in its body, on a reader's own lists (018 stage 3) --- docs/design/008-module-format.md | 10 ++++++++++ docs/design/018-lifetimes-and-computation.md | 11 ++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'docs/design') diff --git a/docs/design/008-module-format.md b/docs/design/008-module-format.md index e968ecc..63d260a 100644 --- a/docs/design/008-module-format.md +++ b/docs/design/008-module-format.md @@ -170,6 +170,10 @@ bool은 실행 중에 수의 칸에 든 0이나 1이고, i64는 같은 8바이 실행기는 가장 안쪽 걷기의 자리만 고친다. LOOP의 블록은 둘레 블록과 같은 자리(핸들러나 걷기)의 코드로 검증하고 둘레는 LOOP와 그 블록을 명령 하나로 본다. LOOP는 수 둘이나 i64 둘을 꺼내고 그 칸을 그 타입의 지역 칸으로 쓴다(한 핸들러에서 한 칸은 한 가지다). BREAK는 반복 안에서, 스택이 빈 자리에서만 쓰고 블록 끝으로의 점프로 검증한다. 응답은 어느 반복 안에도 없다. +- 보기의 본문(018의 3단계): 표 밖의 보기는 계산할 수 있다. 그 코드는 지역 칸, LOOP, BREAK, EACH를 쓰고 이벤트의 리스트를 + 바꿀 수 있지만(LIST_APPEND·LIST_INSERT·LIST_REMOVE·ITEM_SET) 다른 상태는 바꾸지 못한다(`view changes a state`). 반복의 블록은 + 값을 남기지 않는 보기의 문장으로, 걷기의 블록은 그 항목을 읽는 보기의 문장으로 검증한다. 상태 쓰기, SEND, REPLY, REQUIRE, 문서 + 연산, DT, NOW는 보기 어디에도 없다. 로드할 때 보기마다 계산하는지(지역 칸이나 반복을 쓰는지)와 바꾸는 이벤트의 리스트를 적는다. - 이벤트의 리스트: 플래그 256(PURE_LIST_ROWS)을 가진 리스트는 이벤트가 끝날 때마다 비워지고 저장되지 않으며 되돌리기 기록을 쌓지 않는다. 이름은 경로다. `입력.필드`이면 그 메시지의 행 필드가 채우고(키 없이), `let.이름`이면 코드만 채운다(aup의 `let 이름: list of 레코드`, 키를 둘 수 있다: 플래그 256 + 키 필드 + 1). 저장하지 않는 상태(비트 8)일 수 없다. @@ -200,6 +204,12 @@ bool은 실행 중에 수의 칸에 든 0이나 1이고, i64는 같은 8바이 이벤트 동안 리스트 변경은 되돌리기 기록에 쌓이고, 실패하면 거꾸로 되돌리며 성공하면 지운 항목과 바뀐 text를 해제한다. 항목의 text 필드를 읽으면 이벤트 공간에 복사한다. +**계산하는 보기.** 본문이 있는 보기는 평가마다 지역 칸을 0으로, 바꾸는 이벤트의 리스트를 빈 것으로 시작한다. 스냅숏을 읽는 쪽 +(`pure_app_read`)은 그 리스트를 자기 것으로 가진다(처음 쓸 때 만들고, 읽는 동안 다시 쓴다): 같은 스냅숏을 여러 스레드가 다른 +인자로 동시에 평가해도 서로의 리스트를 보지 않는다. 앱 자신에서 평가하면(이벤트 사이라 비어 있다) 앱의 것을 쓰고 끝나면 비운다. +보기의 실행량은 이벤트와 같게 세고, 이벤트의 리스트가 더하는 것은 이벤트처럼 메모리 예산과 몫에 센다(`pure-serve`는 읽는 쪽에 앱의 +예산을 준다: 넘으면 422 `work`, 503 `memory`). + **세는 반복과 BREAK.** LOOP는 낮음과 높음 사이의 값을 지역 칸에 두며 블록을 돌린다. 블록 안의 BREAK는 그 블록을 거기서 끝내고 반복을 멈춘다(걷기도 같다). 안쪽 반복의 BREAK는 안쪽만 끝낸다. 바깥 걷기의 항목은 aup가 안쪽 반복 앞에서 인덱스 지역 칸에 담아 읽는다. 바깥 걷기의 리스트는 안쪽에서 넣거나 지울 수 없으니 그 칸은 그 항목을 가리킨 채다. diff --git a/docs/design/018-lifetimes-and-computation.md b/docs/design/018-lifetimes-and-computation.md index b27c13a..2ed3e78 100644 --- a/docs/design/018-lifetimes-and-computation.md +++ b/docs/design/018-lifetimes-and-computation.md @@ -2,7 +2,7 @@ 작성일: 2026-10-04. 상태: 설계와 착수 기준. 1단계(transient) 구현, 검사로 고정하고 쟀다 ([117](../research/117-transient-states.md)). 2단계(핸들러의 계산) 구현, 검사로 고정하고 쟀다 -([118](../research/118-computing-in-one-event.md)). +([118](../research/118-computing-in-one-event.md)). 3단계(보기의 본문) 구현, 검사로 고정했다. [외부 리뷰 005](../outside-feedback/feedback-005.md)의 (1) "순수 인메모리 연산 및 알고리즘의 단절"과, 상태의 영속성과 상태성을 aup 안에서 정할 수단이 필요하다는 요청에서 시작한다. @@ -71,10 +71,10 @@ on route { if seen.has(route.to) { reached = reached + 1 } } -view distance(from: u32, to: u32) = { # 보기의 본문(3단계): 스냅숏에서 돈다 +view distance(start: u32, goal: u32) { # 보기의 본문(3단계): 스냅숏에서 돈다 let seen: list of Seen by node ... - if seen.has(to) { seen[to].depth } else { -1 } # 마지막 줄이 보기의 값 + return if seen.has(goal) { seen[goal].depth } else { -1 } # 마지막 줄이 보기의 값 } ``` @@ -129,8 +129,9 @@ view distance(from: u32, to: u32) = { # 보기의 본문(3단계): 스냅숏 ### 보기의 본문 (3단계) -- `view 이름(인자…) = { 문장… 식 }`: 수, bool, i64, text 보기의 값을 블록으로 쓴다. 블록 안에 `let`(값과 리스트), `for`, - `break`, `if`, 걷기를 쓴다. 마지막 줄의 식이 값이다. 표 보기의 열과 필터는 지금처럼 식이다. +- `view 이름(인자…) { 문장… return 식 }`: 수, bool, i64, text 보기의 값을 블록으로 쓴다. 블록 안에 `let`(값과 리스트), `for`, + `break`, `if`, 걷기를 쓴다. 마지막 줄의 `return 식`이 보기의 값이다(처음 적은 `= { 문장… 식 }`은 구현하며 바꿨다: 마지막 줄의 + `if 식 { … } else { … }`가 문장인지 값인지 파서가 그 줄을 읽기 전에 가를 수 없다). 표 보기의 열과 필터는 지금처럼 식이다. - 본문은 상태를 바꾸지 못한다. 바꾸는 것은 지역 칸과 이벤트의 리스트뿐이다(검증기가 보기 안의 다른 효과를 거절한다). - 스냅숏을 읽는 쪽(`pure_app_read`)은 이벤트의 리스트를 자기 것으로 따로 가진다. 그래서 여러 연결 스레드가 같은 보기를 다른 인자로 동시에 평가한다. 소유자에서 평가하는 보기(`pure-run`, Vega의 호스트)는 평가가 끝나면 그 리스트를 비운다. -- cgit v1.2.3