swiftc: changing the format of the AST dumper
The Swift compiler pipeline supports options that will emit the output of different compilation stages. One such option is -dump-ast
, which by default prints out a textual representation of the (typechecked) AST. This typically looks like a bunch of nested ‘S-expressions’ containing some metadata about each element. For example, compiling the following code with this option:
func square(_ i: Int) -> Int { i * i }
Might produce something like this:
(source_file "/app/example.swift"
(func_decl range=[/app/example.swift:1:1 - line:1:38] "square(_:)" interface_type="(Int) -> Int" access=internal result="Int" thrown_type="<null>"
(parameter_list range=[/app/example.swift:1:12 - line:1:21]
(parameter "i" interface_type="Int"))
(brace_stmt range=[/app/example.swift:1:30 - line:1:38]
(return_stmt implicit range=[/app/example.swift:1:32 - line:1:36]
(binary_expr type="Int" location=/app/example.swift:1:34 range=[/app/example.swift:1:32 - line:1:36] nothrow isolation_crossing="none"
(dot_syntax_call_expr implicit type="(Int, Int) -> Int" location=/app/example.swift:1:34 range=[/app/example.swift:1:34 - line:1:34] nothrow isolation_crossing="none"
(declref_expr type="(Int.Type) -> (Int, Int) -> Int" location=/app/example.swift:1:34 range=[/app/example.swift:1:34 - line:1:34] decl="Swift.(file).Int extension.*" function_ref=single_apply)
(argument_list implicit
(argument
(type_expr implicit type="Int.Type" location=/app/example.swift:1:34 range=[/app/example.swift:1:34 - line:1:34] typerepr="Int"))))
(argument_list implicit
(argument
(declref_expr type="Int" location=/app/example.swift:1:32 range=[/app/example.swift:1:32 - line:1:32] decl="output.(file).square(_:).i@/app/example.swift:1:15" function_ref=unapplied))
(argument
(declref_expr type="Int" location=/app/example.swift:1:36 range=[/app/example.swift:1:36 - line:1:36] decl="output.(file).square(_:).i@/app/example.swift:1:15" function_ref=unapplied))))))))
Somewhat recently, a few additional options have been introduced that can be used to alter how this ‘AST dump’ output is formatted.
To control the output format, the additional flag -dump-ast-format
must also be specified with an appropriate parameter. As of the ~6.1/6.2 Swift compilers, the following options are supported:
The JSON output formats were added here and look potentially useful for source tooling, as they emit USRs for (most of) the dumped elements. The output with the (uncompressed) option enabled looks something like:
{
"_kind": "source_file",
"filename": "/app/example.swift",
"compiler_version": {
"_kind": "compiler_version",
"major": "6",
"minor": "1",
"full": "Swift version 6.1 (swift-6.1-RELEASE)"
},
"items": [
{
"_kind": "func_decl",
"usr": "s:6output6square1nS2i_tF",
"range": {
"start": 44,
"end": 90
},
"name": {
"_kind": "decl_name",
"base_name": {
"_kind": "base_name",
"name": "square"
},
"args": [
"n"
]
},
"interface_type": "$s1nS2i_tcD",
"access": "internal",
"result": "$sSiD",
"thrown_type": "",
"params": {
"_kind": "parameter_list",
"range": {
"start": 55,
"end": 62
},
"params": [
{
"_kind": "parameter",
"name": {
"_kind": "decl_name",
"base_name": {
"_kind": "base_name",
"name": "n"
}
},
"apiName": "n",
"interface_type": "$sSiD"
}
]
},
...<snip>...
The default-with-decl-context
option was added here and, as the name suggests, the output looks like the default S-expression form, but with the declaration context (DC) hierarchy printed out at the top, which for this example looks something like:
0x5ce4eef00440 Module name=output
0x5ce4eef00b28 FileUnit file="/app/example.swift"
0x5ce4ef12a6c8 AbstractFunctionDecl name=square(n:) : (Int) -> Int
Having recently worked on some aspects of the compiler in which determining the DC hierarchy was relevant, this seems like a nice, if somewhat niche, option to have available.