Skip to content

Commit

Permalink
macro_rules - Add operators
Browse files Browse the repository at this point in the history
  • Loading branch information
thepowersgang committed Dec 5, 2023
1 parent 27d9838 commit 5a17160
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 13 deletions.
38 changes: 27 additions & 11 deletions src/macro_rules/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1996,14 +1996,19 @@ void Macro_InvokeRules_CountSubstUses(ParameterMappings& bound_tts, const ::std:
while(const auto* ent_ptr = state.next_ent())
{
DEBUG(*ent_ptr);
TU_IFLET(MacroExpansionEnt, (*ent_ptr), NamedValue, e,
if( e >> 30 ) {
}
else {
if(const auto* e = ent_ptr->opt_NamedValue()) {
switch(*e & ~NAMEDVALUE_VALMASK)
{
case 0:
case NAMEDVALUE_TY_IGNORE:
// Increment a counter in `bound_tts`
bound_tts.inc_count(state.iterations(), e);
bound_tts.inc_count(state.iterations(), *e & NAMEDVALUE_VALMASK);
break;
case NAMEDVALUE_TY_MAGIC:
default:
break;
}
)
}
}
}

Expand Down Expand Up @@ -2079,11 +2084,20 @@ Token MacroExpander::realGetToken()
}
}
TU_ARMA(NamedValue, e) {
if( e >> 30 ) {
switch( e & 0x3FFFFFFF )
switch(e & ~NAMEDVALUE_VALMASK)
{
default:
BUG(Span(), "Unknown macro metavar");
case NAMEDVALUE_TY_IGNORE: {
auto* frag = m_mappings.get(m_state.iterations(), e & NAMEDVALUE_VALMASK);
ASSERT_BUG(this->point_span(), frag, "Cannot find '" << (e & NAMEDVALUE_VALMASK) << "' for " << m_state.iterations());
// - Ignore
break; }
case NAMEDVALUE_TY_MAGIC: // NAMEDVALUE_TY_MAGIC
switch( e )
{
// - XXX: Hack for $crate special name
case 0:
case NAMEDVALUE_MAGIC_CRATE:
DEBUG("[" << m_log_index << "] Crate name hack");
if( m_crate_name == "" )
{
Expand All @@ -2098,11 +2112,12 @@ Token MacroExpander::realGetToken()
return Token(TOK_DOUBLE_COLON);
}
break;
case NAMEDVALUE_MAGIC_INDEX:
default:
BUG(Span(), "Unknown macro metavar");
}
}
else {
break;
case 0: {
auto* frag = m_mappings.get(m_state.iterations(), e);
ASSERT_BUG(this->point_span(), frag, "Cannot find '" << e << "' for " << m_state.iterations());

Expand All @@ -2126,6 +2141,7 @@ Token MacroExpander::realGetToken()
return Token( *frag );
}
}
} break;
}
}
TU_ARMA(Loop, e) {
Expand Down
6 changes: 6 additions & 0 deletions src/macro_rules/macro_rules.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ TAGGED_UNION(MacroExpansionEnt, Token,
})
);
extern ::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x);
static const unsigned int NAMEDVALUE_VALMASK = ((1<<30) - 1);
static const unsigned int NAMEDVALUE_TY_MAGIC = 1<<30;
static const unsigned int NAMEDVALUE_MAGIC_CRATE = NAMEDVALUE_TY_MAGIC | 0;
static const unsigned int NAMEDVALUE_MAGIC_INDEX = NAMEDVALUE_TY_MAGIC | 1;
static const unsigned int NAMEDVALUE_TY_IGNORE = 2<<30;
static const unsigned int NAMEDVALUE_TY_COUNT = 3<<30;

/// Matching pattern entry
struct MacroPatEnt
Expand Down
62 changes: 60 additions & 2 deletions src/macro_rules/parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ ::std::vector<MacroPatEnt> Parse_MacroRules_Pat(TokenStream& lex, enum eTokenTyp
{
case TOK_SQUARE_CLOSE:
case TOK_PAREN_CLOSE:
case TOK_BRACE_CLOSE:
ret.push_back( MacroPatEnt(lex.end_span(ps), TOK_DOLLAR) );
PUTBACK(tok, lex);
break;
Expand Down Expand Up @@ -382,9 +381,68 @@ ::std::vector<MacroExpansionEnt> Parse_MacroRules_Cont(
DEBUG("joiner = " << Token(joiner) << ", controlling_loops = {" << controlling_loops << "}, content = " << content);
ret.push_back( MacroExpansionEnt::make_Loop({ mv$(content), joiner, mv$(controlling_loops) }) );
}
// - `${operator(args}` - Extensions
else if( tok.type() == TOK_BRACE_OPEN )
{
auto ident = lex.getTokenCheck(TOK_IDENT).ident().name;
if( ident == "ignore" ) {
lex.getTokenCheck(TOK_PAREN_OPEN);
GET_TOK(tok, lex);
auto name = tok.type() == TOK_IDENT ? tok.ident().name : RcString::new_interned(tok.to_str());
lex.getTokenCheck(TOK_PAREN_CLOSE);
const auto* ns = state.find_name(name);
if( !ns ) {
TODO(lex.point_span(), "Handle ${ignore(" << name << ")} - Missing");
}

DEBUG("$" << name << " #" << ns->idx << " [" << ns->loops << "]");

// If the current loop depth is smaller than the stack for this variable, then error
if( loop_depth < ns->loops.size() ) {
ERROR(lex.point_span(), E0000, "Variable $" << name << " is still repeating at this depth (" << loop_depth << " < " << ns->loops.size() << ")");
}

if( var_usage_ptr ) {
var_usage_ptr->insert( ::std::make_pair(ns->idx, ContentLoopVariableUse(ns->loops)) );
}
ret.push_back( MacroExpansionEnt(NAMEDVALUE_TY_IGNORE | ns->idx) );
}
else if( ident == "count" ) {
lex.getTokenCheck(TOK_PAREN_OPEN);
GET_TOK(tok, lex);
auto name = tok.type() == TOK_IDENT ? tok.ident().name : RcString::new_interned(tok.to_str());
lex.getTokenCheck(TOK_PAREN_CLOSE);
const auto* ns = state.find_name(name);
if( !ns ) {
TODO(lex.point_span(), "Handle ${count(" << name << ")} - Missing");
}

DEBUG("$" << name << " #" << ns->idx << " [" << ns->loops << "]");

// Can still be repeating
//// If the current loop depth is smaller than the stack for this variable, then error
//if( loop_depth < ns->loops.size() ) {
// ERROR(lex.point_span(), E0000, "Variable $" << name << " is still repeating at this depth (" << loop_depth << " < " << ns->loops.size() << ")");
//}

if( var_usage_ptr ) {
var_usage_ptr->insert( ::std::make_pair(ns->idx, ContentLoopVariableUse(ns->loops)) );
}
ret.push_back( MacroExpansionEnt(NAMEDVALUE_TY_COUNT | ns->idx) );
}
else if( ident == "index" ) {
lex.getTokenCheck(TOK_PAREN_OPEN);
lex.getTokenCheck(TOK_PAREN_CLOSE);
ret.push_back( MacroExpansionEnt(NAMEDVALUE_MAGIC_INDEX) );
}
else {
TODO(lex.point_span(), "Handle ${" << ident << "...}");
}
lex.getTokenCheck(TOK_BRACE_CLOSE);
}
else if( tok.type() == TOK_RWORD_CRATE )
{
ret.push_back( MacroExpansionEnt( (1<<30) | 0 ) );
ret.push_back( MacroExpansionEnt(NAMEDVALUE_MAGIC_CRATE) );
}
else if( tok.type() == TOK_IDENT || Token::type_is_rword(tok.type()) )
{
Expand Down

0 comments on commit 5a17160

Please sign in to comment.