이 단계가 답하는 질문은 하나다 — 이 모듈 하나만 보고 무엇을 결정할 수 있는가.
그 경계를 산출물로 만들었다.
결정할 수 있는 것은 오류로 보고한다: 중복 정의, 중복 파라미터·제네릭,
선언되지 않은 effect 변수, 같은 블록의 재바인딩, 불변 바인딩에 대한 대입,
모듈에 없는 reexport 대상, 지역 바인딩이 아닌 scope 이름, variant 인자 개수.
결정할 수 없는 것은 외부 참조로 기록하고 오류로 만들지 않는다. 모듈 로딩이
아직 없으므로 해소할 방법이 없고, 이 목록이 곧 모듈의 의존 표면이자
interface hash가 소비할 입력이다. cool deps로 볼 수 있다.
이름 해소가 아니면 못 하는 판정 하나를 구현했다: match의 맨 이름이 바인딩인지
인자 없는 생성자인지는 구문으로 갈리지 않는다. enum 선언에서 만든 생성자
표로 판정하고, 같은 표로 인자 개수도 검사한다.
샘플에서 실제 오류 둘을 잡았다:
- 03의 scope inner가 어디서도 오지 않는다. scope X { }의 X가 "이미 가진
TaskScope를 쓴다"인지 "새 자식 스코프를 만들어 X로 묶는다"인지가 정해지지
않은 탓이다. 후자라면 자식의 부모가 구문에 없어 ambient authority가 된다.
결정 전까지 해당 예제를 주석으로 두고 이유를 적었다.
- 03이 List를 import 없이 쓰고 있었다. 외부 참조 목록에 드러나 채웠다.
TaskScope가 use 값이라는 사실에서 검사 하나가 따라 나온다: scope의 머리는
모듈 수준 이름일 수 없고 반드시 지역 바인딩이어야 한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZVDeU6KLuUVL3gs18Hm3E
samples — 문법 탐침
여기 있는 .cool 파일은 명세가 아니라 탐침이다. 목적은
docs/thesis.md의 v0 성공 기준 중 "체감" 항목 — 확정된 규칙으로 짠 코드가
사람이 읽을 만한지 — 을 눈으로 확인하는 것. 문법 정의는 docs/grammar.ebnf.
파서는 아직 없으므로 이 파일들은 컴파일되지 않는다.
| 파일 | 검증 대상 |
|---|---|
| 01_capability_signature | capability 파라미터, effects 절 어순, capability struct 관용구 |
| 02_higher_order_effects | effect 변수, 구문 수준 제한, 명시적 인스턴스화 |
| 03_scope_concurrency | TaskScope, 이름 있는 scope, 중첩 시 수명 표현 |
| 04_enum_match_interface | enum 정의 본문이 interface surface에 들어가는 경로 |
| 05_move_errors | 에러가 나야 하는 코드 — 진단 하나씩 |
| 06_affine_closure | callable affinity (fn vs affine fn), own과의 직교성 |
| 07_module_interface | interface artifact가 담아야 할 것 전부 |
| 08_syntax_errors | 파서가 거부해야 하는 코드 |
05와 08은 통과하면 안 되는 파일이다. 각 함수 주석의 [E-...] 태그가 기대
진단이다. 둘의 목적이 다르다 — 05는 구문은 맞지만 검사기가 거부해야 하고,
08은 파서가 거부해야 한다. 그래서 파일을 나눴다: 한 파일에 섞으면 파서가
첫 오류에서 멈춰 검사기 케이스에 영영 도달하지 못한다.
오류 복구는 아직 없다. 파서는 첫 오류에서 멈춘다.
확정된 표기
- 어순:
fn 이름(파라미터) effects {...} -> 반환타입. 함수 타입도 동일:fn(a) effects e -> b - 파라미터는 기본이 빌림(use, 무표기). 소유 이전만
own유표기. capability든 클로저든 일반 affine 값이든 규칙은 하나다 - 파라미터 밖(반환 타입, struct 필드, channel 원소)은 항상 owned, 무표기
- 제네릭은 대괄호: 타입
List[a], 식map[Int, String, {fs.read}](xs, f). 인덱싱 연산자는 두지 않는다 (List.at) - 수식어 순서:
own/mut가 먼저, 타입 수식어affine은 타입 안 - 모듈: 파일 = 모듈,
pub이 exported,import "domain/path" as Name - 재수출:
reexport Name(전용 키워드 — hash 전파를 동반한다) - effect 집합:
effects {Type.method, ...}, 빈 집합은 생략 - effect 변수:
[e: effects]선언, 합집합e1 | e2는 결과 위치 전용 - 문 구분은 줄바꿈 (Go식 자동 삽입)
- 블록은 식. 마지막 식이 값이고
return은 조기 탈출 전용 if와match는 식.match가드 없음- 리스트 리터럴
[a, b, c], 빈 리터럴은 타입 주석 필요 - 오류 전파
?는Result전용