aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/design/008-module-format.md24
-rw-r--r--docs/research/078-app-connections.md7
2 files changed, 27 insertions, 4 deletions
diff --git a/docs/design/008-module-format.md b/docs/design/008-module-format.md
index dd16c90..e67afa8 100644
--- a/docs/design/008-module-format.md
+++ b/docs/design/008-module-format.md
@@ -29,7 +29,7 @@ v5에는 뒤에 집계(FOLD), 걸러진 표, 마크, 그리고 **키 있는 리�
| 32 | u32 상수 블롭 바이트 수, u16 레코드 필드, u16 0 |
| 40 | 상태 × 16 B: u32 이름, u32 타입(0 수, 1 text, 2 커서, 3 리스트, 4 인덱스), 8 B 값: 수는 f64 초기값, text는 u32 초기 상수, 커서는 u32 대상 text 상태와 u32 플래그(1이면 마크: 그 자리에 넣은 글 앞에 남는다), 리스트는 u32 레코드와 u32 키(0이면 없음, 아니면 키 필드 + 1), 인덱스는 u32 대상 리스트 상태 |
| | 컬렉션 × 12 B: u32 이름, u32 1(바이트), u32 1(키별) |
-| | 입력 × 16 B: u32 이름, u8 종류(1 키, 2 메시지, 3 text, 4 타이머), u8 키별 여부, u16 0, u32 키 이름(키 입력)·주기(타이머, 1 ms–24시간을 ms로) 또는 0, u16 첫 필드, u16 필드 수 |
+| | 입력 × 16 B: u32 이름, u8 종류(1 키, 2 메시지, 3 text, 4 타이머, 5 출력: 앱이 보내는 메시지, 모양은 메시지와 같고 핸들러가 없다), u8 키별 여부, u16 0, u32 키 이름(키 입력)·주기(타이머, 1 ms–24시간을 ms로) 또는 0, u16 첫 필드, u16 필드 수 |
| | 필드 × 8 B: u32 이름(식별자, 또는 그룹 안의 필드면 점으로 이은 경로 `user.name`), u32 타입(1 u32le, 2 바이트, 3 수(binary64), 4 text). 페이로드는 접두부와 가변 필드의 바이트다. 접두부에는 선언 순서로 고정 필드의 값과 가변 필드(바이트·text)의 u32 길이가 들어가는데, 마지막 가변 필드는 길이 없이 나머지를 차지한다. 가변 필드의 바이트는 접두부 뒤에 선언 순서로 이어진다(가변 필드가 하나면 예전의 "바이트 꼬리"와 같다) |
| | 상수 × 8 B: u32 블롭 오프셋, u32 길이 (UTF-8) |
| | 레코드 × 8 B: u32 이름, u16 첫 레코드 필드, u16 필드 수(1–16) |
@@ -105,6 +105,7 @@ v5에는 뒤에 집계(FOLD), 걸러진 표, 마크, 그리고 **키 있는 리�
| 69 | NOW | → n | 이벤트가 보는 지금(1970년부터 ms, UTC). 호스트가 정하고 스크립트는 아무 때나 재현한다. 핸들러 전용: 보기는 상태의 순수 함수로 남는다 |
| 70 | FLOOR | n → n | 내림 |
| 71 | MOD | n n → n | 나눗셈을 내림한 나머지. 결과는 나누는 수의 부호를 따른다(0도). 0으로 나누면 `divide` |
+| 72 | SEND | f… → | 출력 `인자`의 필드 값을 필드 순서대로 받아(u32·수는 n, 바이트는 b, text는 t) 메시지 페이로드(접두부와 가변 필드)로 만들고 이벤트의 일부로 보낸다. u32 필드의 값이 0–2³²−1의 정수가 아니면 `limit`. 핸들러 전용 |
`f`는 레코드 필드의 타입(수 또는 text)이고, `k`는 그 리스트의 키 필드 타입이다. 수 연산 결과가 유한하지 않으면 실패한다. 실패하면 그 이벤트의 모든
핸들러가 한 일이 취소된다.
@@ -258,6 +259,27 @@ text·리스트가 남을 때만 위치를 유지한다.
앱이 멈추고 저장소가 닫힌 뒤에도 만들 때 그대로다. 실패한 저장 뒤의 스냅숏은 실패 전과 같다. 두 스레드가 최신
스냅숏을 읽는 동안 앱이 계속 적용한다(ASan·UBSan·LeakSanitizer 빌드 포함).
+## 앱 사이의 연결
+
+출력으로 보낸 메시지(outbox)와 보낸 쪽별로 들은 번호(inbox)는 런타임이 소유하는 상태다([078](../research/078-app-connections.md)).
+
+- **보냄은 이벤트의 일부다.** `SEND`는 출력마다 1부터 매긴 번호를 붙여 메시지를 둔다. 이벤트가 실패하면 보내지 않았고,
+ 저장이 실패하면 마지막 저장 뒤의 보냄과 그 번호가 모두 돌아간다. 호스트는 저장된 보냄만 본다(`pure_app_outbox`).
+ 받는 쪽이 저장한 번호까지 호스트가 덜어 내면(`pure_app_trim`) 다음 저장과 함께 사라진다.
+- **받는 쪽은 한 번만 적용한다.** `pure_app_deliver(app, 입력, 보낸 쪽, 번호, 페이로드)`는 메시지 이벤트다. 보낸 쪽(1–64바이트,
+ 공백 없는 인쇄 가능 ASCII)마다 마지막으로 들은 번호를 두고, 그 이하는 적용하지 않고 성공한다(`app->duplicate`). 번호는
+ 이벤트의 변경과 함께 저장된다. 앱이 거절한 메시지(실패 종류가 있는 실패)도 들은 것으로 친다. 전달은 끝났고 효과는
+ 거절이다. 저장이 실패하면 들은 번호도 돌아간다.
+- **저장.** `links` 상태 문서(`PLK1`)에 출력 표(이름, 필드 타입, 마지막 번호), 보낸 쪽별 번호, 덜어 내지 않은 보냄을
+ 담는다. 바뀐 저장에서만 다시 쓴다. 모듈을 바꾸면 출력은 이름으로 이어진다. 보낸 것이 남은 출력을 없애거나 필드
+ 타입을 바꾸는 모듈은 거절한다(`conflict`, 시작도 같다). 보낸 것이 없으면 그 번호를 기억해 두었다가 같은 이름의 출력이
+ 돌아오면 이어서 매긴다. 받는 쪽이 이미 들은 번호를 다시 쓰지 않기 위해서다.
+
+검증(`test-module`): 실패한 이벤트의 보냄, 지연 저장의 보냄, 실패한 저장(보냄·덜어 냄·번호가 돌아간다), 재시작, 덜어 냄,
+중복·건너뛴 번호·다른 보낸 쪽의 전달, 거절한 전달, 저장 실패 뒤 다시 전달, 출력이 없는 모듈로의 교체와 되돌아옴, 잘못된
+`SEND`(타입, 출력이 아닌 인자, 모자란 값)와 출력의 핸들러. 커밋의 단계마다 프로세스를 죽여도 보내는 앱은 이벤트와
+보냄이, 받는 앱은 전달과 그 효과가 함께 남거나 함께 사라진다.
+
## HTTP 호스트 (`pure-serve`)
`pure-serve --module 앱.pmod --store 경로`는 앱의 **보기와 입력이 곧 HTTP 인터페이스**다. 라우터 코드가 없다.
diff --git a/docs/research/078-app-connections.md b/docs/research/078-app-connections.md
index fbe7f34..5e89853 100644
--- a/docs/research/078-app-connections.md
+++ b/docs/research/078-app-connections.md
@@ -1,8 +1,9 @@
# 078 — 앱 사이의 연결: 런타임이 소유하는 outbox와 정확히 한 번의 효과
-2026-09-26. 설계 노트이며 구현 순서를 포함한다. 상태: 설계만 했다. [로드맵](../roadmap.md)의 단기 과제(대여 완성, 저장과
-적용의 겹치기, 읽기 독립화, JSON 확장)를 먼저 하고, 중기 1(외부로 나가는 호출)과 함께 구현한다. 외부 API 호출도 같은
-outbox 위에 선다(출력을 HTTP 끝점에 잇는 배선).
+2026-09-26. 설계 노트이며 구현 순서를 포함한다. 상태: 1단계(Pure 런타임: 출력, `SEND`, outbox·inbox와 그 저장)와
+2단계(aup `output`·`send`)를 2026-09-27에 구현했다([008 앱 사이의 연결](../design/008-module-format.md)). 호스트의 배선과
+전달(3·4단계)은 [로드맵](../roadmap.md) 중기 1(외부로 나가는 호출)과 함께 한다. 외부 API 호출도 같은 outbox 위에 선다(출력을
+HTTP 끝점에 잇는 배선).
착수 기준: