구문 객체 내용
구문 객체 내용 (Syntax Object Content)
이 섹션은 구문 객체의 내용을 읽고 만드는 절차들을 다뤄요. 구문 객체가 되는 조건, 그 안에 담긴 데이터를 꺼내는 syntax-e 계열, 그리고 데이터에서 구문 객체를 만드는 datum->syntax, 임시 식별자 생성 등을 다뤄요.
출처: Racket Reference
본문
(syntax? v) → boolean?
v : any/c
v가 구문 객체이면 #t, 아니면 #f를 반환해요. 구문 객체(Syntax Objects)도 함께 보세요.
예제:
> (syntax? #'quinoa)
#t
> (syntax? #'(spelt triticale buckwheat))
#t
> (syntax? (datum->syntax #f 'millet))
#t
> (syntax? "barley")
#f
(identifier? v) → boolean?
v : any/c
v가 구문 객체이고 (syntax-e stx)가 심볼을 만들어내면 #t를 반환해요.
예제:
> (identifier? #'linguine)
#t
> (identifier? #'(if wheat? udon soba))
#f
> (identifier? 'ramen)
#f
> (identifier? 15)
#f
(syntax-source stx) → any/c
stx : syntax?
구문 객체 stx의 소스 위치 중 소스 구성 요소를 반환하고, 알려진 것이 없으면 #f를 반환해요. 소스는 임의의 값(예: read-syntax에 전달된 값)으로 표현되지만, 보통 파일 경로 문자열이에요.
racket/syntax-srcloc의 syntax-srcloc도 함께 보세요.
(syntax-line stx) → (or/c exact-positive-integer? #f)
stx : syntax?
그 소스에서 구문 객체의 시작에 대한 소스 위치의 줄 번호(양의 정확한 정수)를 반환하고, 줄 번호나 소스가 알려지지 않았으면 #f를 반환해요. 위치, 줄, 열 세기(Counting Positions, Lines, and Columns)도 함께 보세요.
base 패키지 7.0 버전에서
syntax-line과syntax-column이 둘 다#f를 만들거나 둘 다 정수를 만든다는 보장을 버렸어요.
(syntax-column stx) → (or/c exact-nonnegative-integer? #f)
stx : syntax?
그 소스에서 구문 객체의 시작에 대한 소스 위치의 열 번호(음이 아닌 정확한 정수)를 반환하고, 소스 열이 알려지지 않았으면 #f를 반환해요. 위치, 줄, 열 세기(Counting Positions, Lines, and Columns)도 함께 보세요.
base 패키지 7.0 버전에서
syntax-line과syntax-column이 둘 다#f를 만들거나 둘 다 정수를 만든다는 보장을 버렸어요.
(syntax-position stx) → (or/c exact-positive-integer? #f)
stx : syntax?
그 소스에서 구문 객체의 시작에 대한 소스 위치의 위치(양의 정확한 정수)를 반환하고, 소스 위치가 알려지지 않았으면 #f를 반환해요. 위치는 문자 위치를 의도하지만, 줄 세기가 활성화되지 않은 포트에서 읽으면 바이트 오프셋으로 위치가 만들어져요. 위치, 줄, 열 세기(Counting Positions, Lines, and Columns)도 함께 보세요.
(syntax-span stx) → (or/c exact-nonnegative-integer? #f)
stx : syntax?
그 소스에서 구문 객체에 대한 소스 위치의 범위(span, 음이 아닌 정확한 정수)를 반환하고, 범위가 알려지지 않았으면 #f를 반환해요. 범위는 문자로 세는 것을 의도하지만, 줄 세기가 활성화되지 않은 포트에서 읽으면 바이트 단위의 범위가 만들어져요. 위치, 줄, 열 세기(Counting Positions, Lines, and Columns)도 함께 보세요.
(syntax-original? stx) → boolean?
stx : syntax?
stx가 read-syntax가 만드는 구문 객체에 붙이는 속성(구문 객체 속성 참고)을 가지고 있고, stx의 어휘 정보가 매크로 도입 스코프(객체가 구문 변환기에 의해 도입되었음을 나타냄. 구문 객체 참고)를 포함하지 않으면 #t를, 아니면 #f를 반환해요.
이 술어는 확장된 표현식에서 원래 표현식에 직접 있던 구문 객체와 매크로가 삽입한 구문 객체를 구별하는 데 쓸 수 있어요.
원래 구문을 나타내는 (숨겨진) 속성은 컴파일된 코드의 일부로 마샬링되는 구문 객체에 대해 버려져요. current-compile도 함께 보세요.
(syntax-source-module stx [source?])
→ (or/c module-path-index? symbol? path? resolved-module-path? #f)
stx : syntax?
source? : any/c = #f
소스가 stx를 포함하는 모듈의 표시를 반환하고, stx에 대한 소스 모듈이 그 어휘 문맥에서 추론될 수 없으면 #f를 반환해요. source?가 #f면 결과는 모듈 경로 인덱스, 심볼(컴파일된 모듈과 참조 참고), 또는 해석된 모듈 경로예요. source?가 참이면 결과는 current-module-declare-source의 의미에서 로드된 모듈 소스에 대응하는 경로나 심볼이에요.
syntax-source-module은 stx의 소스 위치를 참고하지 않는다는 점을 기억하세요. 결과는 stx의 어휘 정보에 기반해요.
(syntax-e stx) → any/c
stx : syntax?
구문 객체에서 즉시 데이터 구조를 언랩하고, 중첩된 구문 구조(있으면)는 그 자리에 남겨둬요. (syntax-e stx)의 결과는 다음 중 하나예요.
- 심볼
- 구문 쌍(아래에서 설명)
- 빈 목록
- 구문 객체를 담은 불변 벡터
- 구문 객체를 담은 불변 상자
- 구문 객체 값을 담은(반드시 구문 객체 키는 아닌) 불변 해시 테이블
- 구문 객체를 담은 불변 prefab 구조체
datum-intern-literal이 값을 변환하면 인터닝되는 다른 종류의 데이터—보통 숫자, 불리언, 또는 문자열
예제:
> (syntax-e #'a)
'a
> (syntax-e #'(x . y))
'(#<syntax:eval:11:0 x> . #<syntax:eval:11:0 y>)
> (syntax-e #'#(1 2 (+ 3 4)))
'#(#<syntax:eval:12:0 1> #<syntax:eval:12:0 2> #<syntax:eval:12:0 (+ 3 4)>)
> (syntax-e #'#&"hello world")
'#&#<syntax:eval:13:0 "hello world">
> (syntax-e #'#hash((imperial . "yellow") (festival . "green")))
'#hash((festival . #<syntax:eval:14:0 "green">)
(imperial . #<syntax:eval:14:0 "yellow">))
> (syntax-e #'#(point 3 4))
'#(#<syntax:eval:15:0 point> #<syntax:eval:15:0 3> #<syntax:eval:15:0 4>)
> (syntax-e #'3)
3
> (syntax-e #'"three")
"three"
> (syntax-e #'#t)
#t
구문 쌍(syntax pair)은 첫 번째 요소가 구문 객체이고 두 번째 요소가 빈 목록, 구문 쌍, 또는 구문 객체인 쌍이에요.
read-syntax의 결과인 구문 객체는 입력에서 구분된 .의 사용을 반영하는데, 소스의 모든 괄호 쌍마다 구문 객체를 만들고, 소스의 괄호에 대해서만 쌍-값 구문 객체를 만들어요. 쌍과 목록 읽기(Reading Pairs and Lists)에서 더 자세한 정보를 확인하세요.
stx가 오염되어 있으면, (syntax-e stx)의 결과에 있는 모든 구문 객체는 오염돼요. stx에 대한 syntax-e의 여러 호출 결과들은 eq?예요.
(syntax->list stx) → (or/c list? #f)
stx : syntax?
구문 객체의 목록이나 #f를 반환해요. (syntax->datum stx)가 목록을 만들 때 결과는 구문 객체들의 목록이에요. 즉 (syntax-e stx)의 구문 쌍들은 펴집니다(flatten).
stx가 오염되어 있으면, (syntax->list stx)의 결과에 있는 모든 구문 객체는 오염돼요.
예제:
> (syntax->list #'())
'()
> (syntax->list #'(1 (+ 3 4) 5 6))
'(#<syntax:eval:20:0 1>
#<syntax:eval:20:0 (+ 3 4)>
#<syntax:eval:20:0 5>
#<syntax:eval:20:0 6>)
> (syntax->list #'a)
#f
(syntax->datum stx) → any/c
stx : syntax?
stx에서 어휘 정보, 소스 위치 정보, 속성, 그리고 변조(tamper) 상태를 벗겨내 데이터(datum)를 반환해요. 쌍, (불변) 벡터, (불변) 상자, 불변 해시 테이블 값(키는 아님), 그리고 불변 prefab 구조체 안에서 구문 객체는 재귀적으로 벗겨져요.
벗기는 동작은 stx를 변형하지 않아요. 어휘 정보와 소스 위치 정보를 재귀적으로 벗기기 위해 필요할 때 새 쌍, 벡터, 상자, 해시 테이블, prefab 구조체를 만들어요.
예제:
> (syntax->datum #'a)
'a
> (syntax->datum #'(x . y))
'(x . y)
> (syntax->datum #'#(1 2 (+ 3 4)))
'#(1 2 (+ 3 4))
> (syntax->datum #'#&"hello world")
'#&"hello world"
> (syntax->datum #'#hash((imperial . "yellow") (festival . "green")))
'#hash((festival . "green") (imperial . "yellow"))
> (syntax->datum #'#(point 3 4))
'#(point 3 4)
> (syntax->datum #'3)
3
> (syntax->datum #'"three")
"three"
> (syntax->datum #'#t)
#t
(datum->syntax ctxt v [srcloc prop ignored]) → syntax?
ctxt : (or/c syntax? #f)
v : any/c
srcloc : (or/c #f syntax? srcloc?
(list/c any/c
(or/c exact-positive-integer? #f)
(or/c exact-nonnegative-integer? #f)
(or/c exact-positive-integer? #f)
(or/c exact-nonnegative-integer? #f))
(vector/c any/c
(or/c exact-positive-integer? #f)
(or/c exact-nonnegative-integer? #f)
(or/c exact-positive-integer? #f)
(or/c exact-nonnegative-integer? #f))) = #f
prop : (or/c syntax? #f) = #f
ignored : (or/c syntax? #f) = #f
데이터 v를 구문 객체로 변환해요. v가 이미 구문 객체라면 변환이 없고, v가 수정되지 않은 채 반환돼요. 쌍, 벡터, 상자의 내용, 불변 해시 테이블의 값, 불변 prefab 구조체의 필드는 재귀적으로 변환돼요. prefab 구조체의 키와 불변 해시 테이블의 키는 변환되지 않아요. 변경 가능한 벡터와 상자는 불변 벡터와 상자로 대체돼요. 쌍, 벡터, 상자, 불변 해시 테이블, 불변 prefab 구조체, 구문 객체 외의 다른 종류의 값에 대해 변환은 datum-intern-literal로 값을 인터닝한 뒤 어휘 정보, 소스 위치 정보, 속성으로 값을 감싸는 것을 의미해요.
v의 변환된 객체들에는 ctxt의 어휘 문맥 정보와 srcloc의 소스 위치 정보가 주어져요. 변환에서 만들어진 즉시 구문 객체에는 prop의 속성(구문 객체 속성 참고)이 주어져요(syntax-property-symbol-keys로는 보이지 않을 숨겨진 것까지). v가 쌍, 벡터, 상자, 불변 해시 테이블, 또는 불변 prefab 구조체라면 재귀적으로 변환된 값에는 속성이 주어지지 않아요. ctxt가 오염되어 있으면 datum->syntax의 결과 구문 객체는 오염돼요. ctxt의 코드 검사자(있으면)는 현재 변환되고 있는 매크로의 모듈 코드 검사자(있으면)와 비교돼요. 두 검사자 모두 사용 가능하고 한쪽이 다른 쪽과 같거나 열등하면 결과 구문은 같거나 열등한 검사자를 갖고, 그렇지 않으면 코드 검사자가 없어요.
ctxt, srcloc, prop 중 어느 것이든 #f일 수 있고, 그 경우 결과 구문은 어휘 문맥, 소스 정보, 및/또는 새 속성이 없어요.
srcloc이 #f, srcloc 인스턴스, 또는 구문 객체가 아니라면, srcloc 필드에 대응하는 다섯 요소의 목록이나 벡터여야 해요.
v의 변환에서 그래프 구조는 보존되지 않아요. 대신 v는 본질적으로 트리로 펴집니다. v가 쌍, 벡터, 상자, 불변 해시 테이블, 불변 prefab 구조체를 통한 순환을 가지면 exn:fail:contract 예외가 발생해요.
ignored 인자는 하위 호환성을 위해 허용되며 반환된 구문 객체에 효과가 없어요.
base 패키지 8.2.0.5 버전에서
srcloc인자로srcloc값을 허용하도록 바뀌었어요.
(syntax-binding-set? v) → boolean?
v : any/c
(syntax-binding-set) → syntax-binding-set?
(syntax-binding-set->syntax binding-set datum) → syntax?
binding-set : syntax-binding-set?
datum : any/c
(syntax-binding-set-extend binding-set symbol phase mpi
[ #:source-symbol source-symbol
#:source-phase source-phase
#:nominal-module nominal-mpi
#:nominal-phase nominal-phase
#:nominal-symbol nominal-symbol
#:nominal-require-phase nominal-require-phase
#:inspector inspector])
→ syntax-binding-set?
binding-set : syntax-binding-set?
symbol : symbol?
phase : (or/c exact-integer? #f)
mpi : module-path-index?
source-symbol : symbol? = symbol
source-phase : (or/c exact-integer? #f) = phase
nominal-mpi : module-path-index? = mpi
nominal-phase : (or/c exact-integer? #f) = source-phase
nominal-symbol : symbol? = source-symbol
nominal-require-phase : (or/c exact-integer? #f) = 0
inspector : (or/c inspector? #f) = #f
구문 바인딩 집합(syntax binding set)은 구문 객체에 대한 바인딩 정보의 명시적 구성을 지원해요. syntax-binding-set으로 빈 바인딩 집합을 만들기 시작하고, syntax-binding-set-extend로 바인딩을 추가하고, syntax-binding-set->syntax로 바인딩을 어휘 정보로 가진 구문 객체를 만들어요.
syntax-binding-set-extend의 처음 세 인자는 phase에서 symbol의 바인딩을 mpi가 참조하는 모듈에 정의된 식별자로 설정해요. source-symbol을 제공해 symbol의 바인딩이 mpi의 다른 제공 변수를 가리키게 하는 식이에요. 선택적 인자들은 identifier-binding의 결과에 대응해요.
base 패키지 7.0.0.12 버전에서 추가.
(datum-intern-literal v) → any/c
v : any/c
일부 값을 기본 리더가 read-syntax 모드에서 만들어내는 인터닝된 결과와 일관되도록 변환해요.
v가 숫자, 문자, 문자열, 바이트 문자열, 또는 정규식이면, 결과는 v와 equal?이고 기본 리더의 잠재적 결과와 eq?인 값이에요. (변경 가능한 문자열과 바이트 문자열은 불변 문자열과 바이트 문자열로 인터닝된다는 점에 주의하세요.)
v가 인터닝되지 않았거나 읽을 수 없는 심볼이면 결과는 여전히 v예요. 인터닝된 심볼은 v와 equal?이지 않기 때문이에요.
변환 과정은 복합 값을 통과하지 않아요. 예를 들어 v가 문자열을 담은 쌍이라면, v 안의 문자열은 인터닝되지 않아요.
v1과 v2가 equal?인데 eq?가 아니라면, (datum-intern-literal v1)은 v1을 반환하고—v1이 가비지 컬렉터가 결정하는 대로(가비지 컬렉션 참고) 도달 불가능해진 후 어느 시점—(datum-intern-literal v2)는 여전히 v2를 반환할 가능성이 있어요. 즉 datum-intern-literal은 주어진 값을 인터닝된 대표로 채택할 수 있지만, 이전 대표가 그 외에는 도달 불가능해지면 datum-intern-literal은 새 대표를 채택할 수 있어요.
(syntax-shift-phase-level stx shift) → syntax?
stx : syntax?
shift : (or/c exact-integer? #f)
stx와 같지만 모든 최상위 및 모듈 바인딩이 shift 단계 수준만큼 이동된 구문 객체를 반환해요. shift가 #f면 단계 수준 0의 바인딩만 라벨 단계 수준으로 이동해요. 정수 shift로 이동하면 어떤 단계가 라벨 단계 수준으로 옮겨졌는지 효과적으로 조정돼요. shift가 0이면 결과는 stx예요.
base 패키지 9.0.0.1 버전에서 정수 단계 수준으로 이동하면 라벨 단계 수준에서 어떤 원래 단계가 보이는지 조정하도록 바뀌었어요.
(generate-temporaries v) → (listof identifier?)
v : stx-list?
다른 모든 식별자와 구별되는 식별자들의 목록을 반환해요. 목록은 v가 가진 요소 수만큼의 식별자를 담아요. v의 요소는 무엇이든 될 수 있지만, 문자열, 심볼, 키워드(구문으로 감싸여 있을 수 있음), 식별자 요소는 대응하는 생성된 이름에 포함되며, 이는 디버깅에 유용해요.
생성된 식별자는 인터닝된 심볼로 만들어져요(gen이 아님). 컴파일된 코드 인쇄(Printing Compiled Code)도 함께 보세요.
예제:
> (generate-temporaries '(a b c d))
'(#<syntax a1> #<syntax b2> #<syntax c3> #<syntax d4>)
> (generate-temporaries #'(1 2 3 4))
'(#<syntax temp5> #<syntax temp6> #<syntax temp7> #<syntax temp8>)
> (define-syntax (set!-values stx)
(syntax-case stx ()
[(_ (id ...) expr)
(with-syntax ([(temp ...) (generate-temporaries #'(id ...))])
#'(let-values ([(temp ...) expr])
(set! id temp) ... (void)))]))
(identifier-prune-lexical-context id-stx [syms]) → identifier?
id-stx : identifier?
syms : (listof symbol?) = (list (syntax-e id-stx))
id-stx와 같은 바인딩을 가지지만, syms의 심볼에는 적용되지 않는 id-stx의 어휘 정보(있으면)가 없는 식별자를 반환해요. 여기서 어휘 정보의 추가 확장은 다른 심볼에 대한 정보를 버려요. 특히 이 함수 결과의 어휘 문맥을 datum->syntax로 전달해 syms에 없는 심볼에 전달하면 바인딩 없는 식별자를 만들 수 있어요.
현재 결과는 항상 정확히 id-stx예요. 가지치기(pruning)는 주로 이전 Racket 버전에서 일종의 최적화로 의도되었지만, 현재 매크로 확장기에서는 덜 유용하고 효율적으로 구현하기 어려워요.
quote-syntax/prune도 함께 보세요.
base 패키지 6.5 버전에서 항상
id-stx를 반환하도록 바뀌었어요.
(identifier-prune-to-source-module id-stx) → identifier?
id-stx : identifier?
어휘 문맥이 syntax-source-module에 필요한 것만 남도록 최소화된 식별자를 반환해요. 최소화된 어휘 문맥은 바인딩을 포함하지 않아요.
(syntax-recertify new-stx old-stx inspector key) → syntax?
new-stx : syntax?
old-stx : syntax?
inspector : inspector?
key : any/c
하위 호환성을 위해서만 존재하며, new-stx를 반환해요.
(syntax-debug-info stx [phase all-bindings?]) → hash?
stx : syntax?
phase : (or/c exact-integer? #f) = (syntax-local-phase-level)
all-bindings? : any/c = #f
stx의 어휘 정보를 설명하는 해시 테이블을 만들어내요((syntax-e stx)가 복합 값을 반환할 때 구성 요소는 세지 않음). 결과는 다음 키를 포함할 수 있지만 그에 국한되지는 않아요.
-
'name—(syntax-e stx)의 결과(심볼일 때) -
'context— 벡터들의 목록. 각 벡터는stx에 붙은 스코프를 나타냄.각 벡터는 모든 스코프에 구별되는 숫자로 시작해요. 그 뒤의 심볼은 스코프의 기원에 대한 힌트를 제공해요: 모듈 스코프는
'module, 매크로 도입 스코프는'macro, 매크로 사용 지점 스코프는'use-site, 지역 바인딩 형식은'local. 안쪽 가장자리(inside edge)에 대응하는'module스코프의 경우 모듈의 이름과 단계가 표시돼요(안쪽 가장자리 스코프는 각 단계에 대해 생성되므로). -
'bindings— 각각 해시 테이블로 표현되는 바인딩들의 목록. 바인딩 테이블은 다음 키를 포함할 수 있지만 그에 국한되지는 않아요.'name— 바인딩의 기호 이름.'context— 바인딩의 스코프들(벡터들의 목록).'local— 지역 바인딩을 나타내는 심볼. 이 키가 있으면'module은 없다.'module— 다른 모듈에서의 가져오기 인코딩. 이 키가 있으면'local은 없다.'free-identifier=?— 바인딩이 별명인 식별자로부터의 디버깅 정보 해시 테이블.'fallbacks— 크로스 네임스페이스 바인딩 폴백을 위한syntax-debug-info가 만든 것과 같은 해시 테이블들의 목록.
base 패키지 6.3 버전에서 추가.
12.2.1 구문 객체 소스 위치
(require racket/syntax-srcloc) ; package: base
이 섹션에서 다루는 바인딩은 racket/base나 racket이 아니라 racket/syntax-srcloc 라이브러리가 제공해요.
(syntax-srcloc stx) → (or/c #f srcloc?)
stx : syntax?
구문 객체 stx의 소스 위치를 반환하고, 알려진 것이 없으면 #f를 반환해요.
base 패키지 8.2.0.5 버전에서 추가.
더 알아보기
- 구문 객체(Syntax Objects)
- 구문 객체 속성(Syntax Object Properties)
datum-intern-literal,datum->syntax- 위치, 줄, 열 세기(Counting Positions, Lines, and Columns)