### Code Lowering and Source Mapping Source: https://github.com/juliadebug/cthulhu.jl/blob/master/TypedSyntax/README.md Demonstrates the challenges in mapping type-inferred code back to its original source after Julia's code lowering process, showing empty or ambiguous mappings. ```julia julia> function summer(list) s = 0 for x in list s += x end return s end; ``` ```julia julia> tsn, mappings = TypedSyntax.tsn_and_mappings(summer, (Vector{Float64},)); julia> hcat(1:length(mappings), tsn.typedsource.code, mappings) 16×3 Matrix{Any}: 1 :(_4 = 0) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[0] 2 :(_2) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[list] 3 :(_3 = Base.iterate(%2)) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[(= x list)] 4 :(_3 === nothing) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 5 :(Base.not_int(%4)) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 6 :(goto %16 if not %5) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 7 :(_3::Tuple{Float64, Int64}) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 8 :(_5 = Core.getfield(%7, 1)) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[x] 9 :(Core.getfield(%7, 2)) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 10 :(_4 = _4 + _5) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[(+= s x)] 11 :(_3 = Base.iterate(%2, %9)) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 12 :(_3 === nothing) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 13 :(Base.not_int(%12)) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 14 :(goto %16 if not %13) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 15 :(goto %7) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[] 16 :(return _4) Union{TreeNode{SyntaxData}, TreeNode{TypedSyntaxData}}[s] ``` -------------------------------- ### Analyze Backtrace with ascend Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Manually analyze a captured backtrace using `ascend`. This is an alternative when the global `err` variable is not available. ```julia julia> bt = try [sqrt(x) for x in [1, -1]] catch catch_backtrace() end; julia> ascend(bt) Choose a call for analysis (q to quit): > throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:33 sqrt at ./math.jl:582 => sqrt at ./math.jl:608 => iterate at ./generator.jl:47 => collect_to! at ./array.jl:710 => collect_to_with_first!(::Vector{Float64}, ::Float64, ::Base.Generator{Vector{Int64}, typeof(sqrt)}, ::Int64) at ./array.jl:688 collect(::Base.Generator{Vector{Int64}, typeof(sqrt)}) at ./array.jl:669 eval(::Module, ::Any) at ./boot.jl:360 eval_user_input(::Any, ::REPL.REPLBackend) at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:139 ... ``` -------------------------------- ### Enable Highlighter in Cthulhu.CONFIG Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Change the default behavior of the highlighter in the @descend menu. This change is temporary for the current session. ```julia julia> Cthulhu.CONFIG.enable_highlighter = true # Change default true ``` -------------------------------- ### Explore Callers of a Method Instance with ascend Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Use `ascend` to explore the inferred callers of a specific method instance. This helps in understanding the call chain leading to a particular function. ```julia julia> m = which(length, (Set{Symbol},)) length(s::Set) in Base at set.jl:55 julia> mi = m.specializations[1] # or `mi = first(Base.specializations(m))` on Julia 1.10+ MethodInstance for length(::Set{Symbol}) julia> ascend(mi) Choose a call for analysis (q to quit): > length(::Set{Symbol}) union!(::Set{Symbol}, ::Vector{Symbol}) Set{Symbol}(::Vector{Symbol}) intersect!(::Set{Union{Int64, Symbol}}, ::Vector{Symbol}) _shrink(::typeof(intersect!), ::Vector{Union{Int64, Symbol}}, ::Tuple{Vector{Symbol}}) intersect(::Vector{Union{Int64, Symbol}}, ::Vector{Symbol}) union!(::Set{Symbol}, ::Set{Symbol}) union!(::Set{Symbol}, ::Set{Symbol}, ::Set{Symbol}) union(::Set{Symbol}, ::Set{Symbol}) ``` -------------------------------- ### Force Save Cthulhu Configuration Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Forcefully overwrite any existing preferences with the current Cthulhu.CONFIG settings. Use this option when you want to ensure the latest configuration is saved. ```julia julia> Cthulhu.save_config!(Cthulhu.CONFIG; force = true) # to overwrite any existing preferences ``` -------------------------------- ### TypedSyntax Annotation with Named Variables Source: https://github.com/juliadebug/cthulhu.jl/blob/master/TypedSyntax/README.md Shows how TypedSyntax can still provide detailed type annotations for source code, even after lowering, by leveraging information from named variables. ```julia julia> tsn line:col│ tree │ type 1:1 │[function] │Union{Float64, Int64} 1:10 │ [call] 1:10 │ summer 1:17 │ list │Vector{Float64} 1:22 │ [block] 2:5 │ [=] 2:5 │ s │Int64 2:9 │ 0 │Int64 3:5 │ [for] 3:8 │ [=] │Union{Nothing, Tuple{Float64, Int64}} 3:9 │ x │Float64 3:14 │ list │Vector{Float64} 3:18 │ [block] 4:9 │ [+=] │Float64 4:9 │ s │Float64 4:14 │ x │Float64 6:5 │ [return] │Union{Float64, Int64} 6:12 │ s │Union{Float64, Int64} ``` -------------------------------- ### Define Functions for Static Type Analysis Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Defines `foo` and `bar` functions to demonstrate static type information. Note the comment about potential union splitting issues on Julia v1.6. ```julia using Infiltrator: @infiltrate using Cthulhu: @descend using Base: @noinline # already exported, but be explcit function foo(n) x = n < 2 ? 2 * n : 2.5 * n y = n < 4 ? 3 * n : 3.5 * n z = n < 5 ? 4 * n : 4.5 * n # on Julia v1.6, there is no union splitting for this number of cases. bar(x, y, z) end @noinline function bar(x, y, z) string(x + y + z) end ``` -------------------------------- ### Analyze Stacktrace with ascend Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Use `ascend` to analyze a stacktrace, such as one from a recent error stored in the `err` variable. This helps in tracing the execution path that led to an error. ```julia julia> using Cthulhu julia> sqrt(-1) ERROR: DomainError with -1.0: sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)). Stacktrace: [1] throw_complex_domainerror(f::Symbol, x::Float64) @ Base.Math ./math.jl:33 [2] sqrt @ ./math.jl:677 [inlined] [3] sqrt(x::Int64) @ Base.Math ./math.jl:1491 [4] top-level scope @ REPL[1]:1 julia> ascend(err) Choose a call for analysis (q to quit): > throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:33 sqrt(::Int64) at ./math.jl:1491 ``` -------------------------------- ### Save Cthulhu Configuration Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Persistently save the current Cthulhu.CONFIG settings using Preferences.jl. This configuration will be automatically loaded the next time Cthulhu.jl is used. ```julia julia> Cthulhu.save_config!(Cthulhu.CONFIG) # Will be automatically read next time you `using Cthulhu` ``` -------------------------------- ### Invoke descend function Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Use the `descend` function with a function and a tuple of argument types, or use the `@descend` macro with a normal function call. ```julia descend(f, tt) # function `f` and Tuple `tt` of argument types @descend f(args) # normal call ``` -------------------------------- ### Display TypedSyntaxNode with All Types Source: https://github.com/juliadebug/cthulhu.jl/blob/master/TypedSyntax/README.md Prints a TypedSyntaxNode to the console, showing all inferred types for variables and expressions. Set `hide_type_stable=false` to display concrete types. ```julia printstyled(stdout, node; hide_type_stable=false) ``` -------------------------------- ### Display TypedSyntaxNode with Type Instability Warnings Source: https://github.com/juliadebug/cthulhu.jl/blob/master/TypedSyntax/README.md Prints a TypedSyntaxNode, highlighting type instability with bold text for non-concrete or 'small union' types. Use `iswarn=false` to suppress color warnings. ```julia printstyled(stdout, TypedSyntaxNode(f, (Float64, Int, Real))) ``` -------------------------------- ### Add Infiltrator for Runtime Information Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Modifies the `foo` function to include `@infiltrate` before the call to `bar`. This allows pausing execution and inspecting runtime types. ```julia function foo(n) x = n < 2 ? 2 * n : 2.5 * n y = n < 4 ? 3 * n : 3.5 * n z = n < 5 ? 4 * n : 4.5 * n # on Julia v1.6, there is no union splitting for this number of cases. @infiltrate bar(x, y, z) end @noinline function bar(x, y, z) string(x + y + z) end ``` -------------------------------- ### Specify Function Signature for descend Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Use the function form of `descend` to explicitly provide the function and its signature for debugging. This is useful when automatic signature extraction is not desired or possible. ```julia function foo(x) T = rand() > 0.5 ? Int64 : Float64 x + sum(rand(T, 100)) end # option 1: use the function form to specify the signature descend(foo, (Int,)) descend(foo, Tuple{Type{Int}}) descend(Tuple{typeof(foo), Type{Int}}) # option 2: use `@descend` with valid syntax to automatically extract the signature @descend foo(1) @descend foo(::Int) # 1.13+ only ``` -------------------------------- ### Descend into Function with Cthulhu Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Invokes Cthulhu's `@descend` macro on the `foo` function to inspect its call graph and type information statically. ```julia Cthulhu.@descend foo(5) ``` -------------------------------- ### Invoke Infiltrated Function and Debug Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md Calls the modified `foo` function with `foo(4)` to trigger the Infiltrator REPL. From there, you can use `@descend` to analyze `bar` with runtime types. ```julia julia> foo(4) Infiltrating foo(n::Int64) at ex.jl:10: infil> ``` -------------------------------- ### Runtime Call Indication Source: https://github.com/juliadebug/cthulhu.jl/blob/master/README.md When `descend` encounters a runtime call that cannot be descended into, it provides an informational message. This indicates that the call is dynamic and Cthulhu cannot perform static analysis on it. ```julia [ Info: This is a runtime call. You cannot descend into it. ``` -------------------------------- ### Anonymous Function Type Inference Source: https://github.com/juliadebug/cthulhu.jl/blob/master/TypedSyntax/README.md Illustrates how types within anonymous functions might be inferred as 'Any' due to internal Julia handling, making them hidden from the annotator. ```julia julia> sumfirst(c) = sum(x -> first(x), c); # better to use `sum(first, c)` but this is just an illustration julia> printstyled(stdout, TypedSyntaxNode(sumfirst, (Vector{Any},))) sumfirst(c)::Any = sum(x -> first(x), c)::Any ``` -------------------------------- ### Generate TypedSyntaxNode Source: https://github.com/juliadebug/cthulhu.jl/blob/master/TypedSyntax/README.md Generates a TypedSyntaxNode by analyzing a function and its argument types. This node represents the function's structure with inferred types attached. ```julia using TypedSyntax f(x, y, z) = x + y * z; node = TypedSyntaxNode(f, (Float64, Int, Float32)) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.