diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/deserialise.cpp | 9 | ||||
-rw-r--r-- | src/hir/serialise.cpp | 8 | ||||
-rw-r--r-- | src/macro_rules/eval.cpp | 12 | ||||
-rw-r--r-- | src/macro_rules/macro_rules.hpp | 3 | ||||
-rw-r--r-- | src/macro_rules/parse.cpp | 24 |
5 files changed, 34 insertions, 22 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 1cf5f0e0..08662fe2 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -338,10 +338,13 @@ namespace { case 2: { auto entries = deserialise_vec_c< ::MacroExpansionEnt>( [&](){ return deserialise_macroexpansionent(); } ); auto joiner = deserialise_token(); - ::std::set<unsigned int> variables; + ::std::map<unsigned int, bool> variables; size_t n = read_count(); - while(n--) - variables.insert( static_cast<unsigned int>(read_count()) ); + while(n--) { + auto idx = static_cast<unsigned int>(read_count()); + bool flag = read_bool(); + variables.insert( ::std::make_pair(idx, flag) ); + } return ::MacroExpansionEnt::make_Loop({ mv$(entries), mv$(joiner), mv$(variables) }); diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index 832177e1..a45759b8 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -435,10 +435,12 @@ namespace { write_tag(2); serialise_vec(e.entries); serialise(e.joiner); - // ::std::set<unsigned int> + // ::std::map<unsigned int,bool> write_count(e.variables.size()); - for(const auto& var : e.variables) - write_count(var); + for(const auto& var : e.variables) { + write_count(var.first); + write_bool(var.second); + } ) ) } diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp index 66382ed7..9af766b6 100644 --- a/src/macro_rules/eval.cpp +++ b/src/macro_rules/eval.cpp @@ -731,7 +731,7 @@ bool Macro_HandlePattern(TokenStream& lex, const MacroPatEnt& pat, ::std::vector /// Parse the input TokenTree according to the `macro_rules!` patterns and return a token stream of the replacement ::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, TokenTree input, AST::Module& mod) { - TRACE_FUNCTION_F(name); + TRACE_FUNCTION_F("'" << name << "', " << input); ParameterMappings bound_tts; unsigned int rule_index = Macro_InvokeRules_MatchPattern(rules, mv$(input), mod, bound_tts); @@ -1052,14 +1052,16 @@ const MacroExpansionEnt* MacroExpandState::next_ent() (Loop, // 1. Get number of times this will repeat (based on the next iteration count) unsigned int num_repeats = 0; - for(const auto idx : e.variables) { - unsigned int this_repeats = m_mappings.count_in(m_iterations, idx); - // If a variable doesn't have data, don't loop - if( this_repeats == 0 ) { + // TODO: Have a flag for each of these that indicates if it's a definitive controller? (I.e. if zero, don't loop) + for(const auto& var : e.variables) { + unsigned int this_repeats = m_mappings.count_in(m_iterations, var.first); + // If a variable doesn't have data and it's a required controller, don't loop + if( this_repeats == 0 && var.second ) { num_repeats = 0; break; } // TODO: Ideally, all variables would have the same repeat count. + // Options: 0 (optional), 1 (higher), N (all equal) if( this_repeats > num_repeats ) num_repeats = this_repeats; } diff --git a/src/macro_rules/macro_rules.hpp b/src/macro_rules/macro_rules.hpp index 550068b8..ddf11dcb 100644 --- a/src/macro_rules/macro_rules.hpp +++ b/src/macro_rules/macro_rules.hpp @@ -31,7 +31,8 @@ TAGGED_UNION_EX(MacroExpansionEnt, (: public Serialisable), Token, ( /// Token used to join iterations
Token joiner;
/// List of variables within this loop that control its iteration count
- ::std::set< unsigned int> variables;
+ /// Boolean is true if the variable will be unconditionally expanded
+ ::std::map< unsigned int, bool> variables;
})
),
(),
diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp index 56fa6518..dce01c86 100644 --- a/src/macro_rules/parse.cpp +++ b/src/macro_rules/parse.cpp @@ -128,7 +128,7 @@ public: TokenStream& lex, enum eTokenType open, enum eTokenType close, const ::std::vector< ::std::string>& var_names, - ::std::set<unsigned int>* var_set_ptr=nullptr + ::std::map<unsigned int,bool>* var_set_ptr=nullptr ) { TRACE_FUNCTION; @@ -166,15 +166,10 @@ public: // `$(` if( tok.type() == TOK_PAREN_OPEN ) { - ::std::set<unsigned int> var_set; + ::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 - if( var_set_ptr ) { - for(const auto& v : var_set) - var_set_ptr->insert( v ); - } - GET_TOK(tok, lex); enum eTokenType joiner = TOK_NULL; if( tok.type() != TOK_PLUS && tok.type() != TOK_STAR ) @@ -182,12 +177,21 @@ public: joiner = tok.type(); GET_TOK(tok, lex); } + bool is_optional = (tok.type() == TOK_STAR); + if( var_set_ptr ) { + for(const auto& v : var_set) { + // If `is_optional`: Loop may not be expanded, so var_not_opt=false + // Else, inherit + bool var_not_opt = (is_optional ? false : v.second); + var_set_ptr->insert( ::std::make_pair(v.first, var_not_opt) ).first->second |= var_not_opt; + } + } DEBUG("joiner = " << Token(joiner) << ", content = " << content); switch(tok.type()) { - case TOK_STAR: case TOK_PLUS: - // TODO: Ensure that +/* match up + case TOK_STAR: + // TODO: Ensure that +/* match up? ret.push_back( MacroExpansionEnt({mv$(content), joiner, mv$(var_set)}) ); break; default: @@ -202,7 +206,7 @@ public: if( idx == var_names.size() ) ERROR(lex.getPosition(), E0000, "Macro variable $" << tok.str() << " not found"); if( var_set_ptr ) { - var_set_ptr->insert( idx ); + var_set_ptr->insert( ::std::make_pair(idx,true) ); } ret.push_back( MacroExpansionEnt(idx) ); } |