#[macro]
, the second are marked with #[macro_attribute]
. Macro functions are used in the form of foo!(tokens)
, and attribute macros in the form of #[foo]
or #[foo(tokens)]
, while connecting to the AST node, following the usual rules for using attributes. Attributes #![...]
also supported, in accordance with the obvious semantics (they refer not to the next AST node, but to the parent node - approx. Transl.) . #[macro] pub fn foo(TokenStream, &mut MacroContext) -> TokenStream
#[macro_attribute] pub fn foo(Option<TokenStream>, TokenStream, &mut MacroContext) -> TokenStream
tokens
from #[foo(tokens)]
). The second argument, TokenStream
is the stream of tokens from the AST node to which the macro attribute belongs. The returned TokenStream
replaces the original AST node, and may be zero or more AST nodes (that is, we replace the Modifier
and Decorator
syntax extensions at once).TokenStream
parsed to some valid AST node, while the first can parse, or maybe not.TokenStream
parsed in the context of the macro call.libsyntax
library remains, but it will be a compiler implementation detail: procedural macros should not use it and it will not be marked as stable (that is, stable macros should not use it).libmacro
will provide a fairly low-level interface. We expect containers with higher-level libraries to appear in the ecosystem. In particular, libmacro
will not have the concept of AST. It is expected that containers in a wider ecosystem will provide AST, as well as functionality for parsing tokens in AST, and building AST.libsyntax
) and MacroContext
, passed to macros. Libmacro will include the following functionality:#[feature(name)]
, including various, usually unstable, compiler features — note translator) and setting #[feature(name)]
flags for use during code generation,MacroContext
methods.MacroContext
. mod tokens { use {Span, HygieneObject, InternedString}; pub struct TokenStream(Vec<TokenTree>); impl TokenStream { // Methods for adding and removing tokens, etc. } pub struct TokenTree { pub kind: TokenKind, pub span: Span, pub hygiene: HygieneObject, } pub enum TokenKind { Delimited(Delimiter, Vec<TokenTree>), // String includes the commenting tokens. Comment(String, CommentKind), String(String, StringKind), Dollar, Semicolon, Eof, Word(InternedString), Punctuation(char), } pub enum Delimiter { // { } Brace, // ( ) Parenthesis, // [ ] Bracket, } pub enum CommentKind { Regular, InnerDoc, OuterDoc, } pub enum StringKind { Regular, Raw(usize), Byte, RawByte(usize), } }
We could only store HygieneInformation
for TokenKind::Word
, and not for all tokens. We could also store it for token ranges, and not for each token separately.$
and ;
: dollar is used to designate metavariables in macros, and semicolon to separate elements from each other, so it may be useful to distinguish from. Perhaps we should distinguish !
and #
, as they are used when calling macros, although I can't figure out where this might be useful.TokenTree
or &[TokenTree]
:is_keyword
is_reserved_word
is_special_ident
is_operator
is_ident
is_path
metavariables
- extracts meta variables from TokenStream
, for example for foo($x:ident, $y:expr)
returns [("x", 2 ident), ("y", 6, expr)]
in the form of a certain data structure.MacroContext
performs several roles:libmacro
, which requires the preservation of some state.MacroContext
will be some structure, but I think most of the fields will be private. It is possible that this will be a type.TokenStream
macro arguments also have their own span),libmacro
. The most important functionality includes displaying errors, warnings, etc. This includes the ability to display comments and suggestions on the code, and provide information about spans, based on the tokens available to the macro.libmacro
part by part. As soon as a sufficient part of the functionality becomes stable (and we rewrite the internal syntax extensions to the new system), we will have to remove support for the old syntax extensions.IdentTT
syntax extension, which represents a macro function with an identifier between the macro name and the separator separator. I would like to stop this support. However, it may be useful to emulate some elements (for example my_struct! foo { ... }
). Unfortunately, such an application is unsatisfactory, since it does not support modifiers (like pub my_struct! foo ...
), and some authors want different types of tokens after the macro name when it is called, and not just identifiers. My suggestion is that we should remove this feature at the moment. It can be added in the future with preserving backward compatibility, either by adding a new attribute ( #[macro_with_ident]
), or by adding information to the MacroContext
.MacroContext
somewhat heavy, perhaps it would be better to divide it into several smaller types or structures. However, this may make writing macros less ergonomic.Source: https://habr.com/ru/post/274225/
All Articles