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 مخزن في حقل types من متغير Point نفسه:

julia> Point.types
svec(Int64, Any)

بينما تم توضيح x كـ Int، لم يتم توضيح 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 لفحص شجرة الأنواع الكاملة.

لاحظ أن subtypes يقع داخل InteractiveUtils ولكنه يتم تصديره تلقائيًا عند استخدام REPL.

DataType layout

تمثيل DataType الداخلي مهم للغاية عند التفاعل مع كود C وتتوفر عدة وظائف لفحص هذه التفاصيل. isbitstype(T::DataType) تعيد true إذا كان T مخزناً بمحاذاة متوافقة مع C. fieldoffset(T::DataType, i::Integer) تعيد الإزاحة (بالبايت) للحقل i بالنسبة لبداية النوع.

Function methods

يمكن سرد طرق أي دالة عامة باستخدام methods. يمكن البحث في جدول إرسال الطرق عن الطرق التي تقبل نوعًا معينًا باستخدام methodswith.

Expansion and lowering

كما تم مناقشته في قسم Metaprogramming، فإن دالة macroexpand تعطي التعبير غير المقتبس والمُدخل (Expr) في شكل ماكرو معين. لاستخدام macroexpand، يجب عليك quote كتلة التعبير نفسها (وإلا، سيتم تقييم الماكرو وسيتم تمرير النتيجة بدلاً من ذلك!). على سبيل المثال:

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

تستخدم الدوال Base.Meta.show_sexpr و dump لعرض طرق عرض على طراز S-expr وطرق عرض تفصيلية متداخلة بعمق لأي تعبير.

أخيرًا، تعطي دالة 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_warntype يضيف تمييزًا إلى مخرجات 4d61726b646f776e2e436f64652822222c2022636f64655f74797065642229_40726566.

أقرب إلى الآلة، يمكن طباعة تمثيل LLVM الوسيط لدالة باستخدام code_llvm، وأخيرًا، يتوفر كود الآلة المترجم باستخدام code_native (سيؤدي ذلك إلى تفعيل الترجمة الفورية/توليد الكود لأي دالة لم يتم استدعاؤها سابقًا).

لراحة، هناك نسخ ماكرو من الوظائف المذكورة أعلاه التي تأخذ استدعاءات دالة قياسية وتقوم بتوسيع أنواع المعاملات تلقائيًا:

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.