Changeset 3982384 for src


Ignore:
Timestamp:
May 17, 2023, 1:35:09 AM (2 years ago)
Author:
JiadaL <j82liang@…>
Branches:
ADT, master
Children:
f11010e
Parents:
6e4c44d (diff), 8db4708 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
2 added
18 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r6e4c44d r3982384  
    567567        }
    568568
     569    const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
     570                // There is no old-AST WhenClause, so this should never be called.
     571                assert( !node );
     572                return nullptr;
     573        }
     574
    569575        const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
    570576                if ( inCache( node ) ) return nullptr;
     
    573579                for ( auto clause : node->clauses ) {
    574580                        stmt->clauses.push_back({{
    575                                         get<Expression>().accept1( clause->target_func ),
     581                                        get<Expression>().accept1( clause->target ),
    576582                                        get<Expression>().acceptL( clause->target_args ),
    577583                                },
    578584                                get<Statement>().accept1( clause->stmt ),
    579                                 get<Expression>().accept1( clause->cond ),
     585                                get<Expression>().accept1( clause->when_cond ),
    580586                        });
    581587                }
     
    594600        const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
    595601                // There is no old-AST WaitForClause, so this should never be called.
     602                assert( !node );
     603                return nullptr;
     604        }
     605
     606    const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
     607        // There is no old-AST WaitUntilStmt, so this should never be called.
    596608                assert( !node );
    597609                return nullptr;
     
    21582170                        auto clause = new ast::WaitForClause( old->location );
    21592171
    2160                         clause->target_func = GET_ACCEPT_1(clauses[i].target.function, Expr);
     2172                        clause->target = GET_ACCEPT_1(clauses[i].target.function, Expr);
    21612173                        clause->target_args = GET_ACCEPT_V(clauses[i].target.arguments, Expr);
    21622174                        clause->stmt = GET_ACCEPT_1(clauses[i].statement, Stmt);
    2163                         clause->cond = GET_ACCEPT_1(clauses[i].condition, Expr);
     2175                        clause->when_cond = GET_ACCEPT_1(clauses[i].condition, Expr);
    21642176
    21652177                        stmt->clauses.push_back( clause );
  • src/AST/Fwd.hpp

    r6e4c44d r3982384  
    5858class FinallyClause;
    5959class SuspendStmt;
     60class WhenClause;
    6061class WaitForStmt;
    6162class WaitForClause;
     63class WaitUntilStmt;
    6264class WithStmt;
    6365class DeclStmt;
  • src/AST/Node.cpp

    r6e4c44d r3982384  
    174174template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::weak >;
    175175template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::strong >;
     176template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::weak >;
     177template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::strong >;
    176178template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >;
    177179template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >;
    178180template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::weak >;
    179181template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::strong >;
     182template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::weak >;
     183template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::strong >;
    180184template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::weak >;
    181185template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::strong >;
  • src/AST/Pass.hpp

    r6e4c44d r3982384  
    162162        const ast::FinallyClause *    visit( const ast::FinallyClause        * ) override final;
    163163        const ast::Stmt *             visit( const ast::SuspendStmt          * ) override final;
     164    const ast::WhenClause *       visit( const ast::WhenClause           * ) override final;
    164165        const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
    165166        const ast::WaitForClause *    visit( const ast::WaitForClause        * ) override final;
     167    const ast::Stmt *             visit( const ast::WaitUntilStmt        * ) override final;
    166168        const ast::Decl *             visit( const ast::WithStmt             * ) override final;
    167169        const ast::NullStmt *         visit( const ast::NullStmt             * ) override final;
  • src/AST/Pass.impl.hpp

    r6e4c44d r3982384  
    2222#include "AST/TranslationUnit.hpp"
    2323#include "AST/TypeSubstitution.hpp"
    24 #include "Common/Iterate.hpp"
    2524
    2625#define VISIT_START( node ) \
     
    127126        }
    128127
    129         template< typename node_t >
    130         template< typename object_t, typename super_t, typename field_t >
    131         void __pass::result1< node_t >::apply( object_t * object, field_t super_t::* field ) {
    132                 object->*field = value;
    133         }
    134 
    135128        template< typename core_t >
    136129        template< typename node_t >
     
    234227
    235228                return {true, compound};
    236         }
    237 
    238         template< template <class...> class container_t >
    239         template< typename object_t, typename super_t, typename field_t >
    240         void __pass::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {
    241                 auto & container = object->*field;
    242                 __pedantic_pass_assert( container.size() <= values.size() );
    243 
    244                 auto cit = enumerate(container).begin();
    245 
    246                 container_t<ptr<Stmt>> nvals;
    247                 for (delta & d : values) {
    248                         if ( d.is_old ) {
    249                                 __pedantic_pass_assert( cit.idx <= d.old_idx );
    250                                 std::advance( cit, d.old_idx - cit.idx );
    251                                 nvals.push_back( std::move( (*cit).val) );
    252                         } else {
    253                                 nvals.push_back( std::move(d.new_val) );
    254                         }
    255                 }
    256 
    257                 container = std::move(nvals);
    258         }
    259 
    260         template< template <class...> class container_t >
    261         template< template <class...> class incontainer_t >
    262         void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Stmt>> * stmts ) {
    263                 if (!stmts || stmts->empty()) return;
    264 
    265                 std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ),
    266                         [](ast::ptr<ast::Stmt>& stmt) -> delta {
    267                                 return delta( stmt.release(), -1, false );
    268                         });
    269                 stmts->clear();
    270                 differs = true;
    271         }
    272 
    273         template< template<class...> class container_t >
    274         template< template<class...> class incontainer_t >
    275         void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Decl>> * decls ) {
    276                 if (!decls || decls->empty()) return;
    277 
    278                 std::transform(decls->begin(), decls->end(), std::back_inserter( values ),
    279                         [](ast::ptr<ast::Decl>& decl) -> delta {
    280                                 auto loc = decl->location;
    281                                 auto stmt = new DeclStmt( loc, decl.release() );
    282                                 return delta( stmt, -1, false );
    283                         });
    284                 decls->clear();
    285                 differs = true;
    286229        }
    287230
     
    353296
    354297                return new_kids;
    355         }
    356 
    357         template< template <class...> class container_t, typename node_t >
    358         template< typename object_t, typename super_t, typename field_t >
    359         void __pass::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {
    360                 auto & container = object->*field;
    361                 __pedantic_pass_assert( container.size() == values.size() );
    362 
    363                 for(size_t i = 0; i < container.size(); i++) {
    364                         // Take all the elements that are different in 'values'
    365                         // and swap them into 'container'
    366                         if( values[i] != nullptr ) swap(container[i], values[i]);
    367                 }
    368 
    369                 // Now the original containers should still have the unchanged values
    370                 // but also contain the new values
    371298        }
    372299
     
    1066993
    1067994//--------------------------------------------------------------------------
     995// WhenClause
     996template< typename core_t >
     997const ast::WhenClause * ast::Pass< core_t >::visit( const ast::WhenClause * node ) {
     998        VISIT_START( node );
     999
     1000        if ( __visit_children() ) {
     1001                maybe_accept( node, &WhenClause::target );
     1002                maybe_accept( node, &WhenClause::stmt );
     1003                maybe_accept( node, &WhenClause::when_cond );
     1004        }
     1005
     1006        VISIT_END( WhenClause, node );
     1007}
     1008
     1009//--------------------------------------------------------------------------
    10681010// WaitForStmt
    10691011template< typename core_t >
     
    10901032
    10911033        if ( __visit_children() ) {
    1092                 maybe_accept( node, &WaitForClause::target_func );
     1034                maybe_accept( node, &WaitForClause::target );
    10931035                maybe_accept( node, &WaitForClause::target_args );
    10941036                maybe_accept( node, &WaitForClause::stmt );
    1095                 maybe_accept( node, &WaitForClause::cond );
     1037                maybe_accept( node, &WaitForClause::when_cond );
    10961038        }
    10971039
    10981040        VISIT_END( WaitForClause, node );
     1041}
     1042
     1043//--------------------------------------------------------------------------
     1044// WaitUntilStmt
     1045template< typename core_t >
     1046const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitUntilStmt * node ) {
     1047        VISIT_START( node );
     1048
     1049        if ( __visit_children() ) {
     1050                maybe_accept( node, &WaitUntilStmt::clauses );
     1051                maybe_accept( node, &WaitUntilStmt::timeout_time );
     1052                maybe_accept( node, &WaitUntilStmt::timeout_stmt );
     1053                maybe_accept( node, &WaitUntilStmt::timeout_cond );
     1054                maybe_accept( node, &WaitUntilStmt::else_stmt );
     1055                maybe_accept( node, &WaitUntilStmt::else_cond );
     1056        }
     1057
     1058        VISIT_END( Stmt, node );
    10991059}
    11001060
     
    22032163}
    22042164
     2165#undef __pedantic_pass_assertf
     2166#undef __pedantic_pass_assert
    22052167#undef VISIT_START
    22062168#undef VISIT_END
  • src/AST/Pass.proto.hpp

    r6e4c44d r3982384  
    1717// IWYU pragma: private, include "Pass.hpp"
    1818
     19#include "Common/Iterate.hpp"
    1920#include "Common/Stats/Heap.h"
    2021namespace ast {
     
    2425        template<typename node_t> node_t * deepCopy( const node_t * );
    2526}
     27
     28#ifdef PEDANTIC_PASS_ASSERT
     29#define __pedantic_pass_assert(...) assert (__VA_ARGS__)
     30#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
     31#else
     32#define __pedantic_pass_assert(...)
     33#define __pedantic_pass_assertf(...)
     34#endif
    2635
    2736namespace ast::__pass {
     
    130139
    131140        template< typename object_t, typename super_t, typename field_t >
    132         void apply( object_t *, field_t super_t::* field );
     141        void apply( object_t * object, field_t super_t::* field ) {
     142                object->*field = value;
     143        }
    133144};
    134145
     
    150161
    151162        template< typename object_t, typename super_t, typename field_t >
    152         void apply( object_t *, field_t super_t::* field );
     163        void apply( object_t * object, field_t super_t::* field ) {
     164                field_t & container = object->*field;
     165                __pedantic_pass_assert( container.size() <= values.size() );
     166
     167                auto cit = enumerate(container).begin();
     168
     169                container_t<ptr<Stmt>> nvals;
     170                for ( delta & d : values ) {
     171                        if ( d.is_old ) {
     172                                __pedantic_pass_assert( cit.idx <= d.old_idx );
     173                                std::advance( cit, d.old_idx - cit.idx );
     174                                nvals.push_back( std::move( (*cit).val ) );
     175                        } else {
     176                                nvals.push_back( std::move( d.new_val ) );
     177                        }
     178                }
     179
     180                container = std::move(nvals);
     181        }
    153182
    154183        template< template<class...> class incontainer_t >
    155         void take_all( incontainer_t<ptr<Stmt>> * stmts );
     184        void take_all( incontainer_t<ptr<Stmt>> * stmts ) {
     185                if ( !stmts || stmts->empty() ) return;
     186
     187                std::transform( stmts->begin(), stmts->end(), std::back_inserter( values ),
     188                        [](ast::ptr<ast::Stmt>& stmt) -> delta {
     189                                return delta( stmt.release(), -1, false );
     190                        });
     191                stmts->clear();
     192                differs = true;
     193        }
    156194
    157195        template< template<class...> class incontainer_t >
    158         void take_all( incontainer_t<ptr<Decl>> * decls );
     196        void take_all( incontainer_t<ptr<Decl>> * decls ) {
     197                if ( !decls || decls->empty() ) return;
     198
     199                std::transform( decls->begin(), decls->end(), std::back_inserter( values ),
     200                        [](ast::ptr<ast::Decl>& decl) -> delta {
     201                                ast::Decl const * d = decl.release();
     202                                return delta( new DeclStmt( d->location, d ), -1, false );
     203                        });
     204                decls->clear();
     205                differs = true;
     206        }
    159207};
    160208
     
    166214
    167215        template< typename object_t, typename super_t, typename field_t >
    168         void apply( object_t *, field_t super_t::* field );
     216        void apply( object_t * object, field_t super_t::* field ) {
     217                field_t & container = object->*field;
     218                __pedantic_pass_assert( container.size() == values.size() );
     219
     220                for ( size_t i = 0; i < container.size(); ++i ) {
     221                        // Take all the elements that are different in 'values'
     222                        // and swap them into 'container'
     223                        if ( values[i] != nullptr ) swap(container[i], values[i]);
     224                }
     225                // Now the original containers should still have the unchanged values
     226                // but also contain the new values.
     227        }
    169228};
    170229
     
    517576
    518577} // namespace ast::__pass
     578
     579#undef __pedantic_pass_assertf
     580#undef __pedantic_pass_assert
  • src/AST/Print.cpp

    r6e4c44d r3982384  
    208208        }
    209209
     210    void print( const ast::WaitStmt * node ) {
     211                if ( node->timeout_time ) {
     212                        os << indent-1 << "timeout of:" << endl;
     213                        node->timeout_time->accept( *this );
     214
     215                        if ( node->timeout_stmt ) {
     216                                os << indent-1 << "... with statment:" << endl;
     217                                node->timeout_stmt->accept( *this );
     218                        }
     219
     220                        if ( node->timeout_cond ) {
     221                                os << indent-1 << "... with condition:" << endl;
     222                                node->timeout_cond->accept( *this );
     223                        }
     224                }
     225
     226                if ( node->else_stmt ) {
     227                        os << indent-1 << "else:" << endl;
     228                        node->else_stmt->accept( *this );
     229
     230                        if ( node->else_cond ) {
     231                                os << indent-1 << "... with condition:" << endl;
     232                                node->else_cond->accept( *this );
     233                        }
     234                }
     235        }
     236
    210237        void preprint( const ast::NamedTypeDecl * node ) {
    211238                if ( ! node->name.empty() ) {
     
    756783        }
    757784
     785        virtual const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
     786                os << indent-1 << "target: ";
     787                safe_print( node->target );
     788
     789                if ( node->stmt ) {
     790                        os << indent-1 << "... with statment:" << endl;
     791                        node->stmt->accept( *this );
     792                }
     793
     794                if ( node->when_cond ) {
     795                        os << indent-1 << "... with when condition:" << endl;
     796                        node->when_cond->accept( *this );
     797                }
     798
     799                return node;
     800        }
     801
    758802        virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
    759803                os << "Waitfor Statement" << endl;
     
    793837        virtual const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
    794838                os << indent-1 << "target function: ";
    795                 safe_print( node->target_func );
     839                safe_print( node->target );
    796840
    797841                if ( !node->target_args.empty() ) {
     
    807851                }
    808852
    809                 if ( node->cond ) {
     853                if ( node->when_cond ) {
    810854                        os << indent-1 << "... with condition:" << endl;
    811                         node->cond->accept( *this );
    812                 }
    813 
     855                        node->when_cond->accept( *this );
     856                }
     857
     858                return node;
     859        }
     860
     861    virtual const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
     862                os << "Waituntil Statement" << endl;
     863                indent += 2;
     864                for( const auto & clause : node->clauses ) {
     865                        clause->accept( *this );
     866                }
     867        print(node);    // calls print( const ast::WaitStmt * node )
    814868                return node;
    815869        }
  • src/AST/Stmt.hpp

    r6e4c44d r3982384  
    378378};
    379379
    380 // Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...
    381 class WaitForStmt final : public Stmt {
    382   public:
    383         std::vector<ptr<WaitForClause>> clauses;
    384         ptr<Expr> timeout_time;
     380// Base class of WaitFor/WaitUntil statements
     381// form: KEYWORD(...) ... timeout(...) ... else ...
     382class WaitStmt : public Stmt {
     383  public:
     384    ptr<Expr> timeout_time;
    385385        ptr<Stmt> timeout_stmt;
    386386        ptr<Expr> timeout_cond;
     
    388388        ptr<Expr> else_cond;
    389389
     390    WaitStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
     391                : Stmt(loc, std::move(labels)) {}
     392
     393  private:
     394    WaitStmt * clone() const override = 0;
     395        MUTATE_FRIEND
     396};
     397
     398// Base class for WaitFor/WaitUntil clauses
     399// form: when( when_cond ) KEYWORD( target ) stmt
     400class WhenClause : public StmtClause {
     401  public:
     402        ptr<Expr> target;
     403        ptr<Stmt> stmt;
     404        ptr<Expr> when_cond;
     405
     406        WhenClause( const CodeLocation & loc )
     407                : StmtClause( loc ) {}
     408
     409        const WhenClause * accept( Visitor & v ) const override { return v.visit( this ); }
     410  private:
     411        WhenClause * clone() const override { return new WhenClause{ *this }; }
     412        MUTATE_FRIEND
     413};
     414
     415// Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...
     416class WaitForStmt final : public WaitStmt {
     417  public:
     418        std::vector<ptr<WaitForClause>> clauses;
     419
    390420        WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
    391                 : Stmt(loc, std::move(labels)) {}
     421                : WaitStmt(loc, std::move(labels)) {}
    392422
    393423        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     
    398428
    399429// Clause in a waitfor statement: waitfor (..., ...) ...
    400 class WaitForClause final : public StmtClause {
    401   public:
    402         ptr<Expr> target_func;
     430class WaitForClause final : public WhenClause {
     431  public:
    403432        std::vector<ptr<Expr>> target_args;
    404         ptr<Stmt> stmt;
    405         ptr<Expr> cond;
    406433
    407434        WaitForClause( const CodeLocation & loc )
    408                 : StmtClause( loc ) {}
     435                : WhenClause( loc ) {}
    409436
    410437        const WaitForClause * accept( Visitor & v ) const override { return v.visit( this ); }
    411438  private:
    412439        WaitForClause * clone() const override { return new WaitForClause{ *this }; }
     440        MUTATE_FRIEND
     441};
     442
     443// waituntil statement: when (...) waituntil (...) ... timeout(...) ... else ...
     444class WaitUntilStmt final : public WaitStmt {
     445  public:
     446    // Non-ast node used during compilation to store data needed to generate predicates
     447    //    and set initial status values for clauses
     448    // Used to create a tree corresponding to the structure of the clauses in a WaitUntil
     449    struct ClauseNode {
     450        enum Op { AND, OR, LEFT_OR, LEAF, ELSE, TIMEOUT } op; // operation/type tag
     451        // LEFT_OR used with TIMEOUT/ELSE to indicate that we ignore right hand side after parsing
     452
     453        ClauseNode * left;
     454        ClauseNode * right;
     455        WhenClause * leaf;  // only set if this node is a leaf (points into vector of clauses)
     456
     457        bool ambiguousWhen; // used to paint nodes of predicate tree based on when() clauses
     458        bool whenState;     // used to track if when_cond is toggled on or off for generating init values
     459        bool childOfAnd;      // true on leaf nodes that are children of AND, false otherwise
     460
     461        ClauseNode( Op op, ClauseNode * left, ClauseNode * right )
     462            : op(op), left(left), right(right), leaf(nullptr),
     463            ambiguousWhen(false), whenState(true), childOfAnd(false) {}
     464        ClauseNode( Op op, WhenClause * leaf )
     465            : op(op), left(nullptr), right(nullptr), leaf(leaf),
     466            ambiguousWhen(false), whenState(true), childOfAnd(false) {}
     467        ClauseNode( WhenClause * leaf ) : ClauseNode(LEAF, leaf) {}
     468       
     469        ~ClauseNode() {
     470            if ( left ) delete left;
     471            if ( right ) delete right;
     472        }
     473    };
     474
     475        std::vector<ptr<WhenClause>> clauses;
     476    ClauseNode * predicateTree;
     477
     478        WaitUntilStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
     479                : WaitStmt(loc, std::move(labels)) {}
     480
     481    ~WaitUntilStmt() { delete predicateTree; }
     482
     483        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     484  private:
     485        WaitUntilStmt * clone() const override { return new WaitUntilStmt{ *this }; }
    413486        MUTATE_FRIEND
    414487};
  • src/AST/Visitor.hpp

    r6e4c44d r3982384  
    5050    virtual const ast::FinallyClause *    visit( const ast::FinallyClause        * ) = 0;
    5151    virtual const ast::Stmt *             visit( const ast::SuspendStmt          * ) = 0;
     52    virtual const ast::WhenClause *       visit( const ast::WhenClause           * ) = 0;
    5253    virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
    5354    virtual const ast::WaitForClause *    visit( const ast::WaitForClause        * ) = 0;
     55    virtual const ast::Stmt *             visit( const ast::WaitUntilStmt        * ) = 0;
    5456    virtual const ast::Decl *             visit( const ast::WithStmt             * ) = 0;
    5557    virtual const ast::NullStmt *         visit( const ast::NullStmt             * ) = 0;
  • src/Common/CodeLocationTools.cpp

    r6e4c44d r3982384  
    128128    macro(FinallyClause, FinallyClause) \
    129129    macro(SuspendStmt, Stmt) \
     130    macro(WhenClause, WhenClause) \
    130131    macro(WaitForStmt, Stmt) \
    131132    macro(WaitForClause, WaitForClause) \
     133    macro(WaitUntilStmt, Stmt) \
    132134    macro(WithStmt, Decl) \
    133135    macro(NullStmt, NullStmt) \
  • src/Concurrency/WaitforNew.cpp

    r6e4c44d r3982384  
    305305
    306306        const ast::VariableExpr * variableExpr =
    307                 clause->target_func.as<ast::VariableExpr>();
     307                clause->target.as<ast::VariableExpr>();
    308308        ast::Expr * castExpr = new ast::CastExpr(
    309309                location,
    310310                new ast::CastExpr(
    311311                        location,
    312                         clause->target_func,
     312                        clause->target,
    313313                        ast::deepCopy( variableExpr->result.get() ),
    314314                        ast::GeneratedCast ),
     
    325325
    326326        ResolveContext context{ symtab, transUnit().global };
    327         out->push_back( maybeCond( location, clause->cond.get(), {
     327        out->push_back( maybeCond( location, clause->when_cond.get(), {
    328328                makeAccStmt( location, acceptables, index, "is_dtor",
    329                         detectIsDtor( location, clause->target_func ), context ),
     329                        detectIsDtor( location, clause->target ), context ),
    330330                makeAccStmt( location, acceptables, index, "func",
    331331                        funcExpr, context ),
  • src/Concurrency/module.mk

    r6e4c44d r3982384  
    2323        Concurrency/WaitforNew.cpp \
    2424        Concurrency/Waitfor.cc \
    25         Concurrency/Waitfor.h
     25        Concurrency/Waitfor.h \
     26        Concurrency/Waituntil.cpp \
     27        Concurrency/Waituntil.hpp
  • src/Parser/StatementNode.cc

    r6e4c44d r3982384  
    328328ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
    329329        auto clause = new ast::WaitForClause( location );
    330         clause->target_func = maybeBuild( targetExpr );
     330        clause->target = maybeBuild( targetExpr );
    331331        clause->stmt = maybeMoveBuild( stmt );
    332         clause->cond = notZeroExpr( maybeMoveBuild( when ) );
     332        clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    333333
    334334        ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
     
    359359        return existing;
    360360} // build_waitfor_timeout
     361
     362ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
     363    ast::WhenClause * clause = new ast::WhenClause( loc );
     364    clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     365    clause->stmt = maybeMoveBuild( stmt );
     366    clause->target = maybeMoveBuild( targetExpr );
     367    return new ast::WaitUntilStmt::ClauseNode( clause );
     368}
     369ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation & loc, ExpressionNode * when, StatementNode * stmt ) {
     370    ast::WhenClause * clause = new ast::WhenClause( loc );
     371    clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     372    clause->stmt = maybeMoveBuild( stmt );
     373    return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::ELSE, clause );
     374}
     375ast::WaitUntilStmt::ClauseNode * build_waituntil_timeout( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
     376    ast::WhenClause * clause = new ast::WhenClause( loc );
     377    clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     378    clause->stmt = maybeMoveBuild( stmt );
     379    clause->target = maybeMoveBuild( timeout );
     380    return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::TIMEOUT, clause );
     381}
     382
     383ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation & loc, ast::WaitUntilStmt::ClauseNode * root ) {
     384    ast::WaitUntilStmt * retStmt = new ast::WaitUntilStmt( loc );
     385    retStmt->predicateTree = root;
     386   
     387    // iterative tree traversal
     388    std::vector<ast::WaitUntilStmt::ClauseNode *> nodeStack; // stack needed for iterative traversal
     389    ast::WaitUntilStmt::ClauseNode * currNode = nullptr;
     390    ast::WaitUntilStmt::ClauseNode * lastInternalNode = nullptr;
     391    ast::WaitUntilStmt::ClauseNode * cleanup = nullptr; // used to cleanup removed else/timeout
     392    nodeStack.push_back(root);
     393
     394    do {
     395        currNode = nodeStack.back();
     396        nodeStack.pop_back(); // remove node since it will be processed
     397
     398        switch (currNode->op) {
     399            case ast::WaitUntilStmt::ClauseNode::LEAF:
     400                retStmt->clauses.push_back(currNode->leaf);
     401                break;
     402            case ast::WaitUntilStmt::ClauseNode::ELSE:
     403                retStmt->else_stmt = currNode->leaf->stmt
     404                    ? ast::deepCopy( currNode->leaf->stmt )
     405                    : nullptr;
     406               
     407                retStmt->else_cond = currNode->leaf->when_cond
     408                    ? ast::deepCopy( currNode->leaf->when_cond )
     409                    : nullptr;
     410
     411                delete currNode->leaf;
     412                break;
     413            case ast::WaitUntilStmt::ClauseNode::TIMEOUT:
     414                retStmt->timeout_time = currNode->leaf->target
     415                    ? ast::deepCopy( currNode->leaf->target )
     416                    : nullptr;
     417                retStmt->timeout_stmt = currNode->leaf->stmt
     418                    ? ast::deepCopy( currNode->leaf->stmt )
     419                    : nullptr;
     420                retStmt->timeout_cond = currNode->leaf->when_cond
     421                    ? ast::deepCopy( currNode->leaf->when_cond )
     422                    : nullptr;
     423
     424                delete currNode->leaf;
     425                break;
     426            default:
     427                nodeStack.push_back( currNode->right ); // process right after left
     428                nodeStack.push_back( currNode->left );
     429
     430                // Cut else/timeout out of the tree
     431                if ( currNode->op == ast::WaitUntilStmt::ClauseNode::LEFT_OR ) {
     432                    if ( lastInternalNode )
     433                        lastInternalNode->right = currNode->left;
     434                    else    // if not set then root is LEFT_OR
     435                        retStmt->predicateTree = currNode->left;
     436   
     437                    currNode->left = nullptr;
     438                    cleanup = currNode;
     439                }
     440               
     441                lastInternalNode = currNode;
     442                break;
     443        }
     444    } while ( !nodeStack.empty() );
     445
     446    if ( cleanup ) delete cleanup;
     447
     448    return retStmt;
     449}
    361450
    362451ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
  • src/Parser/StatementNode.h

    r6e4c44d r3982384  
    100100ast::WaitForStmt * build_waitfor_else( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt );
    101101ast::WaitForStmt * build_waitfor_timeout( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt );
     102ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation &, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt );
     103ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation &, ExpressionNode * when, StatementNode * stmt );
     104ast::WaitUntilStmt::ClauseNode * build_waituntil_timeout( const CodeLocation &, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt );
     105ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation &, ast::WaitUntilStmt::ClauseNode * root );
    102106ast::Stmt * build_with( const CodeLocation &, ExpressionNode * exprs, StatementNode * stmt );
    103107ast::Stmt * build_mutex( const CodeLocation &, ExpressionNode * exprs, StatementNode * stmt );
  • src/Parser/lex.ll

    r6e4c44d r3982384  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Sat Mar 25 08:09:03 2023
    13  * Update Count     : 768
     12 * Last Modified On : Tue May  2 08:45:21 2023
     13 * Update Count     : 769
    1414 */
    1515
     
    258258enable                  { KEYWORD_RETURN(ENABLE); }                             // CFA
    259259enum                    { KEYWORD_RETURN(ENUM); }
     260exception               { KEYWORD_RETURN(EXCEPTION); }                  // CFA
    260261__extension__   { KEYWORD_RETURN(EXTENSION); }                  // GCC
    261 exception               { KEYWORD_RETURN(EXCEPTION); }                  // CFA
    262262extern                  { KEYWORD_RETURN(EXTERN); }
    263263fallthrough             { KEYWORD_RETURN(FALLTHROUGH); }                // CFA
  • src/Parser/parser.yy

    r6e4c44d r3982384  
    307307        ClauseNode * clause;
    308308        ast::WaitForStmt * wfs;
     309    ast::WaitUntilStmt::ClauseNode * wucn;
    309310        CondCtl * ifctl;
    310311        ForCtrl * forctl;
     
    427428%type<expr> when_clause                                 when_clause_opt                         waitfor         waituntil               timeout
    428429%type<stmt> waitfor_statement                           waituntil_statement
    429 %type<wfs> wor_waitfor_clause                   waituntil_clause                        wand_waituntil_clause   wor_waituntil_clause
     430%type<wfs> wor_waitfor_clause
     431%type<wucn> waituntil_clause                    wand_waituntil_clause       wor_waituntil_clause
    430432
    431433// declarations
     
    16851687waituntil_clause:
    16861688        when_clause_opt waituntil statement
    1687                 { printf( "waituntil_clause 1\n" ); $$ = nullptr; }
     1689                { $$ = build_waituntil_clause( yylloc, $1, $2, maybe_build_compound( yylloc, $3 ) ); }
    16881690        | '(' wor_waituntil_clause ')'
    1689                 { printf( "waituntil_clause 2\n" ); $$ = nullptr; }
     1691                { $$ = $2; }
    16901692        ;
    16911693
    16921694wand_waituntil_clause:
    16931695        waituntil_clause                                                                        %prec THEN
    1694                 { printf( "wand_waituntil_clause 1\n" ); $$ = nullptr; }
     1696                { $$ = $1; }
    16951697        | waituntil_clause wand wand_waituntil_clause
    1696                 { printf( "wand_waituntil_clause 2\n" ); $$ = nullptr; }
     1698                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::AND, $1, $3 ); }
    16971699        ;
    16981700
    16991701wor_waituntil_clause:
    17001702        wand_waituntil_clause
    1701                 { printf( "wor_waituntil_clause 1\n" ); $$ = nullptr; }
     1703                { $$ = $1; }
    17021704        | wor_waituntil_clause wor wand_waituntil_clause
    1703                 { printf( "wor_waituntil_clause 2\n" ); $$ = nullptr; }
     1705                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR, $1, $3 ); }
    17041706        | wor_waituntil_clause wor when_clause_opt ELSE statement
    1705                 { printf( "wor_waituntil_clause 3\n" ); $$ = nullptr; }
     1707                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_else( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
    17061708        | wor_waituntil_clause wor when_clause_opt timeout statement    %prec THEN
    1707                 { printf( "wor_waituntil_clause 4\n" ); $$ = nullptr; }
     1709                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ) ); }
    17081710        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    17091711        | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
    17101712                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    17111713        | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
    1712                 { printf( "wor_waituntil_clause 6\n" ); $$ = nullptr; }
     1714                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1,
     1715                new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR,
     1716                    build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ),
     1717                    build_waituntil_else( yylloc, $7, maybe_build_compound( yylloc, $9 ) ) ) ); }
    17131718        ;
    17141719
     
    17161721        wor_waituntil_clause                                                            %prec THEN
    17171722                // SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement.
    1718                 { $$ = new StatementNode( build_compound( yylloc, nullptr ) ); }
     1723                {
     1724            $$ = new StatementNode( build_waituntil_stmt( yylloc, $1 ) );
     1725            // $$ = new StatementNode( build_compound( yylloc, nullptr ) );
     1726        }
    17191727        ;
    17201728
  • src/ResolvExpr/Resolver.cc

    r6e4c44d r3982384  
    17301730
    17311731                        // Find all candidates for a function in canonical form
    1732                         funcFinder.find( clause.target_func, ResolvMode::withAdjustment() );
     1732                        funcFinder.find( clause.target, ResolvMode::withAdjustment() );
    17331733
    17341734                        if ( funcFinder.candidates.empty() ) {
    17351735                                stringstream ss;
    17361736                                ss << "Use of undeclared indentifier '";
    1737                                 ss << clause.target_func.strict_as< ast::NameExpr >()->name;
     1737                                ss << clause.target.strict_as< ast::NameExpr >()->name;
    17381738                                ss << "' in call to waitfor";
    17391739                                SemanticError( stmt->location, ss.str() );
     
    19221922                        auto clause2 = new ast::WaitForClause( clause.location );
    19231923
    1924                         clause2->target_func = funcCandidates.front()->expr;
     1924                        clause2->target = funcCandidates.front()->expr;
    19251925
    19261926                        clause2->target_args.reserve( clause.target_args.size() );
     
    19451945
    19461946                        // Resolve the conditions as if it were an IfStmt, statements normally
    1947                         clause2->cond = findSingleExpression( clause.cond, context );
     1947                        clause2->when_cond = findSingleExpression( clause.when_cond, context );
    19481948                        clause2->stmt = clause.stmt->accept( *visitor );
    19491949
  • src/main.cc

    r6e4c44d r3982384  
    4848#include "Concurrency/Keywords.h"           // for implementMutex, implement...
    4949#include "Concurrency/Waitfor.h"            // for generateWaitfor
     50#include "Concurrency/Waituntil.hpp"        // for generateWaitUntil
    5051#include "ControlStruct/ExceptDecl.h"       // for translateExcept
    5152#include "ControlStruct/ExceptTranslate.h"  // for translateThrows, translat...
     
    340341                PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords, transUnit );
    341342                PASS( "Forall Pointer Decay", Validate::decayForallPointers, transUnit );
     343        PASS( "Implement Waituntil", Concurrency::generateWaitUntil, transUnit  );
    342344                PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls, transUnit );
    343345
Note: See TracChangeset for help on using the changeset viewer.