aboutsummaryrefslogtreecommitdiffstats
path: root/docs/research/004-authoring.md
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-24 17:14:54 +0100
committereunhhu <[email protected]>2026-09-24 17:14:54 +0100
commitb1ce1927022d374198441afafeb27199fc8a052a (patch)
tree6021f175f4c67ed03b44240eaa2f90d846f12f6f /docs/research/004-authoring.md
parentd34f9426d5317a1948f12f229439946728bc342a (diff)
downloadpure-b1ce1927022d374198441afafeb27199fc8a052a.tar.gz
pure-b1ce1927022d374198441afafeb27199fc8a052a.zip
Establish native micro runtime checkpoint
Diffstat (limited to 'docs/research/004-authoring.md')
-rw-r--r--docs/research/004-authoring.md176
1 files changed, 176 insertions, 0 deletions
diff --git a/docs/research/004-authoring.md b/docs/research/004-authoring.md
new file mode 100644
index 0000000..6ced695
--- /dev/null
+++ b/docs/research/004-authoring.md
@@ -0,0 +1,176 @@
+# Pure 연구 보고서 004: 빈 작업물에서 직접 작성하기
+
+작성일: 2026-09-22
+
+**이번에는 빈 문서에서 상태·입력·도형·반응을 작성하는 도구를 구현했다.**
+새 동작을 추가하는 데 실행기 내부를 수정하지 않아도 된다. 자동 검사와 실제 브라우저 조작은
+통과했지만, 사용자가 배우기 쉬운지와 기존 코드보다 제작하기 편한지는 아직 모른다.
+실행 비용을 비교한 현재 구현은 고정된 JavaScript 예제보다 느렸다.
+
+후속 사용자 관찰: 문법은 매력적이고 기본 사용에 걸림돌이 없었지만, 현재 결과는 작은 DSL이며
+실제 큰 서비스·앱·CLI를 개발해야 가치를 판단할 수 있다는 피드백을 받았다.
+이 관찰은 사용자 한 명의 현재 경험이다. 대규모 제작·성능·독창성은 여전히 미검증이다.
+다음 설계는 [기반 계약 보고서 005](005-foundation-contract.md)에 기록했다.
+
+[제작 화면 실행 안내](../../prototypes/workbench/README.md)를 따라 자신의 작은 동작을 만들어볼 수 있다.
+첫 화면은 비어 있고, 예제는 직접 선택했을 때만 편집기에 들어온다.
+사용자가 전달할 관찰은 **하려던 일 / 실제로 일어난 일 / 기대했던 일**이면 된다.
+도구의 표현이나 설명이 막히는 지점을 재현하고 개선하는 일은 Codex가 맡는다.
+
+## 이전 실험에서 바로잡은 점
+
+사용자는 “Dino를 직접 만든 것이 아니므로 개발 경험을 평가할 수 없다”고 지적했다.
+맞는 지적이다. 기존 데모는 정해진 동작의 설정 변경과 상태 보존을 시험했으며,
+새 동작을 만드는 과정은 제공하지 않았다. 그 결과를 개발 경험의 증거로 쓰지 않는다.
+
+이번 실험에서는 사용자가 직접 다음을 정의한다.
+
+| 작성할 것 | 표현 |
+|---|---|
+| 기억할 값 | `state x = 80` |
+| 입력 이름과 키 | `input right = ArrowRight` |
+| 보여줄 대상과 상태 연결 | `circle seed(x, 180, 20, "#7ed9ae")` |
+| 누름·놓음·시간 반응 | `on right.down`, `on right.up`, `on frame` |
+| 계산·조건 | 대입, 산술·비교, `if`, `min/max/clamp` |
+
+점프·중력·충전·충돌은 코어에 내장하지 않았다. 충전 예제의 중력과 바닥 판정도 작성한 코드에 있다.
+화면의 입력 버튼, 상태 목록과 도형은 선언한 내용에서 만들어진다.
+현재 범위는 숫자 상태와 간단한 도형을 사용하는 작은 상호작용이다. 임의 앱, 센서,
+자유로운 창 관리, 셰이더, 문자열·배열·함수 등을 지원한다는 뜻은 아니다.
+
+## 실제 제작 과정에서 확인한 의미
+
+편집 중인 코드와 실행에 적용한 코드를 구분한다. 적용할 때 **같은 이름의 숫자 상태**는 유지한다.
+상태 선언 순서를 바꿔도 이름으로 대응하며, 새 이름은 초깃값을 사용한다.
+이름을 바꾸는 행위의 의미까지 추론하지는 않는다. 초깃값 변경을 현재 값에 반영하려면 초기화를 누른다.
+
+문법·이름·용량 오류가 있는 수정은 기존 작업을 유지한다. 계산 중 오류가 생기면 해당 이벤트에서
+실행한 모든 반응의 숫자 상태 변경을 함께 취소한다. 키보드와 포인터가 같은 입력을 동시에
+누르면 첫 누름과 마지막 놓음만 전달한다. 누른 상태에서는 새 코드를 적용할 수 없다.
+
+브라우저 검증 중 서로 다른 도형·입력·반응을 소스만 편집해 추가했다. 기존 실행기 변경은 없었다.
+미적용 초안의 저장·불러오기도 확인했다. 실제 사용자의 자유로운 제작 성공률이나 소요 시간은
+이 자동화로 측정되지 않는다.
+
+## 이번에는 실제로 명령 해석기가 있다
+
+초기 대화의 네이티브 C 함수 구성에는 자체 바이트코드 VM이 없었다.
+이번에는 작성한 동작을 실행 중 교체하는 실험을 위해 **작은 중간 명령 해석기**를 도입했다.
+구성이 달라졌으므로 바이트코드 저장량을 0이라고 말할 수 없다.
+
+```text
+작성한 .pure 텍스트
+ → JavaScript 컴파일러: 이름·타입의 범위와 용량 검사, 중간 명령 생성
+ → Zig 코어: 중간 명령 실행, 상태·오류·적용 관리
+ → 브라우저 SVG 또는 터미널 JSON
+```
+
+Zig 코어 자체는 WebAssembly로 빌드한다. 사용자가 작성한 중간 명령과 이 Wasm 파일은
+서로 다른 대상이다. 브라우저와 터미널은 같은 컴파일러·코어를 사용하지만 별도 인스턴스다.
+이 선택이 최종 제품의 언어·컴파일 방식으로 확정된 것은 아니다.
+
+## 보관 공간과 실행 명령 수
+
+[충전 예제](../../prototypes/workbench/examples/charge.pure)를 실제 컴파일·실행한 값이다.
+소스는 674바이트, 상태 4개, 입력 1개, 출력 4개, 반응 3개이며 중간 명령은 66개다.
+
+| 항목 | 바이트 | 의미 |
+|---|---:|---|
+| 사용 중인 명령·반응 정보 | **1,092** | 명령 66 × 16 + 반응 3 × 12; 표시 계산 명령 포함 |
+| 현재 숫자 상태 값 | **32** | 4 × 8 |
+| 프로그램 한 개의 예약 공간 | 9,392 | 명령·반응·초깃값 등의 고정 용량 |
+| 코어 구조체 예약 공간 | **19,072** | 실행 중 프로그램, 다음 적용을 위한 준비 공간, 상태·관리 정보 포함 |
+| 그중 다음 프로그램 준비 공간 | 9,392 | 위 코어 구조체에 포함 |
+| 한 번의 계산 평가 스택 용량 | 512 | 64 × 8; 영구 상태와 다른 임시 공간 |
+| Wasm 선형 메모리 | **65,536** | 초기·최대값 고정; 코어와 예약한 16 KiB 호출 스택 포함 |
+| 배포 Wasm 파일 | **48,182** | `ReleaseSafe`, 디버그 정보 제거한 파일 크기 |
+
+표의 포함 관계를 무시하고 합산하면 안 된다. 특히 32바이트 상태만으로 전체 프로그램이
+돌아간다는 뜻이 아니다. JS 컴파일러·소스·중간 명령 객체, 브라우저·Node 엔진, SVG,
+기계어 코드와 프로세스 전체 메모리는 이 선형 메모리 수치에 포함되지 않는다.
+JavaScript 비교 모델의 힙 사용량도 측정하지 않았으므로 메모리 우월성은 판단하지 않는다.
+
+고정 용량 덕분에 이 코어는 작업이 작아도 프로그램 두 개 분량을 예약한다.
+작업에 비례해 메모리가 줄어드는 구현도 아니고, 이 19 KiB를 최적이라고 주장하지도 않는다.
+
+해당 예제에서 관찰한 이벤트당 중간 명령 실행 수는 다음과 같다.
+
+| 실제 상황 | 실행한 중간 명령 |
+|---|---:|
+| 바닥에 정지한 상태로 한 프레임 | 22 |
+| 바닥에서 입력 누르기 | 8 |
+| 충전 중 한 프레임 | 29 |
+| 한 프레임 충전한 뒤 놓기 | 13 |
+| 이후 공중에서 한 프레임 | 18 |
+
+이 값은 **해당 이벤트에서 해석한 명령** 수다. CPU 명령 수·CPU 사이클·함수 호출 횟수가 아니다.
+컴파일, 호스트 입력 처리, 표시 표현식 평가와 렌더링도 제외한다.
+[빌드·검사·명령 수 기록](../../prototypes/workbench/results/2026-09-22-linux-aarch64/verification.json)에
+당시 상태와 코드·Wasm 해시를 남겼다.
+
+## 일반 JavaScript와 비교한 결과
+
+[독립 JavaScript 모델](../../prototypes/workbench/web/baseline.mjs)은 컴파일러나 Pure 코어를 사용하지 않는다.
+같은 충전·해제·중력·바닥 계산과 출력 값을 일반 코드로 구현했다.
+이 JS 모델에는 임의 프로그램의 실행 중 교체나 이름에 따른 상태 이전 기능이 없다.
+
+길거나 짧은 누름, 중복 누름, 두 입력원, 공중 입력, 놓기, 초기화를 포함하는
+**6,663회 호스트 호출**을 양쪽에 재생했다. 각 호출 뒤 상태·출력·틱·누른 입력을 비교했다.
+초기 상태 포함 **6,664개 스냅샷**, 숫자 **126,616개**에서 차이가 0이었다.
+이는 기록한 실행열에서의 일치다. 모든 가능한 실행의 동등성 증명은 아니다.
+예를 들어 코어의 틱 카운터는 32비트에서 순환하지만 JS 모델의 틱은 같은 방식으로 순환하지 않는다.
+이번 실행열은 그 경계에 도달하지 않는다.
+
+같은 실행열로 준비 실행 후 측정 순서를 교대하며 7회 측정했다.
+환경은 **Linux aarch64, Cortex-A76, Node 24.20.0, Zig 0.15.2**다.
+M3 macOS에서 얻은 결과가 아니다.
+
+| 경로 | 호출당 시간 중앙값 | 7회 측정값의 범위 |
+|---|---:|---:|
+| Pure 호스트 + Wasm 명령 해석기 | **569 ns** | 516~735 ns |
+| 고정 JavaScript 모델 | **53.4 ns** | 52.7~74.6 ns |
+
+이 실행열에서는 Pure 경로가 약 **10.7배** 오래 걸렸다.
+누름·놓음 처리, 프레임 계산, 초기화 등의 총 시간을 호출 수로 나눈 배치 처리량이다.
+한 입력의 지연 분포나 화면 응답 시간은 아니다. Pure 쪽의 일반 명령 해석과 진단 관리 비용도
+함께 들어 있으므로 이 차이를 특정 연산이나 Wasm 경계 하나의 비용으로 단정하지 않는다.
+컴파일·표시 표현식·스냅샷 생성·DOM 렌더링·코드 교체 시간은 제외했다.
+CPU 고정·전력·온도 통제도 하지 않았으므로 절대 수치를 일반화하지 않는다.
+
+작성 파일은 `.pure` 34줄·674바이트, JS 모델 68줄·2,251바이트다.
+이는 주석·빈 줄을 포함한 물리적 파일 길이이며, 편집기의 줄 수는 마지막 빈 줄까지 세어 다를 수 있다.
+JS 모델에는 입력원 관리와 출력 데이터 생성 코드도 들어간다. Pure는 그 일부를 공통 실행기로
+옮겼으며 컴파일러·호스트 코드가 사라진 것이 아니다. 이 길이로 학습 부담이나 개발 시간을 판정하지 않는다.
+
+재현 가능한 실행열 생성기·모든 측정값·환경·해시는
+[비교 원자료](../../prototypes/workbench/results/2026-09-22-linux-aarch64/comparison.json)에 있다.
+
+## 검사와 남은 질문
+
+- Zig 네이티브 18개: 이벤트 원자성, 범위·스택·분기, 상태 이전, 메모리 집계 등.
+- 컴파일러 13개: 문법·이름·식·분기·용량·예제 작성 범위.
+- 실제 Wasm 호스트 통합 13개: 새 동작 작성, 입력원 결합, 적용 실패 보존, 상태 이름 대응,
+ 오류 보존, 표시 계산의 순수성, 별도 인스턴스 일치, 고정 메모리.
+- 독립 JS 모델 7개, 실제 터미널 프로세스 4개.
+- Chromium 실제 조작 44개: 빈 작업물 작성부터 새 동작 추가, 편집 중 키 입력 격리,
+ 잘못된 수정·실행 오류, 초안 파일 저장·복원, 390px 화면과 Wasm 로드 실패 처리.
+
+검사 중 외부에서 반환된 프로그램 정보를 변경하면 다음 적용의 상태 대응이 틀어질 수 있는 문제를
+발견해 해당 정보를 변경 불가능하게 만들었다. 실패한 누름 뒤 정상적인 놓음이 오류를 지워버리는
+문제도 고쳤다. 마지막 실패와 가장 최근 입력을 따로 표시한다.
+
+[브라우저 증거](../../prototypes/workbench/results/2026-09-22-linux-aarch64/browser-checks.json),
+[빈 화면](../../prototypes/workbench/results/2026-09-22-linux-aarch64/blank.png),
+[작성한 화면](../../prototypes/workbench/results/2026-09-22-linux-aarch64/authored.png),
+[좁은 화면](../../prototypes/workbench/results/2026-09-22-linux-aarch64/mobile.png)을 보관했다.
+좁은 화면 검사는 데스크톱 브라우저의 뷰포트 검사이며 실제 휴대폰 센서·터치를 검증하지 않는다.
+
+다음 사용자 관찰은 **자신이 정한 동작을 이 표현으로 끝까지 작성할 수 있는가**다.
+원하는 작은 숫자·도형 동작도 실행기 수정을 요청해야 한다면 그 지점이 표현 범위의 실패다.
+구현 세부사항을 이해하지 못했다는 이유로 사용자의 책임으로 돌리지 않는다.
+
+다음 성능 연구에서는 같은 의미를 유지하면서 실제 사용하는 상태·명령 수가 달라질 때
+예약 공간, 상태 복사, 명령 해석, 호스트 경계, 표시 계산의 비용을 각각 분리해야 한다.
+현재 전체 경로의 측정만으로 어느 부분을 최적화해야 할지 확정하지 않는다.
+새 원리나 기존 런타임 대비 우월성은 아직 입증하지 않았다. 이번 산출물은
+그 판단에 필요한 제작 경험과 수치를 얻기 위한 실행 가능한 실험이다.