introduce Attributes for classes and methods

This commit is contained in:
ruby0x1
2021-04-05 21:52:09 -07:00
parent e3c76a3e76
commit 07f0579ebe
11 changed files with 608 additions and 10 deletions

View File

@ -621,6 +621,117 @@ class Derived is Base {
}
</pre>
## Attributes
<small>**experimental stage**: subject to minor changes</small>
A class and methods within a class can be tagged with 'meta attributes'.
Like this:
<pre class="snippet">
#hidden = true
class Example {}
</pre>
These attributes are metadata, they give you a way to annotate and store
any additional information about a class, which you can then access at runtime.
This information can also be used by external tools, to provide additional
hints and information from code to the tool.
<small>
Since this feature has just been introduced, **take note**.
**Currently** there are no attributes with a built-in meaning.
Attributes are user-defined metadata. Note that this may not remain
true as some may become well defined through convention or potentially
through use by Wren itself.
</small>
Attributes are placed before a class or method definition,
and use the `#` hash/pound symbol. They can be
- a `#key` on it's own
- a `#key = value`
- a `#group(with, multiple = true, keys = "value")`
An attribute _key_ can only be a `Name`. This is the same type of name
as a method name, a class name or variable name, an identifier that matches
the Wren identifier rules. A name results in a String value at runtime.
An attribute _value_ can be any of these literal values: `Name, String, Bool, Num`.
Values cannot contain expressions, just a value, there is no compile time
evaluation.
Groups can span multiple lines, methods have their own attributes, and duplicate
keys are valid.
<pre class="snippet">
#key
#key = value
#group(
multiple,
lines = true,
lines = 0
)
class Example {
#test(skip = true, iterations = 32)
doStuff() {}
}
</pre>
### Accessing attributes at runtime
Attributes are stored on the class. You can access them via
`YourClass.attributes`. The `attributes` field on a class will
be null if a class has no attributes.
If the class contains class or method attributes, it will be an object with
two getters:
- `YourClass.attributes.self` for the class attributes
- `YourClass.attributes.methods` for the method attributes
Attributes are stored by group in a regular Wren Map.
Keys that are not grouped, use `null` as the group key.
Values are stored in a list, since duplicate keys are allowed, multiple
values need to be stored. They're stored in order of definition.
Method attributes are stored in a map by method signature, and each method
has it's own attributes that match the above structure. The method signature
is prefixed by `static` or `foreign static` as needed.
Let's see what that looks like:
<pre class="snippet">
// Example.attributes.self =
// {
// null: { "key":[null] },
// group: { "key":[value, 32, false] }
// }
#key
#group(key=value, key=32, key=false)
class Example {
#getter
getter {}
// { regular(_,_): { regular:[null] } }
#regular
regular(arg0, arg1) {}
// { static other(): { isStatic:[true] } }
#isStatic = true
static other()
// { foreign static example(): { isForeignStatic:[32] } }
#isForeignStatic=32
foreign static example()
}
</pre>
<br><hr>
<a class="right" href="concurrency.html">Concurrency &rarr;</a>
<a href="functions.html">&larr; Functions</a>