1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
/*
* MRustC - Rust Compiler
* - By John Hodge (Mutabah/thePowersGang)
*
* macro_rules/macro_rules.hpp
* - Macros by example - `macro_rules!`
*/
#ifndef MACROS_HPP_INCLUDED
#define MACROS_HPP_INCLUDED
#include "parse/lex.hpp"
#include "parse/tokentree.hpp"
#include <common.hpp>
#include <map>
#include <memory>
#include <cstring>
#include "macro_rules_ptr.hpp"
#include <set>
class MacroExpander;
TAGGED_UNION_EX(MacroExpansionEnt, (: public Serialisable), Token, (
// TODO: have a "raw" stream instead of just tokens
(Token, Token),
// TODO: Have a flag on `NamedValue` that indicates that it is the only/last usage of this particular value (at this level)
// NOTE: This is a 2:30 bitfield - with the high range indicating $crate
(NamedValue, unsigned int),
(Loop, struct {
/// Contained entries
::std::vector< MacroExpansionEnt> entries;
/// Token used to join iterations
Token joiner;
/// List of variables within this loop that control its iteration count
::std::set< unsigned int> variables;
})
),
(),
(),
(
public:
SERIALISABLE_PROTOTYPES();
)
);
extern ::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x);
/// Matching pattern entry
struct MacroPatEnt:
public Serialisable
{
::std::string name;
unsigned int name_index = 0;
Token tok;
::std::vector<MacroPatEnt> subpats;
enum Type {
PAT_TOKEN, // A token
PAT_LOOP, // $() Enables use of subpats
PAT_TT, // :tt
PAT_PAT, // :pat
PAT_IDENT,
PAT_PATH,
PAT_TYPE,
PAT_EXPR,
PAT_STMT,
PAT_BLOCK,
PAT_META,
PAT_ITEM, // :item
} type;
MacroPatEnt():
tok(TOK_NULL),
type(PAT_TOKEN)
{
}
MacroPatEnt(Token tok):
tok( mv$(tok) ),
type(PAT_TOKEN)
{
}
MacroPatEnt(::std::string name, unsigned int name_index, Type type):
name( mv$(name) ),
name_index( name_index ),
tok(),
type(type)
{
}
MacroPatEnt(Token sep, bool need_once, ::std::vector<MacroPatEnt> ents):
name( need_once ? "+" : "*" ),
tok( mv$(sep) ),
subpats( move(ents) ),
type(PAT_LOOP)
{
}
friend ::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt& x);
friend ::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt::Type& x);
SERIALISABLE_PROTOTYPES();
};
/// An expansion arm within a macro_rules! blcok
struct MacroRulesArm:
public Serialisable
{
/// Names for the parameters
::std::vector< ::std::string> m_param_names;
/// Patterns
::std::vector<MacroPatEnt> m_pattern;
/// Rule contents
::std::vector<MacroExpansionEnt> m_contents;
MacroRulesArm()
{}
MacroRulesArm(::std::vector<MacroPatEnt> pattern, ::std::vector<MacroExpansionEnt> contents):
m_pattern( mv$(pattern) ),
m_contents( mv$(contents) )
{}
MacroRulesArm(const MacroRulesArm&) = delete;
MacroRulesArm& operator=(const MacroRulesArm&) = delete;
MacroRulesArm(MacroRulesArm&&) = default;
MacroRulesArm& operator=(MacroRulesArm&&) = default;
SERIALISABLE_PROTOTYPES();
};
/// A sigle 'macro_rules!' block
class MacroRules:
public Serialisable
{
public:
bool m_exported;
::std::string m_source_crate; // Populated on load, used for $crate
/// Expansion rules
::std::vector<MacroRulesArm> m_rules;
MacroRules()
{
}
virtual ~MacroRules();
MacroRules(MacroRules&&) = default;
SERIALISABLE_PROTOTYPES();
};
extern ::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, const TokenTree& input, AST::Module& mod);
extern MacroRulesPtr Parse_MacroRules(TokenStream& lex);
#endif // MACROS_HPP_INCLUDED
|