-
Notifications
You must be signed in to change notification settings - Fork 0
Attributes #24
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?
Attributes #24
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# Attributes syntax | ||
|
||
We're currently using `@` and some ad hoc following stuff. | ||
|
||
Proposed changes: | ||
|
||
- Inner vs outer attribute semantics | ||
- Attachment in AST | ||
- Inner attributes with no identifier | ||
- Tool attributes | ||
|
||
## Proposal | ||
|
||
Goal: to be flexible and extensible. | ||
|
||
### Syntax | ||
|
||
Inner/outer is not meant to be user-facing jargon. | ||
|
||
``` | ||
item ::= ... | fn_decl | const_decl | import | inner_attr | outer_attr item | ||
stmt ::= ... | const_decl | outer_attr stmt | ||
|
||
inner_attr ::= `@` `(` (annot_item,)* `)` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The lack of identifier after the
I know KCL is very different from Rust, so the specifics don't apply. But in most languages that have item attributes, it's common to want to apply multiple, unrelated attributes to the same declaration. I think I'd prefer a different token or tokens the way Rust does it with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking like:
So, the logic here is that the name after the |
||
outer_attr ::= `@` id (`(` (annot_item,)* `)`)? | ||
annot_item ::= id `=` expr | ||
``` | ||
|
||
Note: `expr` in `annot_item` is a parsing requirement but not a semantic one, so e.g., `@(defaultLengthUnit = mm)` is ok and `mm` is interpreted as a unit, not an identifier. | ||
|
||
Inner attributes cannot be applied to outer attributes, but multiple attributes (inner or outer) can be applied to a single item, attributes combine rather than override, precisely how this is handled depends on the attribute handler for the specific attribute. | ||
|
||
### Semantics | ||
|
||
`outer_attr` applies to the surrounding scope, e.g., an outer attributes at the top level of a file applies to the whole module. | ||
|
||
`inner_attr` applies to the following item. | ||
|
||
Values are specified below or may be specified by tools. Incorrect values are warnings (not errors). | ||
|
||
### Initial values | ||
|
||
#### Outer attributes | ||
|
||
- `settings` | ||
- `defaultLengthUnit`: a length unit, `mm`, ... | ||
- `defaultAngleUnit`: an angle unit, `deg`, `rad` | ||
- `attrs`: identifier[], to register consumers of attributes | ||
- `metadata` | ||
- `kclVersion`: a semver string | ||
- `title`: string | ||
- `description`: string | ||
- any other `ident: string` values | ||
- `no_std` - no implicit import of the std prelude | ||
|
||
Possibly: | ||
|
||
- `warnings` | ||
- `allow`: identifier | identifier[], silence warnings (or lints) | ||
- `deny`: identifier | identifier[], make warnings (or lints) into errors | ||
|
||
#### Inner attributes | ||
|
||
- `import` of non-KCL files | ||
- `format`: ident, one of `fbx`, `gltf`, `glb`, `obj`, `ply`, `sldprt`, `step`, `stl` | ||
- `lengthUnit`: a length unit, `mm`, ... | ||
- `coords`: ident, one of `zoo`, `opengl`, `vulkan` | ||
- functions | ||
- `impl`: `kcl` (default) or `std_rust` (body must be empty, implemented in Rust as part of KCL interpreter) | ||
|
||
|
||
### Examples | ||
|
||
``` | ||
@settings(defaultLengthUnit = in, attrs = [fmt]) | ||
|
||
import "foo.kcl" | ||
@(lengthUnit = mm) | ||
import "foo.obj" | ||
|
||
@(impl = std_rust) | ||
fn bar(@sketch, radius: number): Circle {} | ||
|
||
@(fmt = ignore) | ||
fn baz() { | ||
@settings(...) | ||
@fmt(ignore = true) | ||
} | ||
``` | ||
|
||
|
||
## Alternatives | ||
|
||
- `#` and `#!` like Rust but without `[]` | ||
- `#!settings(defaultLengthUnit = in)`, `#(lengthUnit = mm)` | ||
- `#` instead of `@` | ||
- `#settings(defaultLengthUnit = in)`, `#(lengthUnit = mm)` | ||
|
||
``` | ||
#!settings(defaultLengthUnit = in) | ||
|
||
import "foo.kcl" | ||
#(lengthUnit = mm) | ||
import "foo.obj" | ||
|
||
#(impl = std_rust) | ||
fn bar(@sketch, radius: number): Circle {} | ||
|
||
fn baz() { | ||
#!settings(...) | ||
} | ||
``` | ||
|
||
## Issues | ||
|
||
- "Attributes" or "annotations"? I prefer the former, we've been using a mix, but mostly the latter. Other languages use either or both, no consensus. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I'd choose attributes too. It's pretty arbitrary, as long as we stick with one. The only theme I've seen maybe hinted at is that annotations have no runtime effect by default. But it's all just metadata. |
||
- Syntax overlap with `@` for 'self' | ||
- Remove `@` on self-arg once we've finished the kwarg migration | ||
Comment on lines
+117
to
+118
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we remove the An alternative is how Python does it with a separator between positional and named parameters. I don't particularly like this, but it's optimized so that in the common case, the separator is rarely needed at all. For KCL, it would potentially allow us to free up the token. If we need to keep it, couldn't we use basically any other token?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "I thought someone said that we needed a way to distinguish between a regular function and one that has a "self" parameter." - hmm, yeah "If we need to keep it, couldn't we use basically any other token?" - yes |
||
- Discoverability and docs | ||
- settings and attributes on imports are now documented, not sure if we want to document attributes in one place or in many places based on what they do. Some attributes designed for use in the standard library are probably better left undocumented. |
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.
Instead of inner and outer, could we call them item attributes and scope attributes, respectively? Seems clearer.
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 like item attr, but I find 'scope' a bit ambiguous. I was hoping to not use either terminology in user-facing docs, just named/unnamed and explain how they apply