aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-25 15:14:08 +0100
committereunhhu <[email protected]>2026-09-25 15:14:08 +0100
commitc298c2eec0b7ec0fcdacb8f661a9da3c184d2960 (patch)
treeaffe490db2b070f0b064bbb9bf5ade49d45a9293 /docs
parent91aa0afcd34cff345f1f7293d82fec7d00082d8b (diff)
downloadaup-c298c2eec0b7ec0fcdacb8f661a9da3c184d2960.tar.gz
aup-c298c2eec0b7ec0fcdacb8f661a9da3c184d2960.zip
Add fns and libraries
fn name(params) = value declares one expression, inlined where it is called: arguments are computed once onto the stack and the body reads them with PICK, so a fn costs no runtime call and keeps Pure's bound on work. Parameters take any kind of value; recursion is a compile error. use name reads name.aup beside the source or from AUP_PATH. A library declares only fns and uses, sees only its parameters, and is called as name.fn(...). Diagnostics now carry the file they are in, and the compiler takes a loader so that sources come from the host. examples/words.aup is such a library; examples/tasks.aup uses it and still matches its reference model.
Diffstat (limited to 'docs')
-rw-r--r--docs/design/001-language-v0.md7
-rw-r--r--docs/design/002-dsl-direction.md32
2 files changed, 34 insertions, 5 deletions
diff --git a/docs/design/001-language-v0.md b/docs/design/001-language-v0.md
index 30a26c4..f07102b 100644
--- a/docs/design/001-language-v0.md
+++ b/docs/design/001-language-v0.md
@@ -1,6 +1,6 @@
# aup v0 — 한 언어, 한 모듈 형식
-2026-09-25. 상태: v0a(scalar)와 v0b(바이트·영속 문서·text·커서), v0c의 레코드·리스트·인덱스·조건식·표 보기 구현.
+2026-09-25. 상태: v0a(scalar), v0b(바이트·영속 문서·text·커서), v0c(레코드·리스트·인덱스·조건식·표 보기·fn·use) 구현.
text와 리스트 문법은 [002](002-dsl-direction.md).
착수 기준:
@@ -48,7 +48,7 @@ on frame { # 1/60초 진행. 핸들러 안에서 dt를 쓸
```
- 선언과 문장은 줄바꿈이나 `;`로 끝난다. 이름은 ASCII `[A-Za-z_][A-Za-z_0-9]*`, 31바이트 이하다.
-- 예약어: `state input view on if else key frame dt min max clamp message by bytes u32 reply require record each`.
+- 예약어: `state input view on if else key frame dt min max clamp message by bytes u32 reply require record each fn use`.
- 키: `Space Enter ArrowLeft ArrowRight ArrowUp ArrowDown KeyA..KeyZ Digit0..Digit9`. 입력 이름과
키는 각각 한 번만 쓴다. 상태·입력·보기의 이름공간은 서로 겹칠 수 없다.
- 식: 숫자, 상태 이름, `dt`(핸들러 안에서만), 괄호, 단항 `- !`, 이항 `* /`, `+ -`,
@@ -79,7 +79,8 @@ Pure는 로드할 때 범위·이름·분기·스택 높이를 모두 정적으�
## 툴체인
-- `aup check FILE`: 진단만 한다. 오류는 `파일:줄:열: 메시지` 한 줄이다.
+- `aup check FILE`: 진단만 한다. 오류는 `파일:줄:열: 메시지` 한 줄이다(라이브러리 안이면 그 파일).
+- `use 이름`은 `이름.aup`을 FILE 옆, 그다음 `AUP_PATH`의 디렉터리 순서로 찾는다.
- `aup build FILE -o OUT.pmod`: 모듈을 만든다. 같은 소스는 바이트 단위로 같은 모듈을 만든다.
- C17, 외부 의존성 없음. 컴파일러는 Pure를 링크하지 않는다. 시험에서는 Pure의 검증기로 결과를 확인한다.
diff --git a/docs/design/002-dsl-direction.md b/docs/design/002-dsl-direction.md
index 815e16c..46a104a 100644
--- a/docs/design/002-dsl-direction.md
+++ b/docs/design/002-dsl-direction.md
@@ -1,6 +1,6 @@
# 002 — DSL 방향과 text
-2026-09-25. 상태: 방향 확정. v0b 구현, v0c는 레코드·리스트·인덱스·조건식·표 보기까지 구현.
+2026-09-25. 상태: 방향 확정. v0b 구현, v0c는 레코드·리스트·인덱스·조건식·표 보기·`fn`·`use`까지 구현.
## 위치
@@ -64,7 +64,7 @@ view current = note.line(at) # 커서가 있는 줄. 복사하지 않�
|---|---|---|
| v0a ✅ | 스칼라 상태, 키 입력, 핸들러, 보기 | 워크벤치 엔진과 비트 단위 일치 |
| v0b ✅ | `bytes`, 키별 영속 문서, `message` 입력, 응답, `require`, `text`(리터럴·보간·`cursor in`·`char`/`line`), `text` 입력 | 기존 편집기 CLI와 바이트 단위 일치, text 편집이 참조 모델과 일치 |
-| v0c | `record`, `list of`, `index of`, 조건식, 항목 투영(`each`) ✅ / 순수 `fn`, `use` 모듈, `i64 bool`, `map` | 모든 연산에 실행량 상한, 리스트가 참조 모델과 일치 ✅ |
+| v0c | `record`, `list of`, `index of`, 조건식, 항목 투영(`each`), 순수 `fn`, `use` 라이브러리 ✅ / `i64 bool`, `map` | 모든 연산에 실행량 상한, 리스트가 참조 모델과 일치 ✅ |
| v0d | `use vega`로 첫 인터페이스 투영(목록·표·커서·톤) | 한 명세가 두 표면 이상에서 동작 |
### 구현된 text (v0b)
@@ -148,4 +148,32 @@ view board = each task in tasks { # 항목마다 한 행
검증: 표 열과 조건 보기를 더한 할 일 목록이 참조 모델과 4,800단계에서 같고, 고르지 않은 가지가 계산되지 않음을 확인한다.
7단계 중첩은 컴파일되고 Pure가 받아들이며, 8단계는 aup가 거부한다(Pure도 거부하는 깊이). 진단 16건을 더했다.
+### 구현된 fn과 use (v0c-3)
+
+```text
+# examples/words.aup: 상태 없이 fn만 가진 라이브러리
+fn plural(count, one, many) = if count == 1 { one } else { many }
+fn counted(count, one, many) = "{count} {plural(count, one, many)}"
+
+# examples/tasks.aup
+use words
+view summary = words.counted(tasks.count, "task", "tasks")
+```
+
+- **fn은 식 하나다.** `fn 이름(매개변수, ...) = 값`, 매개변수가 없으면 `fn limit = 3`(상수처럼 `limit`으로 쓴다).
+ 매개변수에 타입을 적지 않는다. 부르는 곳마다 인라인하므로 수·text·커서·인덱스 무엇이든 받는다. 본문의
+ 타입 오류는 본문 위치에 `(in fn 'f' called at 줄:열)`을 붙여 알린다.
+- **런타임 호출이 없다.** 인자는 부를 때 한 번 계산해 스택에 두고, 본문은 Pure의 PICK으로 읽고 SLIDE로 치운다.
+ 인자를 여러 번 써도 다시 계산하지 않으며, 쓰지 않는 인자도 계산한다(값 전달). 재귀는 컴파일 오류다.
+ 그래서 실행량 상한과 로드 전 검증이 그대로 유지된다.
+- **use는 라이브러리를 가져온다.** `use words`는 소스 옆의 `words.aup`, 없으면 `AUP_PATH`(`:`로 구분)의 디렉터리에서
+ 찾는다. 라이브러리는 `fn`과 `use`만 선언하고 앱의 상태를 볼 수 없다(매개변수만 읽는다). 부를 때는
+ `words.counted(...)`처럼 라이브러리 이름을 붙인다. 순환 use는 오류이고, 라이브러리의 오류는 그 파일 경로로 알린다.
+- Vega는 이 자리에 들어간다. 인터페이스 어휘를 fn과 표 보기 위의 규약으로 제공하는 aup 라이브러리다.
+
+한도: fn 64개, 매개변수 8개, 라이브러리 8개.
+
+검증: 라이브러리를 쓴 할 일 목록이 참조 모델과 일치하고, 인자를 한 번만 계산하며(값 전달), 라이브러리 경로·순환·
+상태 선언·앱 상태 읽기 오류가 해당 파일 위치로 보고된다. 같은 소스와 라이브러리는 같은 모듈을 만든다. 진단 10건을 더했다.
+
구현은 C로 손수 쓴 재귀 하강 파서를 유지한다. 문법은 EBNF로 문서화하고, 이후 `aup fmt`와 언어 서버를 붙인다.