-
Notifications
You must be signed in to change notification settings - Fork 213
Create Static Enough Metaprogramming proposal #4374
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
base: main
Are you sure you want to change the base?
Conversation
introspect program structure which are _required_ to execute in compile time | ||
toolchain supports that. These two together should give enough expressive power | ||
to solve a wide range of problems where metaprogramming is currently wanted. cc | ||
@dart-lang/language-team |
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.
No cc needed here.
@@ -0,0 +1,1222 @@ | |||
tldr: I propose we follow the lead of **D**, **Zig** and **C++26** when it comes |
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'd give this file a header.
- A title line at the top.
- An author line:
Author: @mralpeh
. - Consider a version line:
version: 1.0
and a version section/changelog at the end, to track changes.
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.
LGTM. (Very interesting indeed!)
I could suggest the addition of 'a' or 'the' in many locations, but decided that this wouldn't be the top priority at this time.
to metaprogramming. We introduce an optional (toolchain) feature to force | ||
compile time execution of certain constructs. We add library functions to | ||
introspect program structure which are _required_ to execute in compile time | ||
toolchain supports that. These two together should give enough expressive power |
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.
Perhaps?:
toolchain supports that. These two together should give enough expressive power | |
if the toolchain supports that. These two together should give enough expressive power |
Also, 'at compile time' seems to be more common than 'in compile time'.
# History of `dart:mirrors` | ||
|
||
In the first days of 2017 I have written a blog post ["The fear of | ||
`dart:mirrors`"][the-fear-of-dartmirrors] which contained started with the |
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.
`dart:mirrors`"][the-fear-of-dartmirrors] which contained started with the | |
`dart:mirrors`"][the-fear-of-dartmirrors] which started with the |
> fog of uncertainty and marked as _Status: Unstable_ in the documentation - | ||
> even though APIs have not changed for a very long time. | ||
In 2017 type system was still optional, AOT was a glorified |
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.
In 2017 type system was still optional, AOT was a glorified | |
In 2017 the type system was still optional, AOT was a glorified |
_"ahead-off-time-JIT"_, and the team maintained at least 3 different Dart | ||
front-ends (VM, dart2js and analyzer). Things really started shifting with Dart | ||
2 release: it had replaced optional types with a static type system and | ||
introduced _common front-end (CFE)_ infrastructure to be shared by all backends. |
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.
introduced _common front-end (CFE)_ infrastructure to be shared by all backends. | |
introduced a _common front-end (CFE)_ infrastructure to be shared by all backends. |
and necessity to use _AOT-compilation_ for deployment. | ||
|
||
Dart 1 was all in on dynamic typing. You don't know what a variable contains - | ||
but you can do anything with it. Can pass it anywhere. Can all any methods on |
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.
Perhaps?:
but you can do anything with it. Can pass it anywhere. Can all any methods on | |
but you can do anything with it. Can pass it anywhere. Can call any methods on |
> | ||
> - [Reflection Analysis for Java][paper-java-suif-reflection] | ||
> - [Understanding and Analyzing Java Reflection][paper-java-reflection-2019] | ||
> - [Challenges for Static Analysis of Java Reflection – Literature Review and Empirical Study](paper-java-reflection-challenges) |
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.
Just guessing:
> - [Challenges for Static Analysis of Java Reflection – Literature Review and Empirical Study](paper-java-reflection-challenges) | |
> - [Challenges for Static Analysis of Java Reflection – Literature Review and Empirical Study][paper-java-reflection-challenges] |
> [!NOTE] | ||
> | ||
> Another exploration similar in nature was | ||
> (go/const-tree-shakeable-reflection-objects)[http://go/const-tree-shakeable-reflection-objects]. |
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.
Perhaps?:
> (go/const-tree-shakeable-reflection-objects)[http://go/const-tree-shakeable-reflection-objects]. | |
> [go/const-tree-shakeable-reflection-objects](http://go/const-tree-shakeable-reflection-objects). |
very small and excludes a lot of expressions which feel like they should | ||
actually be included. It just feels wrong that `const x = [].length` is invalid | ||
while `const x = "".length` is valid. For some seemingly arbitrary reason | ||
`String.length` is the only blessed property which can't be accessed in a |
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.
`String.length` is the only blessed property which can't be accessed in a | |
`String.length` is the only blessed property which can be accessed in a |
> Another exploration similar in nature was | ||
> (go/const-tree-shakeable-reflection-objects)[http://go/const-tree-shakeable-reflection-objects]. | ||
Fundamentally both of these approaches were dead ends and Web applications |
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.
Fwiw, I wouldn't say that the const reflection proposal was a dead end at all, we just simply didn't end up doing it but there wasn't any sort of blocker or anything that I remember encountering.
> This proposal does not suffer the same issue, even if we decide to support | ||
> `@konst` evaluation in these tools: as `@konst` actually provides a syntactic | ||
> marker which partitions the program. Only bodies of methods with `@konst` | ||
> parameters need to be included into the outline. |
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.
Can these functions only invoke other @konst
functions? This was a big problem with enhanced const - it quickly ends up being that all functions end up being marked as "const" just because some other const function completely unrelated to your function wants to invoke them, and your function could be const so you say sure, but now all these functions end up in outlines.
I think you need something like @konst
imports so it is defined at the usage site and not the definition site which functions can be called by @konst
functions.
Dart source code generation or which are supported by macro systems in other | ||
programming languages. For example the following capabilities are out of scope: | ||
|
||
- injecting new declarations into the program; |
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 definitely does drastically simplify the proposal - but it also makes it a lot less useful. Ultimately trying to accomplish this was the downfall of the original macros proposal though.
But, I think it is important to look at the original motivations for macros, and which of those use cases are covered by this.
Ultimately, I think you can end up with some fairly decent solutions for automatic encoding/decoding, equality, toString, etc. But not copyWith or constructors due to the signatures being dependent on the shape of the class (you could generate the bodies of these but that's only half the boilerplate).
Edit: I see you have an interesting copyWith idea using records, that is fairly reasonable actually.
> } | ||
> ``` | ||
> | ||
> Though usability of this method will be questionable as there will be good |
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.
> Though usability of this method will be questionable as there will be good | |
> Though usability of this method will be questionable as there will be no good |
- Average code size overhead per class: 270 bytes | ||
- Average JIT kernel generation overhead per-class: 0.2ms (cost of producing | ||
specialized functions using Kernel-to-Kernel AST transformation) | ||
- Average AOT compilation overhead per-class: 2.6ms |
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.
What is the baseline?
code: | ||
|
||
```dart | ||
mixin DataClass<@konst T> { |
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 would be 🔥 (and help a lot with the reduction of boilerplate)
|
||
This requires the definition of constant expression to be expanded to cover a | ||
significantly larger subset of Dart than it currently includes. Such feature | ||
does however exist in other programming languages, most notably **C++**, **D**, |
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.
does however exist in other programming languages, most notably **C++**, **D**, | |
do however exist in other programming languages, most notably **C++**, **D**, |
} | ||
``` | ||
|
||
Note that all methods are annotated with `@konst` so if compiler supports |
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.
Note that all methods are annotated with `@konst` so if compiler supports | |
Note that all methods are annotated with `@konst` so if the compiler supports |
This moves content from #4271 into a markdown file in the repository to make discussion and revisions easier.
I have incorporated some of the feedback from discussions on the issue - but I continue to maintain focus on this as a toolchain feature. I have added some remarks that analyzer can't constant fold everything anyway because it does not have access to the compilation environment.
I would like to collect a few rounds of feedback and then rejuvenate the prototype implementation to get something experimental working across all platforms in the SDK so that we can have an idea of how well this could work in a real world.