5.5 KiB
Function Attribute Parameters
Summary
This RFC proposes a syntax for function attribute parameters. This is a follow up to the Attributes RFC, which proposed a design for function attributes. We only propose a syntactic extension in this RFC; the rest of the implementation details remain unchanged.
Motivation
The Attributes RFC provides a syntax for parameterless function attributes. This suffices for some potential use cases, such as @native
, and @inline
. However, other potential cases such as @deprecated
will benefit from an expressive attribute syntax that allows parameters to be supplied. We can use the parameters to provide the name of the function to be used in place of the deprecated function, and the reason for deprecation. This information can be used to generate informative deprecation warning messages. Another potential use case could be an @unroll
attribute for loop unrolling which could use a numeric parameter for specifying the number of iterations to be unrolled. This would also require supporting attributes on loops, which would be a topic of discussion for a separate RFC.
Design
The following syntax is proposed for attributes:
table ::= '{' [fieldlist] '}'
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= Name '=' literal | literal
fieldsep ::= ',' | ';'
literal ::= 'nil' | 'false' | 'true' | Number | String | table
parattr ::= NAME [literal]
attribute ::= '@' NAME | '@[' parattr {',' parattr} ']'
attributes ::= {attribute}
Attributes can appear before function
and local function
statements, augmenting the allowed statement syntax as follows:
stat ::= attributes 'function' funcname funcbody
stat ::= attributes 'local' 'function' Name funcbody
Attributes can also used in declaration files with the following syntax:
type ::= Type | Name ':' Type
decl ::= attributes 'declare' 'function' '(' {type} ')' : Type
decl ::= 'declare' Name ':' '{' {Name ':' attributes '(' {type} ')' '->' Type} '}'
The primary extension proposed to the Attributes RFC is an attribute list, @[]
, for specifying multiple comma-separated attributes with an optional literal parameter, and, an attribute syntax for declaration files.
The important syntactic features are:
- Attribute lists cannot be empty; they should have at least one attribute.
- Attributes inside attribute lists are separated by a
,
. - Attribute names cannot have a leading
@
inside attribute list. - Attribute lists cannot be nested.
- Attributes cannot be used inside an attribute parameter.
- Only attributes inside attribute lists can take a parameter, standalone attributes cannot.
- An attribute parameter is a Luau literal:
true
,false
,nil
,Number
,String
, or atable
composed of these literals with optional names. A trailing field separator is allowed. - Standalone and list style attributes can be mixed arbitrarily:
@attr1 @[attr2, attr3{2, "hi"}]
,@attr1 @attr2 @[attr3{2, "hi"}]
,@attr1 @[attr3{2, "hi"}] @attr2
, and@[attr1, attr2, attr3{2, "hi"}]
are all legal and equivalent.
Currently there is an ad-hoc implementation of @checked
attribute, used in declaration files. It is specified in two ways:
declare function @checked abs(n: number): number
writef64: @checked (b: buffer, offset: number, value: number) -> ()
According to the syntax proposed in this RFC, the declarations using the first style will be modified to use @checked
attribute before declare
keyword. Declarations in the second style will remain unchanged.
Few important factors went in the design of this syntax:
- Attributes are a mechanism for providing tagged metadata to the implementation. They are not user-extensible and have no evaluation semantics of their own. Hence, an attribute parameter can only be a literal, i.e., a value that evaluates to itself. This is also the reason we disallow entries of the form
[exp1] = [exp2]
in parameter table, since it would require evaluatingexp1
at construction time. - Function-style attribute syntax of the form
@attr({parameters})
were initially considered, but dropped becuase they do not allow us to specify parameter names. The optional table parameter proposed in the current syntax lets use specify multiple parameters as table entries, with and without names. - Using attributes with a table parameter outside attribute list,
@attr {...}
, will create ambiguity when used on tables, should we decide to allow attributes on arbitrary expressions in the future. Hence, the@[]
delimited syntax was chosen to provide a]
delimiter which marks the end of attributes, leaving open the possibility of syntax evolution without introducing parsing ambiguity.
The parser is responsible for for enforcing the syntax specified by this RFC and ensuring that attributes are not repeated on a definition or a declaration. The number and type of parameters accepted by a particular attribute will be specified by its own RFC, and enforced by the relevant component of the implementation (typechecker, compiler, etc.), after parsing.
Drawbacks
Extending attribute syntax to accept parameters contributes to the complexity of the language in the parsing phase.
Alternatives
The alternative would be to not support attribute parameters. This will lead to substandard warning messages from @deprecated
attribute. It would also prevent us from introducing @unroll
attribute in the future.