توظف JET نظام الاستدلال نوع جوليا للكشف عن الأخطاء المحتملة وتكوين عدم الاستقرار.
تحذير
يرجى ملاحظة أنه بسبب التكامل الضيق لـ Jet مع برنامج التحويل البرمجي Julia ، يمكن أن تختلف النتائج التي قدمتها JET بشكل كبير اعتمادًا على إصدار Julia الذي تستخدمه. بالإضافة إلى ذلك ، يمكن أن يؤثر تنفيذ الوحدة Base والمكتبات القياسية المجمعة مع جوليا على النتائج.
علاوة على ذلك ، لا يزال نظام البرنامج المساعد لجامعة جوليا غير مستقر ويتغير واجهةه بشكل متكرر ، لذلك كل إصدار من Jet متوافق مع إصدارات محدودة فقط من جوليا. سيقوم Julia Package Manager تلقائيًا بتحديد وتثبيت أحدث إصدار من Jet متوافق مع إصدار Julia الخاص بك. ومع ذلك ، إذا كنت تستخدم الإصدار الليلي من جوليا ، فيرجى ملاحظة أن إصدارًا متوافقًا من JET قد لا يتم إصداره بعد ، وقد لا يعمل تثبيت JET عبر مدير حزمة Julia بشكل صحيح.
شاهد المزيد من الأوامر والخيارات والتفسيرات في الوثائق.
طائرة هي حزمة جوليا قياسية. لذلك يمكنك فقط تثبيته عبر مدير الحزم المدمج في Julia واستخدامه تمامًا مثل أي حزمة أخرى:
julia> using Pkg; Pkg . add ( " JET " )
[ some output elided ]
julia> using JET@report_opt يمكن اكتشاف عدم الاستقرار في مكالمات الوظائف باستخدام Macro @report_opt ، والذي يعمل على غرار MACRO @code_warntype . لاحظ أنه نظرًا لأن Jet تعتمد على استنتاج نوع جوليا ، إذا تم كسر سلسلة من الاستدلال بسبب الإرسال الديناميكي ، فإن جميع مكالمات وظائف المصب ستكون غير معروفة للمترجم ، وبالتالي لا يمكن لتحليلها.
julia> @report_opt foldl ( + , Any[]; init = 0 )
═════ 2 possible errors found ═════
┌ kwcall(::@NamedTuple{init::Int64}, ::typeof(foldl), op::typeof(+), itr::Vector{Any}) @ Base ./reduce.jl:198
│┌ foldl(op::typeof(+), itr::Vector{Any}; kw::@Kwargs{init::Int64}) @ Base ./reduce.jl:198
││┌ kwcall(::@NamedTuple{init::Int64}, ::typeof(mapfoldl), f::typeof(identity), op::typeof(+), itr::Vector{Any}) @ Base ./reduce.jl:175
│││┌ mapfoldl(f::typeof(identity), op::typeof(+), itr::Vector{Any}; init::Int64) @ Base ./reduce.jl:175
││││┌ mapfoldl_impl(f::typeof(identity), op::typeof(+), nt::Int64, itr::Vector{Any}) @ Base ./reduce.jl:44
│││││┌ foldl_impl(op::Base.BottomRF{typeof(+)}, nt::Int64, itr::Vector{Any}) @ Base ./reduce.jl:48
││││││┌ _foldl_impl(op::Base.BottomRF{typeof(+)}, init::Int64, itr::Vector{Any}) @ Base ./reduce.jl:58
│││││││┌ (::Base.BottomRF{typeof(+)})(acc::Int64, x::Any) @ Base ./reduce.jl:86
││││││││ runtime dispatch detected: +(acc::Int64, x::Any)::Any
│││││││└────────────────────
││││││┌ _foldl_impl(op::Base.BottomRF{typeof(+)}, init::Int64, itr::Vector{Any}) @ Base ./reduce.jl:62
│││││││┌ (::Base.BottomRF{typeof(+)})(acc::Any, x::Any) @ Base ./reduce.jl:86
││││││││ runtime dispatch detected: +(acc::Any, x::Any)::Any
│││││││└────────────────────@report_call يعمل هذا بشكل أفضل على رمز النوع المستقر ، لذا استخدم @report_opt حريصًا قبل استخدام @report_call .
julia> @report_call foldl ( + , Char[])
═════ 2 possible errors found ═════
┌ foldl(op::typeof(+), itr::Vector{Char}) @ Base ./reduce.jl:198
│┌ foldl(op::typeof(+), itr::Vector{Char}; kw::@Kwargs{}) @ Base ./reduce.jl:198
││┌ mapfoldl(f::typeof(identity), op::typeof(+), itr::Vector{Char}) @ Base ./reduce.jl:175
│││┌ mapfoldl(f::typeof(identity), op::typeof(+), itr::Vector{Char}; init::Base._InitialValue) @ Base ./reduce.jl:175
││││┌ mapfoldl_impl(f::typeof(identity), op::typeof(+), nt::Base._InitialValue, itr::Vector{Char}) @ Base ./reduce.jl:44
│││││┌ foldl_impl(op::Base.BottomRF{typeof(+)}, nt::Base._InitialValue, itr::Vector{Char}) @ Base ./reduce.jl:48
││││││┌ _foldl_impl(op::Base.BottomRF{typeof(+)}, init::Base._InitialValue, itr::Vector{Char}) @ Base ./reduce.jl:62
│││││││┌ (::Base.BottomRF{typeof(+)})(acc::Char, x::Char) @ Base ./reduce.jl:86
││││││││ no matching method found `+(::Char, ::Char)`: (op::Base.BottomRF{typeof(+)}).rf::typeof(+)(acc::Char, x::Char)
│││││││└────────────────────
│││││┌ foldl_impl(op::Base.BottomRF{typeof(+)}, nt::Base._InitialValue, itr::Vector{Char}) @ Base ./reduce.jl:49
││││││┌ reduce_empty_iter(op::Base.BottomRF{typeof(+)}, itr::Vector{Char}) @ Base ./reduce.jl:383
│││││││┌ reduce_empty_iter(op::Base.BottomRF{typeof(+)}, itr::Vector{Char}, ::Base.HasEltype) @ Base ./reduce.jl:384
││││││││┌ reduce_empty(op::Base.BottomRF{typeof(+)}, ::Type{Char}) @ Base ./reduce.jl:360
│││││││││┌ reduce_empty(::typeof(+), ::Type{Char}) @ Base ./reduce.jl:343
││││││││││ no matching method found `zero(::Type{Char})`: zero(T::Type{Char})
│││││││││└────────────────────report_package هذا يبحث عن جميع تعاريف وتحليلات وظائف المكالمات استنادًا إلى توقيعاتها. لاحظ أن هذا أقل دقة من @report_call ، لأن أنواع الإدخال الفعلية لا يمكن أن تكون معروفة بالطرق العامة.
julia> using Pkg; Pkg . activate (; temp = true , io = devnull ); Pkg . add ( " AbstractTrees " ; io = devnull );
julia> Pkg . status ()
Status `/private/var/folders/xh/6zzly9vx71v05_y67nm_s9_c0000gn/T/jl_h07K2m/Project.toml`
[1520ce14] AbstractTrees v0.4.4
julia> report_package ( " AbstractTrees " )
[ some output elided ]
═════ 7 possible errors found ═════
┌ isroot(root::Any, x::Any) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/base.jl:102
│ no matching method found `parent(::Any, ::Any)`: AbstractTrees.parent(root::Any, x::Any)
└────────────────────
┌ AbstractTrees.IndexNode(tree::Any) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/indexing.jl:117
│ no matching method found `rootindex(::Any)`: rootindex(tree::Any)
└────────────────────
┌ parent(idx::AbstractTrees.IndexNode) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/indexing.jl:127
│ no matching method found `parentindex(::Any, ::Any)`: pidx = parentindex((idx::AbstractTrees.IndexNode).tree::Any, (idx::AbstractTrees.IndexNode).index::Any)
└────────────────────
┌ nextsibling(idx::AbstractTrees.IndexNode) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/indexing.jl:132
│ no matching method found `nextsiblingindex(::Any, ::Any)`: sidx = nextsiblingindex((idx::AbstractTrees.IndexNode).tree::Any, (idx::AbstractTrees.IndexNode).index::Any)
└────────────────────
┌ prevsibling(idx::AbstractTrees.IndexNode) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/indexing.jl:137
│ no matching method found `prevsiblingindex(::Any, ::Any)`: sidx = prevsiblingindex((idx::AbstractTrees.IndexNode).tree::Any, (idx::AbstractTrees.IndexNode).index::Any)
└────────────────────
┌ prevsibling(csr::AbstractTrees.IndexedCursor) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/cursors.jl:234
│ no matching method found `getindex(::Nothing, ::Int64)` (1/2 union split): (AbstractTrees.parent(csr::AbstractTrees.IndexedCursor)::Union{Nothing, AbstractTrees.IndexedCursor})[idx::Int64]
└────────────────────
┌ (::AbstractTrees.var"#17#18")(n::Any) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/iteration.jl:323
│ no matching method found `parent(::Any, ::Any)`: AbstractTrees.parent(getfield(#self#::AbstractTrees.var"#17#18", :tree)::Any, n::Any)
└──────────────────── يستكشف Jet الوظائف التي تسميها مباشرة وكذلك Callees يمكن استنتاجها . ومع ذلك ، إذا كان لا يمكن استنتاج أنواع الوسيطة للمكالمة ، فإن Jet لا تحلل Callee. وبالتالي ، لا يعني تقرير عن No errors detected أن قاعدة الشفرة بالكامل خالية من الأخطاء. لزيادة الثقة في نتائج JET ، استخدم @report_opt للتأكد من استدلال الكود الخاص بك.
تتكامل Jet مع Snoopcompile ، ويمكنك في بعض الأحيان استخدام Snoopcompile لجمع البيانات لإجراء تحليلات أكثر شمولاً. يتمثل قيود Snoopcompile في أنه يجمع فقط بيانات المكالمات التي لم يتم استنتاجها مسبقًا ، لذلك يجب عليك إجراء هذا النوع من التحليل في جلسة جديدة.
راجع وثائق Snoopcompile's Jet-Cemration لمزيد من التفاصيل.
بدأ هذا المشروع كمشروع أطروحة البكالوريوس في جامعة كيوتو ، التي يشرف عليها البروفيسور تاكاشي ساكوراجاوا. لقد استلهمنا بشدة من Ruby/TypeProf ، وهي أداة فهم/فحص من النوع التجريبي لروبي. يتم نشر أطروحة GRAD حول هذا المشروع على https://github.com/aviatesk/grad-thesis ، ولكن حاليًا ، فهي متوفرة فقط باللغة اليابانية.