이 제안은 Swift 2.2에 새로운 빌드 설정 옵션인 #if swift
를 추가하는 것을 목표로 한다.
Swift-evolution 관련 스레드: - Swift 2.2: #if swift 언어 버전 - 리뷰
시간이 지나면서 Swift 문법은 변경될 수 있지만, 라이브러리와 패키지 작성자는 자신의 코드가 여러 버전의 언어와 호환되기를 원한다. 지금까지 개발자들이 취할 수 있는 유일한 방법은 언어 버전을 따라가는 별도의 릴리스 브랜치를 유지하는 것이었다. 이제 개발자들은 별도의 소스 트리를 유지하지 않고도 문법 변경을 추적할 수 있는 또 다른 도구를 얻게 된다.
또한 소스 코드를 배포하는 패키지 작성자들이 언어 개정판 간 전환을 더 쉽게 할 수 있도록 지원하고자 한다. 이를 통해 클라이언트는 더 오래되거나 더 최신의 Swift 버전으로 패키지를 빌드할 수 있다.
이 솔루션은 간단한 예제를 통해 가장 잘 설명할 수 있다:
#if swift(>=2.2)
print("Active!")
#else
this! code! will! not! parse! or! produce! diagnostics!
#endif
이 기능은 이미 컴파일러에 존재하는 버전 메커니즘을 사용한다. 언어의 버전은 컴파일러가 빌드될 때 함께 포함되므로, 특정 코드 블록이 활성화되어야 하는지를 판단할 수 있다. 버전이 조건에 지정된 값보다 최신이면, 활성 분기를 파싱하고 코드로 컴파일한다.
다른 빌드 설정과 마찬가지로, #if swift
는 라인 기반이 아니다. 전체 문장이나 선언을 감싸는 방식으로 동작한다. 하지만 다른 설정과 달리, 컴파일러는 #if swift
로 보호된 비활성 분기를 파싱하지 않으며, 어휘 분석 관련 진단 메시지를 출력하지 않는다. 따라서 다른 Swift 버전의 문법적 차이를 동일한 파일에 포함할 수 있다.
현재는 두 가지 버전 구성 요소까지만 고려한다. 구문 변경이 +0.0.1 리비전에서 발생할 가능성은 희박하기 때문이다.
설정 함수의 인자는 단항 접두사 표현식으로, 간단함을 위해 >=
연산자 하나만 사용한다. 필요할 경우, 다른 비교 연산자를 포함하도록 확장할 수 있다.
이 메커니즘은 선택적으로 적용하는 방식이므로, 기존 코드는 이 변경으로 인해 영향을 받지 않는다.
버전 인자를 위한 두 가지 다른 형식을 고려했다:
문자열 리터럴 (#if swift("2.2")
): 이 방식은 임의의 수의 버전 구성 요소를 포함할 수 있지만, 마이너 리비전에서 문법 변경이 발생할 가능성은 낮다. 추가 버전 구성 요소가 필요할 경우, 파서 변경이 크게 어렵지 않다.
단순 형식 (#if swift(2.2)
): >=
가 기본값으로 적절하지만, 여기서 비교가 무엇인지 명확하지 않아 ==
로 오해할 수 있다.
인자 목록 (#if swift(2, 2)
): 이 방식은 유연하게 파싱되지만, 두 번째 2
가 전체 버전의 구성 요소가 아니라 다른 의미의 인자로 해석될 가능성이 있다.