diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | src/common.hpp | 4 | ||||
-rw-r--r-- | src/macros.cpp | 223 | ||||
-rw-r--r-- | src/macros.hpp | 2 | ||||
-rw-r--r-- | src/parse/expr.cpp | 9 | ||||
-rw-r--r-- | src/parse/root.cpp | 11 | ||||
-rw-r--r-- | src/parse/tokentree.hpp | 1 | ||||
-rw-r--r-- | src/parse/types.cpp | 37 |
8 files changed, 219 insertions, 72 deletions
@@ -36,12 +36,12 @@ clean: output/%.ast: samples/%.rs $(BIN) @mkdir -p output/ - $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 20 ; test $${PIPESTATUS[0]} -eq 0 + $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 40 ; test $${PIPESTATUS[0]} -eq 0 RUSTCSRC := ../../../Source/rust/rustc-nightly/ output/core.ast: $(RUSTCSRC)src/libcore/lib.rs $(BIN) @mkdir -p output/ - $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 20 ; test $${PIPESTATUS[0]} -eq 0 + $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 40 ; test $${PIPESTATUS[0]} -eq 0 test: output/core.ast $(BIN) diff --git a/src/common.hpp b/src/common.hpp index c3525d42..457d58b0 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -123,8 +123,8 @@ inline ::std::ostream& operator<<(::std::ostream& os, const ::std::pair<T,U>& v) return os; } -template <typename T, typename U> -inline ::std::ostream& operator<<(::std::ostream& os, const ::std::map<T,U>& v) { +template <typename T, typename U, class Cmp> +inline ::std::ostream& operator<<(::std::ostream& os, const ::std::map<T,U,Cmp>& v) { if( v.size() > 0 ) { bool is_first = true; diff --git a/src/macros.cpp b/src/macros.cpp index ea26fd43..c0782ab9 100644 --- a/src/macros.cpp +++ b/src/macros.cpp @@ -6,6 +6,7 @@ #include "parse/tokentree.hpp"
#include "parse/common.hpp"
#include "ast/ast.hpp"
+#include <limits.h>
typedef ::std::map< ::std::string, MacroRules> t_macro_regs;
@@ -37,15 +38,27 @@ class ParameterMappings };
::std::vector<unsigned int> m_layer_indexes;
- ::std::multimap<t_mapping_key, TokenTree> m_inner;
::std::map<t_mapping_block, unsigned int> m_counts;
+
+ struct Mapping {
+ t_mapping_block block;
+ ::std::vector<TokenTree> entries;
+ friend ::std::ostream& operator<<(::std::ostream& os, const Mapping& x) {
+ os << "(" << x.block.first << ", " << x.block.second << "): '"<<x.entries<<"')";
+ return os;
+ }
+ };
+ struct less_cstr {
+ bool operator()(const char *a, const char *b) const { return ::std::strcmp(a,b) < 0; }
+ };
+ ::std::map<const char *, Mapping, less_cstr> m_inner;
public:
ParameterMappings()
{
}
- const ::std::multimap<t_mapping_key, TokenTree>& inner_() const {
+ const ::std::map<const char *, Mapping, less_cstr>& inner_() const {
return m_inner;
}
@@ -63,35 +76,35 @@ public: }
void insert(unsigned int layer, const char *name, TokenTree data) {
- unsigned int iteration = (layer > 0 ? m_layer_indexes.at(layer-1) : 0);
- m_inner.insert( ::std::make_pair(
- t_mapping_key { {layer, iteration}, name },
- ::std::move(data)
- ) );
+ auto v = m_inner.insert( ::std::make_pair( name, Mapping { {layer, 0}, {} } ) );
+ if(v.first->second.block.first != layer) {
+ throw ParseError::Generic(FMT("matching '"<<name<<"' at multiple layers"));
+ }
+ v.first->second.entries.push_back( data );
}
void calculate_counts()
{
- assert( m_counts.size() == 0 );
- auto ins_it = m_counts.begin();
- const char* name = nullptr;
- for( const auto& p : m_inner )
- {
- // If the first iteration, or the block changes
- if( ins_it == m_counts.end() || ins_it->first < p.first.block )
- {
- ins_it = m_counts.insert(ins_it, ::std::make_pair(p.first.block, 1));
- name = p.first.name;
- }
- else if( ::std::strcmp(name, p.first.name) == 0 )
- {
- ins_it->second ++;
- }
- else
- {
- // Ignore, the name has changed
- }
- }
+ //assert( m_counts.size() == 0 );
+ //auto ins_it = m_counts.begin();
+ //const char* name = nullptr;
+ //for( const auto& p : m_inner )
+ //{
+ // // If the first iteration, or the block changes
+ // if( ins_it == m_counts.end() || ins_it->first < p.first.block )
+ // {
+ // ins_it = m_counts.insert(ins_it, ::std::make_pair(p.first.block, 1));
+ // name = p.first.name;
+ // }
+ // else if( ::std::strcmp(name, p.first.name) == 0 )
+ // {
+ // ins_it->second ++;
+ // }
+ // else
+ // {
+ // // Ignore, the name has changed
+ // }
+ //}
}
unsigned int iter_count(unsigned int layer, unsigned int parent_iteration) const {
@@ -107,24 +120,49 @@ public: const TokenTree* get(unsigned int layer, unsigned int iteration, const char *name, unsigned int idx) const
{
- const auto it_range = m_inner.equal_range( t_mapping_key { {layer, iteration}, name } );
- if( it_range.first == it_range.second ) {
+ const auto it = m_inner.find( name );
+ if( it == m_inner.end() ) {
DEBUG("m_mappings = " << m_inner);
return nullptr;
}
+ const 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];
+ }
+ }
+ unsigned int count(unsigned int layer, unsigned int iteration, const char *name) const
+ {
+ const auto it = m_inner.find( name );
+ if( it == m_inner.end() ) {
+ DEBUG("("<<layer<<","<<iteration<<",'"<<name<<"') not found m_mappings = " << m_inner);
+ return 0;
+ }
+ const auto& e = it->second;
- size_t i = 0;
- for( auto it = it_range.first; it != it_range.second; it ++ )
- {
- if( i == idx )
- {
- DEBUG(name << " #" << i);
- return &it->second;
- }
- i ++;
+ 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 it->second.entries.size();
}
- DEBUG("Not enough mappings for name " << name << " at layer " << layer << " PI " << iteration);
- return nullptr;
}
};
@@ -139,8 +177,14 @@ private: const ::std::vector<MacroRuleEnt>& m_root_contents;
const ParameterMappings m_mappings;
+
+ struct t_offset {
+ unsigned read_pos;
+ unsigned loop_index;
+ unsigned max_index;
+ };
/// Layer states : Index and Iteration
- ::std::vector< ::std::pair<size_t,size_t> > m_offsets;
+ ::std::vector< t_offset > m_offsets;
::std::vector< size_t > m_layer_iters;
/// Cached pointer to the current layer
@@ -155,7 +199,7 @@ public: m_crate_name(x.m_crate_name),
m_root_contents(x.m_root_contents),
m_mappings(x.m_mappings),
- m_offsets({ {0,0} }),
+ m_offsets({ {0,0,0} }),
m_cur_ents(&m_root_contents)
{
prep_counts();
@@ -165,7 +209,7 @@ public: m_crate_name(crate_name),
m_root_contents(contents),
m_mappings(mappings),
- m_offsets({ {0,0} }),
+ m_offsets({ {0,0,0} }),
m_cur_ents(&m_root_contents)
{
prep_counts();
@@ -177,6 +221,7 @@ private: const MacroRuleEnt& getCurLayerEnt() const;
const ::std::vector<MacroRuleEnt>* getCurLayer() const;
void prep_counts();
+ unsigned int count_repeats(const ::std::vector<MacroRuleEnt>& ents, unsigned layer, unsigned iter);
};
class MacroToken:
@@ -274,6 +319,8 @@ bool Macro_TryPattern(TTStream& lex, const MacroPatEnt& pat) catch( const CompileError::Base& e ) {
return false;
}
+ case MacroPatEnt::PAT_META:
+ return LOOK_AHEAD(lex) == TOK_IDENT;
}
throw ParseError::Todo(lex, FMT("Macro_TryPattern : " << pat));
}
@@ -356,6 +403,9 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay case MacroPatEnt::PAT_BLOCK:
val = Parse_TT_Block(lex);
if(0)
+ case MacroPatEnt::PAT_META:
+ val = Parse_TT_Meta(lex);
+ if(0)
case MacroPatEnt::PAT_IDENT:
{
GET_CHECK_TOK(tok, lex, TOK_IDENT);
@@ -499,7 +549,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay Position MacroExpander::getPosition() const
{
DEBUG("olex.getPosition() = " << m_olex.getPosition());
- return Position(FMT("Macro:" << ""), m_offsets[0].first);
+ return Position(FMT("Macro:" << ""), m_offsets[0].read_pos);
}
Token MacroExpander::realGetToken()
{
@@ -527,8 +577,7 @@ Token MacroExpander::realGetToken() const auto& ents = *m_cur_ents;
// Obtain current read position in layer, and increment
- size_t idx = m_offsets.back().first;
- m_offsets.back().first ++;
+ size_t idx = m_offsets.back().read_pos++;
// Check if limit has been reached
if( idx < ents.size() )
@@ -549,11 +598,12 @@ Token MacroExpander::realGetToken() // - Expand to a parameter
else if( ent.name != "" )
{
+ DEBUG("lookup '" << ent.name << "'");
const TokenTree* tt;
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).second;
+ const size_t iter_idx = m_offsets.at(search_layer).loop_index;
tt = m_mappings.get(search_layer, parent_iter, ent.name.c_str(), iter_idx);
} while( !tt && search_layer-- > 0 );
if( ! tt )
@@ -571,13 +621,15 @@ Token MacroExpander::realGetToken() {
DEBUG("desc: layer = " << layer << ", m_layer_iters = " << m_layer_iters);
unsigned int layer_iter = m_layer_iters.at(layer);
- unsigned int num_repeats = m_mappings.iter_count(layer+1, layer_iter);
+ 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( ::std::make_pair(0, 0) );
+ m_offsets.push_back( {0, 0, num_repeats} );
// - Save the current layer
m_cur_ents = getCurLayer();
// - Restart loop for new layer
@@ -600,16 +652,15 @@ Token MacroExpander::realGetToken() {
// - Otherwise, restart/end loop and fall through
DEBUG("layer = " << layer << ", m_layer_iters = " << m_layer_iters);
- unsigned int parent_layer_iter = m_layer_iters.at(layer-1);
- unsigned int layer_max = m_mappings.iter_count(layer, parent_layer_iter);
- DEBUG("Layer #" << layer << " Cur: " << m_offsets.back().second << ", Max: " << layer_max);
- if( m_offsets.back().second + 1 < layer_max )
+ 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) ++;
DEBUG("Restart layer");
- m_offsets.back().first = 0;
- m_offsets.back().second ++;
+ cur_ofs.read_pos = 0;
+ cur_ofs.loop_index ++;
auto& loop_layer = getCurLayerEnt();
assert(loop_layer.subpats.size());
@@ -654,11 +705,11 @@ const MacroRuleEnt& MacroExpander::getCurLayerEnt() const const ::std::vector<MacroRuleEnt>* ents = &m_root_contents;
for( unsigned int i = 0; i < m_offsets.size()-2; i ++ )
{
- unsigned int ofs = m_offsets[i].first;
+ unsigned int ofs = m_offsets[i].read_pos;
assert( ofs > 0 && ofs <= ents->size() );
ents = &(*ents)[ofs-1].subpats;
}
- return (*ents)[m_offsets[m_offsets.size()-2].first-1];
+ return (*ents)[m_offsets[m_offsets.size()-2].read_pos-1];
}
const ::std::vector<MacroRuleEnt>* MacroExpander::getCurLayer() const
@@ -667,7 +718,7 @@ const ::std::vector<MacroRuleEnt>* MacroExpander::getCurLayer() const const ::std::vector<MacroRuleEnt>* ents = &m_root_contents;
for( unsigned int i = 0; i < m_offsets.size()-1; i ++ )
{
- unsigned int ofs = m_offsets[i].first;
+ 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;
@@ -675,6 +726,60 @@ const ::std::vector<MacroRuleEnt>* MacroExpander::getCurLayer() const }
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;
+ }
+}
void Macro_Invoke_Concat_Once(::std::string& s, TokenStream& lex, enum eTokenType exp)
{
@@ -801,6 +906,7 @@ void operator%(Serialiser& s, MacroPatEnt::Type c) { _(PAT_STMT);
_(PAT_PATH);
_(PAT_BLOCK);
+ _(PAT_META);
_(PAT_IDENT);
#undef _
}
@@ -820,6 +926,7 @@ void operator%(::Deserialiser& s, MacroPatEnt::Type& c) { _(PAT_STMT);
_(PAT_PATH);
_(PAT_BLOCK);
+ _(PAT_META);
_(PAT_IDENT);
else
throw ::std::runtime_error( FMT("No conversion for '" << n << "'") );
diff --git a/src/macros.hpp b/src/macros.hpp index 1111b2f2..b28370d9 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -70,6 +70,7 @@ struct MacroPatEnt: PAT_EXPR,
PAT_STMT,
PAT_BLOCK,
+ PAT_META,
PAT_LOOP, // Enables use of subpats
} type;
@@ -112,6 +113,7 @@ struct MacroPatEnt: case PAT_EXPR: os << "expr "; break;
case PAT_STMT: os << "stmt "; break;
case PAT_BLOCK: os << "block "; break;
+ case PAT_META: os << "meta "; break;
case PAT_LOOP: os << "loop "; break;
}
if(x.name.size())
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index b9a3d003..12aa3d3a 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -640,6 +640,7 @@ bool Parse_IsTokValue(eTokenType tok_type) case TOK_MACRO:
+ case TOK_PIPE:
case TOK_EXCLAM:
case TOK_DASH:
case TOK_STAR:
@@ -1297,3 +1298,11 @@ TokenTree Parse_TT_Block(TokenStream& lex) throw ParseError::Todo("Parse_TT_Block");
}
+TokenTree Parse_TT_Meta(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+ TTLexer wlex(lex);
+ SET_PARSE_FLAG(wlex, no_expand_macros);
+ Parse_MetaItem(wlex);
+ return wlex.get_output();
+}
diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 15268ce9..eeeafb0e 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -395,6 +395,13 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems meta_items) break;
}
CHECK_TOK(tok, TOK_PAREN_CLOSE);
+
+ if(LOOK_AHEAD(lex) == TOK_RWORD_WHERE)
+ {
+ GET_TOK(tok, lex);
+ Parse_WhereClause(lex, params);
+ }
+ // TODO: Where block
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
if( refs.size() == 0 )
throw ParseError::Generic(lex, "Use 'struct Name;' instead of 'struct Name();' ... ning-nong");
@@ -1008,8 +1015,10 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_EXPR) );
else if( type == "ty" )
ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_TYPE) );
+ else if( type == "meta" )
+ ret.push_back( MacroPatEnt(name, MacroPatEnt::PAT_META) );
else
- throw ParseError::Generic(FMT("Unknown fragment type " << type));
+ throw ParseError::Generic(lex, FMT("Unknown fragment type " << type));
break; }
case TOK_PAREN_OPEN:
if( allow_sub )
diff --git a/src/parse/tokentree.hpp b/src/parse/tokentree.hpp index 34418340..cde35c8c 100644 --- a/src/parse/tokentree.hpp +++ b/src/parse/tokentree.hpp @@ -65,5 +65,6 @@ extern TokenTree Parse_TT_Type(TokenStream& lex); extern TokenTree Parse_TT_Stmt(TokenStream& lex);
extern TokenTree Parse_TT_Block(TokenStream& lex);
extern TokenTree Parse_TT_Path(TokenStream& lex, bool mode_expr);
+extern TokenTree Parse_TT_Meta(TokenStream& lex);
#endif // TOKENTREE_HPP_INCLUDED
diff --git a/src/parse/types.cpp b/src/parse/types.cpp index 2070a0d2..95076e29 100644 --- a/src/parse/types.cpp +++ b/src/parse/types.cpp @@ -35,7 +35,7 @@ static const struct { // === PROTOTYPES === TypeRef Parse_Type(TokenStream& lex); -TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi); +TypeRef Parse_Type_Fn(TokenStream& lex); // === CODE === TypeRef Parse_Type(TokenStream& lex) @@ -52,16 +52,18 @@ TypeRef Parse_Type(TokenStream& lex) // '_' = Wildcard (type inferrence variable) case TOK_UNDERSCORE: return TypeRef(); + // 'unsafe' - An unsafe function type + case TOK_RWORD_UNSAFE: + lex.putback(tok); + return Parse_Type_Fn(lex); // 'extern' - A function type with an ABI - case TOK_RWORD_EXTERN: { - GET_CHECK_TOK(tok, lex, TOK_STRING); - ::std::string abi = tok.str(); - GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); - return Parse_Type_Fn(lex, abi); - } + case TOK_RWORD_EXTERN: + lex.putback(tok); + return Parse_Type_Fn(lex); // 'fn' - Rust function case TOK_RWORD_FN: - return Parse_Type_Fn(lex, ""); + lex.putback(tok); + return Parse_Type_Fn(lex); // '<' - An associated type cast case TOK_LT: lex.putback(tok); @@ -222,11 +224,28 @@ TypeRef Parse_Type(TokenStream& lex) throw ParseError::BugCheck("Reached end of Parse_Type"); } -TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi) +TypeRef Parse_Type_Fn(TokenStream& lex) { TRACE_FUNCTION; Token tok; + ::std::string abi = ""; + + GET_TOK(tok, lex); + + if( tok.type() == TOK_RWORD_UNSAFE ) + { + // TODO: Unsafe functions in types + GET_TOK(tok, lex); + } + if( tok.type() == TOK_RWORD_EXTERN ) + { + GET_CHECK_TOK(tok, lex, TOK_STRING); + abi = tok.str(); + GET_TOK(tok, lex); + } + CHECK_TOK(tok, TOK_RWORD_FN); + ::std::vector<TypeRef> args; GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE ) |