Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Pass.proto.hpp

    r10a1225 re4b6cf78  
    107107                bool     * m_prev;
    108108                bool_ref * m_ref;
     109        };
     110
     111        /// "Short hand" to check if this is a valid previsit function
     112        /// Mostly used to make the static_assert look (and print) prettier
     113        template<typename pass_t, typename node_t>
     114        struct is_valid_previsit {
     115                using ret_t = decltype( ((pass_t*)nullptr)->previsit( (const node_t *)nullptr ) );
     116
     117                static constexpr bool value = std::is_void< ret_t >::value ||
     118                        std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value;
     119        };
     120
     121        /// Used by previsit implementation
     122        /// We need to reassign the result to 'node', unless the function
     123        /// returns void, then we just leave 'node' unchanged
     124        template<bool is_void>
     125        struct __assign;
     126
     127        template<>
     128        struct __assign<true> {
     129                template<typename pass_t, typename node_t>
     130                static inline void result( pass_t & pass, const node_t * & node ) {
     131                        pass.previsit( node );
     132                }
     133        };
     134
     135        template<>
     136        struct __assign<false> {
     137                template<typename pass_t, typename node_t>
     138                static inline void result( pass_t & pass, const node_t * & node ) {
     139                        node = pass.previsit( node );
     140                        assertf(node, "Previsit must not return NULL");
     141                }
     142        };
     143
     144        /// Used by postvisit implementation
     145        /// We need to return the result unless the function
     146        /// returns void, then we just return the original node
     147        template<bool is_void>
     148        struct __return;
     149
     150        template<>
     151        struct __return<true> {
     152                template<typename pass_t, typename node_t>
     153                static inline const node_t * result( pass_t & pass, const node_t * & node ) {
     154                        pass.postvisit( node );
     155                        return node;
     156                }
     157        };
     158
     159        template<>
     160        struct __return<false> {
     161                template<typename pass_t, typename node_t>
     162                static inline auto result( pass_t & pass, const node_t * & node ) {
     163                        return pass.postvisit( node );
     164                }
    109165        };
    110166
     
    126182        template<typename pass_t, typename node_t>
    127183        static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) {
    128                 node = pass.previsit( node );
    129                 assert(node);
     184                static_assert(
     185                        is_valid_previsit<pass_t, node_t>::value,
     186                        "Previsit may not change the type of the node. It must return its paremeter or void."
     187                );
     188
     189                __assign<
     190                        std::is_void<
     191                                decltype( pass.previsit( node ) )
     192                        >::value
     193                >::result( pass, node );
    130194        }
    131195
     
    135199        // PostVisit : never mutates the passed pointer but may return a different node
    136200        template<typename pass_t, typename node_t>
    137         static inline auto postvisit( pass_t & pass, const node_t * node, int ) -> decltype( pass.postvisit( node ), (const node_t *)nullptr ) {
    138                 return pass.postvisit( node );
     201        static inline auto postvisit( pass_t & pass, const node_t * node, int ) ->
     202                decltype( pass.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
     203        {
     204                return __return<
     205                        std::is_void<
     206                                decltype( pass.postvisit( node ) )
     207                        >::value
     208                >::result( pass, node );
    139209        }
    140210
Note: See TracChangeset for help on using the changeset viewer.