Feature #9938
property syntax for annotations
0%
History
#1 Updated by Greg Shah about 1 year ago
In TRPL 1.0, annotations are "second class" features. The syntax of the language itself does not provide any facility for accessing or working with annotations.
Since annotations are crucial to processing in TRPL, the idea is that making annotations a first class part of the language might make TRPL code simpler, cleaner and safer. If it is easier to read/write and ensure correctness, then this is potentially an important feature.
A key design point with annotations is that they are not implemented as individual member fields in the AnnotatedAst class. Instead, we store them in a map, using the name as a key. This allows the annotations to be defined by the writer of the TRPL rules rather than requiring subclasses of AnnotatedAst or larding AnnotatedAst with many unrelated field members.
This "TRPL programmer can define the annotations" concept must remain. This suggests that we need to provide TRPL with more information about the annotations to be honored in a given rule-set. Let's think of this as an "annotation definition". An annotation definition would need the following information:
- annotation name (required)
- data type (required)
- default value when it does not exist (optional)
These definitions can be provided at the top of a rule-set or function. Then we could implement a direct access syntax that would be type safe and have clean default behavior.
| _ Idiom | _ Possible Syntax |
node.isAnnotation("name")isNote("name") (implicitly only works for this) |
node.name != null (only needed/used for annotations with no default value) |
!node.isAnnotation("name")!isNote("name") (implicitly only works for this) |
node.name null (only needed/used for annotations with no default value) |
#(type) node.getAnnotation("name") |
node.name |
getNote<type>("name") (implicitly only works for this) |
this.name |
node.isAnnotation("name") and #(boolean) node.getAnnotation("name") |
node.name (only semantically the same if there is a default value) |
isNote("name") and getNoteBoolean("name") |
this.name (only semantically the same if there is a default value) |
<action>var = default_value</action>
<rule>node.isAnnotation("name")
<action>var = #(type) node.getAnnotation("name")</action>
</rule>
|
node.name (only semantically the same if there is a default value or if the default value is null) |
!node.isAnnotation("name") or #(type) node.getAnnotation("name") some_value |
node.name null or node.name some_value |
We might still need a way to explicitly check for existence (maybe a node.exists(name) construct).
#2 Updated by Constantin Asofiei about 1 year ago
- for the
this.namesyntax, thenamemust not collide with aAastgetter method (as we can do anode.firstChildinstead ofnode.getFirstChild()at this time) - annotations which are computed during conversion (not static, like some schema-related annotations you mentioned to Radu some time ago, where the table name was added as a suffix to the annotation).
#3 Updated by Greg Shah about 1 year ago
for the
this.namesyntax, thenamemust not collide with aAastgetter method (as we can do anode.firstChildinstead ofnode.getFirstChild()at this time)
Correct. We can give precedence to method names and warn if we see a conflict.
annotations which are computed during conversion (not static, like some schema-related annotations you mentioned to Radu some time ago, where the table name was added as a suffix to the annotation).
I don't think this is something that we should be doing. We should remove this dynamic usage.
#4 Updated by Constantin Asofiei about 1 year ago
Something else to mention: we allow node.getAnnotation(someVar) (and put/is), especially from TRPL functions I think. This should still be honored somehow.