How to Use JET.jl
JET's analysis entry points follow the naming conventions below:
report_xxx
: runs analysis, and then prints the collected error pointsanalyze_xxx
: just runs analysis, and returns the final state of the analysis
The report_xxx
entries are for general users, while analyze_xxx
is mainly for internal usages or debugging purposes.
Entry Points into Analysis
JET can analyze your "top-level" code. This means you can just give your Julia file or code to JET and get error reports. report_file
, report_and_watch_file
, report_package
and report_text
are the main entry points for that.
JET will analyze your code "half-statically" – JET will selectively interpret "top-level definitions" (like a function definition) and try to simulate Julia's top-level code execution, while it tries to avoid executing any other parts of code like function calls, but analyze them using abstract interpretation (this is a part where JET "statically" analyzes your code). If you're interested in how JET selects "top-level definitions", please see JET.virtual_process
.
Because JET will actually interpret "top-level definitions" in your code, it certainly runs your code. So we should note that JET can cause some side effects from your code; for example JET will try to expand all the macros used in your code, and so the side effects involved with macro expansions will also happen in JET's analysis process.
JET.report_file
— Functionreport_file([io::IO = stdout],
filename::AbstractString;
jetconfigs...) -> res::ReportResult
Analyzes filename
, prints the collected error reports to the io
stream, and finally returns res::ReportResult
res.included_files::Set{String}
: files analyzed by JETres.any_reported::Bool
: indicates if there was any error point reported
This function will look for .JET.toml
configuration file in the directory of filename
, and search up the file tree until any .JET.toml
is (or isn't) found. When found, the configurations specified in the file will overwrite the given jetconfigs
. See Configuration File for more details.
When you want to analyze your package, but any file using it isn't available, the analyze_from_definitions
option can be useful (see ToplevelConfig
's analyze_from_definitions
option).
For example, JET can analyze JET itself like below:
# from the root directory of JET.jl
julia> report_file("src/JET";
analyze_from_definitions = true)
See also: report_package
This function will enable the toplevel_logger
configuration by default with the default logging level. You can still explicitly specify and configure it:
report_file(args...;
toplevel_logger = nothing, # suppress toplevel logger
jetconfigs...) # other configurations
See Logging Configurations for more details.
JET.report_and_watch_file
— Functionreport_and_watch_file([io::IO = stdout],
filename::AbstractString;
jetconfigs...)
Watches filename
and keeps re-triggering analysis with report_file
on code update. JET will try to analyze all the include
d files reachable from filename
, and it will re-trigger analysis if there is code update detected in any of the include
d files.
This function internally uses Revise.jl to track code updates. Revise also offers possibilities to track changes in files that are not directly analyzed by JET, or even changes in Base
files. See Watch Configurations for more details.
See also: report_file
JET.report_package
— Functionreport_package([io::IO = stdout],
package::Union{AbstractString,Module};
jetconfigs...) -> res::ReportResult
Analyzes package
in the same way as report_file
with the option analyze_from_definitions=true
. See report_file
for details. package
can be either a module or a string. In the latter case it must be the name of a package in your current environment.
report_package([io::IO = stdout];
jetconfigs...) -> res::ReportResult
Like above but analyzes the package in the current project.
See also: report_file
JET.report_text
— Functionreport_text([io::IO = stdout],
text::AbstractString,
filename::AbstractString = "top-level";
jetconfigs...) -> res::ReportResult
Analyzes text
, prints the collected error reports to the io
stream, and finally returns res::ReportResult
res.included_files::Set{String}
: files analyzed by JETres.any_reported::Bool
: indicates if there was any error point reported
Testing, Interactive Usage
There are utilities for checking JET analysis in a running Julia session like REPL or such.
JET.report_call
— Functionreport_call(f, types = Tuple{}; jetconfigs...) -> result_type::Any
Analyzes the generic function call with the given type signature, and then prints collected error points to stdout
, and finally returns the result type of the call.
JET.@report_call
— Macro@report_call [jetconfigs...] f(args...)
Evaluates the arguments to the function call, determines its types, and then calls report_call
on the resulting expression. As with @code_typed
and its family, any of JET configurations can be given as the optional arguments like this:
# reports `rand(::Type{Bool})` with `aggressive_constant_propagation` configuration turned off
julia> @report_call aggressive_constant_propagation=false rand(Bool)
JET.analyze_call
— Functionanalyze_call(f, types = Tuple{}; jetconfigs...) -> (interp::JETInterpreter, frame::Union{InferenceFrame,Nothing})
Analyzes the generic function call with the given type signature, and returns:
interp::JETInterpreter
: contains analyzed error reports and suchframe::Union{InferenceFrame,Nothing}
: the final state of the abstract interpretation, ornothing
iff
is a generator and the code generation failed
JET.@analyze_call
— Macro@analyze_call [jetconfigs...] f(args...)
Evaluates the arguments to the function call, determines its types, and then calls analyze_call
on the resulting expression. As with @code_typed
and its family, any of JET configurations can be given as the optional arguments like this:
# analyzes `rand(::Type{Bool})` with `aggressive_constant_propagation` configuration turned off
julia> @analyze_call aggressive_constant_propagation=false rand(Bool)