aboutsummaryrefslogtreecommitdiffstats
path: root/docs/design
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-30 16:16:08 +0100
committereunhhu <[email protected]>2026-09-30 16:16:08 +0100
commit46c303a41e9dd9cd0e6bd50511e8d7253a0ef438 (patch)
tree7564bf80ac43ff0964c64acd6a15f7299fa48997 /docs/design
parente02bfc916743a0327d76144b32b6ec6381e5907f (diff)
downloadpure-46c303a41e9dd9cd0e6bd50511e8d7253a0ef438.tar.gz
pure-46c303a41e9dd9cd0e6bd50511e8d7253a0ef438.zip
Give i64 its own type in modules, lists, stores and the host (016 stage 2)
An i64 is an int64_t in a value's 8 bytes, its own stack type: CONST and NUM_TEXT take argument 2 for one, eleven opcodes are appended (ADD, SUB and MUL fail as overflow past its range, DIV and MOD floor and fail as divide by zero, NEG, COMPARE with a relation, MIN, MAX, and I64_FROM and NUM_FROM, which convert only where the value fits and else fail as limit), and moves (LOAD, STORE, locals, items, FIELD, SEND) copy it as they copy a number. Type codes: state 6, record field 3, message field 7 (8 bytes), view 4, local 3. v6 stays: all of it is added. - Folds with PURE_FOLD_INTEGER sum (overflow fails), keep the most or least of, or count the different i64s; distinct's set keeps an i64's -1 apart from its free mark. Blocks with an i64 run item by item. - A list's kinds are its stored header's (number, text, bytes, bool, integer): integer columns are int64_t, ordered as integers as keys (found without guide keys for now), stored in 8 bytes and logged as zigzag varints of any size. Records name their fields' type in one array (record_field_type) in place of text and bool flags. - A number, a bool and an i64 carry over each other by one rule, pure_cell_as, wherever one becomes another: a module replaced, a stored value or item read by another module, a waiting send recast. A u32 field delivers to an i64 one. - The host reads i64 fields from JSON, rows and queries as integer digits in range and nothing else, and shows every digit in views, tables, deliveries and pure-run. Faults are named by one function, pure_fault_name, in place of three tables; overflow is new. test-module: 28 arithmetic cases at the range's ends, relations, conversions both ways, 14 refusals, a keyed i64 list app (order, a sum that overflows, a failed add undone, messages and sends of 8 bytes, every digit as text), recasts, replacement between numbers, bools and i64s, and three stored runs against memory with restarts (46 images written).
Diffstat (limited to 'docs/design')
-rw-r--r--docs/design/008-module-format.md25
1 files changed, 18 insertions, 7 deletions
diff --git a/docs/design/008-module-format.md b/docs/design/008-module-format.md
index 5b2ff05..02f8900 100644
--- a/docs/design/008-module-format.md
+++ b/docs/design/008-module-format.md
@@ -19,6 +19,8 @@ v5에는 뒤에 집계(FOLD), 걸러진 표, 마크, 그리고 **키 있는 리�
v6은 **bool**을 수와 다른 스택 종류로 더한다([016](016-bool-and-i64.md)). 비교, `has`, 논리가 bool을 내고 분기, `require`,
필터, 집계의 포함 여부가 bool을 받는다. 새 명령은 없다(CONST와 NUM_TEXT의 인자, 새 타입 번호). 비교의 결과 종류가
바뀌므로 v5 모듈은 받지 않는다. 다시 빌드한다.
+v6에는 뒤에 **i64**가 더해졌다([016](016-bool-and-i64.md)의 2단계): 새 명령, 새 타입 번호, 0이던 자리의 값(CONST와 NUM_TEXT의
+인자 2, 집계의 PURE_FOLD_INTEGER)이라 판은 그대로다.
## 바이트 배치
@@ -31,14 +33,14 @@ v6은 **bool**을 수와 다른 스택 종류로 더한다([016](016-bool-and-i6
| 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), 8 B 값: 수와 bool은 f64 초기값(bool은 0이나 1), text는 u32 초기 상수, 커서는 u32 대상 text 상태와 u32 플래그(1이면 마크: 그 자리에 넣은 글 앞에 남는다), 리스트는 u32 레코드와 u32 키(0이면 없음, 아니면 키 필드 + 1, 256이면 메시지의 행 목록: 이름은 그 필드의 경로 `입력.필드`이고 키가 없다), 인덱스는 u32 대상 리스트 상태 |
+| 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 대상 리스트 상태 |
| | 컬렉션 × 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). 페이로드는 접두부와 가변 필드의 바이트다. 접두부에는 선언 순서로 고정 필드의 값과 가변 필드(바이트·text)의 u32 길이가 들어가는데, 마지막 가변 필드는 길이 없이 나머지를 차지한다. 가변 필드의 바이트는 접두부 뒤에 선언 순서로 이어진다(가변 필드가 하나면 예전의 "바이트 꼬리"와 같다) |
+| | 필드 × 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 길이가 들어가는데, 마지막 가변 필드는 길이 없이 나머지를 차지한다. 가변 필드의 바이트는 접두부 뒤에 선언 순서로 이어진다(가변 필드가 하나면 예전의 "바이트 꼬리"와 같다) |
| | 상수 × 8 B: u32 블롭 오프셋, u32 길이 (UTF-8) |
| | 레코드 × 8 B: u32 이름, u16 첫 레코드 필드, u16 필드 수(1–16) |
-| | 레코드 필드 × 16 B: u32 이름, u32 타입(0 수, 1 text, 2 bool), 8 B 기본값: 수와 bool은 f64(bool은 0이나 1), text는 u32 상수 |
-| | 보기 × 16 B: u32 이름, u8 타입(0 수, 1 text, 2 표, 3 bool), u8 걸러진 표의 리스트 상태 + 1(그 밖에는 0), u16 표(열이면 그 표 보기 + 1, 아니면 0), u32 시작 명령, u32 명령 수. 표는 시작 명령 자리에 리스트 상태, 명령 수 0. 걸러진 표는 타입 다음 바이트에 리스트 상태 + 1, 시작·명령 수에 필터 블록 |
+| | 레코드 필드 × 16 B: u32 이름, u32 타입(0 수, 1 text, 2 bool, 3 i64), 8 B 기본값: 수와 bool은 f64(bool은 0이나 1), i64는 정수, text는 u32 상수 |
+| | 보기 × 16 B: u32 이름, u8 타입(0 수, 1 text, 2 표, 3 bool, 4 i64), u8 걸러진 표의 리스트 상태 + 1(그 밖에는 0), u16 표(열이면 그 표 보기 + 1, 아니면 0), u32 시작 명령, u32 명령 수. 표는 시작 명령 자리에 리스트 상태, 명령 수 0. 걸러진 표는 타입 다음 바이트에 리스트 상태 + 1, 시작·명령 수에 필터 블록 |
| | 핸들러 × 12 B: u32 이벤트, u32 시작 명령, u32 명령 수 |
| | 명령 × 16 B: u8 opcode, 0 3바이트, u32 인자, f64 값 |
| | 문자열: `[u8 길이][바이트]`의 연속 |
@@ -113,9 +115,18 @@ v6은 **bool**을 수와 다른 스택 종류로 더한다([016](016-bool-and-i6
| 73 | OUTER_ROW | → i | 열 안의 집계 블록에서 그 열의 행(집계의 항목은 ROW). 걷기 안의 집계에서는 걷는 항목 |
| 74 | EACH | | 걷기. `인자`의 비트 8–15는 리스트 상태, 16–31은 뒤따르는 블록의 길이 L. 그 L개 명령이 리스트가 시작할 때 가진 항목마다 차례로 핸들러의 코드로 돈다(`ROW`가 항목). 블록은 상태, 그 리스트의 항목(필드 바꾸기, 지우기), 다른 리스트를 바꿀 수 있지만 걷는 리스트에 넣을 수는 없다. 걷는 항목이나 그 앞의 항목을 지우면 걷기가 따라가 다음 항목을 건너뛰지 않는다. 핸들러 전용 |
| 75 | LOCAL_LOAD | → n, bool 또는 i | 이벤트의 지역 칸. `인자`의 비트 0–7은 칸(64개), 8–15는 담는 것(0 수, 1 인덱스, 2 bool), 16–31은 인덱스의 리스트. 칸은 이벤트가 시작할 때 0이고 저장되지 않는다. 핸들러와 그 안의 걷기, 그 안의 집계에서 읽는다 |
-| 76 | LOCAL_STORE | n, bool 또는 i → | 그 칸에 넣는다. 핸들러와 그 안의 걷기에서. 한 핸들러는 한 칸을 한 가지(수, bool, 또는 한 리스트의 인덱스)로만 쓴다 |
-
-bool은 실행 중에 수의 칸에 든 0이나 1이다. `f`는 레코드 필드의 타입(수, text 또는 bool)이고, `k`는 그 리스트의 키 필드 타입이다. 수 연산 결과가 유한하지 않으면 실패한다. 실패하면 그 이벤트의 모든
+| 76 | LOCAL_STORE | n, bool, i64 또는 i → | 그 칸에 넣는다. 핸들러와 그 안의 걷기에서. 담는 것 3은 i64. 한 핸들러는 한 칸을 한 가지(수, bool, i64, 또는 한 리스트의 인덱스)로만 쓴다 |
+| 77–79 | I64_ADD I64_SUB I64_MUL | i64 i64 → i64 | 범위를 넘으면 `overflow` |
+| 80–81 | I64_DIV I64_MOD | i64 i64 → i64 | 내림한 몫과 나머지(나머지는 나누는 수의 부호). 0으로 나누면 `divide`, 가장 작은 i64 / −1은 `overflow` |
+| 82 | I64_NEG | i64 → i64 | 가장 작은 i64는 `overflow` |
+| 83 | I64_COMPARE | i64 i64 → bool | `인자`는 관계(TEXT_COMPARE와 같다) |
+| 84–85 | I64_MIN I64_MAX | i64 i64 → i64 | |
+| 86 | I64_FROM | n → i64 | 범위 안의 정수만. 아니면 `limit` |
+| 87 | NUM_FROM | i64 → n | \|i\| ≤ 2^53일 때만(정확하다). 아니면 `limit` |
+
+bool은 실행 중에 수의 칸에 든 0이나 1이고, i64는 같은 8바이트의 정수다. CONST의 인자 2는 i64 상수(값의 8바이트), NUM_TEXT의
+인자 2는 i64의 10진 글자다. LOAD·STORE·지역 칸·항목·FIELD·SEND는 i64를 수처럼 옮긴다. FOLD의 종류에 64(PURE_FOLD_INTEGER)를
+더하면 sum·max·min·distinct가 i64 값을 받는다(sum이 범위를 넘으면 `overflow`). i64 키 목록은 정수로 비교한다. `f`는 레코드 필드의 타입(수, text, bool 또는 i64)이고, `k`는 그 리스트의 키 필드 타입이다. 수 연산 결과가 유한하지 않으면 실패한다. 실패하면 그 이벤트의 모든
핸들러가 한 일이 취소된다.
## 로드할 때 검증하는 것