summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/ast.cpp3
-rw-r--r--src/ast/ast.hpp1
-rw-r--r--src/hir/from_ast.cpp10
-rw-r--r--src/include/serialise.hpp20
-rw-r--r--src/include/tagged_union.hpp1
-rw-r--r--src/macro_rules/eval.cpp403
-rw-r--r--src/macro_rules/macro_rules.hpp75
-rw-r--r--src/macro_rules/mod.cpp37
-rw-r--r--src/macro_rules/parse.cpp53
-rw-r--r--src/main.cpp4
-rw-r--r--src/parse/interpolated_fragment.cpp29
-rw-r--r--src/parse/interpolated_fragment.hpp1
12 files changed, 333 insertions, 304 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 8af991c0..00c4b39b 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -573,7 +573,7 @@ SERIALISE_TYPE(TypeParam::, "AST_TypeParam", {
return os;
}
-
+#if 0
#define SERIALISE_TU_ARM(CLASS, NAME, TAG, ...) case CLASS::TAG_##TAG: { *this = CLASS::make_##TAG({}); auto& NAME = this->as_##TAG(); (void)&NAME; __VA_ARGS__ } break;
#define SERIALISE_TU_ARMS(CLASS, NAME, ...) TU_GMA(__VA_ARGS__)(SERIALISE_TU_ARM, (CLASS, NAME), __VA_ARGS__)
#define SERIALISE_TU(PATH, TAG, NAME, ...) \
@@ -584,6 +584,7 @@ SERIALISE_TYPE(TypeParam::, "AST_TypeParam", {
}, {\
PATH::Tag tag; s % tag; switch(tag) { case PATH::TAGDEAD: throw ""; SERIALISE_TU_ARMS(PATH, NAME, __VA_ARGS__) } \
})
+#endif
SERIALISE_TU(GenericBound, "GenericBound", ent,
(Lifetime,
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 2e939e0c..d57d6693 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -644,6 +644,7 @@ public:
::std::vector<MacroInvocation>& macro_invs() { return m_macro_invocations; }
+ NamedList<MacroRulesPtr>& macros() { return m_macros; }
const NamedList<MacroRulesPtr>& macros() const { return m_macros; }
const ::std::vector<NamedNS<const MacroRules*> > macro_imports_res() const { return m_macro_import_res; }
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index f3a41207..878e7d4c 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -1055,14 +1055,16 @@ public:
auto& macros = rv.m_exported_macros;
// - Extract macros from root module
- for( const auto& mac : crate.m_root_module.macros() ) {
+ for( /*const*/ auto& mac : crate.m_root_module.macros() ) {
//if( mac.data.export ) {
- macros.insert( ::std::make_pair( mac.name, mv$(*mac.data) ) );
+ MacroRulesPtr& mrp = mac.data;
+ MacroRules mac_data = mv$(*mrp);
+ macros.insert( ::std::make_pair( mac.name, mv$(mac_data) ) );
//}
}
- for( const auto& mac : crate.m_root_module.macro_imports_res() ) {
+ for( auto& mac : crate.m_root_module.macro_imports_res() ) {
//if( mac.data->export ) {
- macros.insert( ::std::make_pair( mac.name, *mac.data ) );
+ macros.insert( ::std::make_pair( mac.name, mv$(*const_cast<MacroRules*>(mac.data)) ) );
//}
}
diff --git a/src/include/serialise.hpp b/src/include/serialise.hpp
index 664c5bac..db311bb1 100644
--- a/src/include/serialise.hpp
+++ b/src/include/serialise.hpp
@@ -22,6 +22,26 @@ class Deserialiser;
void method_prefix deserialise(::Deserialiser& s) { des_body }
#define SERIALISE_TYPE_A(method_prefix, tag_str, body) SERIALISE_TYPE(method_prefix, tag_str, body, body)
#define SERIALISE_TYPE_S(class_, body) SERIALISE_TYPE(class_::, #class_, body, body)
+#define SERIALISE_TU(class_, tag_str, val_name, ...) SERIALISE_TYPE(class_::, tag_str,\
+ {\
+ s << class_::tag_to_str(this->tag());\
+ TU_MATCH(class_, (*this), (val_name), __VA_ARGS__);\
+ },/*
+*/ {\
+ ::std::string STU_tag_str;\
+ s.item(STU_tag_str);\
+ auto tag = class_::tag_from_str(STU_tag_str);\
+ switch(tag) { \
+ case class_::TAGDEAD: break;\
+ SERIALISE_TU_MATCH_ARMS(class_, val_name, __VA_ARGS__)\
+ }\
+ })
+#define SERIALISE_TU_MATCH_ARM(CLASS, VAL_NAME, TAG, ...) case CLASS::TAG_##TAG: {/*
+*/ *this = CLASS::make_##TAG({});/*
+*/ auto& VAL_NAME = this->as_##TAG(); /*
+*/ __VA_ARGS__/*
+*/} break;
+#define SERIALISE_TU_MATCH_ARMS(CLASS, NAME, ...) TU_GMA(__VA_ARGS__)(SERIALISE_TU_MATCH_ARM, (CLASS, NAME), __VA_ARGS__)
class DeserialiseFailure:
public ::std::runtime_error
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp
index 9762937e..89ba5be4 100644
--- a/src/include/tagged_union.hpp
+++ b/src/include/tagged_union.hpp
@@ -99,6 +99,7 @@
// TODO: use `decltype` in place of the `class` argument to TU_MATCH/TU_IFLET
// "match"-like statement
// TU_MATCH(Class, m_data, ent, (Variant, CODE), (Variant2, CODE))
+#define TU_MATCHA(VARS, NAMES, ...) TU_MATCH( decltype( ::std::remove_reference(TU_FIRST VARS) ), VARS, NAMES, __VA_ARGS__ )
#define TU_MATCH(CLASS, VAR, NAME, ...) switch( (TU_FIRST VAR).tag()) {/*
*/ case CLASS::TAGDEAD: assert(!"ERROR: destructed tagged union used");/*
*/ TU_MATCH_ARMS(CLASS, VAR, NAME, __VA_ARGS__)/*
diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp
index ed1e1a2e..81898fa9 100644
--- a/src/macro_rules/eval.cpp
+++ b/src/macro_rules/eval.cpp
@@ -14,29 +14,50 @@ extern AST::ExprNodeP Parse_Stmt(TokenStream& lex);
class ParameterMappings
{
- // MultiMap (layer, name) -> TokenTree
- // - Multiple values are only allowed for layer>0
- typedef ::std::pair<unsigned, unsigned> t_mapping_block;
- struct Mapping
- {
- t_mapping_block block;
- ::std::vector<InterpolatedFragment> entries;
- friend ::std::ostream& operator<<(::std::ostream& os, const Mapping& x) {
- os << "(" << x.block.first << ", " << x.block.second << "): [" << x.entries << "])";
+ TAGGED_UNION_EX(CaptureLayer, (), Vals, (
+ (Vals, ::std::vector<InterpolatedFragment>),
+ (Nested, ::std::vector<CaptureLayer>)
+ ),
+ (),
+ (),
+ (
+ public:
+ CaptureLayer& next_layer_or_self(unsigned int idx) {
+ TU_IFLET(CaptureLayer, (*this), Nested, e,
+ return e.at(idx);
+ )
+ else {
+ return *this;
+ }
+ }
+ friend ::std::ostream& operator<<(::std::ostream& os, const CaptureLayer& x) {
+ TU_MATCH(CaptureLayer, (x), (e),
+ (Vals,
+ os << "[" << e << "]";
+ ),
+ (Nested,
+ os << "{" << e << "}";
+ )
+ )
return os;
}
- };
+ )
+ );
- struct less_cstr {
- bool operator()(const char *a, const char *b) const { return ::std::strcmp(a,b) < 0; }
+ /// Represents the value
+ 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<Mapping> m_mappings;
+ ::std::vector<CapturedVar> m_mappings;
unsigned m_layer_count;
-
- //::std::map<const char*, Mapping*, less_cstr> m_map;
- ::std::map<::std::string, Mapping*> m_map;
public:
ParameterMappings():
m_layer_count(0)
@@ -44,94 +65,77 @@ public:
}
ParameterMappings(ParameterMappings&&) = default;
- const ::std::vector<Mapping>& mappings() const { return m_mappings; }
+ const ::std::vector<CapturedVar>& mappings() const { return m_mappings; }
void dump() const {
DEBUG("m_mappings = {" << m_mappings << "}");
- DEBUG("m_map = {" << m_map << "}");
}
size_t layer_count() const {
return m_layer_count+1;
}
- void insert(unsigned int layer, unsigned int name_index, InterpolatedFragment data) {
- if(layer > m_layer_count)
- m_layer_count = layer;
-
+ void insert(unsigned int name_index, const ::std::vector<unsigned int>& iterations, InterpolatedFragment data) {
if( name_index >= m_mappings.size() ) {
m_mappings.resize( name_index + 1 );
}
- auto& mapping = m_mappings[name_index];
-
- if( mapping.entries.size() == 0 ) {
- mapping.block.first = layer;
- }
- else if( mapping.block.first != layer) {
- throw ParseError::Generic(FMT("matching argument #'"<<name_index<<"' at multiple layers"));
- }
- else {
+ auto* layer = &m_mappings[name_index].top_layer;
+ for(const auto iter : iterations)
+ {
+ if( layer->is_Vals() ) {
+ assert( layer->as_Vals().size() == 0 );
+ *layer = CaptureLayer::make_Nested({});
+ }
+ auto& e = layer->as_Nested();
+ if( e.size() < iter ) {
+ // ERROR
+ DEBUG("Iteratoun count jumped from " << e.size() << " to " << iter);
+ assert(!"Iteration count jump");
+ }
+ else if(e.size() == iter) {
+ e.push_back( CaptureLayer::make_Vals({}) );
+ }
+ else {
+ layer = &e[iter];
+ }
}
- mapping.entries.push_back( mv$(data) );
+ layer->as_Vals().push_back( mv$(data) );
}
- void reindex(const ::std::vector< ::std::string>& new_names) {
- m_map.clear();
+ InterpolatedFragment* get(const ::std::vector<unsigned int>& iterations, unsigned int name_idx)
+ {
+ auto& e = m_mappings.at(name_idx);
+ auto* layer = &e.top_layer;
- if( new_names.size() < m_mappings.size() ) {
- BUG(Span(), "Macro parameter name mismatch - len["<<new_names<<"] != len["<<m_mappings<<"]");
+ if( iterations.size() == 0 ) {
+ TU_IFLET(CaptureLayer, (*layer), Vals, e,
+ return &e[0];
+ )
}
- for( unsigned int i = 0; i < m_mappings.size(); i ++ )
+
+ for(const auto iter : iterations)
{
- m_map.insert( ::std::make_pair(new_names[i].c_str(), &m_mappings[i]) );
+ TU_MATCH(CaptureLayer, (*layer), (e),
+ (Vals,
+ return &e[iter];
+ ),
+ (Nested,
+ layer = &e[iter];
+ )
+ )
}
- }
- InterpolatedFragment* get(unsigned int layer, unsigned int iteration, const char *name, unsigned int idx)
- {
- const auto it = m_map.find( name );
- if( it == m_map.end() ) {
- DEBUG("m_map = " << m_map);
- return nullptr;
- }
- auto& e = *it->second;
- if( e.block.first < layer ) {
- DEBUG(name<<" higher layer (" << e.block.first << ")");
- return nullptr;
- }
- else if( e.block.first > layer ) {
- throw ParseError::Generic( FMT("'" << name << "' is still repeating at this layer") );
- }
- else if( idx >= e.entries.size() ) {
- DEBUG("Not enough mappings for name " << name << " at layer " << layer << " PI " << iteration);
- return nullptr;
- }
- else {
- DEBUG(name << " #" << idx << ": " << e.entries[idx]);
- return &e.entries[idx];
- }
+ ERROR(Span(), E0000, "Variable #" << name_idx << " is still repeating at this level (" << iterations.size() << ")");
}
- unsigned int count(unsigned int layer, unsigned int iteration, const char *name) const
+ unsigned int count_in(const ::std::vector<unsigned int>& iterations, unsigned int name_idx)
{
- const auto it = m_map.find( name );
- if( it == m_map.end() ) {
- DEBUG("("<<layer<<","<<iteration<<",'"<<name<<"') not found - m_map={" << m_map << "}");
- return 0;
- }
- const auto& e = *it->second;
-
- if( e.block.first < layer ) {
- DEBUG(name<<" higher layer (" << e.block.first << ")");
- return UINT_MAX;
- }
- else if( e.block.first > layer ) {
- //throw ParseError::Generic( FMT("'" << name << "' is still repeating at this layer") );
- // ignore mismatch
- return UINT_MAX;
- }
- else {
- return e.entries.size();
+ auto& e = m_mappings.at(name_idx);
+ auto* layer = &e.top_layer;
+ for(const auto iter : iterations)
+ {
+ layer = &layer->next_layer_or_self(iter);
}
+ return layer->is_Vals() ? layer->as_Vals().size() : 0;
}
};
@@ -144,7 +148,7 @@ private:
const RcString m_macro_filename;
const ::std::string m_crate_name;
- const ::std::vector<MacroRuleEnt>& m_root_contents;
+ const ::std::vector<MacroExpansionEnt>& m_root_contents;
ParameterMappings m_mappings;
@@ -155,10 +159,10 @@ private:
};
/// Layer states : Index and Iteration
::std::vector< t_offset > m_offsets;
- ::std::vector< size_t > m_layer_iters;
+ ::std::vector< unsigned int> m_iterations;
/// Cached pointer to the current layer
- const ::std::vector<MacroRuleEnt>* m_cur_ents; // For faster lookup.
+ const ::std::vector<MacroExpansionEnt>* m_cur_ents; // For faster lookup.
Token m_next_token; // used for inserting a single token into the stream
::std::unique_ptr<TTStream> m_ttstream;
@@ -166,7 +170,7 @@ private:
public:
MacroExpander(const MacroExpander& x) = delete;
- MacroExpander(const ::std::string& macro_name, const ::std::vector<MacroRuleEnt>& contents, ParameterMappings mappings, ::std::string crate_name):
+ MacroExpander(const ::std::string& macro_name, const ::std::vector<MacroExpansionEnt>& contents, ParameterMappings mappings, ::std::string crate_name):
m_macro_filename( FMT("Macro:" << macro_name) ),
m_crate_name( mv$(crate_name) ),
m_root_contents(contents),
@@ -180,10 +184,9 @@ public:
virtual Position getPosition() const override;
virtual Token realGetToken() override;
private:
- const MacroRuleEnt& getCurLayerEnt() const;
- const ::std::vector<MacroRuleEnt>* getCurLayer() const;
+ const MacroExpansionEnt& getCurLayerEnt() const;
+ const ::std::vector<MacroExpansionEnt>* getCurLayer() const;
void prep_counts();
- unsigned int count_repeats(const ::std::vector<MacroRuleEnt>& ents, unsigned layer, unsigned iter);
};
void Macro_InitDefaults()
@@ -228,9 +231,9 @@ bool Macro_TryPattern(TTStream& lex, const MacroPatEnt& pat)
throw ParseError::Todo(lex, FMT("Macro_TryPattern : " << pat));
}
-bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int layer, ParameterMappings& bound_tts)
+bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, ::std::vector<unsigned int>& iterations, ParameterMappings& bound_tts)
{
- TRACE_FUNCTION_F("layer = " << layer);
+ TRACE_FUNCTION_F("iterations = " << iterations);
Token tok;
switch(pat.type)
@@ -244,6 +247,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
{
unsigned int match_count = 0;
DEBUG("Loop");
+ iterations.push_back(0);
for(;;)
{
if( ! Macro_TryPattern(lex, pat.subpats[0]) )
@@ -251,9 +255,10 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
DEBUG("break");
break;
}
+ iterations.back() += 1;
for( unsigned int i = 0; i < pat.subpats.size(); i ++ )
{
- if( !Macro_HandlePattern(lex, pat.subpats[i], layer+1, bound_tts) ) {
+ if( !Macro_HandlePattern(lex, pat.subpats[i], iterations, bound_tts) ) {
DEBUG("Ent " << i << " failed");
return false;
}
@@ -269,6 +274,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
}
}
}
+ iterations.pop_back();
DEBUG("Done (" << match_count << " matches)");
break; }
@@ -278,32 +284,32 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
throw ParseError::Unexpected(lex, TOK_EOF);
else
PUTBACK(tok, lex);
- bound_tts.insert( layer, pat.name_index, InterpolatedFragment( Parse_TT(lex, false) ) );
+ bound_tts.insert( pat.name_index, iterations, InterpolatedFragment( Parse_TT(lex, false) ) );
break;
case MacroPatEnt::PAT_PAT:
- bound_tts.insert( layer, pat.name_index, InterpolatedFragment( Parse_Pattern(lex, true) ) );
+ bound_tts.insert( pat.name_index, iterations, InterpolatedFragment( Parse_Pattern(lex, true) ) );
break;
case MacroPatEnt::PAT_TYPE:
- bound_tts.insert( layer, pat.name_index, InterpolatedFragment( Parse_Type(lex) ) );
+ bound_tts.insert( pat.name_index, iterations, InterpolatedFragment( Parse_Type(lex) ) );
break;
case MacroPatEnt::PAT_EXPR:
- bound_tts.insert( layer, pat.name_index, InterpolatedFragment( InterpolatedFragment::EXPR, Parse_Expr0(lex).release() ) );
+ bound_tts.insert( pat.name_index, iterations, InterpolatedFragment( InterpolatedFragment::EXPR, Parse_Expr0(lex).release() ) );
break;
case MacroPatEnt::PAT_STMT:
- bound_tts.insert( layer, pat.name_index, InterpolatedFragment( InterpolatedFragment::STMT, Parse_Stmt(lex).release() ) );
+ bound_tts.insert( pat.name_index, iterations, InterpolatedFragment( InterpolatedFragment::STMT, Parse_Stmt(lex).release() ) );
break;
case MacroPatEnt::PAT_PATH:
- bound_tts.insert( layer, pat.name_index, InterpolatedFragment( Parse_Path(lex, PATH_GENERIC_TYPE) ) ); // non-expr mode
+ bound_tts.insert( pat.name_index, iterations, InterpolatedFragment( Parse_Path(lex, PATH_GENERIC_TYPE) ) ); // non-expr mode
break;
case MacroPatEnt::PAT_BLOCK:
- bound_tts.insert( layer, pat.name_index, InterpolatedFragment( InterpolatedFragment::BLOCK, Parse_ExprBlockNode(lex).release() ) );
+ bound_tts.insert( pat.name_index, iterations, InterpolatedFragment( InterpolatedFragment::BLOCK, Parse_ExprBlockNode(lex).release() ) );
break;
case MacroPatEnt::PAT_META:
- bound_tts.insert( layer, pat.name_index, InterpolatedFragment( Parse_MetaItem(lex) ) );
+ bound_tts.insert( pat.name_index, iterations, InterpolatedFragment( Parse_MetaItem(lex) ) );
break;
case MacroPatEnt::PAT_IDENT:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- bound_tts.insert( layer, pat.name_index, InterpolatedFragment( TokenTree(tok) ) );
+ bound_tts.insert( pat.name_index, iterations, InterpolatedFragment( TokenTree(tok) ) );
break;
//default:
@@ -330,7 +336,8 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
{
const auto& pat = cur_frag->m_pats_ents[cur_frag_ofs];
DEBUG("- try " << pat);
- if( !Macro_HandlePattern(lex, pat, 0, bound_tts) )
+ ::std::vector<unsigned int> iterations;
+ if( !Macro_HandlePattern(lex, pat, iterations, bound_tts) )
throw ParseError::Generic(lex, "Macro pattern failed");
// Keep going
cur_frag_ofs ++;
@@ -377,15 +384,14 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
const auto& rule = rules.m_rules[rule_index];
- DEBUG( rule.m_contents.size() << " rule contents bound to " << bound_tts.mappings().size() << " values - " << name );
- bound_tts.reindex( rule.m_param_names );
+ DEBUG( rule.m_contents.size() << " rule contents with " << bound_tts.mappings().size() << " bound values - " << name );
for( unsigned int i = 0; i < bound_tts.mappings().size(); i ++ )
{
DEBUG(" - " << rule.m_param_names[i] << " = [" << bound_tts.mappings()[i] << "]");
}
bound_tts.dump();
- DEBUG("TODO: Obtain crate name correctly");
+ DEBUG("TODO: Obtain crate name correctly, using \"\" for now");
TokenStream* ret_ptr = new MacroExpander(name, rule.m_contents, mv$(bound_tts), "");
// HACK! Disable nested macro expansion
//ret_ptr->parse_state().no_expand_macros = true;
@@ -431,96 +437,80 @@ Token MacroExpander::realGetToken()
{
// - If not, just handle the next entry
const auto& ent = ents[idx];
- // Check type of entry
- // - XXX: Hack for $crate special name
- if( ent.name == "*crate" )
- {
- DEBUG("Crate name hack");
- if( m_crate_name != "" )
- {
- m_next_token = Token(TOK_STRING, m_crate_name);
- return Token(TOK_DOUBLE_COLON);
- }
- }
- // - Expand to a parameter
- else if( ent.name != "" )
- {
- DEBUG("lookup '" << ent.name << "'");
- InterpolatedFragment* frag;
- unsigned int search_layer = layer;
- do {
- unsigned int parent_iter = (search_layer > 0 ? m_layer_iters.at(search_layer-1) : 0);
- const size_t iter_idx = m_offsets.at(search_layer).loop_index;
- frag = m_mappings.get(search_layer, parent_iter, ent.name.c_str(), iter_idx);
- } while( !frag && search_layer-- > 0 );
- if( !frag )
- {
- throw ParseError::Generic(*this, FMT("Cannot find '" << ent.name << "' for " << layer));
+ TU_MATCH( MacroExpansionEnt, (ent), (e),
+ (Token,
+ return e;
+ ),
+ (NamedValue,
+ if( e >> 30 ) {
+ switch( e & 0x3FFFFFFF )
+ {
+ // - XXX: Hack for $crate special name
+ case 0:
+ DEBUG("Crate name hack");
+ if( m_crate_name != "" )
+ {
+ m_next_token = Token(TOK_STRING, m_crate_name);
+ return Token(TOK_DOUBLE_COLON);
+ }
+ break;
+ default:
+ BUG(Span(), "Unknown macro metavar");
+ }
}
- else
- {
- if( frag->m_type == InterpolatedFragment::TT )
+ else {
+ auto* frag = m_mappings.get(m_iterations, e);
+ if( !frag )
{
- m_ttstream.reset( new TTStream( frag->as_tt() ) );
- return m_ttstream->getToken();
+ throw ParseError::Generic(*this, FMT("Cannot find '" << e << "' for " << m_iterations));
}
else
{
- return Token( *frag );
+ if( frag->m_type == InterpolatedFragment::TT )
+ {
+ m_ttstream.reset( new TTStream( frag->as_tt() ) );
+ return m_ttstream->getToken();
+ }
+ else
+ {
+ return Token( *frag );
+ }
}
}
- }
- // - Descend into a repetition
- else if( ent.subpats.size() != 0 )
- {
- DEBUG("desc: layer = " << layer << ", m_layer_iters = " << m_layer_iters);
- unsigned int layer_iter = m_layer_iters.at(layer);
- unsigned int num_repeats = this->count_repeats(ent.subpats, layer+1, layer_iter);
- if(num_repeats == UINT_MAX)
- num_repeats = 0;
- // New layer
- DEBUG("- NL = " << layer+1 << ", count = " << num_repeats );
- if( num_repeats > 0 )
- {
- // - Push an offset
- m_offsets.push_back( {0, 0, num_repeats} );
- // - Save the current layer
- m_cur_ents = getCurLayer();
- // - Restart loop for new layer
- }
- else
- {
- // Layer empty
- DEBUG("Layer " << layer+1 << " is empty");
+ ),
+ (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( this_repeats > num_repeats )
+ num_repeats = this_repeats;
}
- // VVV fall through and continue loop
- }
- // - Emit a raw token
- else
- {
- return ent.tok;
- }
+ m_offsets.push_back( {0, 0, num_repeats} );
+ m_iterations.push_back( 0 );
+ m_cur_ents = getCurLayer();
+ )
+ )
// Fall through for loop
}
else if( layer > 0 )
{
// - Otherwise, restart/end loop and fall through
- DEBUG("layer = " << layer << ", m_layer_iters = " << m_layer_iters);
+ DEBUG("layer = " << layer << ", m_iterations = " << m_iterations);
auto& cur_ofs = m_offsets.back();
DEBUG("Layer #" << layer << " Cur: " << cur_ofs.loop_index << ", Max: " << cur_ofs.max_index);
if( cur_ofs.loop_index + 1 < cur_ofs.max_index )
{
- m_layer_iters.at(layer) ++;
+ m_iterations.back() ++;
DEBUG("Restart layer");
cur_ofs.read_pos = 0;
cur_ofs.loop_index ++;
auto& loop_layer = getCurLayerEnt();
- assert(loop_layer.subpats.size());
- if( loop_layer.tok.type() != TOK_NULL ) {
- DEBUG("- Separator token = " << loop_layer.tok);
- return loop_layer.tok;
+ if( loop_layer.as_Loop().joiner.type() != TOK_NULL ) {
+ DEBUG("- Separator token = " << loop_layer.as_Loop().joiner);
+ return loop_layer.as_Loop().joiner;
}
// Fall through and restart layer
}
@@ -529,6 +519,7 @@ Token MacroExpander::realGetToken()
DEBUG("Terminate layer");
// Terminate loop, fall through to lower layers
m_offsets.pop_back();
+ m_iterations.pop_back();
// - Special case: End of macro, avoid issues
if( m_offsets.size() == 0 )
break;
@@ -550,88 +541,32 @@ Token MacroExpander::realGetToken()
/// Count the number of names at each layer
void MacroExpander::prep_counts()
{
- m_layer_iters.resize(m_mappings.layer_count(), 0);
}
-const MacroRuleEnt& MacroExpander::getCurLayerEnt() const
+const MacroExpansionEnt& MacroExpander::getCurLayerEnt() const
{
assert( m_offsets.size() > 1 );
- const ::std::vector<MacroRuleEnt>* ents = &m_root_contents;
+ const auto* ents = &m_root_contents;
for( unsigned int i = 0; i < m_offsets.size()-2; i ++ )
{
unsigned int ofs = m_offsets[i].read_pos;
assert( ofs > 0 && ofs <= ents->size() );
- ents = &(*ents)[ofs-1].subpats;
+ ents = &(*ents)[ofs-1].as_Loop().entries;
}
return (*ents)[m_offsets[m_offsets.size()-2].read_pos-1];
}
-const ::std::vector<MacroRuleEnt>* MacroExpander::getCurLayer() const
+const ::std::vector<MacroExpansionEnt>* MacroExpander::getCurLayer() const
{
assert( m_offsets.size() > 0 );
- const ::std::vector<MacroRuleEnt>* ents = &m_root_contents;
+ const auto* ents = &m_root_contents;
for( unsigned int i = 0; i < m_offsets.size()-1; i ++ )
{
unsigned int ofs = m_offsets[i].read_pos;
//DEBUG(i << " ofs=" << ofs << " / " << ents->size());
assert( ofs > 0 && ofs <= ents->size() );
- ents = &(*ents)[ofs-1].subpats;
+ ents = &(*ents)[ofs-1].as_Loop().entries;
//DEBUG("ents = " << ents);
}
return ents;
}
-unsigned int MacroExpander::count_repeats(const ::std::vector<MacroRuleEnt>& ents, unsigned layer, unsigned iter)
-{
- bool valid = false;
- unsigned int count = 0;
- for(const auto& ent : ents)
- {
- if( ent.name != "" )
- {
- if( ent.name[0] == '*' ) {
- // Ignore meta-vars, they don't repeat
- }
- else {
- auto c = m_mappings.count(layer, iter, ent.name.c_str());
- DEBUG(c << " mappings for " << ent.name << " at (" << layer << ", " << iter << ")");
- if( c == UINT_MAX ) {
- // Ignore
- }
- else if(!valid || count == c) {
- count = c;
- valid = true;
- }
- else {
- // Mismatch!
- throw ParseError::Generic("count_repeats - iteration count mismatch");
- }
- }
- }
- else if( ent.subpats.size() > 0 )
- {
- auto c = this->count_repeats(ent.subpats, layer, iter);
- if( c == UINT_MAX ) {
- }
- else if(!valid || count == c) {
- count = c;
- valid = true;
- }
- else {
- // Mismatch!
- throw ParseError::Generic("count_repeats - iteration count mismatch (subpat)");
- }
- }
- else
- {
- // Don't care
- }
- }
-
- if(valid) {
- return count;
- }
- else {
- return UINT_MAX;
- }
-}
-
diff --git a/src/macro_rules/macro_rules.hpp b/src/macro_rules/macro_rules.hpp
index 65822fa5..dcd1bbd3 100644
--- a/src/macro_rules/macro_rules.hpp
+++ b/src/macro_rules/macro_rules.hpp
@@ -8,42 +8,33 @@
#include <memory>
#include <cstring>
#include "macro_rules_ptr.hpp"
+#include <set>
class MacroExpander;
-class MacroRuleEnt:
- public Serialisable
-{
- friend class MacroExpander;
+TAGGED_UNION_EX(MacroExpansionEnt, (: public Serialisable), Token, (
+ // TODO: have a "raw" stream instead of just tokens
+ (Token, Token),
+ (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);
- Token tok;
- ::std::string name;
- ::std::vector<MacroRuleEnt> subpats;
-public:
- MacroRuleEnt():
- tok(TOK_NULL),
- name("")
- {
- }
- MacroRuleEnt(Token tok):
- tok( mv$(tok) ),
- name("")
- {
- }
- MacroRuleEnt(::std::string name):
- name( mv$(name) )
- {
- }
- MacroRuleEnt(Token tok, ::std::vector<MacroRuleEnt> subpats):
- tok( mv$(tok) ),
- subpats( mv$(subpats) )
- {
- }
-
- friend ::std::ostream& operator<<(::std::ostream& os, const MacroRuleEnt& x);
-
- SERIALISABLE_PROTOTYPES();
-};
+/// Matching pattern entry
struct MacroPatEnt:
public Serialisable
{
@@ -100,11 +91,15 @@ struct MacroPatEnt:
SERIALISABLE_PROTOTYPES();
};
+/// Fragment of a match pattern
struct MacroRulesPatFrag:
public Serialisable
{
+ /// Pattern entries within this fragment
::std::vector<MacroPatEnt> m_pats_ents;
+ /// Index of the arm that matches if the input ends after this fragment (~0 for nothing)
unsigned int m_pattern_end;
+ /// List of fragments that follow this fragment
::std::vector< MacroRulesPatFrag > m_next_frags;
MacroRulesPatFrag():
@@ -114,18 +109,25 @@ struct MacroRulesPatFrag:
SERIALISABLE_PROTOTYPES();
};
-/// An arm within a macro_rules! blcok
+/// An expansion arm within a macro_rules! blcok
struct MacroRulesArm:
public Serialisable
{
+ /// Names for the parameters
::std::vector< ::std::string> m_param_names;
- ::std::vector<MacroRuleEnt> m_contents;
+
+ /// Rule contents
+ ::std::vector<MacroExpansionEnt> m_contents;
MacroRulesArm()
{}
- MacroRulesArm(::std::vector<MacroRuleEnt> contents):
+ MacroRulesArm(::std::vector<MacroExpansionEnt> contents):
m_contents( mv$(contents) )
{}
+ MacroRulesArm(const MacroRulesArm&) = delete;
+ MacroRulesArm& operator=(const MacroRulesArm&) = delete;
+ MacroRulesArm(MacroRulesArm&&) = default;
+ MacroRulesArm& operator=(MacroRulesArm&&) = default;
SERIALISABLE_PROTOTYPES();
};
@@ -136,13 +138,16 @@ class MacroRules:
{
public:
bool m_exported;
+ /// Parsing patterns
MacroRulesPatFrag m_pattern;
+ /// Expansion rules
::std::vector<MacroRulesArm> m_rules;
MacroRules()
{
}
virtual ~MacroRules();
+ MacroRules(MacroRules&&) = default;
SERIALISABLE_PROTOTYPES();
};
diff --git a/src/macro_rules/mod.cpp b/src/macro_rules/mod.cpp
index 24e877dc..4e914066 100644
--- a/src/macro_rules/mod.cpp
+++ b/src/macro_rules/mod.cpp
@@ -181,20 +181,33 @@ SERIALISE_TYPE_S(MacroPatEnt, {
return os;
}
-SERIALISE_TYPE_S(MacroRuleEnt, {
- s.item(name);
- s.item(tok);
- s.item(subpats);
-});
+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 MacroRuleEnt& x)
+::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x)
{
- if(x.name.size())
- os << "$"<<x.name;
- else if( x.subpats.size() )
- os << "expand w/ " << x.tok << " [" << x.subpats << "]";
- else
- os << "=" << x.tok;
+ TU_MATCH( MacroExpansionEnt, (x), (e),
+ (Token,
+ os << "=" << e;
+ ),
+ (NamedValue,
+ os << "$" << e;
+ ),
+ (Loop,
+ os << "${" << *e.variables.begin() << "}(" << e.entries << ") " << e.joiner;
+ )
+ )
return os;
}
diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp
index 2d8ad374..ad536adb 100644
--- a/src/macro_rules/parse.cpp
+++ b/src/macro_rules/parse.cpp
@@ -13,7 +13,7 @@ class MacroRule
{
public:
::std::vector<MacroPatEnt> m_pattern;
- ::std::vector<MacroRuleEnt> m_contents;
+ ::std::vector<MacroExpansionEnt> m_contents;
};
::std::vector<MacroPatEnt> Parse_MacroRules_Pat(TokenStream& lex, bool allow_sub, enum eTokenType open, enum eTokenType close, ::std::vector< ::std::string>& names)
@@ -120,12 +120,18 @@ public:
return ret;
}
-::std::vector<MacroRuleEnt> Parse_MacroRules_Cont(TokenStream& lex, bool allow_sub, enum eTokenType open, enum eTokenType close)
+/// Parse the contents (replacement) of a macro_rules! arm
+::std::vector<MacroExpansionEnt> Parse_MacroRules_Cont(
+ TokenStream& lex,
+ bool allow_sub, enum eTokenType open, enum eTokenType close,
+ const ::std::vector< ::std::string>& var_names,
+ ::std::set<unsigned int>* var_set_ptr=nullptr
+ )
{
TRACE_FUNCTION;
Token tok;
- ::std::vector<MacroRuleEnt> ret;
+ ::std::vector<MacroExpansionEnt> ret;
int depth = 0;
while( GET_TOK(tok, lex) != close || depth > 0 )
@@ -133,7 +139,8 @@ public:
if( tok.type() == TOK_EOF ) {
throw ParseError::Unexpected(lex, tok);
}
- if( tok.type() == TOK_NULL ) continue ;
+ if( tok.type() == TOK_NULL )
+ continue ;
if( tok.type() == open )
{
@@ -144,20 +151,29 @@ public:
{
DEBUG("depth--");
if(depth == 0)
- throw ParseError::Generic(FMT("Unmatched " << Token(close) << " in macro content"));
+ 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 )
{
if( !allow_sub )
throw ParseError::Unexpected(lex, tok);
- auto content = Parse_MacroRules_Cont(lex, true, TOK_PAREN_OPEN, TOK_PAREN_CLOSE);
+ ::std::set<unsigned int> var_set;
+ auto content = Parse_MacroRules_Cont(lex, true, 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;
@@ -170,11 +186,9 @@ public:
switch(tok.type())
{
case TOK_STAR:
- ret.push_back( MacroRuleEnt(joiner, ::std::move(content)) );
- break;
case TOK_PLUS:
- // TODO: Ensure that the plusses match
- ret.push_back( MacroRuleEnt(joiner, ::std::move(content)) );
+ // TODO: Ensure that +/* match up
+ ret.push_back( MacroExpansionEnt({mv$(content), joiner, mv$(var_set)}) );
break;
default:
throw ParseError::Unexpected(lex, tok);
@@ -183,11 +197,18 @@ public:
}
else if( tok.type() == TOK_IDENT )
{
- ret.push_back( MacroRuleEnt(tok.str()) );
+ // Look up the named parameter in the list of param names for this arm
+ unsigned int idx = ::std::find(var_names.begin(), var_names.end(), tok.str()) - var_names.begin();
+ if( idx == var_names.size() )
+ ERROR(lex.getPosition(), E0000, "Macro variable $" << tok.str() << " not found");
+ if( var_set_ptr ) {
+ var_set_ptr->insert( idx );
+ }
+ ret.push_back( MacroExpansionEnt(idx) );
}
else if( tok.type() == TOK_RWORD_CRATE )
{
- ret.push_back( MacroRuleEnt("*crate") );
+ ret.push_back( MacroExpansionEnt( (1<<30) | 0 ) );
}
else
{
@@ -196,7 +217,7 @@ public:
}
else
{
- ret.push_back( MacroRuleEnt(tok) );
+ ret.push_back( MacroExpansionEnt( mv$(tok) ) );
}
}
@@ -233,7 +254,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex)
default:
throw ParseError::Unexpected(lex, tok);
}
- rule.m_contents = Parse_MacroRules_Cont(lex, true, tok.type(), close);
+ rule.m_contents = Parse_MacroRules_Cont(lex, true, tok.type(), close, names);
DEBUG("Rule - ["<<rule.m_pattern<<"] => "<<rule.m_contents<<"");
@@ -432,8 +453,8 @@ MacroRulesPtr Parse_MacroRules(TokenStream& lex)
// Re-parse the patterns into a unified form
for(unsigned int rule_idx = 0; rule_idx < rules.size(); rule_idx ++)
{
- const auto& rule = rules[rule_idx];
- MacroRulesArm arm( mv$(rule.m_contents) );
+ auto& rule = rules[rule_idx];
+ MacroRulesArm arm = MacroRulesArm( mv$(rule.m_contents) );
enumerate_names(rule.m_pattern, arm.m_param_names);
diff --git a/src/main.cpp b/src/main.cpp
index 85307663..38b060fb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -25,9 +25,9 @@ int g_debug_indent_level = 0;
bool debug_enabled()
{
- //return true;
+ return true;
//return g_cur_phase != "Parse";
- return g_cur_phase != "Parse" && g_cur_phase != "Expand";
+ //return g_cur_phase != "Parse" && g_cur_phase != "Expand";
//return g_cur_phase != "Parse" && g_cur_phase != "Expand" && g_cur_phase != "Resolve";
}
::std::ostream& debug_output(int indent, const char* function)
diff --git a/src/parse/interpolated_fragment.cpp b/src/parse/interpolated_fragment.cpp
index dd490bf5..e907978b 100644
--- a/src/parse/interpolated_fragment.cpp
+++ b/src/parse/interpolated_fragment.cpp
@@ -71,6 +71,35 @@ InterpolatedFragment::InterpolatedFragment(TypeRef v):
::std::ostream& operator<<(::std::ostream& os, InterpolatedFragment const& x)
{
+ switch(x.m_type)
+ {
+ case InterpolatedFragment::TT:
+ os << "tt[" << x.as_tt() << "]";
+ break;
+ case InterpolatedFragment::PAT:
+ os << "pat[" << *reinterpret_cast<AST::Pattern*>(x.m_ptr) << "]";
+ break;
+ case InterpolatedFragment::PATH:
+ os << "path[" << *reinterpret_cast<AST::Path*>(x.m_ptr) << "]";
+ break;
+ case InterpolatedFragment::TYPE:
+ os << "type[" << *reinterpret_cast<TypeRef*>(x.m_ptr) << "]";
+ break;
+
+ case InterpolatedFragment::EXPR:
+ os << "expr[" << *reinterpret_cast<AST::ExprNode*>(x.m_ptr) << "]";
+ break;
+ case InterpolatedFragment::STMT:
+ os << "stmt[" << *reinterpret_cast<AST::ExprNode*>(x.m_ptr) << "]";
+ break;
+ case InterpolatedFragment::BLOCK:
+ os << "block[" << *reinterpret_cast<AST::ExprNode*>(x.m_ptr) << "]";
+ break;
+
+ case InterpolatedFragment::META:
+ os << "meta[" << *reinterpret_cast<AST::MetaItem*>(x.m_ptr) << "]";
+ break;
+ }
return os;
}
diff --git a/src/parse/interpolated_fragment.hpp b/src/parse/interpolated_fragment.hpp
index 40aa764a..db2c770f 100644
--- a/src/parse/interpolated_fragment.hpp
+++ b/src/parse/interpolated_fragment.hpp
@@ -44,6 +44,7 @@ public:
InterpolatedFragment(Type , ::AST::ExprNode*);
TokenTree& as_tt() { assert(m_type == TT); return *reinterpret_cast<TokenTree*>(m_ptr); }
+ const TokenTree& as_tt() const { assert(m_type == TT); return *reinterpret_cast<TokenTree*>(m_ptr); }
friend ::std::ostream& operator<<(::std::ostream& os, const InterpolatedFragment& x);
};