aboutsummaryrefslogtreecommitdiffstats
path: root/docs/design/016-bool-and-i64.md
blob: 5164a7c4c3c19a2cba336b9f61fdf9f4aedce297 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# 016 — 참·거짓과 정확한 정수: `bool`과 `i64`

작성일: 2026-09-30. 상태: 1단계(`bool`) 구현, 검사로 고정. 2단계(`i64`) 설계.
aup의 v0c에 남은 것(aup `docs/design/002-dsl-direction.md`의 `i64 bool`)이고,
[015](015-boundary-meaning.md)가 정한 경계마다의 값의 뜻에 두 종류를 더한다.

## 문제

- **참·거짓이 수다.** 비교와 논리 연산은 0이나 1을 내고, 0이 아니면 참이다. 그래서 할 일의 `done`은 `done = 0`인 수
  필드다. 보기의 JSON에는 `true` 대신 `1`이, 화면에는 `1`이 나온다. `done + 1`도 타입 오류가 아니다. 조건 자리에 아무
  수나 들어간다.
- **정수가 2^53에서 멈춘다.** 수는 binary64다. 밖에서 오는 64비트 ID(많은 서비스의 ID가 2^53을 넘는다), 나노초 시각(2^53
  나노초는 104일), 큰 누계는 정확히 들지 못한다. 015는 수가 비트까지 그대로라고 정했지만, 그 비트가 정수를 담지 못한다.

## 원칙

aup의 원칙(002)을 따른다. 위치가 정수가 아니듯 참·거짓은 수가 아니고, 길이에 단위를 적듯 정수는 정확하다. 둘 다 Pure
검증기의 스택 종류가 되어, 검증된 모듈은 실행 중에 타입을 검사하지 않는다(008).

## 1단계: `bool`

**언어(aup).**

- 타입 `bool`, 리터럴 `true`와 `false`.
- 비교(`< <= > >= == !=`, text 비교), `has`, 논리(`&& || !`)가 bool을 낸다. `&&`와 `||`는 지금처럼 양쪽을 모두 계산한다.
- 조건 자리(`if`, 조건식, `where`, `require`, `count`와 `first`의 조건, 걸러진 표)는 bool만 받는다. 수를 주면 진단이
  고치는 법을 말한다(`x != 0`).
- bool끼리 `==`와 `!=`는 된다. 크기 비교, 산술, `sum`·`max`·`min`·`distinct`는 안 된다. 키 있는 목록의 키가 될 수 없다.
- 선언: `state on = false`, 레코드 필드 `done = false`, 메시지와 출력의 필드 `ok: bool`, 보기와 열은 bool 식이면 bool이다.
- 보간(`"{done}"`)은 `true`나 `false`다.

**모듈 형식 v6(Pure).** 판을 올린다. 비교의 결과 종류가 바뀌므로 v5 모듈은 다시 빌드한다.

- 검증기의 스택 종류에 bool을 더한다. 실행 중의 값은 수 칸의 0과 1이다.
- 새 명령은 없다. CONST의 인자 1이 bool 상수(값 +0이나 1)이고, NUM_TEXT의 인자 1이 bool을 `true`·`false`로 쓴다.
  LOAD·STORE와 지역 칸은 수와 bool을 함께 다룬다(상태의 타입이나 칸의 담는 것이 정한다).
- bool을 내는 명령: LT–NE, TEXT_COMPARE, LIST_HAS, AND·OR·NOT. EQ와 NE는 bool 둘도 비교한다.
- bool을 받는 명령: JZ, REQUIRE, AND·OR·NOT, 집계의 포함 여부(count와 first는 bool 하나, sum·max·min·distinct는 수와
  bool), 걸러진 표의 필터.
- 새 타입 번호: 상태 5(bool, 8 B 값은 f64 0이나 1), 레코드 필드 2(bool, 기본값 f64 0이나 1), 메시지 필드 6(bool, 접두부의
  1바이트 0이나 1), 보기 3(bool). 지역 칸의 담는 것 2(bool). 상수, 초기값, 기본값은 +0이나 1이어야 한다.
- 메시지의 bool 필드 바이트가 0이나 1이 아니면 메시지가 `limit`으로 실패한다(도착할 때, 015의 거절과 같은 자리).

**경계(015에 더한다).**

- JSON: bool 필드는 `true`·`false`만 받는다(`0`, `1`, `"true"`는 거절). 보기와 표의 bool은 `true`·`false`다.
- 쿼리: `true`·`false`.
- 저장: 목록의 bool 필드는 수 열의 0과 1이다(저장 형식도 수다). 레코드의 필드 타입이 뜻을 정한다.
- 전달: 링크의 FIELDS와 HTTP 전달의 JSON이 bool을 bool로 싣는다. 받는 입력의 필드도 bool이어야 한다. 넓히기는 없다.
- 모듈 교체: 수 필드나 상태가 bool이 되면 0(−0도, 015)과 1은 `false`와 `true`로 옮기고, 다른 수는 기본값이 된다. bool이
  수가 되면 `false`와 `true`는 0과 1이다. 저장소에서 다시 열 때와, 교체가 출력의 필드를 바꿀 때 기다리던 보냄도 같다.
- 화면(Vega): 글자로는 `true`·`false`다(보간과 같다). 앱이 다르게 보이고 싶으면 조건식으로 글을 고른다.

**옮기는 비용.** 예제의 수 깃발을 bool로 바꾼다(`done`, `urgent`, `running`, `holding`). 저장된 0과 1은 위의 교체 규칙으로
그대로 이어진다.

### 1단계에서 알게 된 것

- **새 명령은 필요 없었다.** 처음 설계는 BOOL_CONST와 BOOL_TEXT를 더하려 했다. CONST와 NUM_TEXT의 인자 하나(0이던
  자리)로 충분했다. 검증기의 종류와 타입 번호만 늘었고, 실행기는 bool을 수의 칸의 0과 1로 그대로 돈다(잎 단위 실행도).
- **저장된 보냄의 bool을 거절하던 곳이 있었다.** 출력의 필드 타입을 저장소에서 다시 읽는 검사가 `>= 행`으로 bool(6)까지
  막아, bool 필드를 가진 출력의 보냄이 기다리는 노드는 다시 시작하지 못했다. `server_meaning`의 재시작 출구가 잡았고,
  고쳤다. test-module이 잡지 못한 까닭은 bool 보냄을 저장하고 다시 여는 경우가 없어서였다. 그 경우를 더했다(고치기 전의
  코드로는 실패한다).
- **−0은 `false`로 옮긴다.** 수가 bool이 될 때 0과 1만 옮기기로 했는데, 015가 0에는 부호가 없다고 정했으므로 −0도 0이다.
  처음 구현은 −0을 기본값으로 보냈다.
- **JSON의 `True`는 타입이 아니라 문법의 거절이다**(`json`). 1, 0, `"true"`, `null`, 배열은 `json_type`이다.

검사: Pure test-module에 bool 검증 거절 28가지와 실행·메시지 바이트·보냄·링크·교체·저장(보냄 포함)을 더했고, 레인 대조의 무작위
생성기가 수와 bool을 나눠 만든다(3,600 집계가 비트까지 같다). `server_meaning`은 값 67개마다 bool 필드를 싣고 나가는 길 일곱에서
본다(거절 52가지, bool은 거절의 종류까지). HTTP에서 bool 보기의 글자와 bool 인자도 본다. aup는 bool 진단 20가지, 받아들이는
형식, 출력마다 `true`·`false`인지 보는 검사(파이썬의 `True == 1`을 같게 보지 않는 비교)를 더했다. Vega는 bool 보기가 CLI, TUI,
문장, 웹에서 `true`·`false`로 보이는지 본다. 커밋: Pure `86fd4f7`·`d1c90e2`·`d415a5a`, aup `b8e3faa`, Vega `72ecae6`.

## 2단계: `i64`

1단계가 들어간 뒤 같은 방식으로 한다. 정할 것을 미리 적는다.

- 스택 종류 i64. 값 칸은 수와 정수를 겹쳐 든다(검증기가 종류를 보장한다).
- 정수 리터럴은 문맥으로 수나 i64가 된다(`n = n + 1`에서 `n`이 i64면 `1`도 i64).
- `+ - *`는 넘치면 사건이 실패한다. `/`와 `%`는 내림한다(지금의 `%`와 같다). 0으로 나누면 `divide`.
- 수와 섞지 않는다. `number(i)`는 2^53 안에서만, `i64(x)`는 정수이고 범위 안일 때만 되고, 아니면 사건이 실패한다.
- 저장: 목록의 8바이트 열, 저장 형식은 정수(로그에서는 zigzag varint).
- JSON과 쿼리: 소수점과 지수 없는 정수 글자만 받고, 넘치면 거절한다. 보기는 정확한 자릿수다(자바스크립트의 수로 읽는 쪽은
  2^53 너머를 잃는다: 문서에 적는다).
- 전달: u32는 i64로 넓힐 수 있다. i64와 수 사이는 넓히지 않는다.
- 키 있는 목록의 키가 될 수 있다. `sum`은 넘치면 실패한다.

## 검사

- aup: 진단(수를 조건으로, bool 산술, bool 크기 비교, bool 키), 받아들이는 형식, 참조 모델.
- Pure: test-module(검증기가 bool을 섞은 모듈을 거절한다, bool 상태·필드·보기·보냄), `server_meaning`에 bool 필드(JSON,
  쿼리, 링크, HTTP 전달, 재시작, 교체).
- Vega: bool 보기가 표면마다 `true`·`false`로 보인다.