Role of Brace-Stmt in Swift AST


(Toni Suter) #1

Hi,

I am trying to understand the Swift AST by looking at output produced from swiftc -dump-ast <file>.
Most of it makes sense to me, but there are some things that I don’t understand. For example, consider
the following code:

var x = 42

This produces the following output:

(source_file
  (top_level_code_decl
    (brace_stmt
      (pattern_binding_decl
        (pattern_named type='Int' 'x')
        (call_expr implicit type='Int' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] nothrow
          (constructor_ref_call_expr implicit type='(_builtinIntegerLiteral: Int2048) -> Int' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] nothrow
            (declref_expr implicit type='Int.Type -> (_builtinIntegerLiteral: Int2048) -> Int' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] decl=Swift.(file).Int.init(_builtinIntegerLiteral:) specialized=no)
            (type_expr implicit type='Int.Type' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] typerepr='Int'))
          (tuple_expr implicit type='(_builtinIntegerLiteral: Int2048)' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] names=_builtinIntegerLiteral
            (integer_literal_expr type='Int2048' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] value=42))))
))
  (var_decl "x" type='Int' access=internal storage_kind=stored))

Intuitively, I would have expected that the initializer is part of the var_decl. Also, why is there a brace_stmt involved?
As far as I have seen, the term brace statement doesn’t appear anywhere in the Swift Language Reference. Is it the
same as code-block <https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/code-block>?

Thanks in advance!

Best regards,
Toni


(Greg Titus) #2

Hi Toni,

What you are seeing is a side-effect of / workaround for the use of top-level executable statements.

In general, at the top level of a source file you expect declarations (of types, of functions, etc) and then statements will be inside those declarations (the implementations of free functions or members, etc). Various portions of the type checker and AST checker depend on these assumptions — that scanning through the top-level parts of a source file will be all declarations, and conversely, that every statement will be inside braces (e.g. “{}”) to control scopes and so on.

When compiling in library-mode, this setup is always true. But when compiling for playgrounds/tools/etc you can have executable statements at the top level. In order to keep the expected invariants of declarations on top and statements inside, top_level_code_decl is a declaration that contains a brace_stmt that contains the parsed top-level executable statements.

And then finally, because you are declaring a variable “x” that ought to be visible further down in the file, the var_decl, which would normally be in the scope inside the braces in a ‘normal’ declaration is emitted at the top level as well.

In short, the AST for this kind of thing is a bit weird looking in order to preserve expected structure invariants of the tree.

Hope this helps!
  - Greg

···

On Mar 23, 2016, at 5:58 AM, Toni Suter via swift-dev <swift-dev@swift.org> wrote:

Hi,

I am trying to understand the Swift AST by looking at output produced from swiftc -dump-ast <file>.
Most of it makes sense to me, but there are some things that I don’t understand. For example, consider
the following code:

var x = 42

This produces the following output:

(source_file
  (top_level_code_decl
    (brace_stmt
      (pattern_binding_decl
        (pattern_named type='Int' 'x')
        (call_expr implicit type='Int' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] nothrow
          (constructor_ref_call_expr implicit type='(_builtinIntegerLiteral: Int2048) -> Int' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] nothrow
            (declref_expr implicit type='Int.Type -> (_builtinIntegerLiteral: Int2048) -> Int' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] decl=Swift.(file).Int.init(_builtinIntegerLiteral:) specialized=no)
            (type_expr implicit type='Int.Type' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] typerepr='Int'))
          (tuple_expr implicit type='(_builtinIntegerLiteral: Int2048)' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] names=_builtinIntegerLiteral
            (integer_literal_expr type='Int2048' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] value=42))))
))
  (var_decl "x" type='Int' access=internal storage_kind=stored))

Intuitively, I would have expected that the initializer is part of the var_decl. Also, why is there a brace_stmt involved?
As far as I have seen, the term brace statement doesn’t appear anywhere in the Swift Language Reference. Is it the
same as code-block <https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/code-block>?

Thanks in advance!

Best regards,
Toni
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


(Toni Suter) #3

Hi Greg,

Thanks very much for the clear answer. This helps me a lot!

Best regards,
Toni

···

On 23 Mar 2016, at 17:53, Greg Titus <greg@omnigroup.com> wrote:

Hi Toni,

What you are seeing is a side-effect of / workaround for the use of top-level executable statements.

In general, at the top level of a source file you expect declarations (of types, of functions, etc) and then statements will be inside those declarations (the implementations of free functions or members, etc). Various portions of the type checker and AST checker depend on these assumptions — that scanning through the top-level parts of a source file will be all declarations, and conversely, that every statement will be inside braces (e.g. “{}”) to control scopes and so on.

When compiling in library-mode, this setup is always true. But when compiling for playgrounds/tools/etc you can have executable statements at the top level. In order to keep the expected invariants of declarations on top and statements inside, top_level_code_decl is a declaration that contains a brace_stmt that contains the parsed top-level executable statements.

And then finally, because you are declaring a variable “x” that ought to be visible further down in the file, the var_decl, which would normally be in the scope inside the braces in a ‘normal’ declaration is emitted at the top level as well.

In short, the AST for this kind of thing is a bit weird looking in order to preserve expected structure invariants of the tree.

Hope this helps!
  - Greg

On Mar 23, 2016, at 5:58 AM, Toni Suter via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

Hi,

I am trying to understand the Swift AST by looking at output produced from swiftc -dump-ast <file>.
Most of it makes sense to me, but there are some things that I don’t understand. For example, consider
the following code:

var x = 42

This produces the following output:

(source_file
  (top_level_code_decl
    (brace_stmt
      (pattern_binding_decl
        (pattern_named type='Int' 'x')
        (call_expr implicit type='Int' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] nothrow
          (constructor_ref_call_expr implicit type='(_builtinIntegerLiteral: Int2048) -> Int' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] nothrow
            (declref_expr implicit type='Int.Type -> (_builtinIntegerLiteral: Int2048) -> Int' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] decl=Swift.(file).Int.init(_builtinIntegerLiteral:) specialized=no)
            (type_expr implicit type='Int.Type' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] typerepr='Int'))
          (tuple_expr implicit type='(_builtinIntegerLiteral: Int2048)' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] names=_builtinIntegerLiteral
            (integer_literal_expr type='Int2048' location=test.swift:1:9 range=[test.swift:1:9 - line:1:9] value=42))))
))
  (var_decl "x" type='Int' access=internal storage_kind=stored))

Intuitively, I would have expected that the initializer is part of the var_decl. Also, why is there a brace_stmt involved?
As far as I have seen, the term brace statement doesn’t appear anywhere in the Swift Language Reference. Is it the
same as code-block <https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/code-block>?

Thanks in advance!

Best regards,
Toni
_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev