#include "externals.hh" #include "c-opopt.hh" #include "c-sync.hh" using namespace ebcl; using namespace opast; using namespace opopt; // Macro to use either the specified visitor or a visitor created just for the // occation #define M_VISITOR_( E ) \ T_OwnPtr< T_Visitor< A_Node > > localVisitor_; \ if ( !(E) ) { \ localVisitor_ = NewOwned< T_Visitor< A_Node > >( ASTVisitorBrowser ); \ } \ T_Visitor< A_Node >& visitor{ (E) ? *(E) : *localVisitor_ } /*= CONSTANT FOLDING =========================================================*/ namespace { struct T_ConstantFolder_ { // Input T_Optional< std::pair< uint32_t , uint32_t > > fixedSize; T_SyncCurves const* curves; // Result bool didFold{ false }; bool operator()( A_Node& node , bool exit ) noexcept; private: using F_ExprGet_ = std::function< A_ExpressionNode&( A_Node& ) >; using F_ExprSet_ = std::function< void( A_Node& , P_ExpressionNode ) >; void handleParentNode( A_Node& node , F_ExprGet_ get , F_ExprSet_ set ) noexcept; P_ExpressionNode checkExpression( A_ExpressionNode const& node ) noexcept; }; /*----------------------------------------------------------------------------*/ bool T_ConstantFolder_::operator()( A_Node& node , const bool exit ) noexcept { if ( exit ) { return true; } switch ( node.type( ) ) { case A_Node::TN_ARG: handleParentNode( node , []( A_Node& n ) -> A_ExpressionNode& { return ((T_ArgumentNode&)n).expression( ); } , []( A_Node& n , P_ExpressionNode e ) { ((T_ArgumentNode&)n).expression( std::move( e ) ); } ); return false; case A_Node::TN_CONDITION: handleParentNode( node , []( A_Node& n ) -> A_ExpressionNode& { return ((T_CondInstrNode::T_Expression&)n).expression( ); } , []( A_Node& n , P_ExpressionNode e ) { ((T_CondInstrNode::T_Expression&)n).expression( std::move( e ) ); } ); return false; case A_Node::OP_SET: handleParentNode( node , []( A_Node& n ) -> A_ExpressionNode& { return ((T_SetInstrNode&)n).expression( ); } , []( A_Node& n , P_ExpressionNode e ) { ((T_SetInstrNode&)n).setExpression( std::move( e ) ); } ); return false; default: return true; } } void T_ConstantFolder_::handleParentNode( A_Node& node , F_ExprGet_ get , F_ExprSet_ set ) noexcept { auto r{ checkExpression( get( node ) ) }; if ( r ) { set( node , std::move( r ) ); didFold = true; } } /*----------------------------------------------------------------------------*/ P_ExpressionNode T_ConstantFolder_::checkExpression( A_ExpressionNode const& node ) noexcept { #warning TODO optimize the fuck // 1/ Replace inputs with value if no curve/constant curve // Replace $width/$height with value if fixedSize // 2/ Replace UnOp( Cnst ) with result // Replace BinOp( Cnst , Cnst ) with result // 3/ Try to find other optimisations, e.g. for Add( Cnst , Add( Cnst , Expr ) ) if ( node.type( ) == A_Node::EXPR_ID ) { if ( !fixedSize ) { return {}; } T_IdentifierExprNode& n{ (T_IdentifierExprNode&) node }; if ( n.id( ) == "width" ) { auto c{ NewOwned< T_ConstantExprNode >( n.parent( ) , double( fixedSize->first ) ) }; c->location( ) = n.location( ); return c; } if ( n.id( ) == "height" ) { auto c{ NewOwned< T_ConstantExprNode >( n.parent( ) , float( fixedSize->second ) ) }; c->location( ) = n.location( ); return c; } return {}; } return {}; } } // namespace bool opopt::FoldConstants( T_RootNode& root , const T_Optional< std::pair< uint32_t , uint32_t > > fixedSize , T_SyncCurves const* curves , T_Visitor< A_Node >* const extVisitor ) noexcept { M_VISITOR_( extVisitor ); T_ConstantFolder_ folder; folder.fixedSize = fixedSize; folder.curves = curves; visitor.visit( root , folder ); return folder.didFold; } /*= DEAD CODE REMOVAL ========================================================*/ bool opopt::RemoveDeadCode( opast::T_RootNode& root , ebcl::T_Visitor< opast::A_Node >* extVisitor ) noexcept { M_VISITOR_( extVisitor ); #warning blargh return false; }