리스펙스는 입력 S‑표현식 표면과 결정론적 정규화를 정의합니다. 이 문서는 파싱/정규화 단계에서 발생하는 진단을 다룹니다. 런타임 결함은 레퍼런스 인터프리터가 발생시키며, 플레이그라운드에서 직접 시도해 볼 수 있습니다.
진단 코드
권장되는 코드 체계:
- E100 구문 오류. 불법 토큰, 괄호 오류, 점리스트 오류입니다.
- E110 예약어 오류. 예약어 바인딩 시도입니다.
- E120 매크로 오류. 사용자 매크로나 리더 확장 금지 위반입니다.
- E130 파생 폼 오류. 빈
cond같은 잘못된 파생 폼입니다. - E140 구문 오류. 점 뒤 추가 항목 같은 잘못된 점리스트 형태입니다.
- E150 문자열 오류. 잘못됐거나 범위를 넘은 이스케이프입니다.
- W200 정적 경고. 사용되지 않는 바인딩입니다. 예약 항목이며 레퍼런스 인터프리터는 아직 방출하지 않습니다.
- W210 정적 경고.
letrec즉시 자기 참조 가능성입니다. 예약 항목이며 아직 방출하지 않습니다. - W330 스타일 경고.
%별칭 사용 감지입니다.modulo사용을 권장합니다. - W331 스타일 경고.
list-first또는list-rest별칭 사용입니다.first또는rest사용을 권장합니다.
메시지 형식(권장): CODE file:line:col message
예시
E110: 예약어 바인딩 금지
LISPEX
(let ((if 1)) if) ; E110: 예약어 바인딩 불가: ifE120: 금지된 매크로/리더 폼
LISPEX
(define-syntax swap ...) ; E120: 사용자 매크로 금지
#; (reader extension example) ; E120E130: 잘못된 파생 폼
LISPEX
(cond) ; E130: 빈 condE100: 점리스트 구문 오류
LISPEX
(a b . c d) ; E100: 잘못된 점리스트E140: 잘못된 점리스트 형태
LISPEX
(a .) ; E140: 점 뒤 꼬리 누락W330: modulo 별칭 경고
% 대신 modulo 사용을 권장합니다.
LISPEX
(% 10 3) ; W330: (modulo 10 3) 권장복구 가능한 에러 처리
런타임 결함은 잡을 수 있습니다. guard는 던져진 조건을 묶고 cond 식 절을 실행하며, 어느 절도 맞지 않고 else도 없으면 다시 던집니다.
LISPEX
(guard (e ((error-object? e) (error-object-message e))
(else e))
(error "file not found" 404)) ; ⇒ "file not found"(raise obj)는 임의의 객체를 던지며 복구 불가입니다.(raise-continuable obj)는 핸들러가 값을 호출 지점으로 되돌릴 수 있게 합니다.(error message irritant…)는 에러 객체를 만들어 던집니다.error-object?/error-object-message/error-object-irritants로 살핍니다. 잡힌 내장 결함(미정의 변수, 비쌍에 대한car등)도 에러 객체입니다.(with-exception-handler handler thunk)는 저수준 프리미티브이며 핸들러는 raise 지점에서 바깥 핸들러를 현재로 두고 실행됩니다. 평소에는guard를 씁니다.- 결정론적 재귀 한도는 잡히지 않으며 항상 최상위로 빠져나갑니다.
모범 사례
- 코어 폼과 허용된 파생 폼만 사용하고, 사용자 매크로 구성은 피하세요.
- 순차 의존이 있으면
let*, 지역 재귀는letrec을 사용하세요. - (선택)
(module ...)표면 헤더는 간단히 유지하세요. 최상위로 평탄화됩니다. - 정규화 스냅샷/골든 테스트로 E130을 조기에 잡으세요.