Changeset 044ae62 for src


Ignore:
Timestamp:
May 29, 2023, 11:44:29 AM (2 years ago)
Author:
JiadaL <j82liang@…>
Branches:
ADT
Children:
fa2c005
Parents:
3a513d89 (diff), 2b78949 (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' into ADT

Location:
src
Files:
2 added
18 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r3a513d89 r044ae62  
    585585        }
    586586
     587    const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
     588                // There is no old-AST WhenClause, so this should never be called.
     589                assert( !node );
     590                return nullptr;
     591        }
     592
    587593        const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
    588594                if ( inCache( node ) ) return nullptr;
     
    591597                for ( auto clause : node->clauses ) {
    592598                        stmt->clauses.push_back({{
    593                                         get<Expression>().accept1( clause->target_func ),
     599                                        get<Expression>().accept1( clause->target ),
    594600                                        get<Expression>().acceptL( clause->target_args ),
    595601                                },
    596602                                get<Statement>().accept1( clause->stmt ),
    597                                 get<Expression>().accept1( clause->cond ),
     603                                get<Expression>().accept1( clause->when_cond ),
    598604                        });
    599605                }
     
    612618        const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
    613619                // There is no old-AST WaitForClause, so this should never be called.
     620                assert( !node );
     621                return nullptr;
     622        }
     623
     624    const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
     625        // There is no old-AST WaitUntilStmt, so this should never be called.
    614626                assert( !node );
    615627                return nullptr;
     
    21992211                        auto clause = new ast::WaitForClause( old->location );
    22002212
    2201                         clause->target_func = GET_ACCEPT_1(clauses[i].target.function, Expr);
     2213                        clause->target = GET_ACCEPT_1(clauses[i].target.function, Expr);
    22022214                        clause->target_args = GET_ACCEPT_V(clauses[i].target.arguments, Expr);
    22032215                        clause->stmt = GET_ACCEPT_1(clauses[i].statement, Stmt);
    2204                         clause->cond = GET_ACCEPT_1(clauses[i].condition, Expr);
     2216                        clause->when_cond = GET_ACCEPT_1(clauses[i].condition, Expr);
    22052217
    22062218                        stmt->clauses.push_back( clause );
  • src/AST/Fwd.hpp

    r3a513d89 r044ae62  
    5959class FinallyClause;
    6060class SuspendStmt;
     61class WhenClause;
    6162class WaitForStmt;
    6263class WaitForClause;
     64class WaitUntilStmt;
    6365class WithStmt;
    6466class DeclStmt;
  • src/AST/Node.cpp

    r3a513d89 r044ae62  
    176176template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::weak >;
    177177template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::strong >;
     178template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::weak >;
     179template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::strong >;
    178180template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >;
    179181template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >;
    180182template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::weak >;
    181183template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::strong >;
     184template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::weak >;
     185template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::strong >;
    182186template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::weak >;
    183187template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::strong >;
  • src/AST/Pass.hpp

    r3a513d89 r044ae62  
    163163        const ast::FinallyClause *    visit( const ast::FinallyClause        * ) override final;
    164164        const ast::Stmt *             visit( const ast::SuspendStmt          * ) override final;
     165    const ast::WhenClause *       visit( const ast::WhenClause           * ) override final;
    165166        const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
    166167        const ast::WaitForClause *    visit( const ast::WaitForClause        * ) override final;
     168    const ast::Stmt *             visit( const ast::WaitUntilStmt        * ) override final;
    167169        const ast::Decl *             visit( const ast::WithStmt             * ) override final;
    168170        const ast::NullStmt *         visit( const ast::NullStmt             * ) override final;
  • src/AST/Pass.impl.hpp

    r3a513d89 r044ae62  
    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
     
    10971024
    10981025//--------------------------------------------------------------------------
     1026// WhenClause
     1027template< typename core_t >
     1028const ast::WhenClause * ast::Pass< core_t >::visit( const ast::WhenClause * node ) {
     1029        VISIT_START( node );
     1030
     1031        if ( __visit_children() ) {
     1032                maybe_accept( node, &WhenClause::target );
     1033                maybe_accept( node, &WhenClause::stmt );
     1034                maybe_accept( node, &WhenClause::when_cond );
     1035        }
     1036
     1037        VISIT_END( WhenClause, node );
     1038}
     1039
     1040//--------------------------------------------------------------------------
    10991041// WaitForStmt
    11001042template< typename core_t >
     
    11211063
    11221064        if ( __visit_children() ) {
    1123                 maybe_accept( node, &WaitForClause::target_func );
     1065                maybe_accept( node, &WaitForClause::target );
    11241066                maybe_accept( node, &WaitForClause::target_args );
    11251067                maybe_accept( node, &WaitForClause::stmt );
    1126                 maybe_accept( node, &WaitForClause::cond );
     1068                maybe_accept( node, &WaitForClause::when_cond );
    11271069        }
    11281070
    11291071        VISIT_END( WaitForClause, node );
     1072}
     1073
     1074//--------------------------------------------------------------------------
     1075// WaitUntilStmt
     1076template< typename core_t >
     1077const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitUntilStmt * node ) {
     1078        VISIT_START( node );
     1079
     1080        if ( __visit_children() ) {
     1081                maybe_accept( node, &WaitUntilStmt::clauses );
     1082                maybe_accept( node, &WaitUntilStmt::timeout_time );
     1083                maybe_accept( node, &WaitUntilStmt::timeout_stmt );
     1084                maybe_accept( node, &WaitUntilStmt::timeout_cond );
     1085                maybe_accept( node, &WaitUntilStmt::else_stmt );
     1086                maybe_accept( node, &WaitUntilStmt::else_cond );
     1087        }
     1088
     1089        VISIT_END( Stmt, node );
    11301090}
    11311091
     
    22342194}
    22352195
     2196#undef __pedantic_pass_assertf
     2197#undef __pedantic_pass_assert
    22362198#undef VISIT_START
    22372199#undef VISIT_END
  • src/AST/Pass.proto.hpp

    r3a513d89 r044ae62  
    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
     
    534593
    535594} // namespace ast::__pass
     595
     596#undef __pedantic_pass_assertf
     597#undef __pedantic_pass_assert
  • src/AST/Print.cpp

    r3a513d89 r044ae62  
    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() ) {
     
    761788        }
    762789
     790        virtual const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
     791                os << indent-1 << "target: ";
     792                safe_print( node->target );
     793
     794                if ( node->stmt ) {
     795                        os << indent-1 << "... with statment:" << endl;
     796                        node->stmt->accept( *this );
     797                }
     798
     799                if ( node->when_cond ) {
     800                        os << indent-1 << "... with when condition:" << endl;
     801                        node->when_cond->accept( *this );
     802                }
     803
     804                return node;
     805        }
     806
    763807        virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
    764808                os << "Waitfor Statement" << endl;
     
    798842        virtual const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
    799843                os << indent-1 << "target function: ";
    800                 safe_print( node->target_func );
     844                safe_print( node->target );
    801845
    802846                if ( !node->target_args.empty() ) {
     
    812856                }
    813857
    814                 if ( node->cond ) {
     858                if ( node->when_cond ) {
    815859                        os << indent-1 << "... with condition:" << endl;
    816                         node->cond->accept( *this );
    817                 }
    818 
     860                        node->when_cond->accept( *this );
     861                }
     862
     863                return node;
     864        }
     865
     866    virtual const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
     867                os << "Waituntil Statement" << endl;
     868                indent += 2;
     869                for( const auto & clause : node->clauses ) {
     870                        clause->accept( *this );
     871                }
     872        print(node);    // calls print( const ast::WaitStmt * node )
    819873                return node;
    820874        }
  • src/AST/Stmt.hpp

    r3a513d89 r044ae62  
    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

    r3a513d89 r044ae62  
    5151    virtual const ast::FinallyClause *    visit( const ast::FinallyClause        * ) = 0;
    5252    virtual const ast::Stmt *             visit( const ast::SuspendStmt          * ) = 0;
     53    virtual const ast::WhenClause *       visit( const ast::WhenClause           * ) = 0;
    5354    virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
    5455    virtual const ast::WaitForClause *    visit( const ast::WaitForClause        * ) = 0;
     56    virtual const ast::Stmt *             visit( const ast::WaitUntilStmt        * ) = 0;
    5557    virtual const ast::Decl *             visit( const ast::WithStmt             * ) = 0;
    5658    virtual const ast::NullStmt *         visit( const ast::NullStmt             * ) = 0;
  • src/Common/CodeLocationTools.cpp

    r3a513d89 r044ae62  
    129129    macro(FinallyClause, FinallyClause) \
    130130    macro(SuspendStmt, Stmt) \
     131    macro(WhenClause, WhenClause) \
    131132    macro(WaitForStmt, Stmt) \
    132133    macro(WaitForClause, WaitForClause) \
     134    macro(WaitUntilStmt, Stmt) \
    133135    macro(WithStmt, Decl) \
    134136    macro(NullStmt, NullStmt) \
  • src/Concurrency/WaitforNew.cpp

    r3a513d89 r044ae62  
    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

    r3a513d89 r044ae62  
    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

    r3a513d89 r044ae62  
    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

    r3a513d89 r044ae62  
    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

    r3a513d89 r044ae62  
    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

    r3a513d89 r044ae62  
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Sep  1 20:22:55 2001
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr  4 14:02:00 2023
    13 // Update Count     : 6329
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Apr 26 16:45:37 2023
     13// Update Count     : 6330
    1414//
    1515
     
    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
     
    16821684
    16831685waituntil:
    1684         WAITUNTIL '(' cast_expression ')'
     1686        WAITUNTIL '(' comma_expression ')'
    16851687                { $$ = $3; }
    16861688        ;
     
    16881690waituntil_clause:
    16891691        when_clause_opt waituntil statement
    1690                 { printf( "waituntil_clause 1\n" ); $$ = nullptr; }
     1692                { $$ = build_waituntil_clause( yylloc, $1, $2, maybe_build_compound( yylloc, $3 ) ); }
    16911693        | '(' wor_waituntil_clause ')'
    1692                 { printf( "waituntil_clause 2\n" ); $$ = nullptr; }
     1694                { $$ = $2; }
    16931695        ;
    16941696
    16951697wand_waituntil_clause:
    16961698        waituntil_clause                                                                        %prec THEN
    1697                 { printf( "wand_waituntil_clause 1\n" ); $$ = nullptr; }
     1699                { $$ = $1; }
    16981700        | waituntil_clause wand wand_waituntil_clause
    1699                 { printf( "wand_waituntil_clause 2\n" ); $$ = nullptr; }
     1701                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::AND, $1, $3 ); }
    17001702        ;
    17011703
    17021704wor_waituntil_clause:
    17031705        wand_waituntil_clause
    1704                 { printf( "wor_waituntil_clause 1\n" ); $$ = nullptr; }
     1706                { $$ = $1; }
    17051707        | wor_waituntil_clause wor wand_waituntil_clause
    1706                 { printf( "wor_waituntil_clause 2\n" ); $$ = nullptr; }
     1708                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR, $1, $3 ); }
    17071709        | wor_waituntil_clause wor when_clause_opt ELSE statement
    1708                 { printf( "wor_waituntil_clause 3\n" ); $$ = nullptr; }
     1710                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_else( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
    17091711        | wor_waituntil_clause wor when_clause_opt timeout statement    %prec THEN
    1710                 { printf( "wor_waituntil_clause 4\n" ); $$ = nullptr; }
     1712                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ) ); }
    17111713        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    17121714        | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
    17131715                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    17141716        | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
    1715                 { printf( "wor_waituntil_clause 6\n" ); $$ = nullptr; }
     1717                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1,
     1718                new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR,
     1719                    build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ),
     1720                    build_waituntil_else( yylloc, $7, maybe_build_compound( yylloc, $9 ) ) ) ); }
    17161721        ;
    17171722
     
    17191724        wor_waituntil_clause                                                            %prec THEN
    17201725                // SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement.
    1721                 { $$ = new StatementNode( build_compound( yylloc, nullptr ) ); }
     1726                {
     1727            $$ = new StatementNode( build_waituntil_stmt( yylloc, $1 ) );
     1728            // $$ = new StatementNode( build_compound( yylloc, nullptr ) );
     1729        }
    17221730        ;
    17231731
  • src/ResolvExpr/Resolver.cc

    r3a513d89 r044ae62  
    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

    r3a513d89 r044ae62  
    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.