summaryrefslogtreecommitdiff
path: root/src/macro_rules
diff options
context:
space:
mode:
authorJohn Hodge (Mutabah) <acessdev@gmail.com>2016-12-25 17:19:27 +1100
committerGitHub <noreply@github.com>2016-12-25 17:19:27 +1100
commit753a2f44cc4c00b952cddae2ceed066ebb18a470 (patch)
treeed4bbff4be39c44c57164641f4ed32b5ad4675f0 /src/macro_rules
parentd12a8a886caf2e0edf33c1af831b1df990d2c892 (diff)
parent0c14c734fa32014fd24297ccdbed927016185ffd (diff)
downloadmrust-753a2f44cc4c00b952cddae2ceed066ebb18a470.tar.gz
Merge pull request #11 from ubsan/whitespace-fix
No more tears!
Diffstat (limited to 'src/macro_rules')
-rw-r--r--src/macro_rules/eval.cpp178
-rw-r--r--src/macro_rules/macro_rules.hpp324
-rw-r--r--src/macro_rules/macro_rules_ptr.hpp4
-rw-r--r--src/macro_rules/mod.cpp606
-rw-r--r--src/macro_rules/parse.cpp64
5 files changed, 588 insertions, 588 deletions
diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp
index 166dd2cc..11ec74f2 100644
--- a/src/macro_rules/eval.cpp
+++ b/src/macro_rules/eval.cpp
@@ -24,25 +24,25 @@ class ParameterMappings
unsigned int num_used; // Number of times it has been used
InterpolatedFragment frag;
};
-
+
/// A single layer of the capture set
TAGGED_UNION(CaptureLayer, Vals,
(Vals, ::std::vector<CapturedVal>),
(Nested, ::std::vector<CaptureLayer>)
);
-
+
/// Represents the fragments captured for a name
struct CapturedVar
{
CaptureLayer top_layer;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const CapturedVar& x) {
os << "CapturedVar { top_layer: " << x.top_layer << " }";
return os;
}
-
+
};
-
+
::std::vector<CapturedVar> m_mappings;
unsigned m_layer_count;
public:
@@ -51,28 +51,28 @@ public:
{
}
ParameterMappings(ParameterMappings&&) = default;
-
+
const ::std::vector<CapturedVar>& mappings() const { return m_mappings; }
-
+
void dump() const {
DEBUG("m_mappings = {" << m_mappings << "}");
}
-
+
size_t layer_count() const {
return m_layer_count+1;
}
-
+
void insert(unsigned int name_index, const ::std::vector<unsigned int>& iterations, InterpolatedFragment data);
-
+
InterpolatedFragment* get(const ::std::vector<unsigned int>& iterations, unsigned int name_idx);
unsigned int count_in(const ::std::vector<unsigned int>& iterations, unsigned int name_idx) const;
-
+
/// Increment the number of times a particular fragment will be used
void inc_count(const ::std::vector<unsigned int>& iterations, unsigned int name_idx);
/// Decrement the number of times a particular fragment is used (returns true if there are still usages remaining)
bool dec_count(const ::std::vector<unsigned int>& iterations, unsigned int name_idx);
-
-
+
+
friend ::std::ostream& operator<<(::std::ostream& os, const CapturedVal& x) {
os << x.frag;
return os;
@@ -88,7 +88,7 @@ public:
)
return os;
}
-
+
private:
CapturedVal& get_cap(const ::std::vector<unsigned int>& iterations, unsigned int name_idx);
};
@@ -122,10 +122,10 @@ class MacroPatternStream
::std::vector<unsigned int> m_pos;
// Iteration index of each active loop level
::std::vector<unsigned int> m_loop_iterations;
-
+
::std::vector<SimplePatEnt> m_stack;
unsigned int m_skip_count;
-
+
SimplePatEnt m_peek_cache;
bool m_peek_cache_valid = false;
@@ -137,10 +137,10 @@ public:
m_pos({0})
{
}
-
+
/// Get the next pattern entry
SimplePatEnt next();
-
+
const SimplePatEnt& peek() {
if( !m_peek_cache_valid ) {
m_peek_cache = next();
@@ -148,23 +148,23 @@ public:
}
return m_peek_cache;
}
-
+
/// Inform the stream that the `if` rule that was just returned succeeded
void if_succeeded();
/// Get the current loop iteration count
const ::std::vector<unsigned int>& get_loop_iters() const {
return m_loop_iterations;
}
-
+
private:
SimplePatEnt emit_loop_start(const MacroPatEnt& pat);
-
+
SimplePatEnt emit_seq(SimplePatEnt v1, SimplePatEnt v2) {
assert( m_stack.empty() );
m_stack.push_back( mv$(v2) );
return v1;
}
-
+
void break_loop();
};
@@ -188,7 +188,7 @@ void ParameterMappings::insert(unsigned int name_index, const ::std::vector<unsi
for(unsigned int i = 0; i < iterations.size()-1; i ++ )
{
auto iter = iterations[i];
-
+
if( layer->is_Vals() ) {
assert( layer->as_Vals().size() == 0 );
*layer = CaptureLayer::make_Nested({});
@@ -198,7 +198,7 @@ void ParameterMappings::insert(unsigned int name_index, const ::std::vector<unsi
DEBUG("- Skipped iteration " << e.size());
e.push_back( CaptureLayer::make_Nested({}) );
}
-
+
if(e.size() == iter) {
e.push_back( CaptureLayer::make_Vals({}) );
}
@@ -223,7 +223,7 @@ ParameterMappings::CapturedVal& ParameterMappings::get_cap(const ::std::vector<u
auto& e = m_mappings.at(name_idx);
//DEBUG("- e = " << e);
auto* layer = &e.top_layer;
-
+
// - If the top layer is a 1-sized set of values, unconditionally return it
TU_IFLET(CaptureLayer, (*layer), Vals, e,
if( e.size() == 1 ) {
@@ -233,7 +233,7 @@ ParameterMappings::CapturedVal& ParameterMappings::get_cap(const ::std::vector<u
BUG(Span(), "Attempting to get binding for empty capture - #" << name_idx);
}
)
-
+
for(const auto iter : iterations)
{
TU_MATCH(CaptureLayer, (*layer), (e),
@@ -316,28 +316,28 @@ SimplePatEnt MacroPatternStream::next()
{
TRACE_FUNCTION_F("m_pos=[" << m_pos << "], m_stack.size()=" << m_stack.size());
assert(m_pos.size() >= 1);
-
+
if( m_peek_cache_valid ) {
m_peek_cache_valid = false;
return mv$(m_peek_cache);
}
-
+
// Pop off the generation stack
if( ! m_stack.empty() ) {
auto rv = mv$(m_stack.back());
m_stack.pop_back();
return rv;
}
-
+
if( m_break_if_not && ! m_condition_fired ) {
// Break out of the current loop then continue downwards.
break_loop();
}
-
+
m_skip_count = 0;
m_break_if_not = false;
m_condition_fired = false;
-
+
const MacroPatEnt* parent_pat = nullptr;
decltype(m_pattern) parent_ents = nullptr;
const auto* ents = m_pattern;
@@ -351,18 +351,18 @@ SimplePatEnt MacroPatternStream::next()
parent_ents = ents;
ents = &parent_pat->subpats;
}
-
+
DEBUG( (m_pos.size()-1) << " " << m_pos.back() << " / " << ents->size());
if( m_pos.back() < ents->size() )
{
const auto& pat = ents->at( m_pos.back() );
-
+
if( pat.type == MacroPatEnt::PAT_LOOP ) {
DEBUG("Enter " << pat);
// Increase level, return entry control
m_pos.push_back( 0 );
m_loop_iterations.push_back( 0 );
-
+
if( pat.name == "*" )
{
return emit_loop_start(pat);
@@ -391,7 +391,7 @@ SimplePatEnt MacroPatternStream::next()
// - Reset the loop back to the start
m_pos.back() = 0;
m_loop_iterations.back() += 1;
-
+
// - Emit break conditions
if( parent_pat->tok == TOK_NULL ) {
// Loop separator is TOK_NULL - get the first token of the loop and use it.
@@ -437,17 +437,17 @@ namespace {
void get_loop_entry_pats(const MacroPatEnt& pat, ::std::vector<const MacroPatEnt*>& entry_pats)
{
assert( pat.type == MacroPatEnt::PAT_LOOP );
-
+
// If this pattern is a loop, get the entry concrete patterns for it
- // - Otherwise, just
+ // - Otherwise, just
unsigned int i = 0;
while( i < pat.subpats.size() && pat.subpats[i].type == MacroPatEnt::PAT_LOOP )
{
const auto& cur_pat = pat.subpats[i];
bool is_optional = (cur_pat.name == "*");
-
+
get_loop_entry_pats(cur_pat, entry_pats);
-
+
if( !is_optional )
{
// Non-optional loop, MUST be entered, so return after recursing
@@ -456,7 +456,7 @@ namespace {
// Optional, so continue the loop.
i ++;
}
-
+
// First non-loop pattern
if( i < pat.subpats.size() )
{
@@ -471,10 +471,10 @@ SimplePatEnt MacroPatternStream::emit_loop_start(const MacroPatEnt& pat)
{
// Find the next non-loop pattern to control if this loop should be entered
::std::vector<const MacroPatEnt*> m_entry_pats;
-
+
get_loop_entry_pats(pat, m_entry_pats);
DEBUG("m_entry_pats = [" << FMT_CB(ss, for(const auto* p : m_entry_pats) { ss << *p << ","; }) << "]");
-
+
struct H {
static SimplePatEnt get_if(bool flag, const MacroPatEnt& mpe) {
if( mpe.type == MacroPatEnt::PAT_TOKEN )
@@ -483,7 +483,7 @@ SimplePatEnt MacroPatternStream::emit_loop_start(const MacroPatEnt& pat)
return SimplePatEnt::make_IfPat({ flag, mpe.type });
}
};
-
+
const auto* entry_pat = m_entry_pats.back();
m_entry_pats.pop_back();
if( m_entry_pats.size() > 0 )
@@ -521,13 +521,13 @@ void MacroPatternStream::break_loop()
assert( m_pos.size() >= 1 );
// - This should never be called when on the top level
assert( m_pos.size() != 1 );
-
+
// HACK: Clear the stack if an if succeeded
m_stack.clear();
-
+
m_pos.pop_back();
m_pos.back() += 1 + m_skip_count;
-
+
m_loop_iterations.pop_back();
}
@@ -546,10 +546,10 @@ class MacroExpandState
/// Layer states : Index and Iteration
::std::vector< t_offset > m_offsets;
::std::vector< unsigned int> m_iterations;
-
+
/// Cached pointer to the current layer
const ::std::vector<MacroExpansionEnt>* m_cur_ents; // For faster lookup.
-
+
public:
MacroExpandState(const ::std::vector<MacroExpansionEnt>& contents, const ParameterMappings& mappings):
m_root_contents(contents),
@@ -558,11 +558,11 @@ public:
m_cur_ents(&m_root_contents)
{
}
-
+
// Returns a pointer to the next entry to expand, or nullptr if the end is reached
// - NOTE: When a Loop entry is returned, the separator token should be emitted
const MacroExpansionEnt* next_ent();
-
+
const ::std::vector<unsigned int> iterations() const { return m_iterations; }
unsigned int top_pos() const { return m_offsets[0].read_pos; }
@@ -577,17 +577,17 @@ class MacroExpander:
const RcString m_macro_filename;
const ::std::string m_crate_name;
-
+
ParameterMappings m_mappings;
MacroExpandState m_state;
-
+
Token m_next_token; // used for inserting a single token into the stream
::std::unique_ptr<TTStreamO> m_ttstream;
Ident::Hygiene m_hygiene;
-
+
public:
MacroExpander(const MacroExpander& x) = delete;
-
+
MacroExpander(const ::std::string& macro_name, const Ident::Hygiene& parent_hygiene, const ::std::vector<MacroExpansionEnt>& contents, ParameterMappings mappings, ::std::string crate_name):
m_macro_filename( FMT("Macro:" << macro_name) ),
m_crate_name( mv$(crate_name) ),
@@ -683,7 +683,7 @@ InterpolatedFragment Macro_HandlePatternCap(TokenStream& lex, MacroPatEnt::Type
BUG(lex.getPosition(), "Encountered PAT_TOKEN when handling capture");
case MacroPatEnt::PAT_LOOP:
BUG(lex.getPosition(), "Encountered PAT_LOOP when handling capture");
-
+
case MacroPatEnt::PAT_TT:
if( GET_TOK(tok, lex) == TOK_EOF )
throw ParseError::Unexpected(lex, TOK_EOF);
@@ -725,24 +725,24 @@ InterpolatedFragment Macro_HandlePatternCap(TokenStream& lex, MacroPatEnt::Type
::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, TokenTree input, AST::Module& mod)
{
TRACE_FUNCTION_F("'" << name << "', " << input);
-
+
ParameterMappings bound_tts;
unsigned int rule_index = Macro_InvokeRules_MatchPattern(rules, mv$(input), mod, bound_tts);
-
+
const auto& rule = rules.m_rules.at(rule_index);
-
+
DEBUG( rule.m_contents.size() << " rule contents with " << bound_tts.mappings().size() << " bound values - " << name );
for( unsigned int i = 0; i < ::std::min( bound_tts.mappings().size(), rule.m_param_names.size() ); i ++ )
{
DEBUG("- #" << i << " " << rule.m_param_names.at(i) << " = [" << bound_tts.mappings()[i] << "]");
}
//bound_tts.dump();
-
+
// Run through the expansion counting the number of times each fragment is used
Macro_InvokeRules_CountSubstUses(bound_tts, rule.m_contents);
-
+
TokenStream* ret_ptr = new MacroExpander(name, rules.m_hygiene, rule.m_contents, mv$(bound_tts), rules.m_source_crate);
-
+
return ::std::unique_ptr<TokenStream>( ret_ptr );
}
@@ -750,7 +750,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
{
TRACE_FUNCTION;
Span sp;// = input.span();
-
+
struct Capture {
unsigned int binding_idx;
::std::vector<unsigned int> iterations;
@@ -768,10 +768,10 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
{
active_arms.push_back( ActiveArm { i, {}, MacroPatternStream(rules.m_rules[i].m_pattern) } );
}
-
+
// - List of captured values
::std::vector<InterpolatedFragment> captures;
-
+
TTStreamO lex( mv$(input) );
SET_MODULE(lex, mod);
while(true)
@@ -783,7 +783,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
{
auto idx = arm.index;
SimplePatEnt pat;
- // Consume all If* rules
+ // Consume all If* rules
do
{
pat = arm.stream.next();
@@ -809,7 +809,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
break;
}
} while( pat.is_IfPat() || pat.is_IfTok() );
-
+
TU_MATCH( SimplePatEnt, (pat), (e),
(IfPat, BUG(sp, "IfTok unexpected here");),
(IfTok, BUG(sp, "IfTok unexpected here");),
@@ -826,14 +826,14 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
arm_pats.push_back( mv$(pat) );
}
assert( arm_pats.size() == active_arms.size() );
-
+
// 2. Prune imposible arms
for(unsigned int i = 0, j = 0; i < arm_pats.size(); )
{
auto idx = active_arms[i].index;
const auto& pat = arm_pats[i];
bool fail = false;
-
+
TU_MATCH( SimplePatEnt, (pat), (e),
(IfPat, BUG(sp, "IfTok unexpected here");),
(IfTok, BUG(sp, "IfTok unexpected here");),
@@ -862,12 +862,12 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
}
j ++;
}
-
+
if( arm_pats.size() == 0 ) {
auto tok = lex.getToken();
ERROR(tok.get_pos(), E0000, "No rules expected " << tok);
}
-
+
// 3. If there is a token pattern in the list, take that arm (and any other token arms)
const SimplePatEnt* tok_pat = nullptr;
unsigned int ident_pat_idx = arm_pats.size();
@@ -893,7 +893,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
}
)
}
-
+
if( tok_pat )
{
auto tok = lex.getToken();
@@ -936,7 +936,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
(End, TODO(sp, "Handle End following a conflicting :ident"); )
)
}
-
+
if( discard ) {
arm_pats.erase( arm_pats.begin() + i );
active_arms.erase( active_arms.begin() + i );
@@ -945,7 +945,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
++ i;
}
}
-
+
// If there are any remaining ident rules, erase the non-ident rules.
if( ident_rule_kept ) {
// If no rules were discarded, remove the non-ident rules
@@ -963,7 +963,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
assert(arm_pats.size() > 0);
assert(arm_pats.size() == active_arms.size());
}
-
+
// 3. Check that all remaining arms are the same pattern.
const auto& active_pat = arm_pats[0];
for(unsigned int i = 1; i < arm_pats.size(); i ++)
@@ -990,7 +990,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
)
)
}
-
+
// 4. Apply patterns.
TU_MATCH( SimplePatEnt, (arm_pats[0]), (e),
(End,
@@ -1025,9 +1025,9 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
}
}
};
-
+
auto cap = Macro_HandlePatternCap(lex, e.type);
-
+
unsigned int cap_idx = captures.size();
captures.push_back( mv$(cap) );
for(unsigned int i = 0; i < active_arms.size(); i ++)
@@ -1039,7 +1039,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
)
)
}
-
+
// Keep looping - breakout is handled in 'End' above
}
}
@@ -1048,7 +1048,7 @@ void Macro_InvokeRules_CountSubstUses(ParameterMappings& bound_tts, const ::std:
{
TRACE_FUNCTION;
MacroExpandState state(contents, bound_tts);
-
+
while(const auto* ent_ptr = state.next_ent())
{
DEBUG(*ent_ptr);
@@ -1096,7 +1096,7 @@ Token MacroExpander::realGetToken()
return rv;
m_ttstream.reset();
}
-
+
// Loop to handle case where $crate expands to nothing
while( const auto* next_ent_ptr = m_state.next_ent() )
{
@@ -1125,7 +1125,7 @@ Token MacroExpander::realGetToken()
else {
auto* frag = m_mappings.get(m_state.iterations(), e);
ASSERT_BUG(this->getPosition(), frag, "Cannot find '" << e << "' for " << m_state.iterations());
-
+
bool can_steal = ( m_mappings.dec_count(m_state.iterations(), e) == false );
DEBUG("Insert replacement #" << e << " = " << *frag);
if( frag->m_type == InterpolatedFragment::TT )
@@ -1162,7 +1162,7 @@ Token MacroExpander::realGetToken()
throw "";
}
}
-
+
DEBUG("EOF");
return Token(TOK_EOF);
}
@@ -1176,10 +1176,10 @@ const MacroExpansionEnt* MacroExpandState::next_ent()
{
unsigned int layer = m_offsets.size() - 1;
const auto& ents = *m_cur_ents;
-
+
// Obtain current read position in layer, and increment
size_t idx = m_offsets.back().read_pos++;
-
+
// Check if limit has been reached
if( idx < ents.size() )
{
@@ -1230,11 +1230,11 @@ const MacroExpansionEnt* MacroExpandState::next_ent()
if( cur_ofs.loop_index + 1 < cur_ofs.max_index )
{
m_iterations.back() ++;
-
+
DEBUG("Restart layer");
cur_ofs.read_pos = 0;
cur_ofs.loop_index ++;
-
+
auto& loop_layer = getCurLayerEnt();
if( loop_layer.as_Loop().joiner.type() != TOK_NULL ) {
DEBUG("- Separator token = " << loop_layer.as_Loop().joiner);
@@ -1261,14 +1261,14 @@ const MacroExpansionEnt* MacroExpandState::next_ent()
assert( m_offsets.size() == 0 );
}
} // while( m_offsets NONEMPTY )
-
+
return nullptr;
}
const MacroExpansionEnt& MacroExpandState::getCurLayerEnt() const
{
assert( m_offsets.size() > 1 );
-
+
const auto* ents = &m_root_contents;
for( unsigned int i = 0; i < m_offsets.size()-2; i ++ )
{
@@ -1277,7 +1277,7 @@ const MacroExpansionEnt& MacroExpandState::getCurLayerEnt() const
ents = &(*ents)[ofs-1].as_Loop().entries;
}
return (*ents)[m_offsets[m_offsets.size()-2].read_pos-1];
-
+
}
const ::std::vector<MacroExpansionEnt>* MacroExpandState::getCurLayer() const
{
diff --git a/src/macro_rules/macro_rules.hpp b/src/macro_rules/macro_rules.hpp
index 337a4707..aed0e8ce 100644
--- a/src/macro_rules/macro_rules.hpp
+++ b/src/macro_rules/macro_rules.hpp
@@ -1,162 +1,162 @@
-/*
- * 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
- /// Boolean is true if the variable will be unconditionally expanded
- ::std::map< unsigned int, bool> 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:
- /// Marks if this macro should be exported from the defining crate
- bool m_exported = false;
-
- /// Crate that defined this macro
- /// - Populated on deserialise if not already set
- ::std::string m_source_crate;
-
- Ident::Hygiene m_hygiene;
-
- /// 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, TokenTree input, AST::Module& mod);
-extern MacroRulesPtr Parse_MacroRules(TokenStream& lex);
-
-#endif // MACROS_HPP_INCLUDED
+/*
+ * 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
+ /// Boolean is true if the variable will be unconditionally expanded
+ ::std::map< unsigned int, bool> 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:
+ /// Marks if this macro should be exported from the defining crate
+ bool m_exported = false;
+
+ /// Crate that defined this macro
+ /// - Populated on deserialise if not already set
+ ::std::string m_source_crate;
+
+ Ident::Hygiene m_hygiene;
+
+ /// 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, TokenTree input, AST::Module& mod);
+extern MacroRulesPtr Parse_MacroRules(TokenStream& lex);
+
+#endif // MACROS_HPP_INCLUDED
diff --git a/src/macro_rules/macro_rules_ptr.hpp b/src/macro_rules/macro_rules_ptr.hpp
index c5c01488..fdb01fbe 100644
--- a/src/macro_rules/macro_rules_ptr.hpp
+++ b/src/macro_rules/macro_rules_ptr.hpp
@@ -25,9 +25,9 @@ public:
m_ptr = x.m_ptr; x.m_ptr = nullptr;
return *this;
}
-
+
~MacroRulesPtr();
-
+
const MacroRules& operator*() const { assert(m_ptr); return *m_ptr; }
MacroRules& operator*() { assert(m_ptr); return *m_ptr; }
const MacroRules* operator->() const { assert(m_ptr); return m_ptr; }
diff --git a/src/macro_rules/mod.cpp b/src/macro_rules/mod.cpp
index 2803b061..f685f6dc 100644
--- a/src/macro_rules/mod.cpp
+++ b/src/macro_rules/mod.cpp
@@ -1,303 +1,303 @@
-/*
- */
-#include <common.hpp>
-#include "macro_rules.hpp"
-#include <parse/parseerror.hpp>
-#include <parse/tokentree.hpp>
-#include <parse/common.hpp>
-#include <limits.h>
-
-#include "pattern_checks.hpp"
-
-bool is_token_path(eTokenType tt) {
- switch(tt)
- {
- case TOK_IDENT:
- case TOK_DOUBLE_COLON:
- case TOK_LT:
- case TOK_DOUBLE_LT:
- case TOK_RWORD_SELF:
- case TOK_RWORD_SUPER:
- case TOK_INTERPOLATED_PATH:
- return true;
- default:
- return false;
- }
-}
-bool is_token_pat(eTokenType tt) {
- if( is_token_path(tt) )
- return true;
- switch( tt )
- {
- case TOK_PAREN_OPEN:
- case TOK_SQUARE_OPEN:
-
- case TOK_UNDERSCORE:
- case TOK_AMP:
- case TOK_RWORD_BOX:
- case TOK_RWORD_REF:
- case TOK_RWORD_MUT:
- case TOK_STRING:
- case TOK_INTEGER:
- case TOK_CHAR:
- case TOK_INTERPOLATED_PATTERN:
- return true;
- default:
- return false;
- }
-}
-bool is_token_type(eTokenType tt) {
- if( is_token_path(tt) )
- return true;
- switch( tt )
- {
- case TOK_PAREN_OPEN:
- case TOK_SQUARE_OPEN:
- case TOK_STAR:
- case TOK_AMP:
- case TOK_RWORD_EXTERN:
- case TOK_RWORD_UNSAFE:
- case TOK_RWORD_FN:
- case TOK_INTERPOLATED_TYPE:
- return true;
- default:
- return false;
- }
-}
-bool is_token_expr(eTokenType tt) {
- if( is_token_path(tt) )
- return true;
- switch( tt )
- {
- // Leading unary operators
- case TOK_AMP: // Borrow
- case TOK_STAR: // Deref
- case TOK_DASH: // Negate
- case TOK_EXCLAM: // Invert
- case TOK_RWORD_BOX: // Box
- // Composite values
- case TOK_MACRO:
- case TOK_PAREN_OPEN: // Parenthesised
- case TOK_SQUARE_OPEN: // Array
-
- // Flow
- case TOK_RWORD_RETURN:
- case TOK_RWORD_BREAK:
- case TOK_RWORD_CONTINUE:
-
- // Blocks
- case TOK_BRACE_OPEN:
- case TOK_RWORD_MATCH:
- case TOK_RWORD_IF:
- case TOK_RWORD_FOR:
- case TOK_RWORD_WHILE:
- case TOK_RWORD_LOOP:
- case TOK_RWORD_UNSAFE:
-
- // Closures
- case TOK_RWORD_MOVE:
- case TOK_PIPE:
- case TOK_DOUBLE_PIPE:
-
- // Literal tokens
- case TOK_INTEGER:
- case TOK_FLOAT:
- case TOK_STRING:
- case TOK_BYTESTRING:
- case TOK_RWORD_TRUE:
- case TOK_RWORD_FALSE:
-
- case TOK_INTERPOLATED_EXPR:
- return true;
- default:
- return false;
- }
-}
-bool is_token_stmt(eTokenType tt) {
- if( is_token_expr(tt) )
- return true;
- switch( tt )
- {
- case TOK_BRACE_OPEN:
- case TOK_RWORD_LET:
- case TOK_INTERPOLATED_STMT:
- return true;
- default:
- return false;
- }
-}
-
-bool is_token_item(eTokenType tt) {
- switch( tt )
- {
- case TOK_ATTR_OPEN:
-
- case TOK_RWORD_PUB:
- case TOK_RWORD_UNSAFE:
- case TOK_RWORD_TYPE:
- case TOK_RWORD_CONST:
- case TOK_RWORD_STATIC:
- case TOK_RWORD_FN:
- case TOK_RWORD_STRUCT:
- case TOK_RWORD_ENUM:
- case TOK_RWORD_TRAIT:
- case TOK_RWORD_MOD:
- case TOK_RWORD_USE:
- case TOK_RWORD_EXTERN:
- case TOK_RWORD_IMPL:
- // TODO: more?
- case TOK_INTERPOLATED_ITEM:
- return true;
- default:
- return false;
- }
-}
-
-MacroRulesPtr::~MacroRulesPtr()
-{
- if(m_ptr)
- {
- delete m_ptr;
- m_ptr = nullptr;
- }
-}
-
-SERIALISE_TYPE_S(MacroRulesArm, {
-})
-
-void operator%(Serialiser& s, MacroPatEnt::Type c) {
- switch(c) {
- #define _(v) case MacroPatEnt::v: s << #v; return
- _(PAT_TOKEN);
- _(PAT_TT);
- _(PAT_PAT);
- _(PAT_TYPE);
- _(PAT_EXPR);
- _(PAT_LOOP);
- _(PAT_STMT);
- _(PAT_PATH);
- _(PAT_BLOCK);
- _(PAT_META);
- _(PAT_ITEM);
- _(PAT_IDENT);
- #undef _
- }
-}
-void operator%(::Deserialiser& s, MacroPatEnt::Type& c) {
- ::std::string n;
- s.item(n);
- #define _(v) else if(n == #v) c = MacroPatEnt::v
- if(0) ;
- _(PAT_TOKEN);
- _(PAT_TT);
- _(PAT_PAT);
- _(PAT_TYPE);
- _(PAT_EXPR);
- _(PAT_LOOP);
- //_(PAT_OPTLOOP);
- _(PAT_STMT);
- _(PAT_PATH);
- _(PAT_BLOCK);
- _(PAT_META);
- _(PAT_IDENT);
- _(PAT_ITEM);
- else
- throw ::std::runtime_error( FMT("No conversion for '" << n << "'") );
- #undef _
-}
-SERIALISE_TYPE_S(MacroPatEnt, {
- s % type;
- s.item(name);
- s.item(tok);
- s.item(subpats);
-});
-::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt& x)
-{
- switch(x.type)
- {
- case MacroPatEnt::PAT_TOKEN: os << "=" << x.tok; break;
- case MacroPatEnt::PAT_LOOP: os << "loop w/ " << x.tok << " [" << x.subpats << "]"; break;
- default:
- os << "$" << x.name << ":";
- switch(x.type)
- {
- case MacroPatEnt::PAT_TOKEN: throw "";
- case MacroPatEnt::PAT_LOOP: throw "";
- case MacroPatEnt::PAT_TT: os << "tt"; break;
- case MacroPatEnt::PAT_PAT: os << "pat"; break;
- case MacroPatEnt::PAT_IDENT: os << "ident"; break;
- case MacroPatEnt::PAT_PATH: os << "path"; break;
- case MacroPatEnt::PAT_TYPE: os << "type"; break;
- case MacroPatEnt::PAT_EXPR: os << "expr"; break;
- case MacroPatEnt::PAT_STMT: os << "stmt"; break;
- case MacroPatEnt::PAT_BLOCK: os << "block"; break;
- case MacroPatEnt::PAT_META: os << "meta"; break;
- case MacroPatEnt::PAT_ITEM: os << "item"; break;
- }
- break;
- }
- return os;
-}
-::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt::Type& x)
-{
- switch(x)
- {
- case MacroPatEnt::PAT_TOKEN: os << "PAT_TOKEN"; break;
- case MacroPatEnt::PAT_LOOP: os << "PAT_LOOP"; break;
- case MacroPatEnt::PAT_TT: os << "PAT_TT"; break;
- case MacroPatEnt::PAT_PAT: os << "PAT_PAT"; break;
- case MacroPatEnt::PAT_IDENT: os << "PAT_IDENT"; break;
- case MacroPatEnt::PAT_PATH: os << "PAT_PATH"; break;
- case MacroPatEnt::PAT_TYPE: os << "PAT_TYPE"; break;
- case MacroPatEnt::PAT_EXPR: os << "PAT_EXPR"; break;
- case MacroPatEnt::PAT_STMT: os << "PAT_STMT"; break;
- case MacroPatEnt::PAT_BLOCK: os << "PAT_BLOCK"; break;
- case MacroPatEnt::PAT_META: os << "PAT_META"; break;
- case MacroPatEnt::PAT_ITEM: os << "PAT_ITEM"; break;
- }
- return os;
-}
-
-SERIALISE_TU(MacroExpansionEnt, "MacroExpansionEnt", e,
-(Token,
- s.item(e);
- ),
-(NamedValue,
- s.item(e);
- ),
-(Loop,
- s.item(e.entries);
- s.item(e.joiner);
- //s.item(e.variables);
- )
-);
-
-::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x)
-{
- TU_MATCH( MacroExpansionEnt, (x), (e),
- (Token,
- os << "=" << e;
- ),
- (NamedValue,
- if( e >> 30 ) {
- os << "$crate";
- }
- else {
- os << "$" << e;
- }
- ),
- (Loop,
- os << "${" << *e.variables.begin() << "}(" << e.entries << ") " << e.joiner;
- )
- )
- return os;
-}
-
-MacroRules::~MacroRules()
-{
-}
-SERIALISE_TYPE_S(MacroRules, {
- s.item( m_exported );
- s.item( m_rules );
-});
-
+/*
+ */
+#include <common.hpp>
+#include "macro_rules.hpp"
+#include <parse/parseerror.hpp>
+#include <parse/tokentree.hpp>
+#include <parse/common.hpp>
+#include <limits.h>
+
+#include "pattern_checks.hpp"
+
+bool is_token_path(eTokenType tt) {
+ switch(tt)
+ {
+ case TOK_IDENT:
+ case TOK_DOUBLE_COLON:
+ case TOK_LT:
+ case TOK_DOUBLE_LT:
+ case TOK_RWORD_SELF:
+ case TOK_RWORD_SUPER:
+ case TOK_INTERPOLATED_PATH:
+ return true;
+ default:
+ return false;
+ }
+}
+bool is_token_pat(eTokenType tt) {
+ if( is_token_path(tt) )
+ return true;
+ switch( tt )
+ {
+ case TOK_PAREN_OPEN:
+ case TOK_SQUARE_OPEN:
+
+ case TOK_UNDERSCORE:
+ case TOK_AMP:
+ case TOK_RWORD_BOX:
+ case TOK_RWORD_REF:
+ case TOK_RWORD_MUT:
+ case TOK_STRING:
+ case TOK_INTEGER:
+ case TOK_CHAR:
+ case TOK_INTERPOLATED_PATTERN:
+ return true;
+ default:
+ return false;
+ }
+}
+bool is_token_type(eTokenType tt) {
+ if( is_token_path(tt) )
+ return true;
+ switch( tt )
+ {
+ case TOK_PAREN_OPEN:
+ case TOK_SQUARE_OPEN:
+ case TOK_STAR:
+ case TOK_AMP:
+ case TOK_RWORD_EXTERN:
+ case TOK_RWORD_UNSAFE:
+ case TOK_RWORD_FN:
+ case TOK_INTERPOLATED_TYPE:
+ return true;
+ default:
+ return false;
+ }
+}
+bool is_token_expr(eTokenType tt) {
+ if( is_token_path(tt) )
+ return true;
+ switch( tt )
+ {
+ // Leading unary operators
+ case TOK_AMP: // Borrow
+ case TOK_STAR: // Deref
+ case TOK_DASH: // Negate
+ case TOK_EXCLAM: // Invert
+ case TOK_RWORD_BOX: // Box
+ // Composite values
+ case TOK_MACRO:
+ case TOK_PAREN_OPEN: // Parenthesised
+ case TOK_SQUARE_OPEN: // Array
+
+ // Flow
+ case TOK_RWORD_RETURN:
+ case TOK_RWORD_BREAK:
+ case TOK_RWORD_CONTINUE:
+
+ // Blocks
+ case TOK_BRACE_OPEN:
+ case TOK_RWORD_MATCH:
+ case TOK_RWORD_IF:
+ case TOK_RWORD_FOR:
+ case TOK_RWORD_WHILE:
+ case TOK_RWORD_LOOP:
+ case TOK_RWORD_UNSAFE:
+
+ // Closures
+ case TOK_RWORD_MOVE:
+ case TOK_PIPE:
+ case TOK_DOUBLE_PIPE:
+
+ // Literal tokens
+ case TOK_INTEGER:
+ case TOK_FLOAT:
+ case TOK_STRING:
+ case TOK_BYTESTRING:
+ case TOK_RWORD_TRUE:
+ case TOK_RWORD_FALSE:
+
+ case TOK_INTERPOLATED_EXPR:
+ return true;
+ default:
+ return false;
+ }
+}
+bool is_token_stmt(eTokenType tt) {
+ if( is_token_expr(tt) )
+ return true;
+ switch( tt )
+ {
+ case TOK_BRACE_OPEN:
+ case TOK_RWORD_LET:
+ case TOK_INTERPOLATED_STMT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool is_token_item(eTokenType tt) {
+ switch( tt )
+ {
+ case TOK_ATTR_OPEN:
+
+ case TOK_RWORD_PUB:
+ case TOK_RWORD_UNSAFE:
+ case TOK_RWORD_TYPE:
+ case TOK_RWORD_CONST:
+ case TOK_RWORD_STATIC:
+ case TOK_RWORD_FN:
+ case TOK_RWORD_STRUCT:
+ case TOK_RWORD_ENUM:
+ case TOK_RWORD_TRAIT:
+ case TOK_RWORD_MOD:
+ case TOK_RWORD_USE:
+ case TOK_RWORD_EXTERN:
+ case TOK_RWORD_IMPL:
+ // TODO: more?
+ case TOK_INTERPOLATED_ITEM:
+ return true;
+ default:
+ return false;
+ }
+}
+
+MacroRulesPtr::~MacroRulesPtr()
+{
+ if(m_ptr)
+ {
+ delete m_ptr;
+ m_ptr = nullptr;
+ }
+}
+
+SERIALISE_TYPE_S(MacroRulesArm, {
+})
+
+void operator%(Serialiser& s, MacroPatEnt::Type c) {
+ switch(c) {
+ #define _(v) case MacroPatEnt::v: s << #v; return
+ _(PAT_TOKEN);
+ _(PAT_TT);
+ _(PAT_PAT);
+ _(PAT_TYPE);
+ _(PAT_EXPR);
+ _(PAT_LOOP);
+ _(PAT_STMT);
+ _(PAT_PATH);
+ _(PAT_BLOCK);
+ _(PAT_META);
+ _(PAT_ITEM);
+ _(PAT_IDENT);
+ #undef _
+ }
+}
+void operator%(::Deserialiser& s, MacroPatEnt::Type& c) {
+ ::std::string n;
+ s.item(n);
+ #define _(v) else if(n == #v) c = MacroPatEnt::v
+ if(0) ;
+ _(PAT_TOKEN);
+ _(PAT_TT);
+ _(PAT_PAT);
+ _(PAT_TYPE);
+ _(PAT_EXPR);
+ _(PAT_LOOP);
+ //_(PAT_OPTLOOP);
+ _(PAT_STMT);
+ _(PAT_PATH);
+ _(PAT_BLOCK);
+ _(PAT_META);
+ _(PAT_IDENT);
+ _(PAT_ITEM);
+ else
+ throw ::std::runtime_error( FMT("No conversion for '" << n << "'") );
+ #undef _
+}
+SERIALISE_TYPE_S(MacroPatEnt, {
+ s % type;
+ s.item(name);
+ s.item(tok);
+ s.item(subpats);
+});
+::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt& x)
+{
+ switch(x.type)
+ {
+ case MacroPatEnt::PAT_TOKEN: os << "=" << x.tok; break;
+ case MacroPatEnt::PAT_LOOP: os << "loop w/ " << x.tok << " [" << x.subpats << "]"; break;
+ default:
+ os << "$" << x.name << ":";
+ switch(x.type)
+ {
+ case MacroPatEnt::PAT_TOKEN: throw "";
+ case MacroPatEnt::PAT_LOOP: throw "";
+ case MacroPatEnt::PAT_TT: os << "tt"; break;
+ case MacroPatEnt::PAT_PAT: os << "pat"; break;
+ case MacroPatEnt::PAT_IDENT: os << "ident"; break;
+ case MacroPatEnt::PAT_PATH: os << "path"; break;
+ case MacroPatEnt::PAT_TYPE: os << "type"; break;
+ case MacroPatEnt::PAT_EXPR: os << "expr"; break;
+ case MacroPatEnt::PAT_STMT: os << "stmt"; break;
+ case MacroPatEnt::PAT_BLOCK: os << "block"; break;
+ case MacroPatEnt::PAT_META: os << "meta"; break;
+ case MacroPatEnt::PAT_ITEM: os << "item"; break;
+ }
+ break;
+ }
+ return os;
+}
+::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt::Type& x)
+{
+ switch(x)
+ {
+ case MacroPatEnt::PAT_TOKEN: os << "PAT_TOKEN"; break;
+ case MacroPatEnt::PAT_LOOP: os << "PAT_LOOP"; break;
+ case MacroPatEnt::PAT_TT: os << "PAT_TT"; break;
+ case MacroPatEnt::PAT_PAT: os << "PAT_PAT"; break;
+ case MacroPatEnt::PAT_IDENT: os << "PAT_IDENT"; break;
+ case MacroPatEnt::PAT_PATH: os << "PAT_PATH"; break;
+ case MacroPatEnt::PAT_TYPE: os << "PAT_TYPE"; break;
+ case MacroPatEnt::PAT_EXPR: os << "PAT_EXPR"; break;
+ case MacroPatEnt::PAT_STMT: os << "PAT_STMT"; break;
+ case MacroPatEnt::PAT_BLOCK: os << "PAT_BLOCK"; break;
+ case MacroPatEnt::PAT_META: os << "PAT_META"; break;
+ case MacroPatEnt::PAT_ITEM: os << "PAT_ITEM"; break;
+ }
+ return os;
+}
+
+SERIALISE_TU(MacroExpansionEnt, "MacroExpansionEnt", e,
+(Token,
+ s.item(e);
+ ),
+(NamedValue,
+ s.item(e);
+ ),
+(Loop,
+ s.item(e.entries);
+ s.item(e.joiner);
+ //s.item(e.variables);
+ )
+);
+
+::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x)
+{
+ TU_MATCH( MacroExpansionEnt, (x), (e),
+ (Token,
+ os << "=" << e;
+ ),
+ (NamedValue,
+ if( e >> 30 ) {
+ os << "$crate";
+ }
+ else {
+ os << "$" << e;
+ }
+ ),
+ (Loop,
+ os << "${" << *e.variables.begin() << "}(" << e.entries << ") " << e.joiner;
+ )
+ )
+ return os;
+}
+
+MacroRules::~MacroRules()
+{
+}
+SERIALISE_TYPE_S(MacroRules, {
+ s.item( m_exported );
+ s.item( m_rules );
+});
+
diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp
index 4da91a90..fa82e0e0 100644
--- a/src/macro_rules/parse.cpp
+++ b/src/macro_rules/parse.cpp
@@ -26,9 +26,9 @@ public:
{
TRACE_FUNCTION;
Token tok;
-
+
::std::vector<MacroPatEnt> ret;
-
+
int depth = 0;
while( GET_TOK(tok, lex) != close || depth > 0 )
{
@@ -42,7 +42,7 @@ public:
throw ParseError::Generic(FMT("Unmatched " << Token(close) << " in macro pattern"));
depth --;
}
-
+
switch(tok.type())
{
case TOK_DOLLAR:
@@ -53,11 +53,11 @@ public:
GET_CHECK_TOK(tok, lex, TOK_COLON);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string type = mv$(tok.str());
-
+
unsigned int idx = ::std::find( names.begin(), names.end(), name ) - names.begin();
if( idx == names.size() )
names.push_back( name );
-
+
if(0)
;
else if( type == "tt" )
@@ -119,7 +119,7 @@ public:
break;
}
}
-
+
return ret;
}
@@ -132,10 +132,10 @@ public:
)
{
TRACE_FUNCTION;
-
+
Token tok;
::std::vector<MacroExpansionEnt> ret;
-
+
int depth = 0;
while( GET_TOK(tok, lex) != close || depth > 0 )
{
@@ -144,7 +144,7 @@ public:
}
if( tok.type() == TOK_NULL )
continue ;
-
+
if( tok.type() == open )
{
DEBUG("depth++");
@@ -157,19 +157,19 @@ public:
ERROR(lex.getPosition(), E0000, "Unmatched " << Token(close) << " in macro content");
depth --;
}
-
+
// `$` - Macro metavars
if( tok.type() == TOK_DOLLAR )
{
GET_TOK(tok, lex);
-
+
// `$(`
if( tok.type() == TOK_PAREN_OPEN )
- {
+ {
::std::map<unsigned int, bool> var_set;
auto content = Parse_MacroRules_Cont(lex, TOK_PAREN_OPEN, TOK_PAREN_CLOSE, var_names, &var_set);
// ^^ The above will eat the PAREN_CLOSE
-
+
GET_TOK(tok, lex);
enum eTokenType joiner = TOK_NULL;
if( tok.type() != TOK_PLUS && tok.type() != TOK_STAR )
@@ -197,7 +197,7 @@ public:
default:
throw ParseError::Unexpected(lex, tok);
}
-
+
}
else if( tok.type() == TOK_IDENT )
{
@@ -225,7 +225,7 @@ public:
ret.push_back( MacroExpansionEnt( mv$(tok) ) );
}
}
-
+
return ret;
}
@@ -234,9 +234,9 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex)
{
TRACE_FUNCTION;
Token tok;
-
+
MacroRule rule;
-
+
// Pattern
enum eTokenType close;
switch(GET_TOK(tok, lex))
@@ -249,7 +249,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex)
// - Pattern entries
::std::vector< ::std::string> names;
rule.m_pattern = Parse_MacroRules_Pat(lex, tok.type(), close, names);
-
+
GET_CHECK_TOK(tok, lex, TOK_FATARROW);
// Replacement
@@ -263,7 +263,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex)
rule.m_contents = Parse_MacroRules_Cont(lex, tok.type(), close, names);
DEBUG("Rule - ["<<rule.m_pattern<<"] => "<<rule.m_contents<<"");
-
+
return rule;
}
@@ -271,11 +271,11 @@ bool patterns_are_same(const Span& sp, const MacroPatEnt& left, const MacroPatEn
{
if( left.type > right.type )
return patterns_are_same(sp, right, left);
-
+
//if( left.name != right.name ) {
// TODO(sp, "Handle different binding names " << left << " != " << right);
//}
-
+
// NOTE: left.type <= right.type
switch(right.type)
{
@@ -295,13 +295,13 @@ bool patterns_are_same(const Span& sp, const MacroPatEnt& left, const MacroPatEn
default:
assert( !"" );
}
-
+
case MacroPatEnt::PAT_TT:
if( left.type == right.type )
return true;
ERROR(sp, E0000, "Incompatible macro fragments - " << right << " used with " << left);
break;
-
+
case MacroPatEnt::PAT_PAT:
switch(left.type)
{
@@ -444,15 +444,15 @@ void enumerate_names(const ::std::vector<MacroPatEnt>& pats, ::std::vector< ::st
MacroRulesPtr Parse_MacroRules(TokenStream& lex)
{
TRACE_FUNCTION_F("");
-
+
Token tok;
-
+
// Parse the patterns and replacements
::std::vector<MacroRule> rules;
while( GET_TOK(tok, lex) != TOK_EOF )
{
lex.putback(tok);
-
+
rules.push_back( Parse_MacroRules_Var(lex) );
if(GET_TOK(tok, lex) != TOK_SEMICOLON) {
CHECK_TOK(tok, TOK_EOF);
@@ -460,22 +460,22 @@ MacroRulesPtr Parse_MacroRules(TokenStream& lex)
}
}
DEBUG("- " << rules.size() << " rules");
-
+
::std::vector<MacroRulesArm> rule_arms;
-
+
// Re-parse the patterns into a unified form
for(auto& rule : rules)
{
MacroRulesArm arm = MacroRulesArm( mv$(rule.m_pattern), mv$(rule.m_contents) );
-
+
enumerate_names(arm.m_pattern, arm.m_param_names);
-
+
rule_arms.push_back( mv$(arm) );
}
-
+
auto rv = new MacroRules( );
rv->m_hygiene = lex.getHygiene();
rv->m_rules = mv$(rule_arms);
-
+
return MacroRulesPtr(rv);
}