F5 — "튜플이 없어서 enumerate가 불가능하다"고 적었는데 틀렸다. 제네릭 struct 하나면 된다. fold_indexed보다 이쪽이 낫다: enumerate 하나가 기존 each/map/filter/fold 전부와 조합되고, fold_indexed를 만들면 map_indexed, each_indexed가 따라와 "한 개념 한 방식"을 깬다. samples/app에서 Numbered struct가 사라졌다 (244줄 → 232줄). F2에 이어 두 번째로 관찰자가 틀린 사례다. 마찰 8건 중 2건이 "언어가 못 한다"고 적었다가 확인해 보니 되는 것이었다. F4 — 넣지 않는다. 전체 나열이 귀찮은 것은 맞지만 그 귀찮음이 값을 한다. 필드를 추가하면 모든 생성 지점이 컴파일 오류를 내고, 컴파일러가 전부 방문하도록 강제한다. ..base는 그것을 없앤다. "오류를 더 빨리 잡는다"가 1번 목표인데 F4는 정확히 그것을 깎는 거래다. F8 — 넣지 않는다. 진짜 질문은 "미사용 지역 변수를 잡을 것인가"가 아니라 "경고 등급을 만들 것인가"였다. 오류로 넣으면 성가시고, 경고로 넣으면 경고 등급의 첫 입주자가 된다. 경고가 없다는 것은 이 언어의 좋은 성질이고 죽은 지역 변수 하나 때문에 팔 것이 아니다. 둘 다 "보류"가 아니라 "닫음"으로 적는다. 근거를 적어두지 않으면 다음에 같은 논의를 처음부터 다시 한다. 다시 열 조건도 함께 적었다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZVDeU6KLuUVL3gs18Hm3E
134 lines
4.7 KiB
Markdown
134 lines
4.7 KiB
Markdown
# coollang
|
|
|
|
되돌리기 비싼 결정부터 확정하는 프로그래밍 언어. 현재 v0 — 설계 검증판.
|
|
|
|
```
|
|
$ coolc check samples/run/hello.cool
|
|
$ coolc run samples/run/hello.cool
|
|
area = 12
|
|
area = 9
|
|
area = 3
|
|
```
|
|
|
|
## 무엇을 위한 언어인가
|
|
|
|
세 가지 목표가 나머지 모든 결정을 지배한다.
|
|
|
|
1. **오류를 더 빨리 잡는다** — null 없음, Option/Result, 소진적 match,
|
|
확정 초기화, 선언되지 않은 effect는 컴파일 오류.
|
|
2. **검증이 더 빠르다** — fast path / slow path 분리, 전역 추론 없음,
|
|
복잡한 trait solver 없음, 임의 매크로 없음, 인터페이스 해시 기반 무효화.
|
|
3. **피해 범위가 좁다** — 명시적 capability, ambient authority 없음,
|
|
affine 소유권.
|
|
|
|
설계의 전문은 [`docs/thesis.md`](docs/thesis.md), 문법은
|
|
[`docs/grammar.ebnf`](docs/grammar.ebnf)에 있다.
|
|
|
|
## 지금 되는 것
|
|
|
|
`lex → parse → 이름 해소 → 타입 검사 → effect/capability 검사 →
|
|
move/affinity 검사 → 소진성 검사 → interface 해시 → typed IR → 인터프리터`
|
|
|
|
여섯 종류의 오류를 한국어 진단으로 보고한다: 문법, 이름, 타입, effect,
|
|
capability, 소유권. 여기에 match 소진성과 두 가지 lint(미사용 import,
|
|
effect 과잉 선언)가 더해진다.
|
|
|
|
```
|
|
$ coolc check samples/12_stdlib_effects.cool
|
|
samples/12_stdlib_effects.cool:20:14: 선언되지 않은 effect Console.print
|
|
(leaks_effect의 effects 절은 {}입니다)
|
|
```
|
|
|
|
## 증분 검사
|
|
|
|
이 프로젝트의 중심 주장이다. 10만 줄 / 200 모듈에서 측정 (`bench/bench.ml`):
|
|
|
|
| | 시간 | 재검사한 모듈 |
|
|
|---|---|---|
|
|
| 전체 검사 (cold) | 253ms | 200 |
|
|
| 함수 **본문**만 수정 | 0.8ms | **1** |
|
|
| 함수 **시그니처** 수정 | 2.5ms | **2** |
|
|
|
|
핵심은 시간이 아니라 범위다. 본문 수정이 downstream을 한 칸도 건드리지
|
|
않는 것, 그리고 시그니처 수정이 사슬 끝까지 가지 않고 해시가 변한 곳에서
|
|
멈추는 것 — 이 둘이 아키텍처의 주장 전부다.
|
|
|
|
시그니처 수정 시나리오에서는 두 모듈 건너의 `match`가 실제로 깨진다:
|
|
|
|
```
|
|
m100.cool:15:3: match가 모든 경우를 덮지 않습니다 (빠진 경우: Tri(_))
|
|
m101.cool:21:3: match가 모든 경우를 덮지 않습니다 (빠진 경우: Up.Tri(_))
|
|
```
|
|
|
|
## 실제로 써본 결과
|
|
|
|
`samples/app`은 검사기를 시험하려고 쓴 것이 아니라 일을 하려고 쓴
|
|
프로그램이다 — 설정 파서 + 리포트 도구, 2모듈 232줄.
|
|
|
|
```
|
|
$ coolc run samples/app/main.cool samples/app/example.conf
|
|
설정
|
|
name = "coollang" (text)
|
|
threads = 4 (number)
|
|
...
|
|
항목 5개, 문제 2개
|
|
|
|
문제
|
|
10행: 이름이 비어 있습니다
|
|
11행: = 가 하나여야 합니다: broken = a = b
|
|
```
|
|
|
|
쓰면서 걸린 것들을 [`docs/friction.md`](docs/friction.md)에 남겼다.
|
|
요약하면: **되돌리기 비싼 결정은 하나도 후회되지 않았고, 불편은 전부
|
|
되돌리기 싼 것들이었다.**
|
|
|
|
## 빌드
|
|
|
|
OCaml 5.x와 dune이 필요하다.
|
|
|
|
```
|
|
opam install dune
|
|
dune build
|
|
dune test # 175개 검사
|
|
dune exec bench/bench.exe
|
|
```
|
|
|
|
`coolc`는 `_build/default/bin/main.exe`다. 설치하려면 `dune install`.
|
|
|
|
## 저장소 구성
|
|
|
|
```
|
|
lib/ 컴파일러 (약 4,900줄 OCaml)
|
|
lexer.ml 어휘 분석 — 문법을 하나도 모른다
|
|
parser.ml 재귀 하강, LL(1), backtracking 없음
|
|
resolve.ml 이름 해소 — 모듈 하나만 보고 결정할 수 있는 것
|
|
typecheck.ml 타입 + effect + capability
|
|
move.ml move / affinity
|
|
exhaust.ml 소진성 (Maranget usefulness)
|
|
iface.ml interface artifact + 해시
|
|
session.ml 모듈 로딩 + 고정점 invalidation
|
|
ir.ml 얇은 typed IR
|
|
interp.ml 트리 워킹 인터프리터
|
|
std/ 표준 라이브러리 (본문 없는 선언, 런타임이 구현)
|
|
samples/ 예제 — 통과용 9개, 일부러 틀린 것 7개
|
|
bench/ 증분 루프 측정
|
|
```
|
|
|
|
## v0의 성격
|
|
|
|
이것은 쓸 수 있는 언어가 아니라 **설계가 옳은지 증명된 언어**다.
|
|
되돌리기 비싼 결정 — 문법, 타입, effect, capability, 소유권, 증분
|
|
아키텍처 — 이 전부 코드와 테스트로 못 박혔고, 빠른 검증 루프라는 시스템
|
|
속성이 측정으로 증명됐다.
|
|
|
|
그래서 이 코드를 통째로 버리고 v1로 번역해도 잃을 것이 없다. 애초에
|
|
그것이 v0의 목적이었다.
|
|
|
|
아직 없는 것: 진짜 컴파일(해석 실행만 한다), 병렬 실행(`scope`는 순차),
|
|
파일·네트워크 IO, 완전한 제네릭, 에디터 지원, 패키지 관리자. 표준
|
|
라이브러리는 `len`, `each`, `map`, `concat`, `show` 수준이다.
|
|
|
|
## 이름
|
|
|
|
언어는 coollang, 툴체인 바이너리는 `coolc`. 소스 확장자는 `.cool`.
|