From b9ba04d51bc9f867f72e923c2617983a7497583f Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Fri, 17 Mar 2023 23:35:24 -0700 Subject: [PATCH 01/51] Start outlining a new chapter about macros. --- TSPL.docc/LanguageGuide/Macros.md | 80 +++++++++++++++++++++ TSPL.docc/The-Swift-Programming-Language.md | 1 + 2 files changed, 81 insertions(+) create mode 100644 TSPL.docc/LanguageGuide/Macros.md diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md new file mode 100644 index 000000000..c2d7cf87b --- /dev/null +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -0,0 +1,80 @@ +# Macros + +Transform code at compile time to automate repetition and generate code. + +XXX OUTLINE XXX + + +- What's a macro? +- Comes in two flavors: + - "pound" macros make a value + - "at" macros modify a declaration +- How do I call a macro? + - Use macros from the stdlib in examples, like `#line`. +- How does the compiler expand a macro? +- How do I define a new macro? + - It can go in the same module, or in an external module. + - Q: What guidance can we give + about choosing where the implementation goes? +- You use Swift Syntax APIs to modify the AST + - Q: What are the most important APIs to show in examples? +- Tips for debugging a macro + +## Figure: The moving parts in macro expansion + +Starts with your code: + +```ascii-art +let line = #line +``` + +Swift compiler converts code to an to AST: + +```ascii-art + Assignment + / \ + | | + Constant \ + | Macro + | \ + line #line +``` + +Swift compiler serialized the AST +and passes it to a separate binary +that implement the macro. + +Macro implementation uses Swift Syntax APIs +to manipulate the AST + +```ascii-art + Assignment + / \ + | | + Constant \ + | IntegerLiteral + | \ + line 23 +``` + +Macro binary serializes the AST +and returns it the Swift compiler. + +Swift compiler handles the AST +as if it had been written in source +in the expanded form. + +```ascii-art +let line = 23 +``` + + + diff --git a/TSPL.docc/The-Swift-Programming-Language.md b/TSPL.docc/The-Swift-Programming-Language.md index 57e8c0310..3b20a3e2b 100644 --- a/TSPL.docc/The-Swift-Programming-Language.md +++ b/TSPL.docc/The-Swift-Programming-Language.md @@ -38,6 +38,7 @@ - - - +- - - - From 61dab9e0c7dd3c30d1d148f477a9b2fff682bef9 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Fri, 24 Mar 2023 18:06:09 -0700 Subject: [PATCH 02/51] Add grammar and facts from the SE proposals. --- TSPL.docc/LanguageGuide/Macros.md | 42 +++++++++++++++++++ TSPL.docc/ReferenceManual/Declarations.md | 33 +++++++++++++++ TSPL.docc/ReferenceManual/Expressions.md | 39 +++++++++++++++++ TSPL.docc/ReferenceManual/LexicalStructure.md | 13 ++++++ 4 files changed, 127 insertions(+) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index c2d7cf87b..c74d67d9f 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -12,6 +12,7 @@ XXX OUTLINE XXX - How do I call a macro? - Use macros from the stdlib in examples, like `#line`. - How does the compiler expand a macro? + - A macro is a Swift program that transforms source code. - How do I define a new macro? - It can go in the same module, or in an external module. - Q: What guidance can we give @@ -20,6 +21,47 @@ XXX OUTLINE XXX - Q: What are the most important APIs to show in examples? - Tips for debugging a macro +Facts to be incorporated into the outline: + +Macro arguments are type-checked before macro expansion. +The macro implementation transforms well-typed, well-formed input +into well-typed, well-formed output. + +Macro expansion happens in their surrounding context. +A macro can affect that environment if it needs to — +and a macro that has bugs can interfere with that environment. +Generated symbol names let a macro +avoid accidentally interacting with symbols in that environment. +(FIXME: what’s our spelling of GENSYM?) + +Macros can be nested, +but macro expansion can't be recursive. +Nested macros are expanded from the outside in. +If the AST returned by a macro tries to call other macros, +that's a compile-time error. + +Macro attributes: + +`@freestanding(expression)` +`@attached(peer, names:)` +`@attached(member, names:)` +`@attached(memberAttribute)` (XXX TR: Can this take `names:` too?) +`@attached(accessor, names:)` + +Macro declaration naming: + +- `named(someDeclarationName)` +- `arbitrary` +- `overloaded` +- `prefixed()` usually `prefixed(_)` but others including `$` are allowed. +- `suffixed()` like `suffixed(_docInfo)` + +Every declaration a macro introduces in its expansion +must be included in the list of names the macro declares. +However, a macro can declare a name +but omit a corresponding declaration in the expansion. +(For example, because one already exists.) + ## Figure: The moving parts in macro expansion Starts with your code: diff --git a/TSPL.docc/ReferenceManual/Declarations.md b/TSPL.docc/ReferenceManual/Declarations.md index cdb7fca70..02f22b7c6 100644 --- a/TSPL.docc/ReferenceManual/Declarations.md +++ b/TSPL.docc/ReferenceManual/Declarations.md @@ -45,6 +45,8 @@ the term *declaration* covers both declarations and definitions. > > *declaration* → *subscript-declaration* > +> *declaration* → *macro-declaration* +> > *declaration* → *operator-declaration* > > *declaration* → *precedence-group-declaration* @@ -3442,6 +3444,37 @@ with both the `class` and `final` declaration modifiers. > > *subscript-result* → **`->`** *attributes*_?_ *type* +## Macro Declaration + + + +A macro declaration appears only at file scope. + +> Grammar of a macro declaration: +> +> *macro-declaration* → *macro-head* *identifier* *generic-parameter-clause*_?_ *macro-signature* *macro-definition*_?_ *generic-where-clause* +> +> *macro-head* → *attributes*_?_ *declaration-modifiers*_?_ **`macro`** +> +> *macro-signature* → *parameter-clause* *macro-function-signature-result*_?_ +> +> *macro-function-signature-result* → **`->``** *type* +> +> *macro-definition* → **`=``** *expression* + + + ## Operator Declaration An *operator declaration* introduces a new infix, prefix, diff --git a/TSPL.docc/ReferenceManual/Expressions.md b/TSPL.docc/ReferenceManual/Expressions.md index 1e44658ab..a3fa6fb4b 100644 --- a/TSPL.docc/ReferenceManual/Expressions.md +++ b/TSPL.docc/ReferenceManual/Expressions.md @@ -564,6 +564,8 @@ to make prefix expressions, infix expressions, and postfix expressions. > > *primary-expression* → *wildcard-expression* > +> *primary-expression* → *macro-expansion-expression* +> > *primary-expression* → *key-path-expression* > > *primary-expression* → *selector-expression* @@ -591,6 +593,27 @@ an array or dictionary literal, a playground literal, or one of the following special literals: + + | Literal | Type | Value | | ------- | ---- | ----- | | `#file` | `String` | The path to the file in which it appears. | @@ -1549,6 +1572,22 @@ For example, in the following assignment > > *wildcard-expression* → **`_`** +### Macro-Expansion Expression + + + +A macro expression can't appear as the default value for a parameter, +except for the `#file` and `#line` macros from the Swift standard library. + +> Grammar of a macro-expansion expression: +> +> *macro-expansion-expression* → **`#`** *identifier* *generic-argument-clause*_?_ *function-call-argument-clause*_?_ *trailing-closures*_?_ + ### Key-Path Expression A *key-path expression* diff --git a/TSPL.docc/ReferenceManual/LexicalStructure.md b/TSPL.docc/ReferenceManual/LexicalStructure.md index 3aff8f41f..cb35a9b5e 100644 --- a/TSPL.docc/ReferenceManual/LexicalStructure.md +++ b/TSPL.docc/ReferenceManual/LexicalStructure.md @@ -387,6 +387,19 @@ so they must be escaped with backticks in that context. `#sourceLocation`, and `#warning`. + + + + + +The code above calls three macros: + +- In the first line, + `#line` is a call to the `line` macro from the Swift standard library. + You can recognize that it's a call to a macro + because of the `#` in front of it. + When you compile this code, + Swift calls that macro's implementation, + and replaces `#line` with the current line number. + +- In the second line, + `#warning` calls another macro from the standard library + to produce a custom warning when the code is compiled. + Again, the `#` marks this as a macro call. + Unlike `#line`, `#warning` doesn't produce any value. + +- In the remaining lines, + `@OptionSet` creates a type that conforms to the [`OptionSet`][] protocol, + automatically declaring the necessary static members. + Here, the `@` marks a macro that behaves like an attribute, + modifying the declaration that the macro is attached to. + +[`OptionSet`]: https://developer.apple.com/documentation/swift/optionset + +Macros like `@OptionSet` are known as *attached macros* +because they are always attached to a declaration. +Attached macros can add members to the declaration that they're attached to. +Macros like `#line` and `#warning` are known as *freestanding macros* +because they can appear on their own, +without being attached to a declaration. +Freestanding macros can produce a value, like `#line`, +they can perform some compile-time action, like `#warning`, +or they can generate new declarations. +Both attached and freestanding macros are always additive: +They can expand to add new code, +but they can't ever delete code +or modify code that you wrote by hand. + +Swift expands both attached and freestanding macros +using the following general steps: + +1. The compiler reads and parses the code, + creating an in-memory representation of the syntax. + +1. The compiler passes part of that in-memory representation + to the implementation of the macro, + which returns the macro's expansion. + +1. The compiler replaces the macro with its expanded form, + and then continues compilation. + +[XXX FIGURE XXX] -- XXX High-level view of the macro expansion figure +``` +let currentLine = #line + | + v + #line + | + v + 123 + | + v +let currentLine = 123 +``` ## Freestanding Macros From 6ddef3e0063bee2ea6ee8406197dbe1ad80952b1 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Thu, 20 Apr 2023 17:35:40 -0700 Subject: [PATCH 11/51] Expand prose around macro expansion. --- TSPL.docc/LanguageGuide/Macros.md | 63 ++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index 8d058b27d..8181edcbf 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -5,14 +5,10 @@ Transform code at compile time to automate repetition and generate code. Macros transform your source code when you compile it, letting you avoid writing out repetitive code by hand and omit boilerplate code. -The implementation of a macro is written in Swift, -using the [`SwiftSyntax`][] module. You can identify a call to a macro in Swift code because it starts with either a number sign (`#`) or an at sign (`@`). For example: -[`SwiftSyntax`]: http://github.com/apple/swift-syntax/ - ```swift let currentLine = #line @@ -72,10 +68,12 @@ or modify code that you wrote by hand. Swift expands both attached and freestanding macros using the following general steps: -1. The compiler reads and parses the code, +1. The compiler reads the code, just like when it's compiling, creating an in-memory representation of the syntax. + This representation is known as an _abstract syntax tree_ or AST. 1. The compiler passes part of that in-memory representation + to the implementation of the macro, which returns the macro's expansion. @@ -97,6 +95,55 @@ let currentLine = #line let currentLine = 123 ``` + + +If you've used macros in another programming language, +some parts of Swift macros will be familiar +and some parts will feel different. +All of the components of the Swift macro system are made up of Swift code: + +- The declaration of a Swift macro, + including information about where it can appear + and what kind of output it produces, + is written in Swift like the declaration of a structure or function. + +- The implementation of a macro is written in Swift, + using the functionality provided by the [SwiftSyntax][] module + to read Swift code and add to it. + Even though there are convenience APIs in SwiftSyntax + to create new syntax nodes using strings, + the input, expansion, and output all consists of + structured information (AST nodes). + + +- The result of macro expansion is Swift code, + which you can debug as normal. + XXX debugging - how to expand macros + +[SwiftSyntax]: http://github.com/apple/swift-syntax/ + +Both the input to a macro and the output of macro expansion +are always valid Swift code --- +they're syntactically well-formed +and the values type-check. + + + + + ## Freestanding Macros XXX OUTLINE: @@ -360,6 +407,11 @@ XXX OUTLINE: - Adding a new member by making an instance of `Declaration`, and returning it as part of the `[DeclSyntax]` list. +- Because macros are deterministic and stateless --- + they don't depend on any external state, + don't have any side effects --- + they're a great place to use use test cases during development. + XXX Additional APIs and concepts to introduce in the future, in no particular order: @@ -460,7 +512,6 @@ let line = Color.init(red: 10, green: 20, blue: 30) (This might be a good point to mention the "dump macro expansion" flag.) - -The code above calls three macros: +This version of `SundaeToppings` +calls the `OptionSet` macro from the Swift standard library. +The macro reads the list of cases in the private enumeration, +generates the list of constants for each option, +and marks `SundaeToppings` as conforming to the `OptionSet` protocol. -- In the first line, - `#line` is a call to the `line` macro from the Swift standard library. - You can recognize that it's a call to a macro - because of the `#` in front of it. - When you compile this code, - Swift calls that macro's implementation, - and replaces `#line` with the current line number. + +[`OptionSet`]: https://developer.apple.com/documentation/swift/optionset -- In the second line, - `#warning` calls another macro from the standard library - to produce a custom warning when the code is compiled. - Again, the `#` marks this as a macro call. - Unlike `#line`, `#warning` doesn't produce any value. +You can identify Swift code that uses a macro +because the starts with an at sign (`@`) +like `@OptionSet` in the example above, +or a number sign (`#`) +like `#line` in the example below. -- In the remaining lines, - `@OptionSet` creates a type that conforms to the [`OptionSet`][] protocol, - automatically declaring the necessary static members. - Here, the `@` marks a macro that behaves like an attribute, - modifying the declaration that the macro is attached to. +```swift +let currentLine = #line +let black = #colorLiteral(red: 0, green: 0, blue: 0) +``` -[`OptionSet`]: https://developer.apple.com/documentation/swift/optionset + + +In the first line, +`#line` is a call to the `line` macro from the Swift standard library. +You can recognize that it's a call to a macro +because of the `#` in front of it. +When you compile this code, +Swift calls that macro's implementation, +and replaces `#line` with the current line number. + +In the second line, +`#warning` calls another macro from the standard library +to produce a custom warning when the code is compiled. +Again, the `#` marks this as a macro call. +Unlike `#line`, `#warning` doesn't produce any value. Macros like `@OptionSet` are known as *attached macros* because they are always attached to a declaration. From 6bd71b7dc1a869be01ebd22b11f3ea1c4ef51dea Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 26 Apr 2023 20:47:43 -0700 Subject: [PATCH 13/51] Add naming convention for attributes & macros. --- Style.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Style.md b/Style.md index fb1ac28d7..045b8026b 100644 --- a/Style.md +++ b/Style.md @@ -98,6 +98,11 @@ which means it’s not always suitable for generating a parser for Swift code. # Terms and Rules +## attribute names + +In the guide, write `@` before attribute names; +in the reference, omit it. + ## back deploy Spelled as two words, not closed up or hyphenated. @@ -122,6 +127,13 @@ you should generally try to avoid them. Deeply nested headings often indicate that there’s a better way to organize the content. +## macro names + +In the guide, +write `@` before the name when referring to attached macros +and `#` before the name when referring to freestanding macros. +In the reference, omit it. + ## memberwise initializer Not hyphenated as “member-wise”. From acca003d759f420369ce167189a1b1f6f8c3e2d4 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 26 Apr 2023 20:49:29 -0700 Subject: [PATCH 14/51] Separate freestanding & attached; start on expansion. --- TSPL.docc/LanguageGuide/Macros.md | 387 +++++++++++++++--------------- 1 file changed, 192 insertions(+), 195 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index 144757cc3..40a934de9 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -5,7 +5,7 @@ Transform code at compile time to automate repetition and generate code. Macros transform your source code when you compile it, letting you avoid writing out repetitive code by hand and omit boilerplate code. -For example: +For example, consider the following code: ```swift struct SundaeToppings: OptionSet { @@ -24,8 +24,7 @@ which is repetitive and manual. It would be easy to make a mistake when adding a new option, like typing the wrong number at the end of the line. -Here's what that code looks like -using a macro instead: +Here's a version of this code that uses a macro instead: ```swift @OptionSet @@ -45,16 +44,14 @@ This version of `SundaeToppings` calls the `OptionSet` macro from the Swift standard library. The macro reads the list of cases in the private enumeration, generates the list of constants for each option, -and marks `SundaeToppings` as conforming to the `OptionSet` protocol. +and adds a conformance to the `OptionSet` protocol. [`OptionSet`]: https://developer.apple.com/documentation/swift/optionset -You can identify Swift code that uses a macro -because the starts with an at sign (`@`) -like `@OptionSet` in the example above, -or a number sign (`#`) -like `#line` in the example below. +Macros can also stand on their own, +without being attached to any specific declaration, +as shown in the example below. ```swift let currentLine = #line @@ -65,48 +62,33 @@ let black = #colorLiteral(red: 0, green: 0, blue: 0) In the first line, `#line` is a call to the `line` macro from the Swift standard library. -You can recognize that it's a call to a macro -because of the `#` in front of it. When you compile this code, Swift calls that macro's implementation, and replaces `#line` with the current line number. - In the second line, `#warning` calls another macro from the standard library to produce a custom warning when the code is compiled. -Again, the `#` marks this as a macro call. -Unlike `#line`, `#warning` doesn't produce any value. - -Macros like `@OptionSet` are known as *attached macros* -because they are always attached to a declaration. -Attached macros can add members to the declaration that they're attached to. -Macros like `#line` and `#warning` are known as *freestanding macros* -because they can appear on their own, -without being attached to a declaration. -Freestanding macros can produce a value, like `#line`, -they can perform some compile-time action, like `#warning`, -or they can generate new declarations. -Both attached and freestanding macros are always additive: -They can expand to add new code, -but they can't ever delete code -or modify code that you wrote by hand. -Swift expands both attached and freestanding macros -using the following general steps: +Expanding a macro is always an additive operation: +Macros add new code, +but they never delete code +or modify code that you wrote by hand. +At a high level, macros are expanded as follows: -1. The compiler reads the code, just like when it's compiling, +1. The compiler reads the code, creating an in-memory representation of the syntax. - This representation is known as an _abstract syntax tree_ or AST. + This representation is also called an abstract syntax tree. + +1. The compiler sends part of this in-memory representation + to the executable that implements the macro. + That code expands the macro. -1. The compiler passes part of that in-memory representation - - to the implementation of the macro, - which returns the macro's expansion. +1. The compiler replaces the macro call with its expanded form, + and then continues with compilation. -1. The compiler replaces the macro with its expanded form, - and then continues compilation. + -[XXX FIGURE XXX] +[XXX FIGURE: Overview] ``` let currentLine = #line @@ -121,77 +103,37 @@ let currentLine = #line let currentLine = 123 ``` - - -If you've used macros in another programming language, -some parts of Swift macros will be familiar -and some parts will feel different. -All of the components of the Swift macro system are made up of Swift code: - -- The declaration of a Swift macro, - including information about where it can appear - and what kind of output it produces, - is written in Swift like the declaration of a structure or function. - -- The implementation of a macro is written in Swift, - using the functionality provided by the [SwiftSyntax][] module - to read Swift code and add to it. - Even though there are convenience APIs in SwiftSyntax - to create new syntax nodes using strings, - the input, expansion, and output all consists of - structured information (AST nodes). - - -- The result of macro expansion is Swift code, - which you can debug as normal. - XXX debugging - how to expand macros - -[SwiftSyntax]: http://github.com/apple/swift-syntax/ - Both the input to a macro and the output of macro expansion -are always valid Swift code --- -they're syntactically well-formed -and the values type-check. +are checked to ensure they're syntactically valid Swift code. +Likewise, the values you pass to a macro +and the values in code generated by a macro +are checked to ensure they have the correct types. - +## Freestanding Macros - +A *freestanding macro* is a macro that appears by itself, +and that doesn't modify a declaration. +When you call a freestanding macro, +you write a number sign (`#`) before the macro name. +The `#` indicates that the macro is a compile-time operation, +like `#if` and `#available`. +After the macro's name, +you write any arguments to the macro in parentheses, +like when you call a function. -## Freestanding Macros +Freestanding macros can produce a value, like `#line`, +they can perform some compile-time action, like `#warning`, +or they can generate new declarations. + XXX OUTLINE: -- Spelled with a pound sign (`#`), - indicating that this is a compile-time operation. - This spelling looks like `#if` and other things that happen at compile time. - - Macro declaration includes `@freestanding(expression)`. These are "freestanding" because they produce a value or declaration on their own, rather than being attached to another piece of syntax. Contrast with "attached" macros, described below. -- If the macro doesn't take arguments, - you just write its name to call it. - For example: `#line`. - -- If the macro takes arguments, - you write them after the name like a function call. - For example XXX. - - When you compile your code, the macro implementation modifies your code. (very brief version with xref to section below) @@ -207,18 +149,18 @@ XXX OUTLINE: ## Attached Macros -XXX OUTLINE: +An *attached macro* is a macro that comes before a declaration, +in the same position where you write attributes. +When you call an attached macro, +you write an at sign (`@`) before its name, +followed by any arguments to the macro in parentheses. -- Spelled with an at sign (`@`). - This looks like an attribute because XXX +Attached macros modify the declaration that they're attached to. +They can add code like a new method or property on a type, +conformance of a type to a property, +XXX examples of other roles -- FIXME: Example attached macro from the stdlib - -- These are "attached" because you write them as an attribute - that's attached to a declaration, - like a structure or a property. - Attached macros augment the declaration they're attached to --- - for example, by adding additional members to a structure declaration. +XXX OUTLINE: - Macro declaration includes `@attached` followed by information about the kinds of code the macro produces, @@ -276,6 +218,146 @@ XXX OUTLINE: To generate a unique symbol name, call the `MacroExpansionContext.makeUniqueName()` method. +XXX MOVED PROSE: + +Why can't my macro and the rest of my code all be in one target? +In brief, because that would create a circular dependency. +A macro's implementation has to be compiled +before it can be used to compile other code. +So if your single-target project contained both the macro +and other code that used the macro, +then the compiler would have had to already compiled your code +in order to have the macro expanded and be able to compiler your code. +XXX +Also, the macro runs on your development machine +but the final build product might run elsewhere --- +like compiling code on a computer +to run on a server or mobile device. + +* * * + +All of the components of the Swift macro system are made up of Swift code: + +- The declaration of a Swift macro, + including information about where it can appear + and what kind of output it produces, + is written in Swift like the declaration of a structure or function. + +- The implementation of a macro is written in Swift, + using the functionality provided by the [SwiftSyntax][] module + to read and generate Swift code. + +- The result of macro expansion is Swift code. + +[SwiftSyntax]: http://github.com/apple/swift-syntax/ + +* * * + +If you've used macros in another programming language, +some parts of Swift macros will be familiar +and some parts will feel different. + +hygienic macros +gensym + +XXX END OUTLINE BITS XXX + +To illustrate the process of expanding a macro, +consider the following code: + +```swift +let line = #colorLiteral(red: 10, green: 20, blue: 30) +``` + +Swift reads this code, +checks its syntax and types, +and produces a representation of the code +called an *abstract syntax tree* (AST). +The AST is made of nodes that correspond to +the meaning and structure of the code that it represents. +A simplified AST for the code above looks like this: + +- Constant declaration + - Identifier `black` + - Initial value + - Macro + - Identifier `colorLiteral` + - Arguments + - Label `red:` + - Integer literal `0` + - Label `green:` + - Integer literal `0` + - Label `blue:` + - Integer literal `0` + +To continue with compilation, +Swift needs to expand the `colorLiteral(red:green:blue:)` macro. +It passes that part of the AST +to another executable that implements this macro. +Here's what the macro implementation sees: + +- Macro + - Identifier `colorLiteral` + - Arguments + - Label `red:` + - Integer literal `0` + - Label `green:` + - Integer literal `0` + - Label `blue:` + - Integer literal `0` + +A macro expansion operates only on the code that contains the macro. +In this example, +that means that the AST nodes representing `let black =` are omitted. + +The implementation of the `colorLiteral(red:green:blue:)` macro +generates a new AST with the expanded version of the macro, +calling an initializer on `Color` directly. +Here's what the macro implementation returns: + +- Function call + - Member access + - Identifier `Color` + - Identifier `init` + - Arguments + - Label `red:` + - Integer literal `0` + - Label `green:` + - Integer literal `0` + - Label `blue:` + - Integer literal `0` + +The macro implementation sends this new AST back to the compiler. +Swift replaces the macro node in the AST +with the newly expanded version, +and then checks that the resulting AST is syntactically valid +and that the values in it have the needed types. +The AST looks like this after macro expansion: + +- Constant declaration + - Identifier `black` + - Initial value + - Function call + - Member access + - Identifier `Color` + - Identifier `init` + - Arguments + - Label `red:` + - Integer literal `0` + - Label `green:` + - Integer literal `0` + - Label `blue:` + - Integer literal `0` + +Finally, +the code is compiled +as if it had been written in source +in the expanded form. + +```swift +let black = Color.init(red: 0, green: 0, blue: 0) +``` + ## Declaring a Macro XXX OUTLINE: @@ -396,6 +478,8 @@ XXX OUTLINE: The APIs come from here https://github.com/apple/swift-syntax/blob/main/Sources/SwiftSyntaxBuilder/Syntax%2BStringInterpolation.swift +XXX mention idempotency and sandboxing + ## Debugging macros - Ways to view the macro expansion while debugging. @@ -449,94 +533,7 @@ in no particular order: - `TokenSyntax` -## XXX Figure: The moving parts in macro expansion - -Series of figures for ASTs, interleaved with text - -QUESTION: Is this better served as nested bulleted lists? -Maybe draw out the full tree the first time, -and then switch to the textual version? - -XXX -ASTs below are illustrative only, -and need to be rewritten to at least follow the shape -of what your macro will actually see. -However, for teaching purposes, -I still plan use a simplified AST in this example, -omitting the full details of the SwiftSyntax tree. - -Starts with your code as an unparsed string: - -```swift -let line = #colorLiteral(red: 10, green: 20, blue: 30) -``` - -Swift compiler parses the code to build an AST: - -- assignment - - identifier `line` - - macro - - identifier `colorLiteral` - - label `red:` - - integer 10 - - label `green:` - - integer 20 - - label `blue:` - - integer 30 - -Swift compiler passes the AST nodes that correspond to the macro -to the separate binary that implement the macro. -Here, that means the AST nodes that correspond to `line =` are omitted. - -- macro - - identifier `colorLiteral` - - label `red:` - - integer 10 - - label `green:` - - integer 20 - - label `blue:` - - integer 30 - -Macro implementation uses `SwiftSyntax` APIs -to manipulate the AST. - -- function call - - member access - - identifier `Color` - - identifier `init` - - label `red:` - - integer 10 - - label `green:` - - integer 20 - - label `blue:` - - integer 30 - -Macro binary and returns AST nodes the Swift compiler. -The compiler type-checks that result, -and replaces the macro node with the new syntax tree. - -- assignment - - identifier `line` - - function call - - member access - - identifier `Color` - - identifier `init` - - label `red:` - - integer 10 - - label `green:` - - integer 20 - - label `blue:` - - integer 30 - -The code is compiled -as if it had been written in source -in the expanded form. - -```swift -let line = Color.init(red: 10, green: 20, blue: 30) -``` - -(This might be a good point to mention the "dump macro expansion" flag.) +XXX Swift front-end flag for "dump macro expansion" + +XXX OUTLINE: + +- Macro declaration includes `@freestanding(expression)`. + +- Example of a macro and its expanded form. + + `#colorLiteral(red:green:blue)` expands to `Color.init(red:green:blue)` + + XXX use a different example -- colorLiteral has uninteresting expansion + +## Attached Macros + +To call an attached macro, +you write an at sign (`@`) before its name, +followed by any arguments to the macro in parentheses. + +Attached macros modify the declaration that they're attached to. +They add code to that declaration, +like defining a new method or adding conformance to a protocol. + +For example, consider the following code +that doesn't use macros: ```swift struct SundaeToppings: OptionSet { let rawValue: Int - static let nuts = SundaeToppings(rawValue: 1 << 0) static let cherry = SundaeToppings(rawValue: 1 << 1) static let fudge = SundaeToppings(rawValue: 1 << 2) @@ -27,19 +103,16 @@ like typing the wrong number at the end of the line. Here's a version of this code that uses a macro instead: ```swift -@OptionSet +@OptionSet struct SundaeToppings { private enum Options: Int { - case whippedCream case nuts case cherry - case chocolateSyrup + case fudge } } ``` - - This version of `SundaeToppings` calls the `OptionSet` macro from the Swift standard library. The macro reads the list of cases in the private enumeration, @@ -49,116 +122,28 @@ and adds a conformance to the `OptionSet` protocol. [`OptionSet`]: https://developer.apple.com/documentation/swift/optionset -Macros can also stand on their own, -without being attached to any specific declaration, -as shown in the example below. +For comparison, +after the compiler expands the `@OptionSet` macro, +here's what the source code looks like: ```swift -let currentLine = #line -let black = #colorLiteral(red: 0, green: 0, blue: 0) -``` - - - -In the first line, -`#line` is a call to the `line` macro from the Swift standard library. -When you compile this code, -Swift calls that macro's implementation, -and replaces `#line` with the current line number. -In the second line, -`#warning` calls another macro from the standard library -to produce a custom warning when the code is compiled. - -Expanding a macro is always an additive operation: -Macros add new code, -but they never delete code -or modify code that you wrote by hand. -At a high level, macros are expanded as follows: - -1. The compiler reads the code, - creating an in-memory representation of the syntax. - This representation is also called an abstract syntax tree. - -1. The compiler sends part of this in-memory representation - to the executable that implements the macro. - That code expands the macro. - -1. The compiler replaces the macro call with its expanded form, - and then continues with compilation. - - - -[XXX FIGURE: Overview] +struct SundaeToppings { + private enum Options: Int { + case nuts + case cherry + case fudge + } + typealias RawValue = Int + var rawValue: RawValue + init() { self.rawValue = 0 } + init(rawValue: RawValue) { self.rawValue = rawValue } + static let nuts: Self = Self(rawValue: 1 << Options.nuts.rawValue) + static let cherry: Self = Self(rawValue: 1 << Options.cherry.rawValue) + static let fudge: Self = Self(rawValue: 1 << Options.fudge.rawValue) +} +extension SundaeToppings: OptionSet {} ``` -let currentLine = #line - | - v - #line - | - v - 123 - | - v -let currentLine = 123 -``` - -Both the input to a macro and the output of macro expansion -are checked to ensure they're syntactically valid Swift code. -Likewise, the values you pass to a macro -and the values in code generated by a macro -are checked to ensure they have the correct types. - -## Freestanding Macros - -A *freestanding macro* is a macro that appears by itself, -and that doesn't modify a declaration. -When you call a freestanding macro, -you write a number sign (`#`) before the macro name. -The `#` indicates that the macro is a compile-time operation, -like `#if` and `#available`. -After the macro's name, -you write any arguments to the macro in parentheses, -like when you call a function. - -Freestanding macros can produce a value, like `#line`, -they can perform some compile-time action, like `#warning`, -or they can generate new declarations. - - -XXX OUTLINE: - -- Macro declaration includes `@freestanding(expression)`. - These are "freestanding" because - they produce a value or declaration on their own, - rather than being attached to another piece of syntax. - Contrast with "attached" macros, described below. - -- When you compile your code, - the macro implementation modifies your code. - (very brief version with xref to section below) - -- Example of a macro and its expanded form. - - `#colorLiteral(red:green:blue)` expands to `Color.init(red:green:blue)` - -- NOTE: - Today, expression macros are the only kind of freestanding macros, - but more are expected in the future via - https://github.com/DougGregor/swift-evolution/blob/freestanding-macros/proposals/nnnn-freestanding-macros.md - -## Attached Macros - -An *attached macro* is a macro that comes before a declaration, -in the same position where you write attributes. -When you call an attached macro, -you write an at sign (`@`) before its name, -followed by any arguments to the macro in parentheses. - -Attached macros modify the declaration that they're attached to. -They can add code like a new method or property on a type, -conformance of a type to a property, -XXX examples of other roles XXX OUTLINE: @@ -166,11 +151,6 @@ XXX OUTLINE: followed by information about the kinds of code the macro produces, and information about the names of the generated symbols. -- To apply the macro to a declaration, - you write its name and any parameters it takes before that declaration, - like an attribute. - For example XXX - - Expansion works the same way as for freestanding macros. Arguments also work the same way. @@ -275,9 +255,14 @@ To illustrate the process of expanding a macro, consider the following code: ```swift -let line = #colorLiteral(red: 10, green: 20, blue: 30) +let black = #colorLiteral(red: 0, green: 0, blue: 0) ``` + + Swift reads this code, checks its syntax and types, and produces a structured representation of the code in memory @@ -369,6 +354,23 @@ let black = Color.init(red: 0, green: 0, blue: 0) ## Declaring a Macro +XX INTRO + +Here's the declaration for `#OptionSet` from the Swift standard library: + + +```swift +@attached(member, names: named(RawValue), named(rawValue), named(`init`), arbitrary) +@attached(conformance) +public macro OptionSet() = + #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") +``` +This macro has two roles: member, and conformance. +The first line gives it the member role, +and lists the names of the members that the macro generates --- +`RawValue`, `rawValue`, and `init`. + + XXX OUTLINE: - A macro has two parts: the declaration, and the implementation. From 672c5db2a7182632b4ca4e0f8f9b206c2bd4adc9 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Mon, 8 May 2023 10:12:47 -0700 Subject: [PATCH 17/51] Move some details to a better spot. --- TSPL.docc/LanguageGuide/Macros.md | 49 +++++++++++++++++-------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index 5c562fb6e..7d4408d6f 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -61,16 +61,6 @@ Freestanding macros can produce a value, like `#line`, or they can perform an action at compile time, like `#warning`. -XXX OUTLINE: - -- Macro declaration includes `@freestanding(expression)`. - -- Example of a macro and its expanded form. - - `#colorLiteral(red:green:blue)` expands to `Color.init(red:green:blue)` - - XXX use a different example -- colorLiteral has uninteresting expansion - ## Attached Macros To call an attached macro, @@ -145,19 +135,12 @@ struct SundaeToppings { extension SundaeToppings: OptionSet {} ``` -XXX OUTLINE: - -- Macro declaration includes `@attached` - followed by information about the kinds of code the macro produces, - and information about the names of the generated symbols. - -- Expansion works the same way as for freestanding macros. - Arguments also work the same way. - -- Example of a macro and its expanded form. - ## How Macros Are Expanded +XXX +Defer the AST details to section on creating macros, +maybe move this whole section down + XXX OUTLINE: - The macro expansion process: @@ -354,7 +337,7 @@ let black = Color.init(red: 0, green: 0, blue: 0) ## Declaring a Macro -XX INTRO +XXX INTRO Here's the declaration for `#OptionSet` from the Swift standard library: @@ -420,6 +403,28 @@ XXX OUTLINE: - XXX TR: What guidance can we give about choosing where the implementation goes? + +XXX OUTLINE freestanding: + +- Macro declaration includes `@freestanding(expression)`. + +- Example of a macro and its expanded form. + + `#colorLiteral(red:green:blue)` expands to `Color.init(red:green:blue)` + + XXX use a different example — colorLiteral has uninteresting expansion + +XXX OUTLINE attached: + +- Macro declaration includes `@attached` + followed by information about the kinds of code the macro produces, + and information about the names of the generated symbols. + +- Expansion works the same way as for freestanding macros. + Arguments also work the same way. + +- Example of a macro and its expanded form. + ## Implementing a Macro [TODO: Re-order for better flow, and split into multiple sections.] From 2707d023a14cf62907fc1d04350fe24011aa7294 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Mon, 8 May 2023 12:04:07 -0700 Subject: [PATCH 18/51] Re-order sections, for better learning path flow. --- TSPL.docc/LanguageGuide/Macros.md | 218 +++++++++++++++--------------- 1 file changed, 108 insertions(+), 110 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index 7d4408d6f..c780070b1 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -135,11 +135,99 @@ struct SundaeToppings { extension SundaeToppings: OptionSet {} ``` -## How Macros Are Expanded +## Macro Declarations -XXX -Defer the AST details to section on creating macros, -maybe move this whole section down +XXX INTRO + +Here's the declaration for `#OptionSet` from the Swift standard library: + + +```swift +@attached(member, names: named(RawValue), named(rawValue), named(`init`), arbitrary) +@attached(conformance) +public macro OptionSet() = + #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") +``` +This macro has two roles: member, and conformance. +The first line gives it the member role, +and lists the names of the members that the macro generates --- +`RawValue`, `rawValue`, and `init`. + + +XXX OUTLINE: + +- [This section is mainly focused on *reading* a macro declaration] + +- A macro has two parts: the declaration, and the implementation. + This is different from most things in Swift, + where the declaration also contains the implementation. + +- Macro declaration includes the `macro` keyword. + Attributes on the macro declaration specify where and how it is used. + [`@freestanding` and `@attached` introduced already above] + +- The first half of the declaration, + the parts before the equals sign (`=`) + specify how the macro is used. + The second half tells you which type implements the macro + and what module that type is in. + +- Freestanding macros are marked with `@freestanding`. + Attached macros are marked with `@attached`. + +- Arguments to those macros describe usage more specifically: + + - `@freestanding(expression)` (XXX TR: Any other kind of freestanding?) + - `@attached(peer, names:)` + - `@attached(member, names:)` + - `@attached(memberAttribute)` (Note: You can't specify names here.) + - `@attached(accessor, names:)` + +- Every declaration that a macro creates in its expansion + must be included in the list of names the macro declares in an attribute. + Exception: A macro that uses `arbitrary`. + However, a macro can declare a name + but omit a corresponding declaration in the expansion. + (For example, because one already exists.) + +- Macro declaration naming: + + - `named(someDeclarationName)` + - `arbitrary` + - `overloaded` + - `prefixed()` usually `prefixed(_)` + but others including `$` are allowed. + - `suffixed()` like `suffixed(_docInfo)` + +- After the `=` you either write `#externalMacro(module:type:)` + or call a different macro that expands to the macro's implementation. + +- XXX TR: What guidance can we give + about choosing where the implementation goes? + + +XXX OUTLINE freestanding: + +- Macro declaration includes `@freestanding(expression)`. + +- Example of a macro and its expanded form. + + `#colorLiteral(red:green:blue)` expands to `Color.init(red:green:blue)` + + XXX use a different example — colorLiteral has uninteresting expansion + +XXX OUTLINE attached: + +- Macro declaration includes `@attached` + followed by information about the kinds of code the macro produces, + and information about the names of the generated symbols. + +- Expansion works the same way as for freestanding macros. + Arguments also work the same way. + +- Example of a macro and its expanded form. + +## Macro Expansion XXX OUTLINE: @@ -190,22 +278,6 @@ XXX OUTLINE: To generate a unique symbol name, call the `MacroExpansionContext.makeUniqueName()` method. -XXX MOVED PROSE: - -Why can't my macro and the rest of my code all be in one target? -In brief, because that would create a circular dependency. -A macro's implementation has to be compiled -before it can be used to compile other code. -So if your single-target project contained both the macro -and other code that used the macro, -then the compiler would have had to already compiled your code -in order to have the macro expanded and be able to compiler your code. -XXX -Also, the macro runs on your development machine -but the final build product might run elsewhere --- -like compiling code on a computer -to run on a server or mobile device. - * * * All of the components of the Swift macro system are made up of Swift code: @@ -335,96 +407,6 @@ in the expanded form. let black = Color.init(red: 0, green: 0, blue: 0) ``` -## Declaring a Macro - -XXX INTRO - -Here's the declaration for `#OptionSet` from the Swift standard library: - - -```swift -@attached(member, names: named(RawValue), named(rawValue), named(`init`), arbitrary) -@attached(conformance) -public macro OptionSet() = - #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") -``` -This macro has two roles: member, and conformance. -The first line gives it the member role, -and lists the names of the members that the macro generates --- -`RawValue`, `rawValue`, and `init`. - - -XXX OUTLINE: - -- A macro has two parts: the declaration, and the implementation. - This is different from most things in Swift, - where the declaration also contains the implementation. - -- Macro declaration includes the `macro` keyword. - Attributes on the macro declaration specify where and how it is used. - [`@freestanding` and `@attached` introduced already above] - -- The first half of the declaration, - the parts before the equals sign (`=`) - specify how the macro is used. - The second half tells you which type implements the macro - and what module that type is in. - -- Freestanding macros are marked with `@freestanding`. - Attached macros are marked with `@attached`. - -- Arguments to those macros describe usage more specifically: - - - `@freestanding(expression)` (XXX TR: Any other kind of freestanding?) - - `@attached(peer, names:)` - - `@attached(member, names:)` - - `@attached(memberAttribute)` (Note: You can't specify names here.) - - `@attached(accessor, names:)` - -- Every declaration that a macro creates in its expansion - must be included in the list of names the macro declares in an attribute. - Exception: A macro that uses `arbitrary`. - However, a macro can declare a name - but omit a corresponding declaration in the expansion. - (For example, because one already exists.) - -- Macro declaration naming: - - - `named(someDeclarationName)` - - `arbitrary` - - `overloaded` - - `prefixed()` usually `prefixed(_)` - but others including `$` are allowed. - - `suffixed()` like `suffixed(_docInfo)` - -- After the `=` you either write `#externalMacro(module:type:)` - or call a different macro that expands to the macro's implementation. - -- XXX TR: What guidance can we give - about choosing where the implementation goes? - - -XXX OUTLINE freestanding: - -- Macro declaration includes `@freestanding(expression)`. - -- Example of a macro and its expanded form. - - `#colorLiteral(red:green:blue)` expands to `Color.init(red:green:blue)` - - XXX use a different example — colorLiteral has uninteresting expansion - -XXX OUTLINE attached: - -- Macro declaration includes `@attached` - followed by information about the kinds of code the macro produces, - and information about the names of the generated symbols. - -- Expansion works the same way as for freestanding macros. - Arguments also work the same way. - -- Example of a macro and its expanded form. - ## Implementing a Macro [TODO: Re-order for better flow, and split into multiple sections.] @@ -520,6 +502,22 @@ XXX OUTLINE: - Adding a new member by making an instance of `Declaration`, and returning it as part of the `[DeclSyntax]` list. +XXX MOVED PROSE: + +Why can't my macro and the rest of my code all be in one target? +In brief, because that would create a circular dependency. +A macro's implementation has to be compiled +before it can be used to compile other code. +So if your single-target project contained both the macro +and other code that used the macro, +then the compiler would have had to already compiled your code +in order to have the macro expanded and be able to compiler your code. +XXX +Also, the macro runs on your development machine +but the final build product might run elsewhere --- +like compiling code on a computer +to run on a server or mobile device. + ## Debugging Macros XXX OUTLINE: From b27bc18873bc3d5d473907ffd3c6f333c14c8d6a Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Mon, 8 May 2023 16:44:19 -0700 Subject: [PATCH 19/51] Rough in reference for @attached and @freestanding. --- TSPL.docc/ReferenceManual/Attributes.md | 101 ++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/TSPL.docc/ReferenceManual/Attributes.md b/TSPL.docc/ReferenceManual/Attributes.md index 56c3ff654..8c5975dc2 100644 --- a/TSPL.docc/ReferenceManual/Attributes.md +++ b/TSPL.docc/ReferenceManual/Attributes.md @@ -28,6 +28,91 @@ and their format is defined by the attribute they belong to. You can apply a declaration attribute to declarations only. +### attached + +Apply the `attached` attribute, to the declaration of an macro. +The arguments to this attribute indicate the macro's role. +For a macro that has multiple roles, +apply the `attached` macro multiple times, once for each role. + + + +The first argument to this attribute +indicates the macros role: + +- Peer macros have `peer` as the first argument to this attribute. + The type that implements the macro conforms to the `PeerMacro` protocol. + These macros produce new declarations + in the same scope as the declaration + that the macro is attached to. + For example, + applying a peer macro to a method of a structure + can define additional methods and properties on that structure. + +- Member macros have `member` as the first argument to this attribute. + The type that implements the macro conforms to the `MemberMacro` protocol. + These macros produce new declarations + that are members of the type or extension + that the macro is attached to. + For example, + applying a member macro to a structure declaration + can define additional methods and properties on that structure. + +- Member attribute macros have `memberAttribute` as the first argument to this attribute. + The type that implements the macro conforms to the `MemberAttributeMacro` protocol. + These macros add attributes to members of the type or extension + that the macro is attached to. + +- Accessor macros have `accessor` as the first argument to this attribute. + The type that implements the macro conforms to the `AccessorMacro` protocol. + These macros add accessors to the stored property they're attached to, + turning it into a computed property. + +- Conformance macros have `conformance` as the first argument to this attribute. + The type that implements the macro conforms to the `ConformanceMacro` protocol. + These macros add protocol conformance to the type they're attached to. + +The XXX and XXX macro roles require a `named:` argument, +listing the names of the symbols that the macro generates. +When a macro declaration includes the `named:` argument, +the macro implementation must generate +only symbol with names that match that list. +That said, +a macro need not generate a symbol for every listed name. +The value for that argument is a list of one or more of the following: + +- `named(<#name#>)` + where *name* is that fixed symbol name, + for a name that's known in advanced + +- `overloaded` + for a name that's the same as an existing symbol + +- `prefixed(<#prefix#>)` + where *prefix* is prepended to the symbol name, + for a name that starts with a fixed string + +- `suffixed(<#suffix#>` + where *suffix* is appended to the symbol name, + for a name that ends with a fixed string + +- `arbirtary` + for a name that can't be determined until the macro is expanded + +As a special case, +you can write `prefixed($)` +for a macro that behaves similar to a property wrapper. + + ### available Apply this attribute to indicate a declaration's life cycle @@ -553,6 +638,22 @@ print(wrapper.x) ``` --> +### freestanding + +Apply the `freestanding` attribute +to the declaration of a freestanding macro. + + + ### frozen Apply this attribute to a structure or enumeration declaration From b5eff3d87277ff88d82a2d878ec79e26995e2738 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Mon, 8 May 2023 16:45:02 -0700 Subject: [PATCH 20/51] Start filling out discussion of declaring macros. --- TSPL.docc/LanguageGuide/Macros.md | 97 ++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index c780070b1..b7ff2693f 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -137,10 +137,49 @@ extension SundaeToppings: OptionSet {} ## Macro Declarations -XXX INTRO +Unlike other declarations in Swift, +you declare a macro separate from its implementation. +A macro declaration includes the `macro` keyword +as well as the macro's name, what parameters it takes, +where it can be used, +and what kind of code it generates. +For example, +here's part of the declaration for +`@OptionSet` from the Swift standard library: -Here's the declaration for `#OptionSet` from the Swift standard library: +```swift +public macro OptionSet() = + #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") +``` + +The first line +specifies the macro's name, `OptionSet`, +and the arguments that takes, in this case none. +The second line tells Swift +where to find the implementation of this macro. +In this case, +the `SwiftMacros` module +contains a type named `OptionSetMacro`, +which implements this macro. + + + +> Note: +> Macros are always declared as `public`. +> Because the code that declares a macro +> is always in a different module from code that uses that macro, +> there isn't anywhere in your source code +> where you could apply a non-public macro. +The declaration of `@OptionSet` above is incomplete --- +a macro declaration also includes information about +where that macro can be used, +and information about how the symbols generated by the macro are named. +Here's the full declaration: ```swift @attached(member, names: named(RawValue), named(rawValue), named(`init`), arbitrary) @@ -148,41 +187,40 @@ Here's the declaration for `#OptionSet` from the Swift standard library: public macro OptionSet() = #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") ``` -This macro has two roles: member, and conformance. + +The `@attached` attribute on this macro declaration +indicates that the `@OptionSet` macro is an attached macro. +That attribute appears twice in this declaration, +once for each macro role that `@OptionSet` has. + +A *macro role* indicates where the code that the macro generate goes. +The `@OptionSet` macro above has two roles: member and conformance. +A member macro adds new members to the type you apply the macro to. +A conformance macro adds protocol conformance to that type. + +For more information about macro roles, +see and +in + The first line gives it the member role, and lists the names of the members that the macro generates --- `RawValue`, `rawValue`, and `init`. +XXX it also lists "arbitrary" + +For a freestanding macros, +you use the `@freestanding` attribute instead, +as discussed below. XXX OUTLINE: - [This section is mainly focused on *reading* a macro declaration] -- A macro has two parts: the declaration, and the implementation. - This is different from most things in Swift, - where the declaration also contains the implementation. - -- Macro declaration includes the `macro` keyword. - Attributes on the macro declaration specify where and how it is used. - [`@freestanding` and `@attached` introduced already above] - -- The first half of the declaration, - the parts before the equals sign (`=`) - specify how the macro is used. - The second half tells you which type implements the macro - and what module that type is in. - - Freestanding macros are marked with `@freestanding`. Attached macros are marked with `@attached`. - Arguments to those macros describe usage more specifically: - - `@freestanding(expression)` (XXX TR: Any other kind of freestanding?) - - `@attached(peer, names:)` - - `@attached(member, names:)` - - `@attached(memberAttribute)` (Note: You can't specify names here.) - - `@attached(accessor, names:)` - - Every declaration that a macro creates in its expansion must be included in the list of names the macro declares in an attribute. Exception: A macro that uses `arbitrary`. @@ -190,22 +228,11 @@ XXX OUTLINE: but omit a corresponding declaration in the expansion. (For example, because one already exists.) -- Macro declaration naming: - - - `named(someDeclarationName)` - - `arbitrary` - - `overloaded` - - `prefixed()` usually `prefixed(_)` - but others including `$` are allowed. - - `suffixed()` like `suffixed(_docInfo)` +- Macro declaration lists the names of the generated symbols - After the `=` you either write `#externalMacro(module:type:)` or call a different macro that expands to the macro's implementation. -- XXX TR: What guidance can we give - about choosing where the implementation goes? - - XXX OUTLINE freestanding: - Macro declaration includes `@freestanding(expression)`. From dff0ee8784eae62835ca51c363d394317d7f1431 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Mon, 8 May 2023 21:22:54 -0700 Subject: [PATCH 21/51] Finish drafting the declaring macros section. --- TSPL.docc/LanguageGuide/Macros.md | 156 +++++++++++++++++------------- 1 file changed, 89 insertions(+), 67 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index b7ff2693f..e6001a2fc 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -71,6 +71,7 @@ Attached macros modify the declaration that they're attached to. They add code to that declaration, like defining a new method or adding conformance to a protocol. + For example, consider the following code that doesn't use macros: @@ -104,7 +105,7 @@ struct SundaeToppings { ``` This version of `SundaeToppings` -calls the `OptionSet` macro from the Swift standard library. +calls the `@OptionSet` macro from the Swift standard library. The macro reads the list of cases in the private enumeration, generates the list of constants for each option, and adds a conformance to the `OptionSet` protocol. @@ -135,17 +136,31 @@ struct SundaeToppings { extension SundaeToppings: OptionSet {} ``` +All of the code after the private enumeration +comes from the `@OptionSet` macro. +The version of `SundaeToppings` +that uses a macro to generate all of the static variables +is easier to read and easier to maintain +than the manual version at the start of this section. + ## Macro Declarations -Unlike other declarations in Swift, -you declare a macro separate from its implementation. -A macro declaration includes the `macro` keyword +In most Swift code, +you implement a symbol, like a function or type, +and there's no separate declaration. +However, for macros, the declaration and implementation are separate. +A macro's implementation contains the code +that expands the macro by generating Swift code, +and its declaration as well as the macro's name, what parameters it takes, where it can be used, and what kind of code it generates. + + +You introduce a macro declaration with the `macro` keyword. For example, here's part of the declaration for -`@OptionSet` from the Swift standard library: +the `@OptionSet` macro used in the previous example: ```swift public macro OptionSet() = @@ -155,12 +170,13 @@ public macro OptionSet() = The first line specifies the macro's name, `OptionSet`, and the arguments that takes, in this case none. -The second line tells Swift -where to find the implementation of this macro. +The second line +uses the `#externalMacro(module:type:)` macro from the standard library +to tell Swift where the macro's implementation is. In this case, the `SwiftMacros` module contains a type named `OptionSetMacro`, -which implements this macro. +which implements the `@OptionSet` macro. + +In addition to the macro's role, +a macro's declaration provides information about +the names of the symbols that the macro generates. +This list is included only for the XXX macro roles. +For example, +the `@OptionSet` macro generates +symbols named `RawValue`, `rawValue`, and `init`. +When a macro declaration provides a list of names, +it's guaranteed to produce only declarations that use those names, +which helps you understand and debug the generated code. For more information about macro roles, see and in -The first line gives it the member role, -and lists the names of the members that the macro generates --- -`RawValue`, `rawValue`, and `init`. -XXX it also lists "arbitrary" - - -For a freestanding macros, -you use the `@freestanding` attribute instead, -as discussed below. - -XXX OUTLINE: - -- [This section is mainly focused on *reading* a macro declaration] - -- Freestanding macros are marked with `@freestanding`. - Attached macros are marked with `@attached`. - -- Arguments to those macros describe usage more specifically: - -- Every declaration that a macro creates in its expansion - must be included in the list of names the macro declares in an attribute. - Exception: A macro that uses `arbitrary`. - However, a macro can declare a name - but omit a corresponding declaration in the expansion. - (For example, because one already exists.) - -- Macro declaration lists the names of the generated symbols - -- After the `=` you either write `#externalMacro(module:type:)` - or call a different macro that expands to the macro's implementation. - -XXX OUTLINE freestanding: - -- Macro declaration includes `@freestanding(expression)`. - -- Example of a macro and its expanded form. - - `#colorLiteral(red:green:blue)` expands to `Color.init(red:green:blue)` - - XXX use a different example — colorLiteral has uninteresting expansion - -XXX OUTLINE attached: - -- Macro declaration includes `@attached` - followed by information about the kinds of code the macro produces, - and information about the names of the generated symbols. - -- Expansion works the same way as for freestanding macros. - Arguments also work the same way. - -- Example of a macro and its expanded form. - ## Macro Expansion XXX OUTLINE: From 2c71204ee73e06bef4ea030235b38fdff123c781 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Mon, 8 May 2023 21:27:44 -0700 Subject: [PATCH 22/51] Add a note about freestanding declaration macros. --- TSPL.docc/ReferenceManual/Attributes.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/TSPL.docc/ReferenceManual/Attributes.md b/TSPL.docc/ReferenceManual/Attributes.md index 8c5975dc2..f65b78950 100644 --- a/TSPL.docc/ReferenceManual/Attributes.md +++ b/TSPL.docc/ReferenceManual/Attributes.md @@ -652,6 +652,15 @@ The arguments to this attribute indicate the macro's roles: - `expression` A macro that produces an expression +- `declaration` + A macro that produces a declaration + +XXX +Or are those supported today? +I see #error and #warning as @freestanding(declaration) +in the stdlib already: + +https://github.com/apple/swift/blob/main/stdlib/public/core/Macros.swift#L102 --> ### frozen From 9e263faf0f3499e541175a1f0cbeea19d404a71b Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Mon, 8 May 2023 23:07:04 -0700 Subject: [PATCH 23/51] Try narrowing the guide's discussion of roles. --- TSPL.docc/LanguageGuide/Macros.md | 55 ++++++++----------------------- 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index e6001a2fc..feaabcbfd 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -220,51 +220,24 @@ A *macro role* indicates where the code that the macro generate goes. Every macro has one or more roles, which you write as part of the attributes at the beginning of the macro declaration. -For example, -the `@OptionSet` macro above has two roles --- `member` and `conformance` --- -and the `#line` macro above has the `expression` role. -The full list of macro roles is as follows: - -- A member macro adds new members to the type you apply the macro to. - For example, - a member macro that you write on a structure - can add methods or properties to that structure. - Member macros are always attached. - -- A member-attribute macro adds attributes - to members of the type you apply the macro to. - For example, - a member-attribute macro that you write on a class - can add attributes to that class's properties. - Member macros are always attached. - -- A peer macro adds new declarations - at the same level as the symbol you apply the macro to. - For example, - a peer macro that you write on a method - can define another method that's part of the same structure or class. - Peer macros are always attached. - -- A conformance macro adds protocol conformance to that type. - For example, - a conformance macro that you write on an enumeration - can generate the code to make that enumeration conform to a protocol. - Conformance macros are always attached. - -- An expression macro produces a value or performs an action. - Expression macros are always freestanding. - +For example, +the `#line` macro above has the `expression` role, +and the `@OptionSet` macro above has two roles --- `conformance` and `member`. +An expression macro produces a value or performs an action. +A conformance macro adds one or more protocol conformances. +The `@OptionSet` macro +extends the type that you apply the macro to, +to add conformance to the `OptionSet` protocol. +A member macro adds new members to the type you apply the macro to. +In this case, +the `@OptionSet` macro adds an `init(rawValue:)` initializer +that's required by the `OptionSet` protocol, +as well as some additional members. In addition to the macro's role, a macro's declaration provides information about the names of the symbols that the macro generates. -This list is included only for the XXX macro roles. For example, the `@OptionSet` macro generates symbols named `RawValue`, `rawValue`, and `init`. @@ -272,7 +245,7 @@ When a macro declaration provides a list of names, it's guaranteed to produce only declarations that use those names, which helps you understand and debug the generated code. -For more information about macro roles, +For a full list of macro roles and more information, see and in From 66051d80b29da18020ccddec3a9b1746e9375294 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Tue, 9 May 2023 15:44:43 -0700 Subject: [PATCH 24/51] Build up to the full OptionSet macro declaration. --- TSPL.docc/LanguageGuide/Macros.md | 42 +++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index feaabcbfd..bac1b37f6 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -190,15 +190,13 @@ versus just being covered in the reference? > is in a different module from code that uses that macro, > there isn't anywhere you could apply a non-public macro. -The declaration of `@OptionSet` above is incomplete --- -a macro declaration also includes information about -where that macro can be used, -and information about how the symbols generated by the macro are named. -Here's the full declaration: +A macro declaration also includes information +about where that macro can be used. +Here's a partial declaration of `@OptionSet`, +with those attributes added: ```swift -@attached(member, names: named(RawValue), named(rawValue), - named(`init`), arbitrary) +@attached(member) @attached(conformance) public macro OptionSet() = #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") @@ -238,14 +236,36 @@ as well as some additional members. In addition to the macro's role, a macro's declaration provides information about the names of the symbols that the macro generates. -For example, -the `@OptionSet` macro generates -symbols named `RawValue`, `rawValue`, and `init`. When a macro declaration provides a list of names, it's guaranteed to produce only declarations that use those names, which helps you understand and debug the generated code. +Here's the full declaration of `@OptionSet`: + +```swift +@attached(member, names: named(RawValue), named(rawValue), + named(`init`), arbitrary) +@attached(conformance) +public macro OptionSet() = + #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") +``` + +In the declaration above, +the `@attached(member)` macro includes arguments after the `named:` label +for each of the symbols that the `@OptionSet` macro generates. +The macro adds declarations for symbols named +`RawValue`, `rawValue`, and `init` --- +because those names are known ahead of time, +the macro declaration lists them explicitly. + +The macro declaration also includes `arbitrary` after the list of names, +allowing the macro to generate declarations +whose names aren't known until you use the macro. +In this case, +for each case in the private `Options` enumeration, +`@OptionSet` generates a corresponding declaration with the same name. -For a full list of macro roles and more information, +For more information, +including a full list of macro roles, see and in From 52f28bef19a729b73cae165b524b8fb875549626 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Tue, 9 May 2023 17:05:54 -0700 Subject: [PATCH 25/51] Expand the discussion of macro expansion. --- TSPL.docc/LanguageGuide/Macros.md | 208 +++++++++++++----------------- 1 file changed, 91 insertions(+), 117 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index bac1b37f6..f76dd8cc6 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -271,24 +271,101 @@ in ## Macro Expansion -XXX OUTLINE: +As part of building Swift code that uses macros, +the compiler and the macro's implementation +pass that code back and forth to expand the macros. + +To go through the specific steps, +consider the following code: + +``` +let magicNumber = #fourCharacterCode("ABCD") +``` + +The `#fourCharacterCode` macro takes a string that's four characters long +and returns a unsigned 32-bin integer +that corresponds to the ASCII values in the string joined together. +Some file formats use a integers like this to identify data, +because they're compact but still readable in a debugger. +The section below +shows how to implement this macro. + +To expand the macros in the code above, +the compiler reads the Swift file +and creates an in-memory representation of that code +known an as *abstract syntax tree* or AST. +The AST makes the code's meaning and structure explicit, +which makes it easier to write code that interacts with that structure --- +like a compiler or a macro implementation. +Here's a representation of the AST for the code above, +slightly simplified by omitting some extra detail. + +- Constant declaration + - Identifier `magicNumber` + - Initial value + - Macro + - Identifier `fourCharacterCode` + - Arguments + - String literal `"ABCD"` + + -- The macro expansion process: +The compiler also ensures that the input code is valid Swift: +for example, that the input to macros is syntactically valid +and that the types of values match. +For example, in the code above, +it checks that the argument to `#fourCharacterCode` is a string. + - 1. The compiler ensures that the code inside the macro call is valid Swift. - 1. The compiler represents your code in memory - using an abstract syntax tree. - 1. The compiler calls the code that implements the macro, - passing it information about context where the macro appeared. - 1. The macro implementation creates new AST nodes. - 1. The compiler splices the new AST nodes into the declaration. - 1. The compiler builds the expanded Swift code. +The compiler finds the places in the code where you call a macro, +and loads the external binary that implements those macros. +For each macro call, +the compiler passes part of the AST to that macro's implementation. + +Here's a representation of that partial AST: -- Figure: moving parts [see ASCII art below] +- Macro + - Identifier `fourCharacterCode` + - Arguments + - String literal `"ABCD"` + +The implementation of a macro +operates only on the code that contains the macro. +In this example, +the implementation of the `#fourCharacterCode` macro +reads this partial AST that contains only the macro call. +A macro can't depend on code outside of the place where it's used. + +The implementation of `#fourCharacterCode` +generates a new AST containing the expanded code. +Here's what that code returns to the compiler: + +- Integer literal `1145258561` + +When the compiler gets this expansion back, +it replaces the AST element that contains the macro call +with the element that contains the macro's expansion. +After macro expansion, +the compiler checks again to ensure +the program is still syntactically valid Swift +and the all the types are correct. +That produces a final AST that can be compiled as usual: + +- Constant declaration + - Identifier `magicNumber` + - Initial value + - Integer literal `1145258561` + +This AST corresponds to Swift code like this: + +``` +let magicNumber = 1145258561 +``` -- Macro arguments are type-checked before macro expansion. - The macro implementation transforms well-typed, well-formed input - into well-typed, well-formed output. +## XXX Macro Expansion OUTLINE - Macros can be nested. Nested macros are expanded from the outside in. @@ -346,109 +423,6 @@ and some parts will feel different. hygienic macros gensym -XXX END OUTLINE BITS XXX - -To illustrate the process of expanding a macro, -consider the following code: - -```swift -let black = #colorLiteral(red: 0, green: 0, blue: 0) -``` - - - -Swift reads this code, -checks its syntax and types, -and produces a structured representation of the code in memory -called an *abstract syntax tree* (AST). -The AST is made of nodes that correspond to -the meaning and structure of the code that it represents. -A simplified AST for the code above looks like this: - -- Constant declaration - - Identifier `black` - - Initial value - - Macro - - Identifier `colorLiteral` - - Arguments - - Label `red:` - - Integer literal `0` - - Label `green:` - - Integer literal `0` - - Label `blue:` - - Integer literal `0` - -To continue with compilation, -Swift needs to expand the `colorLiteral(red:green:blue:)` macro. -It passes that part of the AST -to another executable that implements this macro. -Here's what the macro implementation sees: - -- Macro - - Identifier `colorLiteral` - - Arguments - - Label `red:` - - Integer literal `0` - - Label `green:` - - Integer literal `0` - - Label `blue:` - - Integer literal `0` - -A macro expansion operates only on the code that contains the macro. -In this example, -that means that the AST nodes representing `let black =` are omitted. - -The implementation of the `colorLiteral(red:green:blue:)` macro -generates a new AST with the expanded version of the macro, -calling an initializer on `Color` directly. -Here's what the macro implementation returns: - -- Function call - - Member access - - Identifier `Color` - - Identifier `init` - - Arguments - - Label `red:` - - Integer literal `0` - - Label `green:` - - Integer literal `0` - - Label `blue:` - - Integer literal `0` - -The macro implementation sends this new AST back to the compiler. -Swift replaces the macro node in the AST -with the newly expanded version, -and then checks that the resulting AST is syntactically valid -and that the values in it have the needed types. -The AST looks like this after macro expansion: - -- Constant declaration - - Identifier `black` - - Initial value - - Function call - - Member access - - Identifier `Color` - - Identifier `init` - - Arguments - - Label `red:` - - Integer literal `0` - - Label `green:` - - Integer literal `0` - - Label `blue:` - - Integer literal `0` - -Finally, -the code is compiled -as if it had been written in source -in the expanded form. - -```swift -let black = Color.init(red: 0, green: 0, blue: 0) -``` - ## Implementing a Macro [TODO: Re-order for better flow, and split into multiple sections.] From 1d425df75100bcffa48dafed3f81cd28a38b9b7f Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Tue, 9 May 2023 22:02:45 -0700 Subject: [PATCH 26/51] Tidy up placeholder art. --- TSPL.docc/LanguageGuide/Macros.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index f76dd8cc6..e139d664c 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -300,13 +300,15 @@ like a compiler or a macro implementation. Here's a representation of the AST for the code above, slightly simplified by omitting some extra detail. +[XXX placeholder art] + - Constant declaration - - Identifier `magicNumber` - - Initial value + - Identifier: `magicNumber` + - Value - Macro - - Identifier `fourCharacterCode` + - Identifier: `fourCharacterCode` - Arguments - - String literal `"ABCD"` + - String literal: `"ABCD"` Here's a representation of that partial AST: +[XXX placeholder art] + - Macro - - Identifier `fourCharacterCode` + - Identifier: `fourCharacterCode` - Arguments - String literal `"ABCD"` @@ -343,7 +347,9 @@ The implementation of `#fourCharacterCode` generates a new AST containing the expanded code. Here's what that code returns to the compiler: -- Integer literal `1145258561` +[XXX placeholder art] + +- Integer literal: `1145258561` When the compiler gets this expansion back, it replaces the AST element that contains the macro call @@ -354,10 +360,12 @@ the program is still syntactically valid Swift and the all the types are correct. That produces a final AST that can be compiled as usual: +[XXX placeholder art] + - Constant declaration - - Identifier `magicNumber` - - Initial value - - Integer literal `1145258561` + - Identifier: `magicNumber` + - Value + - Integer literal: `1145258561` This AST corresponds to Swift code like this: From a5eba3d6c446dae86d113b901a0ba099f2d57f57 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Tue, 9 May 2023 22:03:10 -0700 Subject: [PATCH 27/51] Start a section on debugging. --- TSPL.docc/LanguageGuide/Macros.md | 46 +++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index e139d664c..f82328d16 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -544,6 +544,47 @@ to run on a server or mobile device. ## Debugging Macros +Macros are well suited to development using tests: +they transform one AST into another AST, +without depending on any external state, +and without causing any any side effects. +In addition, you can create syntax nodes from a string literal, +which simplifies setting up the input for a unit test. +You can also read the `description` property of an AST +to get a string that you can compare to an expected value. +For example, +here's a test of the `#fourCharacterCode` macro from previous sections: + +```swift +let source: SourceFileSyntax = +""" +let abcd = #fourCharacterCode("ABCD") +""" + +let file = BasicMacroExpansionContext.KnownSourceFile( + moduleName: "MyModule", + fullFilePath: "test.swift" +) + +let context = BasicMacroExpansionContext(sourceFiles: [source: file]) + +let transformedSF = source.expand( + macros:["fourCharacterCode": FourCC.self], + in: context +) + +let expectedDescription = +""" +let abcd = 1145258561 +""" + +precondition(transformedSF.description == expectedDescription) +``` + +The example above tests the macro using a precondition, +but you could use a testing framework instead. + + XXX OUTLINE: - Ways to view the macro expansion while debugging. @@ -551,11 +592,6 @@ XXX OUTLINE: [XXX TR: Is this flag what we should suggest folks use, or will there be better command-line options coming?] -- Because macros are deterministic and stateless --- - they don't depend on any external state, - don't have any side effects --- - they're a great place to use use test cases during development. - - Use diagnostics for macros that have constraints/requirements so your code can give a meaningful error to users when those aren't met, instead of letting the compiler try & fail to build the generated code. From 9c0768b774a5213fab5607ff7aa57e0a1da426e1 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Tue, 9 May 2023 22:26:38 -0700 Subject: [PATCH 28/51] Re-order some outline bits. --- TSPL.docc/LanguageGuide/Macros.md | 59 +++++++++++++------------------ 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index f82328d16..4652d2c1e 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -373,7 +373,18 @@ This AST corresponds to Swift code like this: let magicNumber = 1145258561 ``` -## XXX Macro Expansion OUTLINE +In this example, the input source code has only one macro, +but a real program could have several instances of the same macro +and several calls to different macros. +The compiler expands macros one at a time. + +If one macro appears inside another, +the outer macro is expanded first --- +this lets the outer macro modify the inner macro before it's expanded. + + -- The result of macro expansion is Swift code. +## Implementing a Macro [SwiftSyntax]: http://github.com/apple/swift-syntax/ -* * * - -If you've used macros in another programming language, -some parts of Swift macros will be familiar -and some parts will feel different. - -hygienic macros -gensym - -## Implementing a Macro - [TODO: Re-order for better flow, and split into multiple sections.] XXX OUTLINE: @@ -478,6 +457,16 @@ XXX OUTLINE: + Produce diagnostics (`Diagnostic` and `SimpleDiagnosticMessage`) + Find a node's location in source +- Macro expansion happens in their surrounding context. + A macro can affect that environment if it needs to — + and a macro that has bugs can interfere with that environment. + (XXX Give guidance on when you'd do this. It should be rare.) + +- Generated symbol names let a macro + avoid accidentally interacting with symbols in that environment. + To generate a unique symbol name, + call the `MacroExpansionContext.makeUniqueName()` method. + - Ways to create a syntax node include Making an instance of the `Syntax` struct, or `SyntaxToken` From a663f7616fbad326e68d52140af95ea31f65f009 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 10 May 2023 10:34:32 -0700 Subject: [PATCH 29/51] Add macro-expansion overview diagram. Assets from rdar://108348114 --- TSPL.docc/Assets/macro-expansion-full@2x.png | Bin 0 -> 43415 bytes .../Assets/macro-expansion-full~dark@2x.png | Bin 0 -> 42003 bytes TSPL.docc/Assets/macro-expansion@2x.png | Bin 0 -> 21947 bytes TSPL.docc/Assets/macro-expansion~dark@2x.png | Bin 0 -> 20836 bytes TSPL.docc/LanguageGuide/Macros.md | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 TSPL.docc/Assets/macro-expansion-full@2x.png create mode 100644 TSPL.docc/Assets/macro-expansion-full~dark@2x.png create mode 100644 TSPL.docc/Assets/macro-expansion@2x.png create mode 100644 TSPL.docc/Assets/macro-expansion~dark@2x.png diff --git a/TSPL.docc/Assets/macro-expansion-full@2x.png b/TSPL.docc/Assets/macro-expansion-full@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e25ca2aab19798be552d0df6b00b5b5e9657ee20 GIT binary patch literal 43415 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 DW(sYz literal 0 HcmV?d00001 diff --git a/TSPL.docc/Assets/macro-expansion~dark@2x.png b/TSPL.docc/Assets/macro-expansion~dark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cd26ac7cedb4d491b22dbb170fed629bd6d68b53 GIT binary patch literal 20836 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 literal 0 HcmV?d00001 diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index 4652d2c1e..dd9c4cd68 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -18,7 +18,7 @@ At a high level, macros are expanded as follows: 1. The compiler replaces the macro call with its expanded form, and then continues with compilation. -![](macro-expansion) +![](macro-expansion-full) Expanding a macro is always an additive operation: Macros add new code, From 7e63286efffc5b00fe0566aac34366c923998fc2 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 10 May 2023 16:34:24 -0700 Subject: [PATCH 30/51] Expand the macro-implementation section. --- TSPL.docc/LanguageGuide/Macros.md | 233 +++++++++++++++++++++--------- 1 file changed, 163 insertions(+), 70 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index dd9c4cd68..018b7f5d3 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -1,24 +1,14 @@ # Macros -Transform code at compile time to automate generate repetitive code. +Transform code at compile time to generate repetitive code. Macros transform your source code when you compile it, letting you avoid writing out repetitive code by hand and omit boilerplate code. +For code that uses macros, +Swift expands each macro as the first step in building that code. -At a high level, macros are expanded as follows: - -1. The compiler reads the code, - creating an in-memory representation of the syntax. - -1. The compiler sends part of the in-memory representation - to the macro implementation, - which expands the macro. - -1. The compiler replaces the macro call with its expanded form, - and then continues with compilation. - -![](macro-expansion-full) +![](macro-expansion) Expanding a macro is always an additive operation: Macros add new code, @@ -275,6 +265,21 @@ As part of building Swift code that uses macros, the compiler and the macro's implementation pass that code back and forth to expand the macros. +Macros are expanded as follows: + +1. The compiler reads the code, + creating an in-memory representation of the syntax. + +1. The compiler sends part of the in-memory representation + to the macro implementation, + which expands the macro. + +1. The compiler replaces the macro call with its expanded form, + and then continues with compilation. + + +![](macro-expansion-full) + To go through the specific steps, consider the following code: @@ -410,47 +415,159 @@ OUTLINE bits for the future ## Implementing a Macro +To implement a macro, you make two parts: +A type that performs the macro expansion, +and a library that declares the macro to expose it as API. +These parts are built separately from code that uses the macro, +even if you're developing the macro and its clients together, +because the macro implementation runs +as part of building the macro's clients. + +To create a new macro using Swift Package Manager, +run `swift package init --type macro` --- +this creates several files, +including a template for a macro implementation and declaration. +To add macros to an existing project, +add a target for the macro implementation +and a target for the macro library. +For example, +you can add something like the following to your `Package.swift` file, +changing the names to match your project: + +```swift +targets: [ + // Macro implementation that performs the source transformations + .macro( + name: "MyProjectMacros", + dependencies: [ + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax") + ] + ), + + // Library that exposes a macro as part of its API + .target(name: "MyProject", dependencies: ["MyProjectMacros"]), +] +``` + + + +The implementation of a macro is a Swift type +that uses the [SwiftSyntax][] module to interact with an AST. +If you're adding macros to an existing project, +add a dependency on SwiftSyntax in your `Package.swift` file: + [SwiftSyntax]: http://github.com/apple/swift-syntax/ -[TODO: Re-order for better flow, and split into multiple sections.] +```swift +dependencies: [ + .package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0-swift-5.9-DEVELOPMENT-SNAPSHOT-2023-04-25-b"), +], +``` -XXX OUTLINE: + -- You use the `SwiftSyntax` APIs to modify swift code - by manipulating the abstract syntax tree (AST). +Depending on your macro's role, +there's a corresponding protocol from SwiftSystem +that the macro implementation conforms to. +For example, +consider `#fourCharacterCode` from the previous section. +Here's a structure that implements that macro: + +```swift +public struct FourCharacterCode: ExpressionMacro { + public static func expansion( + of node: some FreestandingMacroExpansionSyntax, + in context: some MacroExpansionContext + ) throws -> ExprSyntax { + guard let argument = node.argumentList.first?.expression, + let segments = argument.as(StringLiteralExprSyntax.self)?.segments, + segments.count == 1, + case .stringSegment(let literalSegment)? = segments.first + else { + throw CustomError.message("Need a static string") + } + + let string = literalSegment.content.text + guard let result = fourCharacterCode(for: string) else { + throw CustomError.message("Invalid four-character code") + } + + return "\(raw: result)" + } +} -- Link to `SwiftSyntax` repository - +private func fourCharacterCode(for characters: String) -> UInt32? { + var result: UInt32 = 0 -- Setting up the SwiftPM bits. - This should include an example `Package.swift` file - and a list of the moving parts: - a package that contains the macro implementation, - a package that exposes the macro as API, - and your code that uses the macro - (which might be in a different package). + for character in characters { + result = result << 8 + guard let asciiValue = character.asciiValue else { return nil } + result += UInt32(exactly: asciiValue)! + } + return result.bigEndian +} +``` + +This is a freestanding macro that produces an expression, +so the `FourCharacterCode` type that implements the macro +conforms to the `ExpressionMacro` protocol. +The `ExpressionMacro` protocol has one requirement, +a `expansion(of:in:)` method that expands the AST. +For the list of macro roles and their corresponding SwiftSystem protocols, +see and +in + +To expand the `#fourCharacterCode` macro, +Swift sends the AST for the code that uses this macro +to the library that contains the macro implementation. +Inside the library, Swift calls `FourCharacterCode.expansion(of:in:)`, +passing in the AST and the context as arguments to the method. +The implementation of `expansion(of:in:)` +finds the string that was passed as an argument to `#fourCharacterCode` +and calculates the corresponding integer literal value. + +In the example above, +the first `guard` block extracts the string literal from the AST, +and the second `gaurd` block +calls the private `FourCharacterCode(for:)` function. +Both of these blocks of code throw an error if the macro is use incorrectly --- +the error message becomes a compiler error +at the malformed call site. +For example, +if you try to call the macro as `#fourCharacterCode("AB" + "CD")` +the compiler shows the error "Need a static string". + + +The `expansion(of:in:)` method returns an instance of `ExprSyntax`, +a type from SwiftSyntax that represents an expression in an AST. +Because this type conforms to the `StringLiteralConvertible` protocol, +the macro implementation uses a string literal +as a lightweight syntax to create its result. +All of the SwiftSyntax types that you return from a macro implementation +conform to `StringLiteralConvertible`, +so you can use this approach when implementing any kind of macro. + + + + + + + ## Debugging Macros @@ -573,8 +666,7 @@ precondition(transformedSF.description == expectedDescription) The example above tests the macro using a precondition, but you could use a testing framework instead. - -XXX OUTLINE: + Here's a representation of that partial AST: -[XXX placeholder art] - -- Macro call - - Macro name: `fourCharacterCode` - - Macro rguments - - String literal `"ABCD"` +![](macro-ast-input) The implementation of a macro operates only on the code that contains the macro. @@ -345,9 +340,7 @@ The implementation of `#fourCharacterCode` generates a new AST containing the expanded code. Here's what that code returns to the compiler: -[XXX placeholder art] - -- Integer literal: `1145258561` +![](macro-ast-output) When the compiler gets this expansion back, it replaces the AST element that contains the macro call @@ -358,12 +351,7 @@ the program is still syntactically valid Swift and the all the types are correct. That produces a final AST that can be compiled as usual: -[XXX placeholder art] - -- Constant declaration - - Constant name: `magicNumber` - - Constant value - - Integer literal: `1145258561` +![](macro-ast-result) This AST corresponds to Swift code like this: From e3b98d7000d706885f0887b369e2b72cf569b2e4 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 17 May 2023 17:26:13 -0700 Subject: [PATCH 38/51] Add fixmes about macro roles. --- TSPL.docc/LanguageGuide/Macros.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index bed742fe7..f3b3ffc53 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -196,6 +196,7 @@ The `@attached` attribute on this macro declaration indicates that the `@OptionSet` macro is an attached macro. That attribute appears twice in this declaration, once for each macro role that `@OptionSet` has. + For a freestanding macro, you write `@freestanding` instead. ``` @@ -205,6 +206,12 @@ public macro line() -> T = ``` A *macro role* indicates where the code that the macro generate goes. + Every macro has one or more roles, which you write as part of the attributes at the beginning of the macro declaration. From eed5aa372d18a913fbfc6521e5370aa1b002509e Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Fri, 19 May 2023 23:39:39 -0700 Subject: [PATCH 39/51] Remove syntax that is now a macro. --- TSPL.docc/ReferenceManual/Expressions.md | 100 +----------------- TSPL.docc/ReferenceManual/LexicalStructure.md | 30 ++---- TSPL.docc/ReferenceManual/Statements.md | 72 +------------ 3 files changed, 16 insertions(+), 186 deletions(-) diff --git a/TSPL.docc/ReferenceManual/Expressions.md b/TSPL.docc/ReferenceManual/Expressions.md index a3fa6fb4b..10cc20478 100644 --- a/TSPL.docc/ReferenceManual/Expressions.md +++ b/TSPL.docc/ReferenceManual/Expressions.md @@ -590,13 +590,7 @@ to make prefix expressions, infix expressions, and postfix expressions. A *literal expression* consists of either an ordinary literal (such as a string or a number), an array or dictionary literal, -a playground literal, -or one of the following special literals: - - - -| Literal | Type | Value | -| ------- | ---- | ----- | -| `#file` | `String` | The path to the file in which it appears. | -| `#fileID` | `String` | The name of the file and module in which it appears. | -| `#filePath` | `String` | The path to the file in which it appears. | -| `#line` | `Int` | The line number on which it appears. | -| `#column` | `Int` | The column number in which it begins. | -| `#function` | `String` | The name of the declaration in which it appears. | -| `#dsohandle` | `UnsafeRawPointer` | The dynamic shared object (DSO) handle in use where it appears. | - -The string value of `#file` depends on the language version, -to enable migration from the old `#filePath` behavior -to the new `#fileID` behavior. -Currently, `#file` has the same value as `#filePath`. -In a future version of Swift, -`#file` will have the same value as `#fileID` instead. -To adopt the future behavior, -replace `#file` with `#fileID` or `#filePath` as appropriate. - -The string value of a `#fileID` expression has the form *module*/*file*, -where *file* is the name of the file in which the expression appears -and *module* is the name of the module that this file is part of. -The string value of a `#filePath` expression -is the full file-system path to the file in which the expression appears. -Both of these values can be changed by `#sourceLocation`, -as described in . -Because `#fileID` doesn't embed the full path to the source file, -unlike `#filePath`, -it gives you better privacy and reduces the size of the compiled binary. -Avoid using `#filePath` outside of tests, build scripts, -or other code that doesn't become part of the shipping program. - -> Note: To parse a `#fileID` expression, -> read the module name as the text before the first slash (`/`) -> and the filename as the text after the last slash. -> In the future, the string might contain multiple slashes, -> such as `MyModule/some/disambiguation/MyFile.swift`. - -Inside a function, -the value of `#function` is the name of that function, -inside a method it's the name of that method, -inside a property getter or setter it's the name of that property, -inside special members like `init` or `subscript` -it's the name of that keyword, -and at the top level of a file it's the name of the current module. - -When used as the default value of a function or method parameter, -the special literal's value is determined -when the default value expression is evaluated at the call site. - - - -```swift -func logFunctionName(string: String = #function) { - print(string) -} -func myFunction() { - logFunctionName() // Prints "myFunction()". -} -``` - - - An *array literal* is an ordered collection of values. It has the following form: diff --git a/TSPL.docc/ReferenceManual/LexicalStructure.md b/TSPL.docc/ReferenceManual/LexicalStructure.md index cb35a9b5e..26df4747a 100644 --- a/TSPL.docc/ReferenceManual/LexicalStructure.md +++ b/TSPL.docc/ReferenceManual/LexicalStructure.md @@ -368,37 +368,29 @@ so they must be escaped with backticks in that context. - Keywords that begin with a number sign (`#`): `#available`, `#colorLiteral`, - `#column`, - `#dsohandle`, `#elseif`, `#else`, `#endif`, - `#error`, - `#fileID`, - `#fileLiteral`, - `#filePath`, - `#file`, - `#function`, `#if`, `#imageLiteral`, `#keyPath`, - `#line`, `#selector`, - `#sourceLocation`, - and `#warning`. - - - - +> `#error`, +> `#fileID`, +> `#fileLiteral`, +> `#filePath`, +> `#file`, +> `#function`, +> `#line`, +> and `#warning`. - - - - + ## Availability Condition From c0c911135fb3674935203d25e5d54606fe7cb886 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Thu, 18 May 2023 21:37:21 -0700 Subject: [PATCH 40/51] Apply edits to the new chapter. - Add alt text to new figures. - Introduce macro roles earlier. - Expand discussion of the AST. Incorporates edits from Chuck Toporek . --- TSPL.docc/LanguageGuide/Macros.md | 285 ++++++++++++++++-------------- 1 file changed, 155 insertions(+), 130 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index f3b3ffc53..f6632fa03 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -3,59 +3,71 @@ Transform code at compile time to generate repetitive code. Macros transform your source code when you compile it, -letting you avoid writing out repetitive code by hand -and omit boilerplate code. -For code that uses macros, -Swift expands each macro as the first step in building that code. +letting you avoid writing repetitive code by hand. +During compilation, +Swift expands macros before building your code as usual. -![](macro-expansion) +![A diagram showing an overview of macro expansion. On the left, a stylized representation of Swift code. On the right, the same code with several lines added by the macro.](macro-expansion) Expanding a macro is always an additive operation: Macros add new code, -but they never delete code -or modify code that you wrote by hand. +but they never delete or modify existing code. Both the input to a macro and the output of macro expansion are checked to ensure they're syntactically valid Swift code. Likewise, the values you pass to a macro and the values in code generated by a macro are checked to ensure they have the correct types. +In addition, +if the macro's implementation encounters an error when expanding that macro, +the compiler treats this as a compilation error. +These guarantees make it easier to reason about code that uses macros, +and they make it easier to identify issues +like using macro incorrectly +or a macro implementation that has a bug. -Swift has two kinds of macros. -*Attached macros* modify the declaration that they're attached to. -*Freestanding macros* appear on their own, -without being attached to a declaration. +Swift has two kinds of macros: + +- *Attached macros* modify the declaration that they're attached to. + +- *Freestanding macros* appear on their own, + without being attached to a declaration. + +You call attached and freestanding macros slightly differently, +but they both follow the same model for macro expansion, +and you implement them both using the same approach. +The following sections describe both kinds of macros in more detail. ## Freestanding Macros To call a freestanding macro, you write a number sign (`#`) before its name, -followed by any arguments to the macro in parentheses. +and you write any arguments to the macro in parentheses after its name. For example: ```swift -let currentLine = #line +let currentFunctionname = #function #warning("Something's wrong") ``` In the first line, -`#line` is a call to the `line` macro from the Swift standard library. +`#function` calls the `function` macro from the Swift standard library. When you compile this code, Swift calls that macro's implementation, -which replaces `#line` with the current line number. +which replaces `#function` with the name of the current function. In the second line, `#warning` calls another macro from the standard library -to produce a custom warning when the code is compiled. +to produce a custom compile-time warning. -Freestanding macros can produce a value, like `#line`, -or they can perform an action at compile time, like `#warning`. +Freestanding macros can produce a value, like `#function` does, +or they can perform an action at compile time, like `#warning` does. ## Attached Macros To call an attached macro, you write an at sign (`@`) before its name, -followed by any arguments to the macro in parentheses. +and you write any arguments to the macro in parentheses after its name. Attached macros modify the declaration that they're attached to. They add code to that declaration, @@ -95,17 +107,19 @@ struct SundaeToppings { ``` This version of `SundaeToppings` -calls the `@OptionSet` macro from the Swift standard library. +calls the [`@OptionSet`][] macro from the Swift standard library. The macro reads the list of cases in the private enumeration, generates the list of constants for each option, -and adds a conformance to the `OptionSet` protocol. +and adds a conformance to the [`OptionSet`][] protocol. - -[`OptionSet`]: https://developer.apple.com/documentation/swift/optionset +[`@OptionSet`]: https://developer.apple.com/documentation/swift/optionset-swift.macro +[`OptionSet`]: https://developer.apple.com/documentation/swift/optionset-swift.protocol For comparison, -after the compiler expands the `@OptionSet` macro, -here's what the source code looks like: +here's what the expanded version of the `@OptionSet` macro looks like. +You don't write this code, +and you would see it only if you specifically asked Swift +to show the macro's expansion. ```swift struct SundaeToppings { @@ -131,7 +145,7 @@ comes from the `@OptionSet` macro. The version of `SundaeToppings` that uses a macro to generate all of the static variables is easier to read and easier to maintain -than the manual version at the start of this section. +than the manual-coded version, earlier. ## Macro Declarations @@ -142,7 +156,7 @@ However, for macros, the declaration and implementation are separate. A macro's implementation contains the code that expands the macro by generating Swift code, and its declaration -as well as the macro's name, what parameters it takes, +as well as the macro's name, the parameters it takes, where it can be used, and what kind of code it generates. @@ -161,18 +175,18 @@ The first line specifies the macro's name, `OptionSet`, and the arguments that takes, in this case none. The second line -uses the `#externalMacro(module:type:)` macro from the standard library +uses the `#externalMacro(module:type:)` macro from the Swift standard library to tell Swift where the macro's implementation is. In this case, the `SwiftMacros` module contains a type named `OptionSetMacro`, which implements the `@OptionSet` macro. - +Because `OptionSet` is an attached macro, +its name uses upper camel case +like the names for structures and classes. +Freestanding macros have lower camel case names, +like the names for variables and functions. > Note: > Macros are always declared as `public`. @@ -180,10 +194,14 @@ versus just being covered in the reference? > is in a different module from code that uses that macro, > there isn't anywhere you could apply a non-public macro. -A macro declaration also includes information -about where that macro can be used. +A macro declaration defines the macro's *roles* --- +the places in source code where that macro can be called, +and the kinds of code the macro can generate. +Every macro has one or more roles, +which you write as part of the attributes +at the beginning of the macro declaration. Here's a partial declaration of `@OptionSet`, -with those attributes added: +including the attributes for its roles: ```swift @attached(member) @@ -192,12 +210,21 @@ public macro OptionSet() = #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") ``` -The `@attached` attribute on this macro declaration -indicates that the `@OptionSet` macro is an attached macro. -That attribute appears twice in this declaration, -once for each macro role that `@OptionSet` has. - -For a freestanding macro, you write `@freestanding` instead. +The `@attached` attribute appears twice in this declaration, +once for each macro role. +The first use, `@attached(member)`, indicates that the macro +adds new members to the type you apply it to. +The `@OptionSet` macro adds an `init(rawValue:)` initializer +that's required by the `OptionSet` protocol, +as well as some additional members. +The second use, `@attached(conformance)`, tells you that `@OptionSet` +adds one or more protocol conformances. +The `@OptionSet` macro +extends the type that you apply the macro to, +to add conformance to the `OptionSet` protocol. + +For a freestanding macro, +you write the `@freestanding` attribute to specify its role: ``` @freestanding(expression) @@ -205,30 +232,9 @@ public macro line() -> T = /* ... location of the macro implementation... */ ``` -A *macro role* indicates where the code that the macro generate goes. - -Every macro has one or more roles, -which you write as part of the attributes -at the beginning of the macro declaration. - -For example, -the `#line` macro above has the `expression` role, -and the `@OptionSet` macro above has two roles --- `conformance` and `member`. -An expression macro produces a value or performs an action. -A conformance macro adds one or more protocol conformances. -The `@OptionSet` macro -extends the type that you apply the macro to, -to add conformance to the `OptionSet` protocol. -A member macro adds new members to the type you apply the macro to. -In this case, -the `@OptionSet` macro adds an `init(rawValue:)` initializer -that's required by the `OptionSet` protocol, -as well as some additional members. +The `#line` macro above has the `expression` role. +An expression macro produces a value, +or performs a compile-time action like generating a warning. In addition to the macro's role, a macro's declaration provides information about @@ -286,19 +292,20 @@ Macros are expanded as follows: 1. The compiler continues with compilation, using the expanded source code. -![](macro-expansion-full) +These steps transform the code as shown below: -To go through the specific steps, -consider the following code: +![Diagram showing the four steps of expanding macros. The input is Swift source code. This becomes a tree, representing the code's structure. The macro implementation adds branches to the tree. The result is Swift source with additional code.](macro-expansion-full) + +To go through the specific steps, consider the following: ``` let magicNumber = #fourCharacterCode("ABCD") ``` The `#fourCharacterCode` macro takes a string that's four characters long -and returns a unsigned 32-bin integer +and returns a unsigned 32-bit integer that corresponds to the ASCII values in the string joined together. -Some file formats use a integers like this to identify data, +Some file formats use integers like this to identify data because they're compact but still readable in a debugger. The section below shows how to implement this macro. @@ -306,59 +313,83 @@ shows how to implement this macro. To expand the macros in the code above, the compiler reads the Swift file and creates an in-memory representation of that code -known an as *abstract syntax tree* or AST. +known an as *abstract syntax tree*, or AST. The AST makes the code's meaning and structure explicit, which makes it easier to write code that interacts with that structure --- like a compiler or a macro implementation. Here's a representation of the AST for the code above, -slightly simplified by omitting some extra detail. - -![](macro-ast-original) - - - -The compiler also ensures that the input code is valid Swift: -for example, that the input to macros is syntactically valid -and that the types of values match. -For example, in the code above, -it checks that the argument to `#fourCharacterCode` is a string. - +slightly simplified by omitting some extra detail: + +![A tree diagram, with a constant as the root element. The constant has a name, magic number, and a value. The constant's value is a macro call. The macro call has a name, fourCharacterCode, and arguments. The argument is a string literal, ABCD.](macro-ast-original) + +The diagram above shows how the structure of this code +is represented in memory. +Each of the elements in the AST +corresponds to part of the source code's meaning. +The "Constant declaration" AST element +has two child elements under it, +which represent the two parts of a constant declaration: +its name and its value. +The "Macro call" element has child elements +that represent the macro's name +and the list of arguments being passed to the macro. +As part of constructing this AST, +the compiler checks that the source code is valid Swift. +For example, `#fourCharacterCode` takes a single argument, +which must be a string. +If you tried to pass an integer argument, +or forgot the quotation mark (`"`) at the end of the string literal, +you'd get an error at this point in the process. The compiler finds the places in the code where you call a macro, and loads the external binary that implements those macros. For each macro call, the compiler passes part of the AST to that macro's implementation. - Here's a representation of that partial AST: -![](macro-ast-input) - -The implementation of a macro -operates only on the code that contains the macro. -In this example, -the implementation of the `#fourCharacterCode` macro -reads this partial AST that contains only the macro call. -A macro can't depend on code outside of the place where it's used. +![A tree diagram, with a macro call as the root element. The macro call has a name, fourCharacterCode, and arguments. The argument is a string literal, ABCD.](macro-ast-input) + +The implementation of the `#fourCharacterCode` macro +reads this partial AST as its input when expanding the macro. +A macro's implementation +operates only on the partial AST that it receives as its input, +meaning a macro always expands the same way +regardless of what code comes before and after it. +This limitation helps make macro expansion easier to understand, +and helps your code build faster +because Swift can avoid expanding macros that haven't changed. + +Swift helps macro authors avoid accidentally reading other input +by restricting the code that implements macros: + +- The AST passed to a macro implementation + contains only the AST elements that represent the macro, + not any of the code that comes before or after it. + +- The macro implementation runs in a sandboxed environment + that prevents it from accessing the file system or the network. + +In addition to these safeguards, +the macro's author is responsible for not reading or modifying anything +outside of the macro's inputs. +For example, a macro's expansion can't depend on the current time of day. The implementation of `#fourCharacterCode` generates a new AST containing the expanded code. Here's what that code returns to the compiler: -![](macro-ast-output) +![A tree diagram with a sigle node, the integer literal 1145258561.](macro-ast-output) -When the compiler gets this expansion back, +When the compiler receives this expansion, it replaces the AST element that contains the macro call with the element that contains the macro's expansion. After macro expansion, the compiler checks again to ensure the program is still syntactically valid Swift -and the all the types are correct. +and all the types are correct. That produces a final AST that can be compiled as usual: -![](macro-ast-result) +![A tree diagram, with a constant as the root element. The constant has a name, magic number, and a value. The constant's value is the integer literal 1145258561](macro-ast-result) This AST corresponds to Swift code like this: @@ -375,14 +406,10 @@ If one macro appears inside another, the outer macro is expanded first --- this lets the outer macro modify the inner macro before it's expanded. - ## Implementing a Macro -To implement a macro, you make two parts: +To implement a macro, you make two components: A type that performs the macro expansion, and a library that declares the macro to expose it as API. These parts are built separately from code that uses the macro, @@ -424,7 +450,7 @@ changing the names to match your project: ```swift targets: [ - // Macro implementation that performs the source transformations + // Macro implementation that performs the source transformations. .macro( name: "MyProjectMacros", dependencies: [ @@ -433,7 +459,7 @@ targets: [ ] ), - // Library that exposes a macro as part of its API + // Library that exposes a macro as part of its API. .target(name: "MyProject", dependencies: ["MyProjectMacros"]), ] ``` @@ -521,9 +547,9 @@ and calculates the corresponding integer literal value. In the example above, the first `guard` block extracts the string literal from the AST, -and the second `gaurd` block +and the second `guard` block calls the private `FourCharacterCode(for:)` function. -Both of these blocks of code throw an error if the macro is use incorrectly --- +Both of these blocks throw an error if the macro is use incorrectly --- the error message becomes a compiler error at the malformed call site. For example, @@ -538,7 +564,7 @@ the macro implementation uses a string literal as a lightweight syntax to create its result. All of the SwiftSyntax types that you return from a macro implementation conform to `StringLiteralConvertible`, -so you can use this approach when implementing any kind of macro. +so you can use this approach when implementing any kind of macro. @@ -549,8 +575,7 @@ https://github.com/apple/swift-syntax/blob/main/Sources/SwiftSyntaxBuilder/Synta --> - -## Debugging Macros +## Developing and Debugging Macros Macros are well suited to development using tests: -they transform one AST into another AST, +they transform one AST into another AST without depending on any external state, -and without causing any any side effects. +and without causing any side effects. In addition, you can create syntax nodes from a string literal, which simplifies setting up the input for a unit test. You can also read the `description` property of an AST @@ -628,9 +653,9 @@ here's a test of the `#fourCharacterCode` macro from previous sections: ```swift let source: SourceFileSyntax = -""" -let abcd = #fourCharacterCode("ABCD") -""" + """ + let abcd = #fourCharacterCode("ABCD") + """ let file = BasicMacroExpansionContext.KnownSourceFile( moduleName: "MyModule", @@ -645,9 +670,9 @@ let transformedSF = source.expand( ) let expectedDescription = -""" -let abcd = 1145258561 -""" + """ + let abcd = 1145258561 + """ precondition(transformedSF.description == expectedDescription) ``` @@ -669,7 +694,7 @@ but you could use a testing framework instead. - idempotency and sandboxing --> - +The code above defines two targets: +`MyProjectMacros` contains the implementation of the macros, +and `MyProject` makes those macros available. -The implementation of a macro is a Swift type -that uses the [SwiftSyntax][] module to interact with an AST. +The implementation of a macro +uses the [SwiftSyntax][] module to interact with Swift code +in a structured way, using an abstract syntax trees (AST). +If you created a new macro package with Swift Package Manager, +the generated `Package.swift` file +automatically includes a dependency on SwiftSyntax. If you're adding macros to an existing project, add a dependency on SwiftSyntax in your `Package.swift` file: @@ -475,14 +482,12 @@ add a dependency on SwiftSyntax in your `Package.swift` file: ```swift dependencies: [ - .package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0-swift-5.9-DEVELOPMENT-SNAPSHOT-2023-04-25-b"), + .package(url: "https://github.com/apple/swift-syntax.git", from: "some-tag"), ], ``` - +Replace the `some-tag` placeholder in the code above +with the Git tag for the version of SwiftSyntax you want to use. Depending on your macro's role, there's a corresponding protocol from SwiftSystem @@ -527,8 +532,9 @@ private func fourCharacterCode(for characters: String) -> UInt32? { } ``` -This is a freestanding macro that produces an expression, -so the `FourCharacterCode` type that implements the macro +The `#fourCharacterCode` macro +is a freestanding macro that produces an expression, +so the `FourCharacterCode` type that implements it conforms to the `ExpressionMacro` protocol. The `ExpressionMacro` protocol has one requirement, a `expansion(of:in:)` method that expands the AST. @@ -547,7 +553,8 @@ and calculates the corresponding integer literal value. In the example above, the first `guard` block extracts the string literal from the AST, -and the second `guard` block +assigning that AST element to `literalSegment`. +The second `guard` block calls the private `FourCharacterCode(for:)` function. Both of these blocks throw an error if the macro is use incorrectly --- the error message becomes a compiler error @@ -555,7 +562,7 @@ at the malformed call site. For example, if you try to call the macro as `#fourCharacterCode("AB" + "CD")` the compiler shows the error "Need a static string". - + The `expansion(of:in:)` method returns an instance of `ExprSyntax`, a type from SwiftSyntax that represents an expression in an AST. @@ -566,7 +573,7 @@ All of the SwiftSyntax types that you return from a macro implementation conform to `StringLiteralConvertible`, so you can use this approach when implementing any kind of macro. - + - - +```swift +macro <#name#> = <#macro implementation#> +``` +The *macro implementation* is another macro, +and indicates the location of the code that performs this macro's expansion. +Call the `externalMacro(module:type:)` macro from the Swift standard library, +passing in the name of a type that contains the macro's implementation, +and the name of the module that contains that type. + +Macros can be overloaded, +following the same model used by functions. A macro declaration appears only at file scope. +For more information, see . + > Grammar of a macro declaration: > > *macro-declaration* → *macro-head* *identifier* *generic-parameter-clause*_?_ *macro-signature* *macro-definition*_?_ *generic-where-clause* diff --git a/TSPL.docc/ReferenceManual/Expressions.md b/TSPL.docc/ReferenceManual/Expressions.md index 10cc20478..52342ca43 100644 --- a/TSPL.docc/ReferenceManual/Expressions.md +++ b/TSPL.docc/ReferenceManual/Expressions.md @@ -692,10 +692,6 @@ in Xcode Help. > > *literal-expression* → *array-literal* | *dictionary-literal* | *playground-literal* > -> *literal-expression* → **`#file`** | **`#fileID`** | **`#filePath`** -> -> *literal-expression* → **`#line`** | **`#column`** | **`#function`** | **`#dsohandle`** -> > > > *array-literal* → **`[`** *array-literal-items*_?_ **`]`** @@ -1476,15 +1472,26 @@ For example, in the following assignment ### Macro-Expansion Expression - +```swift +<#macro name#>(<#macro argument 1#>, <#macro argument 2#>) +``` + +A macro-expansion expression omits the parentheses +if the macro doesn't take any arguments. A macro expression can't appear as the default value for a parameter, -except for the `#file` and `#line` macros from the Swift standard library. +except for the [`file`][] and [`line`][] macros from the Swift standard library. +When used as the default value of a function or method parameter, +These macros' value is determined +when the default value expression is evaluated at the call site. + +[`file`]: http://developer.apple.com/documentation/swift/documentation/swift/file +[`line`]: http://developer.apple.com/documentation/swift/documentation/swift/line > Grammar of a macro-expansion expression: > diff --git a/TSPL.docc/ReferenceManual/Statements.md b/TSPL.docc/ReferenceManual/Statements.md index 8cd2e1e95..dd14c05d2 100644 --- a/TSPL.docc/ReferenceManual/Statements.md +++ b/TSPL.docc/ReferenceManual/Statements.md @@ -1356,9 +1356,11 @@ resets the source code location back to the default line numbering and file path Prior to Swift 5.9, the `#warning` and `#error` statements emit a diagnostic during compilation. -This behavior is now implemented as macros in the Swift standard library. +This behavior is now provided by +the [`warning(_:)`][] and [`error(_:)`][] macros in the Swift standard library. - +[`warning(_:)`]: http://developer.apple.com/documentation/swift/documentation/swift/warning(_:) +[`error(_:)`]: http://developer.apple.com/documentation/swift/documentation/swift/error(_:) ## Availability Condition From dff4478b413d6e9c04da9f11de9873b2144ff080 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 31 May 2023 10:33:11 -0700 Subject: [PATCH 46/51] Clear some fix-me markers. --- TSPL.docc/LanguageGuide/Macros.md | 6 ++---- TSPL.docc/ReferenceManual/Attributes.md | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index 8622d5fa2..00662d09b 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -73,7 +73,6 @@ Attached macros modify the declaration that they're attached to. They add code to that declaration, like defining a new method or adding conformance to a protocol. - For example, consider the following code that doesn't use macros: @@ -159,7 +158,6 @@ and its declaration as well as the macro's name, the parameters it takes, where it can be used, and what kind of code it generates. - You introduce a macro declaration with the `macro` keyword. For example, @@ -530,6 +528,7 @@ private func fourCharacterCode(for characters: String) -> UInt32? { } return result.bigEndian } +enum CustomError: Error { case message(String) } ``` The `#fourCharacterCode` macro @@ -562,7 +561,6 @@ at the malformed call site. For example, if you try to call the macro as `#fourCharacterCode("AB" + "CD")` the compiler shows the error "Need a static string". - The `expansion(of:in:)` method returns an instance of `ExprSyntax`, a type from SwiftSyntax that represents an expression in an AST. @@ -691,7 +689,7 @@ but you could use a testing framework instead. - Ways to view the macro expansion while debugging. The SE prototype provides `-Xfrontend -dump-macro-expansions` for this. - [XXX TR: Is this flag what we should suggest folks use, + [TR: Is this flag what we should suggest folks use, or will there be better command-line options coming?] - Use diagnostics for macros that have constraints/requirements diff --git a/TSPL.docc/ReferenceManual/Attributes.md b/TSPL.docc/ReferenceManual/Attributes.md index 36a232355..20375e0a3 100644 --- a/TSPL.docc/ReferenceManual/Attributes.md +++ b/TSPL.docc/ReferenceManual/Attributes.md @@ -660,7 +660,6 @@ The arguments to this attribute indicate the macro's roles: - `declaration` A macro that produces a declaration -XXX Or are those supported today? I see #error and #warning as @freestanding(declaration) in the stdlib already: From 286cef70c27db7e1106729e5b3ad612b558261fb Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 31 May 2023 10:36:14 -0700 Subject: [PATCH 47/51] Fix whitespace in code. --- TSPL.docc/LanguageGuide/Macros.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index 00662d09b..a98e9c5b5 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -136,7 +136,7 @@ struct SundaeToppings { static let cherry: Self = Self(rawValue: 1 << Options.cherry.rawValue) static let fudge: Self = Self(rawValue: 1 << Options.fudge.rawValue) } -extension SundaeToppings: OptionSet {} +extension SundaeToppings: OptionSet { } ``` All of the code after the private enumeration From 50316f6fb734b0cea2b414f993d35ed79f416f54 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Thu, 1 Jun 2023 11:07:11 -0700 Subject: [PATCH 48/51] Fix markup in the grammar. --- TSPL.docc/ReferenceManual/Declarations.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TSPL.docc/ReferenceManual/Declarations.md b/TSPL.docc/ReferenceManual/Declarations.md index b6b79ea1b..6d2f5a565 100644 --- a/TSPL.docc/ReferenceManual/Declarations.md +++ b/TSPL.docc/ReferenceManual/Declarations.md @@ -3470,13 +3470,13 @@ For more information, see . > > *macro-declaration* → *macro-head* *identifier* *generic-parameter-clause*_?_ *macro-signature* *macro-definition*_?_ *generic-where-clause* > -> *macro-head* → *attributes*_?_ *declaration-modifiers*_?_ **`macro`** +> *macro-head* → *attributes*_?_ *declaration-modifiers*_?_ **`macro`** > > *macro-signature* → *parameter-clause* *macro-function-signature-result*_?_ > -> *macro-function-signature-result* → **`->``** *type* +> *macro-function-signature-result* → **`->`** *type* > -> *macro-definition* → **`=``** *expression* +> *macro-definition* → **`=`** *expression* + Swift helps macro authors avoid accidentally reading other input by restricting the code that implements macros: diff --git a/TSPL.docc/ReferenceManual/Attributes.md b/TSPL.docc/ReferenceManual/Attributes.md index 20375e0a3..a70952ddf 100644 --- a/TSPL.docc/ReferenceManual/Attributes.md +++ b/TSPL.docc/ReferenceManual/Attributes.md @@ -35,13 +35,8 @@ The arguments to this attribute indicate the macro's role. For a macro that has multiple roles, apply the `attached` macro multiple times, once for each role. - The first argument to this attribute @@ -115,7 +110,7 @@ As a special case, you can write `prefixed($)` for a macro that behaves similar to a property wrapper. ### available diff --git a/TSPL.docc/ReferenceManual/Declarations.md b/TSPL.docc/ReferenceManual/Declarations.md index 6d2f5a565..fee6231ea 100644 --- a/TSPL.docc/ReferenceManual/Declarations.md +++ b/TSPL.docc/ReferenceManual/Declarations.md @@ -3479,7 +3479,7 @@ For more information, see . > *macro-definition* → **`=`** *expression* ## Operator Declaration From 499ede78e8a5240bbce2021a0f1fedd5e2ce8dce Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Fri, 2 Jun 2023 17:22:55 -0700 Subject: [PATCH 51/51] Iterate on wording; fix minor errors. Incorporates review from Brian Lanier . --- TSPL.docc/LanguageGuide/Macros.md | 95 ++++++++++++++++++------------- 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/TSPL.docc/LanguageGuide/Macros.md b/TSPL.docc/LanguageGuide/Macros.md index ca928d647..6dc75f24e 100644 --- a/TSPL.docc/LanguageGuide/Macros.md +++ b/TSPL.docc/LanguageGuide/Macros.md @@ -1,11 +1,11 @@ # Macros -Transform code at compile time to generate repetitive code. +Use macros to generate code at compile time. Macros transform your source code when you compile it, letting you avoid writing repetitive code by hand. During compilation, -Swift expands macros before building your code as usual. +Swift expands any macros in your code before building your code as usual. ![A diagram showing an overview of macro expansion. On the left, a stylized representation of Swift code. On the right, the same code with several lines added by the macro.](macro-expansion) @@ -23,7 +23,7 @@ if the macro's implementation encounters an error when expanding that macro, the compiler treats this as a compilation error. These guarantees make it easier to reason about code that uses macros, and they make it easier to identify issues -like using macro incorrectly +like using a macro incorrectly or a macro implementation that has a bug. Swift has two kinds of macros: @@ -46,19 +46,26 @@ and you write any arguments to the macro in parentheses after its name. For example: ```swift -let currentFunctionName = #function -#warning("Something's wrong") +func myFunction() { + print("Currently running \(#function)") + #warning("Something's wrong") +} ``` In the first line, -`#function` calls the `function` macro from the Swift standard library. +`#function` calls the [`function`][] macro from the Swift standard library. When you compile this code, Swift calls that macro's implementation, which replaces `#function` with the name of the current function. +When you run this code and call `myFunction()`, +it prints `Currently running myFunction()`. In the second line, -`#warning` calls another macro from the standard library +`#warning` calls the [`warning(_:)`][] macro from the Swift standard library to produce a custom compile-time warning. +[`function`]: https://developer.apple.com/documentation/swift/function +[`warning(_:)`]: https://developer.apple.comdocumentation/swift/warning(_:) + Freestanding macros can produce a value, like `#function` does, or they can perform an action at compile time, like `#warning` does. @@ -144,20 +151,20 @@ comes from the `@OptionSet` macro. The version of `SundaeToppings` that uses a macro to generate all of the static variables is easier to read and easier to maintain -than the manual-coded version, earlier. +than the manually coded version, earlier. ## Macro Declarations In most Swift code, -you implement a symbol, like a function or type, -and there's no separate declaration. +when you implement a symbol, like a function or type, +there's no separate declaration. However, for macros, the declaration and implementation are separate. -A macro's implementation contains the code -that expands the macro by generating Swift code, -and its declaration -as well as the macro's name, the parameters it takes, +A macro's declaration contains its name, +the parameters it takes, where it can be used, and what kind of code it generates. +A macro's implementation contains the code +that expands the macro by generating Swift code. You introduce a macro declaration with the `macro` keyword. For example, @@ -170,18 +177,18 @@ public macro OptionSet() = ``` The first line -specifies the macro's name, `OptionSet`, -and the arguments that takes, in this case none. +specifies the macro's name and its arguments --- +the name is `OptionSet`, and it doesn't take any arguments. The second line uses the `#externalMacro(module:type:)` macro from the Swift standard library -to tell Swift where the macro's implementation is. +to tell Swift where the macro's implementation is located. In this case, the `SwiftMacros` module contains a type named `OptionSetMacro`, which implements the `@OptionSet` macro. Because `OptionSet` is an attached macro, -its name uses upper camel case +its name uses upper camel case, like the names for structures and classes. Freestanding macros have lower camel case names, like the names for variables and functions. @@ -198,7 +205,7 @@ and the kinds of code the macro can generate. Every macro has one or more roles, which you write as part of the attributes at the beginning of the macro declaration. -Here's a partial declaration of `@OptionSet`, +Here's a bit more of the declaration for `@OptionSet`, including the attributes for its roles: ```swift @@ -230,6 +237,13 @@ public macro line() -> T = /* ... location of the macro implementation... */ ``` + + The `#line` macro above has the `expression` role. An expression macro produces a value, or performs a compile-time action like generating a warning. @@ -261,22 +275,24 @@ the macro declaration lists them explicitly. The macro declaration also includes `arbitrary` after the list of names, allowing the macro to generate declarations whose names aren't known until you use the macro. -In this case, -for each case in the private `Options` enumeration, -`@OptionSet` generates a corresponding declaration with the same name. +For example, +when the `@OptionSet` macro is applied to the `SundaeToppings` above, +it generates type properties that correspond to the enumeration cases, +`nuts`, `cherry`, and `fudge`. For more information, including a full list of macro roles, see and -in +in . ## Macro Expansion -As part of building Swift code that uses macros, -the compiler and the macro's implementation -pass that code back and forth to expand the macros. +When building Swift code that uses macros, +the compiler calls the macros' implementation to expand them. -Macros are expanded as follows: +![Diagram showing the four steps of expanding macros. The input is Swift source code. This becomes a tree, representing the code's structure. The macro implementation adds branches to the tree. The result is Swift source with additional code.](macro-expansion-full) + +Specifically, Swift expands macros in the following way: 1. The compiler reads the code, creating an in-memory representation of the syntax. @@ -290,10 +306,6 @@ Macros are expanded as follows: 1. The compiler continues with compilation, using the expanded source code. -These steps transform the code as shown below: - -![Diagram showing the four steps of expanding macros. The input is Swift source code. This becomes a tree, representing the code's structure. The macro implementation adds branches to the tree. The result is Swift source with additional code.](macro-expansion-full) - To go through the specific steps, consider the following: ``` @@ -301,18 +313,18 @@ let magicNumber = #fourCharacterCode("ABCD") ``` The `#fourCharacterCode` macro takes a string that's four characters long -and returns a unsigned 32-bit integer +and returns an unsigned 32-bit integer that corresponds to the ASCII values in the string joined together. Some file formats use integers like this to identify data because they're compact but still readable in a debugger. -The section below +The section below shows how to implement this macro. To expand the macros in the code above, the compiler reads the Swift file and creates an in-memory representation of that code known an as *abstract syntax tree*, or AST. -The AST makes the code's meaning and structure explicit, +The AST makes the code's structure explicit, which makes it easier to write code that interacts with that structure --- like a compiler or a macro implementation. Here's a representation of the AST for the code above, @@ -322,8 +334,8 @@ slightly simplified by omitting some extra detail: The diagram above shows how the structure of this code is represented in memory. -Each of the elements in the AST -corresponds to part of the source code's meaning. +Each element in the AST +corresponds to a part of the source code. The "Constant declaration" AST element has two child elements under it, which represent the two parts of a constant declaration: @@ -331,6 +343,7 @@ its name and its value. The "Macro call" element has child elements that represent the macro's name and the list of arguments being passed to the macro. + As part of constructing this AST, the compiler checks that the source code is valid Swift. For example, `#fourCharacterCode` takes a single argument, @@ -370,7 +383,7 @@ by restricting the code that implements macros: In addition to these safeguards, the macro's author is responsible for not reading or modifying anything outside of the macro's inputs. -For example, a macro's expansion can't depend on the current time of day. +For example, a macro's expansion must not depend on the current time of day. The implementation of `#fourCharacterCode` generates a new AST containing the expanded code. @@ -469,7 +482,7 @@ and `MyProject` makes those macros available. The implementation of a macro uses the [SwiftSyntax][] module to interact with Swift code -in a structured way, using an abstract syntax trees (AST). +in a structured way, using an AST. If you created a new macro package with Swift Package Manager, the generated `Package.swift` file automatically includes a dependency on SwiftSyntax. @@ -538,7 +551,7 @@ conforms to the `ExpressionMacro` protocol. The `ExpressionMacro` protocol has one requirement, a `expansion(of:in:)` method that expands the AST. For the list of macro roles and their corresponding SwiftSystem protocols, -see and +see and in To expand the `#fourCharacterCode` macro, @@ -646,9 +659,9 @@ https://github.com/apple/swift-syntax/blob/main/Sources/SwiftSyntaxBuilder/Synta ## Developing and Debugging Macros Macros are well suited to development using tests: -they transform one AST into another AST +They transform one AST into another AST without depending on any external state, -and without making changes to any external state.. +and without making changes to any external state. In addition, you can create syntax nodes from a string literal, which simplifies setting up the input for a unit test. You can also read the `description` property of an AST