Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Common/CodeLocationTools.cpp

    r7675f58 rf6e6a55  
    1010// Created On       : Fri Dec  4 15:42:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May 11 16:16:00 2022
    13 // Update Count     : 5
     12// Last Modified On : Mon Mar 14 15:14:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    2424namespace {
    2525
     26// There are a lot of helpers in this file that could be used much more
     27// generally if anyone has another use for them.
     28
     29// Check if a node type has a code location.
     30template<typename node_t>
     31struct has_code_location : public std::is_base_of<ast::ParseNode, node_t> {};
     32
     33template<typename node_t, bool has_location>
     34struct __GetCL;
     35
     36template<typename node_t>
     37struct __GetCL<node_t, true> {
     38        static inline CodeLocation const * get( node_t const * node ) {
     39                return &node->location;
     40        }
     41
     42        static inline CodeLocation * get( node_t * node ) {
     43                return &node->location;
     44        }
     45};
     46
     47template<typename node_t>
     48struct __GetCL<node_t, false> {
     49        static inline CodeLocation * get( node_t const * ) {
     50                return nullptr;
     51        }
     52};
     53
     54template<typename node_t>
     55CodeLocation const * get_code_location( node_t const * node ) {
     56        return __GetCL< node_t, has_code_location< node_t >::value >::get( node );
     57}
     58
     59template<typename node_t>
     60CodeLocation * get_code_location( node_t * node ) {
     61        return __GetCL< node_t, has_code_location< node_t >::value >::get( node );
     62}
     63
    2664// Fill every location with a nearby (parent) location.
    2765class FillCore : public ast::WithGuards {
    2866        CodeLocation const * parent;
     67public:
     68        FillCore() : parent( nullptr ) {}
    2969
    3070        template<typename node_t>
    31         node_t const * parse_visit( node_t const * node ) {
    32                 if ( node->location.isUnset() ) {
     71        node_t const * previsit( node_t const * node ) {
     72                GuardValue( parent );
     73                CodeLocation const * location = get_code_location( node );
     74                if ( location && location->isUnset() ) {
    3375                        assert( parent );
    3476                        node_t * newNode = ast::mutate( node );
    35                         newNode->location = *parent;
     77                        CodeLocation * newLocation = get_code_location( newNode );
     78                        assert( newLocation );
     79                        *newLocation = *parent;
     80                        parent = newLocation;
    3681                        return newNode;
    37                 }
    38                 GuardValue( parent ) = &node->location;
     82                } else if ( location ) {
     83                        parent = location;
     84                }
    3985                return node;
    40         }
    41 
    42         bool hasUnsetLabels( const ast::Stmt * stmt ) {
    43                 for ( const ast::Label& label : stmt->labels ) {
    44                         if ( label.location.isUnset() ) {
    45                                 return true;
    46                         }
    47                 }
    48                 return false;
    49         }
    50 
    51         template<typename node_t>
    52         node_t const * stmt_visit( node_t const * node ) {
    53                 assert( node->location.isSet() );
    54 
    55                 if ( hasUnsetLabels( node ) ) {
    56                         node_t * newNode = ast::mutate( node );
    57                         for ( ast::Label& label : newNode->labels ) {
    58                                 if ( label.location.isUnset() ) {
    59                                         label.location = newNode->location;
    60                                 }
    61                         }
    62                         return newNode;
    63                 }
    64                 return node;
    65         }
    66 
    67         template<typename node_t>
    68         auto visit( node_t const * node, long ) {
    69                 return node;
    70         }
    71 
    72         template<typename node_t>
    73         auto visit( node_t const * node, int ) -> typename
    74                         std::remove_reference< decltype( node->location, node ) >::type {
    75                 return parse_visit( node );
    76         }
    77 
    78         template<typename node_t>
    79         auto visit( node_t const * node, char ) -> typename
    80                         std::remove_reference< decltype( node->labels, node ) >::type {
    81                 return stmt_visit( parse_visit( node ) );
    82         }
    83 
    84 public:
    85         FillCore() : parent( nullptr ) {}
    86         FillCore( const CodeLocation& location ) : parent( &location ) {
    87                 assert( location.isSet() );
    88         }
    89 
    90         template<typename node_t>
    91         node_t const * previsit( node_t const * node ) {
    92                 return visit( node, '\0' );
    9386        }
    9487};
     
    240233
    241234        template<typename node_t>
    242         auto previsit( node_t const * node ) -> decltype( node->location, void() ) {
    243                 if ( node->location.isUnset() ) {
     235        void previsit( node_t const * node ) {
     236                CodeLocation const * location = get_code_location( node );
     237                if ( location && location->isUnset() ) {
    244238                        unset.push_back( node );
     239                }
     240        }
     241};
     242
     243class LocalFillCore : public ast::WithGuards {
     244        CodeLocation const * parent;
     245public:
     246        LocalFillCore( CodeLocation const & location ) : parent( &location ) {
     247                assert( location.isSet() );
     248        }
     249
     250        template<typename node_t>
     251        auto previsit( node_t const * node )
     252                        -> typename std::enable_if<has_code_location<node_t>::value, node_t const *>::type {
     253                if ( node->location.isSet() ) {
     254                        GuardValue( parent ) = &node->location;
     255                        return node;
     256                } else {
     257                        node_t * mut = ast::mutate( node );
     258                        mut->location = *parent;
     259                        return mut;
    245260                }
    246261        }
     
    289304ast::Node const * localFillCodeLocations(
    290305                CodeLocation const & location , ast::Node const * node ) {
    291         ast::Pass<FillCore> visitor( location );
     306        ast::Pass<LocalFillCore> visitor( location );
    292307        return node->accept( visitor );
    293308}
Note: See TracChangeset for help on using the changeset viewer.