Extending the Q# Compiler
One of the most exciting things in our work is offering new ways for you to incorporate your own ideas and vision into our tools. In this blog post, I would like to highlight a feature that is especially interesting in that regard and came in with our end-of-January release: Custom compilation steps, which allow you to extend and customize the Q# compilation process.
What is a compilation step?
Like any compiler, the Q# compiler executes a sequence of compilation steps. The first few steps parse and verify the Q# code and create a data structure that represents the state of the compilation. Each step after that walks that data structure and creates a new version. Common tasks that might be performed by such compilation after the initial construction are peephole optimizations, constant folding, loop unrolling, function and operation inlining, … With our 0.10.2001.2831 release, we’ve added an easy way to define your own custom compilation steps and execute them when building a Q# project!
Defining custom compilation steps
A custom compilation step is defined by a class that implements the IRewriteStep interface. I’ll refer to the documentation in the code for details regarding the properties and methods defined by the interface. Fundamentally, the interface defines a transformation method that gets a QsCompilation and returns a potentially transformed
QsCompilation data structure is used to represent a compiled Q# project, and contains all high level abstractions defined in the Q# language.
Like any data structure in the Q# compiler, a
QsCompilation is immutable. Compilation steps are meant to be atomic in the sense that a compilation step indicates whether it was executed successfully by returning a Boolean value, and the compiler only updates the compilation if the transformation completed successfully.
A custom compilation step may generate diagnostics that are presented to the user along with the diagnostics generated by the Q# compiler. In addition to the transformation method, the interface also defines a method for pre- and post-condition verification. The details regarding the intended use and the processing done by the Q# compiler are again documented as part of the interface definition.
Using custom compilation steps when building a Q# project
Any Q# project that is built using the Microsoft.Quantum.Sdk package as described here can easily incorporate custom compilation steps into the build process. This is the case for all projects created using the project templates or extensions with version 0.10.2001.2831 or later.
Custom compilation steps may be included via project and package references. The readme describes in more details how to use custom compilation steps. This project for example uses the rewrite steps defined in the CustomExtension project as part of its build; if you build it you will see the compiled Q# code after executing the simple optimizations implemented by the CustomCompilerExtension class.
Ready to start coding?
Any .NET Core project or NuGet package that contains an implementation of the
IRewriteStep interface may be used as extension to the Q# compiler – and more importantly: Anyone can use those extensions to compile their Q# project(s)!