This post is a high level, end to end, summary of playground design in The Swift Programming Language and how playgrounds manifested into Vim.
I recently became obsessed with playgrounds and the possibilities they could unlock for my development runloop. To play Swift in Vim meant to write up a prototype and learn some things.
Playgrounds are an interactive way to write a program and visualize program state side by side with the actual program. They can speed up the development runloop and make programming more fun.
Working prototype of a Swift playground environment in Vim
Language Level Interface
Language support is required to visualize program state as it happens.
Playgrounds are integrated into the language in a way that is elegant, encapsulated, and easy to extend.
At the front end level, playground specific function calls are inserted into
the provided Swift code ( like
When the user specifies the playground frontend option (
-playground ), calls to the playground runtime are inserted.
In the compiler, it’s implemented via the inclusion of the playground transform. The playground transform searches the AST for relevant usages, like variable assignments, and print calls, and then inserts the playground calls.
The Swift compiler integrates many abilities through transforms, which is an excellent pattern. The complexity of playgrounds is encapsulated: it doesn’t leak to the rest of the compiler.
The actual playground logic is specified by the user; not the language implementation. Playground logic is provided to Swift through an interface which is a set of builtin functions: the Playground Runtime.
These builtin functions are undefined in the Swift standard library. A user provides these functions to Swift; a Playground Runtime must be linked into the final playground executable.
Here are a few key functions in the builtin API:
/// Return an object to the system representing the print invocation func $builtin_postPrint(_ sl : Int, _ el : Int, _ sc : Int, _ ec: Int) -> AnyObject? /// Send data ( for example write to StdOut, or XPC ) func $builtin_send_data(_ object:AnyObject?)
For a program like an IDE, an implementation of these calls could notify the editor about output. For a basic playground implementation, like SwiftPlayground.vim, the implementation of these calls simply writes to standard out.
To see the output of the playground, the compiled playground executable is executed. Playground Runtime ( Logging ) calls are executed with the provided code.
For a given target system, like a playground on the Mac, the implementation of execution could be as simple as running the binary. In vim, it is this trivial
A common case is to run iOS based playgrounds. Conveniently, Apple provides an
API to run processes on a Simulator in performant fashion. See (
) for more information.
Editor Integration ( in Vim )
There is a thin layer between the playground and Vim: a protocol format to write logs and a corresponding parser.
When the user saves a playground buffer, the playground is compiled, executed, and the result is parsed in. Program output is mapped to a buffer.
Hooks for playgrounds are implemented via Vim’s event observing API,
Additionally, when the user scrolls, the playground buffer is synchronized with
the main buffer.
Other Editor Features
Autocomplete and real time code diagnostics ( warnings and errors ) are implemented through iCompleteMe.
Syntax highlighting is available through Swift syntax definitions.
For UI development, it could be interesting to display an interactive UI with
the elements inline: rendering and interacting with
Setting up a corresponding UI is a tangentially related work. This requires integration at the UIKit/AppKit level ( and currently, setting some state in PlaygroundSupport ).
Xcode already has implemented this feature inside of a slick UI. Apple open sourced some of the Xcode support which looks highly reusable.
It’s worth noting that Swift playgrounds can theoretically work on Linux, since at the language level, it boils down to an AST transform.
Playgrounds are onto something big. I think, they are a major selling point for Swift.
World class engineering decisions ( on Swift’s end ) made it easy and fun to implement Swift Playgrounds. To get playgrounds in Vim, I just connected the dots. Basically, trivial stuff on my end.
The entire Vim setup in the demo video is achievable with a few plugins:
- SwiftPlayground.vim for playgrounds
- iCompleteMe for code completion and diagnostics
- Swift.vim for syntax
I am interested in learning about and experimenting with effective development technologies like Playgrounds. Follow along and send issues ( and ideally PRs ) over at SwiftPlayground.vim and iCompleteMe.
Thank you Swift team for implementing this API and opening it up! It’s fun to play around with Apple related technologies and I think open source IDE features are key for Swift.