Skip to content

Commit

Permalink
Add a README
Browse files Browse the repository at this point in the history
  • Loading branch information
DougGregor committed Dec 14, 2022
1 parent ee8c71b commit c30ca8c
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 4 deletions.
13 changes: 13 additions & 0 deletions MacroExamples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
remoteGlobalIDString = BDF5AFED2947E61100FA119B;
remoteInfo = MacroExamplesPlugin;
};
BD8A313629494C4C00E83EB9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BDF5AFD82947E5B000FA119B /* Project object */;
proxyType = 1;
remoteGlobalIDString = BDF5AFED2947E61100FA119B;
remoteInfo = MacroExamplesPlugin;
};
BDFB14B72948484000708DA6 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BDF5AFD82947E5B000FA119B /* Project object */;
Expand Down Expand Up @@ -189,6 +196,7 @@
buildRules = (
);
dependencies = (
BD8A313729494C4C00E83EB9 /* PBXTargetDependency */,
);
name = MacroExamplesLib;
productName = MacroExamplesLib;
Expand Down Expand Up @@ -358,6 +366,11 @@
target = BDF5AFED2947E61100FA119B /* MacroExamplesPlugin */;
targetProxy = BD8A31342949480C00E83EB9 /* PBXContainerItemProxy */;
};
BD8A313729494C4C00E83EB9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = BDF5AFED2947E61100FA119B /* MacroExamplesPlugin */;
targetProxy = BD8A313629494C4C00E83EB9 /* PBXContainerItemProxy */;
};
BDFB14B82948484000708DA6 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
platformFilters = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
Expand Down
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Swift Macro Examples



There is an active effort to introduce [macros](https://forums.swift.org/t/a-possible-vision-for-macros-in-swift/60900) into the Swift programming language. This repository includes some example macros that can be used to explore the macro proposals and experiment with the current implementation of the feature.

## Getting started

Macros are an experimental feature, so you will need a custom Swift toolchain and some extra compiler flags. The Xcode project in this repository is a good starting point. To use it:

1. Download a new-enough Swift toolchain. At the time of this writing, the [snapshots](https://www.swift.org/download/#snapshots) on Swift.org aren't new enough, so please use [this macOS toolchain](https://ci.swift.org/job/swift-PR-toolchain-macos/448/artifact/branch-main/swift-PR-62537-448-osx.tar.gz). Once downloaded, run `cd ~ && tar zxvf ~/Downloads/swift-PR-62537-448-osx.tar.gz` to install the toolchain.
2. Open the project `MacroExamples.xcodeproj` in Xcode.
3. Go to the Xcode -> Toolchains menu and select this toolchain (`Swift PR 62494 (445)`).
4. Make sure the `MacroExamples` scheme is selected, then build and run!

The output of the `MacroExamples` program is pretty simple: it shows the result of running the example macro(s).

## Adding your own macro

This examples package is meant to grow to include additional macros that have interesting behavior. To add a macro requires both *declaring* the macro and also *implementing* the macro, which happen in separate targets:

* **Implementation**: a macro is defined in the `MacroExamplesPlugin` target, by creating a new `public struct` type that implements one of the macro protocols. The `stringify` macro implements the `ExpressionMacro` protocol, e.g.,

```swift
public struct StringifyMacro: ExpressionMacro { ... }
```

To test a macro implementation, introduce new tests into the `MacroExamplesPluginTest` target. These tests start with source code (like `#stringify(x + y)`) and will run the macro implementation to produce new source code. The translation can make use of the [swift-syntax](https://github.com/apple/swift-syntax) package, a copy of which is included in the toolchain. We recommend implementing and testing your macro this way first so you know it does the source translation you want.

* **Declaration**: a macro is declared in the `MacroExamplesLib` target, using the `macro` introducer. For example, the simple `stringify` macro is declared like this:

```swift
public macro stringify<T>(_ value: T) -> (T, String) = MacroExamplesPlugin.StringifyMacro
```

The name after `macro` is the name to be used in source code, whereas the name after the `=` is the module and type name for your macro implementation. If you haven't implemented that type, or get the name wrong, you will get a compiler warning.

Once you have both a declaration and an implementation, it's time to use your macro! Go back to `MacroExamples` and write some code there to exercise your macro however you want.

## Macros proposals

The introduction of macros into Swift will involve a number of different proposals. Here

* [Expression macros](https://forums.swift.org/t/pitch-2-expression-macros/61861): Introduces the ability to add macros that transform expressions into other expressions.

##

0 comments on commit c30ca8c

Please sign in to comment.