diff options
author | John Hodge (Mutabah) <acessdev@gmail.com> | 2016-12-25 17:19:27 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-25 17:19:27 +1100 |
commit | 753a2f44cc4c00b952cddae2ceed066ebb18a470 (patch) | |
tree | ed4bbff4be39c44c57164641f4ed32b5ad4675f0 /src/macro_rules | |
parent | d12a8a886caf2e0edf33c1af831b1df990d2c892 (diff) | |
parent | 0c14c734fa32014fd24297ccdbed927016185ffd (diff) | |
download | mrust-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.cpp | 178 | ||||
-rw-r--r-- | src/macro_rules/macro_rules.hpp | 324 | ||||
-rw-r--r-- | src/macro_rules/macro_rules_ptr.hpp | 4 | ||||
-rw-r--r-- | src/macro_rules/mod.cpp | 606 | ||||
-rw-r--r-- | src/macro_rules/parse.cpp | 64 |
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); } |