Ante: a compile-time language
github.com
github.com
As an aside, it's very cool to see this implemented, though it does give me the depressing thought that none of my ideas are original anymore. Hopefully more languages follow suit and allow for this kind of utility.
One of the only disadvantages is that because llvm is so large it requires some odd build steps that can be a pain to setup, especially on windows. The llvm-config tool however, manages many of required flags for you. Also, because there are so many libraries, compilation of the compiler itself can be rather slow.
Using it for what? If I understand this project correctly, it allows you to put an application and corresponding application-specific language features/optimizations into one source file. You can then always be sure that those language features and optimizations are available.
I have a hard time seeing how this would work with LLVM's C++ API in a comparable way. There you would have to (1) write the application in an LLVM-supported language, (2) use some other transformation language to add features to your surface syntax, (3) separately compile your LLVM extension pass written in C++, (4) make sure your LLVM extension is used when compiling the application.
But from what I can glean from that short example, the proposed API is essentially LLVM's IRBuilder class, with a slightly different interface. This seems like a strategy that's unlikely to be practical, because of all the complexities involved in reimplementing another project's API, particularly one that changes as frequently as LLVM's.
I'm not sure I understand your breakdown of four steps. As far as I know, it would be very hard to make a backend pass that would have enough information encoded purely in IR from a frontend to compile a construct like goto. This is the sort of thing that needs to be deeply integrated into the compiler, so the author of that feature would necessarily need to understand the data structures and architecture of the compiler. At that point, it's probably easier and more reliable to write it as a compiler extension.
I do like the general idea of being able to extend the operation of a compiler at application compile time (rather than compiler compile time), but I am skeptical that the solution involves directly mucking about with LLVM. That's too low level, the language needs to provide a useful model of abstraction above that to be better than just modifying the code of the compiler itself. As others have mentioned here, Lisp is a great example of offering such a model.
You can extend the compiler's functions during compile-time by doing more than just messing with llvm-ir. You are free to implement an automatic linter, or garbage collector for example. You can even do an optimization pass without operating on the llvm-ir. To do this, you could walk the parse tree of a function before it compiles and change around any common node patterns you are looking for before it is translated to llvm-ir. Alternatively, you can muck around in the ir and do the same thing.
The goto construct in the example provided does not need to be deeply integrated because the existing API is setup largely separate from the internal structure of the compiler. For example the function ctStore stores a variable in a compile-time container separate from the scope-separated table used internally by the compiler for other variables. The primary advantage of Ante as a language is that these functions enable compiler extensions to be made within the program and thus allow the swapping out of, eg. a garbage collector, without recompiling the compiler itself. This lets each application developer decide what features they need for their application. Instead of changing languages for a gc or desired optimization pass, just swap out a library.
I share your concern with the LLVM library constantly updating and the need to update bindings with it. I plan sometime to use the clang api to make a C++ -> Ante converter program, although I expect there to be numerous difficulties with its implementation.
I think the general idea is interesting. However, I suspect that you're underestimating the complexity of the things you've mentioned. I don't mean to be too negative, but have you implemented garbage collection? Getting it right for just one language takes lots of serious effort. With the added complication of needing to deal with other arbitrary user-designed language constructs, it might be an intractable problem.
Brainstorming ideas for language design is great. Trying new things is fantastic. But it's important to be humble and realistic, and to recognize that language design requires making thoughtful tradeoffs.
That being said, by no means do I claim that all extensions will work together perfectly, or at all. For example, a garbage collector would be completely incompatible with a plugin that frees all variables once they go out of scope. Compatibility is left up to the plugin's author in the case of multiple plugins having conflicting goals.
I'm not sure where I stated I was opposed to making tradeoffs, I have done several (albeit mostly syntactic) already. I knew the project was ambitious when I first started it, that is part of the fun of working on it.
That's exactly what this language allows you to do, except that it's nicer than C++ and can be interleaved with the application you want to compile with the extended compiler.
> That's too low level, the language needs to provide a useful model of abstraction above that to be better than just modifying the code of the compiler itself.
I agree that a higher-level API would be useful, too. For high-level things, but not necessarily for adding goto.
What do you mean by nicer? The tradeoff here seems to be exchanging useful functionality for a leaner, more limited interface. I'm not sure I agree that the right decision is to forsake the full power of the LLVM interface.
> can be interleaved with the application you want to compile with the extended compiler.
On this we can agree - abstractly, that would be a very powerful thing. Practically, though, what's the cost? How would developers expressively write useful extensions? How do these extensions interact? Answering the hard questions about how this would actually work is going to take some serious thought.
> I agree that a higher-level API would be useful, too. For high-level things, but not necessarily for adding goto.
I'm not sure goto is all that great of an example, except for the dimension of implementability in a README file.
People have lots of more or less subjective preferences concerning programming languages. To me, this programming language looks more productive and more comfortable to use than C++. You might reasonably disagree.
> Answering the hard questions about how this would actually work is going to take some serious thought.
And/or experimentation. No programming language design was ever gotten right on the first try. Programming languages evolve with use, in unplanned and unplannable directions. It's completely fine to do this and see how it comes out.
In a cousin comment, you wrote "Always fun to see new language ideas and watch them grow." This is exactly that.
One possible disadvantage, you can't gain information by automatically converting code to another representation, but you could potentially lose information that would be relevant to an optimization. I don't know of any practical examples of this happening with LLVM, but I believe Java's type erasure carries a very slight penalty.
Another possible disadvantage is if you have a language designed to be compiled extremely fast, then adding an intermediate step could slow it down unacceptably.
* a syntax, including literals
* first class support for llvm IR and primitives
* a macro system allowing you to create new ir-level primitives with aforementioned syntax.
It seems like a lisp without homoiconicity and a complex syntax (compared to sexps). Think: greenfield compiler development, or maybe a DSP DSL.
https://www.youtube.com/playlist?list=PLmV5I2fxaiCKfxMBrNsU1...
https://en.wikipedia.org/wiki/Meta
Most usages of 'meta' that I encountered target the 'beyond' meaning, i.e. raising the abstraction level of something.