Reflection and introspection

줄리아는 다양한 런타임 반사 기능을 제공합니다.

Module bindings

Module의 공개 이름은 names(m::Module)를 사용하여 확인할 수 있으며, 이는 공개 바인딩을 나타내는 Symbol 요소의 배열을 반환합니다. names(m::Module, all = true)는 공개 상태에 관계없이 m의 모든 바인딩에 대한 기호를 반환합니다.

DataType fields

DataType 필드의 이름은 fieldnames를 사용하여 조회할 수 있습니다. 예를 들어, 다음 유형이 주어지면 fieldnames(Point)는 필드 이름을 나타내는 Symbol의 튜플을 반환합니다:

julia> struct Point
           x::Int
           y
       end

julia> fieldnames(Point)
(:x, :y)

Point 객체의 각 필드 유형은 Point 변수 자체의 types 필드에 저장됩니다:

julia> Point.types
svec(Int64, Any)

xInt로 주석이 달려 있지만, y는 타입 정의에서 주석이 없으므로 y는 기본적으로 Any 타입이 됩니다.

유형은 DataType이라고 하는 구조체로 표현됩니다:

julia> typeof(Point)
DataType

fieldnames(DataType)DataType 자체의 각 필드 이름을 제공하며, 이 필드 중 하나가 위의 예에서 관찰된 types 필드입니다.

Subtypes

DataType직접 하위 유형은 subtypes를 사용하여 나열할 수 있습니다. 예를 들어, 추상 DataType AbstractFloat는 네 개의 (구체적인) 하위 유형을 가지고 있습니다:

julia> InteractiveUtils.subtypes(AbstractFloat)
5-element Vector{Any}:
 BigFloat
 Core.BFloat16
 Float16
 Float32
 Float64

이 목록에는 모든 추상 하위 유형도 포함되지만, 그 하위 유형은 포함되지 않습니다; subtypes의 재귀적 적용을 통해 전체 유형 트리를 검사할 수 있습니다.

subtypesInteractiveUtils 내부에 위치하지만, REPL을 사용할 때 자동으로 내보내집니다.

DataType layout

DataType의 내부 표현은 C 코드와 인터페이스할 때 매우 중요하며, 이러한 세부 정보를 검사할 수 있는 여러 함수가 제공됩니다. isbitstype(T::DataType)T가 C 호환 정렬로 저장되어 있으면 true를 반환합니다. fieldoffset(T::DataType, i::Integer)는 필드 i의 (바이트) 오프셋을 타입의 시작에 상대적으로 반환합니다.

Function methods

어떤 일반 함수의 메서드는 methods를 사용하여 나열할 수 있습니다. 주어진 유형을 수용하는 메서드를 찾기 위해 메서드 디스패치 테이블을 검색할 수 있습니다 methodswith.

Expansion and lowering

As discussed in the Metaprogramming section, the macroexpand function gives the unquoted and interpolated expression (Expr) form for a given macro. To use macroexpand, quote the expression block itself (otherwise, the macro will be evaluated and the result will be passed instead!). For example:

julia> InteractiveUtils.macroexpand(@__MODULE__, :(@edit println("")) )
:(InteractiveUtils.edit(println, (Base.typesof)("")))

함수 Base.Meta.show_sexprdump는 모든 표현식에 대해 S-표현식 스타일 보기와 깊이 중첩된 세부 정보 보기를 표시하는 데 사용됩니다.

마침내, Meta.lower 함수는 모든 표현식의 lowered 형태를 제공하며, 이는 언어 구조가 할당, 분기 및 호출과 같은 원시 작업에 어떻게 매핑되는지를 이해하는 데 특히 중요합니다:

julia> Meta.lower(@__MODULE__, :( [1+2, sin(0.5)] ))
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = 1 + 2
│   %2 = sin(0.5)
│   %3 = Base.vect(%1, %2)
└──      return %3
))))

Intermediate and compiled representations

함수를 위한 낮춘 형태를 검사하려면, 특정 방법을 선택하여 표시해야 합니다. 일반 함수는 서로 다른 타입 서명을 가진 여러 방법을 가질 수 있기 때문입니다. 이 목적을 위해, 방법별 코드 낮추기가 code_lowered를 사용하여 가능합니다. 타입 추론된 형태는 code_typed를 사용하여 이용할 수 있습니다. code_warntype4d61726b646f776e2e436f64652822222c2022636f64655f74797065642229_40726566의 출력에 하이라이팅을 추가합니다.

기계에 더 가까운 LLVM 중간 표현은 code_llvm를 사용하여 인쇄할 수 있으며, 마지막으로 컴파일된 기계 코드는 code_native를 사용하여 사용할 수 있습니다(이는 이전에 호출되지 않은 모든 함수에 대해 JIT 컴파일/코드 생성을 트리거합니다).

편의를 위해 위의 함수들의 매크로 버전이 있으며, 이는 표준 함수 호출을 받아들이고 인수 유형을 자동으로 확장합니다:

julia> @code_llvm +(1,1)
;  @ int.jl:87 within `+`
; Function Attrs: sspstrong uwtable
define i64 @"julia_+_476"(i64 signext %0, i64 signext %1) #0 {
top:
  %2 = add i64 %1, %0
  ret i64 %2
}

자세한 내용은 @code_lowered, @code_typed, @code_warntype, @code_llvm, 및 @code_native를 참조하십시오.

Printing of debug information

앞서 언급한 함수와 매크로는 출력되는 디버그 정보의 수준을 제어하는 키워드 인수 debuginfo를 사용합니다.

julia> InteractiveUtils.@code_typed debuginfo=:source +(1,1)
CodeInfo(
    @ int.jl:87 within `+`
1 ─ %1 = Base.add_int(x, y)::Int64
└──      return %1
) => Int64

debuginfo의 가능한 값은 :none, :source, :default입니다. 기본적으로 디버그 정보는 출력되지 않지만, Base.IRShow.default_debuginfo[] = :source를 설정하면 변경할 수 있습니다.