-
Notifications
You must be signed in to change notification settings - Fork 257
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
Refactor compiler to allow loading backends from separate DLLs #1708
Conversation
The Csharp and Go compilers were using a separate FreshIdGenerator for a few variables. Why?
For the moment, I would advise to not move each existing backend to a separate DLL because it makes development easier. I'm working on refactoring the compiler itself so that it's more modular (e.g. no call to a single CreateForEachLoop that is responsible of subtype checking). Hence I not only need to modify the base compiler, but also the different instances, and I run a test for all of them at the same time. |
07cd7c4
to
a59a9ef
Compare
var okVar = FreshId("_ok"); | ||
var iterVar = FreshId("_iter"); | ||
var okVar = idGenerator.FreshId("_ok"); | ||
var iterVar = idGenerator.FreshId("_iter"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does this _ok
=> _iter
rename come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there's a rename here?
👍, although it might be nice to split off the Java compiler, because compiling the runtime every time is a pain. |
I investigated more why I believed we should hold off splitting the compilers into different projects. It turns out I had some instability with some versions of Newtonsoft.Json.dll (DafnyDriver requires 9.0.0.0, DafnyLanguageServer requires 11.0.0.0, so if I compile DafnyDriver, the language server does not work). |
What do we mean by splitting off the compilers? We'd move the compiler file to a new .NET project, sure, but where do we leave that project? If we keep that project in the Dafny solution then it wouldn't impact development, right? It just means that Rider can build DafnyPipeline without building the Java compiler. |
That was my hope, yes. |
|
||
namespace Microsoft.Dafny; | ||
|
||
public interface ICompiler { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This interface is so much nicer. :)
Here's an idea to consider for the very next PR (since it's not necessary here and the PR is already large): could we add a method to be invoked earlier in the pipeline, before verification, that can produce compiler-specific errors? Something like CheckCompatibility
.
The use case would be a codebase using a specific compiler, especially one of the more incomplete ones like C++, where it's currently pretty frustrating to spend a ton of time getting your code to verify successfully only to then find out "oh wait, my compiler doesn't support unbounded int
s" and have to start over. This is particularly easy for newer Dafny programmers to hit, since the documentation on which features are supported by which compilers is something you have to think to look up, and isn't that obvious for newcomers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's an idea to consider for the very next PR (since it's not necessary here and the PR is already large): could we add a method to be invoked earlier in the pipeline, before verification, that can produce compiler-specific errors? Something like CheckCompatibility.
The compiler is fast and verification errors lead to runtime (not compile-time) errors, so we could just run the compiler first or in parallel with verification instead of running verification first and only then running the compiler. So instead of resolve → verify → translate → compile
we could just run
resolve → verify
→ translate → compile
Or even resolve → translate → verify → compile
if we don't want concurrency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably a good entry for your compiler planning doc!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, you're absolutely right that there's other ways to get the same result (and it would be better to not have another method to implement if possible). I'm not sure I believe "verification errors lead to runtime (not compile-time) errors" is always true, or that we want to ensure it is always true in the future, but we can work that into the design. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our compilers are actually "translators", the two are synonyms. When you say "compiler", do you mean the actual language-to-bytecode compiler?
Sounds great, but let's do it in a separate PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, how will it work to provide new compiler assemblies? Are you reusing the same compileTarget option?
|
||
namespace Microsoft.Dafny; | ||
|
||
public interface ICompiler { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our compilers are actually "translators", the two are synonyms. When you say "compiler", do you mean the actual language-to-bytecode compiler?
} | ||
|
||
public CompilationTarget CompileTarget = CompilationTarget.Csharp; | ||
public CompilerFactory CompilerFactoryInstance; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With flags it was obvious we could run multiple compilers at the same time.
How are you going to do it with this? I suggest you use a comma-separated list of compilers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With flags it was obvious we could run multiple compilers at the same time.
I don't think we ever could actually run multiple compilers at the same time, could we?
|
||
namespace Microsoft.Dafny; | ||
|
||
public interface ICompiler { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider renaming ICompiler
to ICodeGenerator
. "Compiler" is generally used to refer to an entire compilation pipeline, including parsing source code, right?
That's right, you just pass |
@MikaelMayer and I disucssed this today. We think it's better if instead of reusing the compileTarget flag to give a DLL we instead make a new flag This same plugin flag can be used for other kinds of plugins, and @MikaelMayer will implement it as part of #1739 . Then I will rebase this PR on top of that. Finally we decided it would be simpler to get rid of the factory and instantiate an |
Why don't we merge this PR first, since this is already approved? |
Maybe because 1) the tests are not working yet, and 2) offering an API to implement a factory and then immediately switching to a plugin strategy would be not backward compatible with the factory (for example, /compilationTarget won't accept a DLL anymore once we switch to the plugin system). and 3) it makes sense to accept DLLs as a separate argument rather than changing the CompilationTarget. |
I'm voluntarily not writing "changes requested" because I don't want to block this PR, but we are still in discussion about the plugins system which would make this PR easier to implement. |
The only client of this PR is my compiler work, which can happen in a branch. The plugin API is the result of discussing with @MikaelMayer how to unify his resolver plugins and my compiler plugins, so I don't think we should merge this until the plugin work is done :) |
Closing this, since it was superseded by my later PR on top of Mikael's one |
This is the first step towards making it easier to plug in compiler backends.
NEEDS REVIEW
.With this PR the
/compileTarget
flag can take a path to a DLL.