Open masak opened 6 years ago
It just struck me that one issue with this change is that it delays how soon we can know which type of statement (or class member, etc) we're parsing. Basically, it goes against the grain of Perl 6's idea of having a "declarative prefix" in each rule after which you know what rule you're parsing.
On second thought, it's not quite that hopeless. If we parse traits alongside statements in the statementlist
rule, it works out fine. Have to mark up some Qtypes as "traitable" (maybe with... a trait?) and check for that, though.
I can't find it right now, but somewhere I had quite a complicated is parsed
that actually used the parameters of the macro for something. (I think it was to do with declarations and scopes.) I'll link it here if I find it.
Anyway, that'd be problematic if we reverse the order of traits and parameters. At least, we'd have to find some other way to achieve the same effect.
I'd like to find that is parsed
example again so I can mull over how to solve that with traits sitting on top.
Another small argument in favor of this syntax change: I find it somewhat easier to read this syntax:
foo(@Defined param) {}
Than this syntax:
foo(param is defined) {}
It just struck me that one issue with this change is that it delays how soon we can know which type of statement (or class member, etc) we're parsing. Basically, it goes against the grain of Perl 6's idea of having a "declarative prefix" in each rule after which you know what rule you're parsing.
Coming back to it, I feel this was a valid objection to have, but it's by no means a show-stopper. Labels are much the same, in that they can precede many different types of statement and we don't know which one until we've finished parsing the label.
Maybe it'd be worth it to explore the dangers of allowing arbitrary expressions inside the @Annotation(...)
. If we allow functions there, that means we indirectly allow statements. Not sure I see the harm, really, though. It's all just nesting.
Working on this in a branch. Realizing we'll probably need an issue where we also nail down the semantics of decorators.
They're interesting beasts. The ones for precedence and associativity will be driving in this, and they are mostly "metadata decorators" in the sense that they want to end up being attached to the declaration somehow, so that the parser can query them when it needs the information. There are more "business rules" connected to them than I remembered, for example (but not exhaustive):
equiv
.It's an interesting question how much of that needs to be code, and how much can be captured declaratively somehow in the declaration of the decorators themselves.
Simple question: how should the Qtree look for statements with decorators? (Hint: I don't know.)
It's an interesting question how much of that needs to be code, and how much can be captured declaratively somehow in the declaration of the decorators themselves.
I think the former can be easily captured using a @unique
decorator, or some such. (And it makes sense to me to do so.) Yay, decorators on decorators — that means we're just as cool as Java, does it not?
The latter sounds like a "business rule" to me, and should most likely be handled by whatever thing consumes those parser-targeting decorators. (That is, they should be handled by the parser.)
By the way, the solution I've struck upon with the 007 parser in Perl 6 is to carry that information from where the decorators are parsed to where the statement they're decorating is parsed, by using a dynamic variable. This, in some sense, feels like a sane solution. I could also imagine it being handled by using some sort of "parser state" — as long as the stack-like aspect of it all is still captured. (A previous comment hints at decorators occurring inside decorators via declarations. The dynamic variable handles this well, by storing its data essentially "in the call stack". A "parser state" solution would need to handle it as well.)
In passing, I note that I'm suddenly writing decorators with lowerCamelCase, like in Python, not with UpperCamelCase, like in Java. I have no idea why.
Decorators can be
Simple question: how should the Qtree look for statements with decorators? (Hint: I don't know.)
What's the Simplest Possible Thing That Could Possibly Work?
From my vantage point, it's a special statement that contains a decorator and an inner statement. That is, a composite.
...or maybe that's to general. Maybe a decorator captures what we want here? (That can't be a coincidence, can it?)
- Enum values
Let's hold off on that one. First, because we don't have enums yet in the language. Second, because it's kind of an exception, and I don't fully understand yet.
With just functions/macros in the mix, the rule is simple: a decorator desugars to a call. That is,
@foo(1, 2)
func whatever() {}
desugars to
my whatever = foo(func whatever() {}, 1, 2);
or something very much like it. In general, a decorator is always a function or a macro with an extra first parameter, which is the wrapped function-or-macro. (Or, if the decorator itself is a macro, its Qnode.)
As to "marker decorators", I think on second thought that all decorators are potential marker decorators. But specifically, if one leaves their implementation empty (or identity function), that's probably because they are meant to be used as markers.
Following Python and Java's lead. Even TypeScript and ES.next, and (modulo a slight difference in syntax) C#.
Not sure I can fully motivate why I want to make this change, but (a) it feels a little bit more robust in some way, and (b) it's becoming clear that we can have use for traits on a number of things besides subs/macros:
An example of the former:
@Abstract
; instead of making it a keyword. An example of the latter:@Readonly
. Maybe@Lazy
too.