Skip to content

Syntactic macro system #969

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Oct 19, 2022
Merged

Conversation

DougGregor
Copy link
Member

Implement a simple, experimental syntactic macro system that allows syntax of the form #macroName(optional-macro-args) to be treated as a macro evaluation, where macros are implemented via syntactic transformations on a SwiftSyntax tree.

There are a few example macros here, one of which is a stringify macro that expands its argument into a tuple containing both the value and the string form of the argument, e.g.,

let b = #stringify(x + y)

will evaluate to

let b = (x + y, #"x + y"#)

New macros can be introduced by creating a type conforming to one of the *Macro protocols, such as the ExpressionMacro protocol for types that use the # expression syntax.

Although this library provides purely syntactic expansion, the idea is to have a semantic component to macros, such that Swift's type checker performs some checking on the macro arguments, then initiates the macro evaluation to produce the final code.

The design here is discussed in A Possible Vision for Macros in Swift.

@DougGregor
Copy link
Member Author

@swift-ci please test

1 similar comment
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor DougGregor marked this pull request as ready for review October 18, 2022 21:58
@DougGregor DougGregor requested a review from ahoppen as a code owner October 18, 2022 21:58
DougGregor and others added 25 commits October 18, 2022 16:06
Use expand-macros to see the effect of expanding all uses of example macros
within the given source file, and emitting and diagnostics they produce.
Instead, have `#line` create the more general
`MacroExpansionExprSyntax` node.
The general macro production works. We can't implement this as a macro just
yet, though.
Stop creating `PoundFunctionSyntaxExpr` nodes in the parser. Implement
a macro version instead.
…eral`

Remove the "object literal" parsing grammar entirely, sending
`#colorLiteral`, `#fileLiteral`, and `#imageLiteral` through the normal
macro-expansion expressions. Implement `FileLiteral` and `ImageLiteral`
macros in the example macro system.
All of these are subsumed by macro expansion expressions.
@DougGregor DougGregor force-pushed the syntactic-macro-system branch from 693c500 to 5c02eb5 Compare October 18, 2022 23:27
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor
Copy link
Member Author

The refactoring here to generalize the parsing of # expressions is quite valuable to simplify the syntax tree. Merging!

@DougGregor DougGregor merged commit 3c11671 into swiftlang:main Oct 19, 2022
@DougGregor DougGregor deleted the syntactic-macro-system branch October 19, 2022 00:57
allevato added a commit to allevato/swift-format that referenced this pull request Oct 19, 2022
This gets swift-format building/tests passing again after
the following changes:

swiftlang/swift-syntax#963 (Allow postfix #if to be empty)
swiftlang/swift-syntax#969 (Syntactic macro system)
Copy link
Member

@ahoppen ahoppen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments from reviewing the parser bits of this PR.

}

// Parse the optional trailing closures.
let trailingClosure: RawClosureExprSyntax?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would a macro expansion declaration with a trailing closure look like?

let (unexpectedBeforeMacro, macro) = self.expectIdentifier()

// Parse the optional parenthesized argument list.
let leftParen = self.consume(if: .leftParen, where: { !$0.isAtStartOfLine })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT parseMacroExpansionExpr and parseMacroExpansionDecl seem pretty similar to me. Do you think we could unify their parsing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants