Changeset 6d2af204


Ignore:
Timestamp:
Feb 5, 2023, 11:42:15 AM (18 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, ast-experimental, master
Children:
8fa77eb
Parents:
9ef5516 (diff), 35d1de5 (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

Files:
6 added
32 edited

Legend:

Unmodified
Added
Removed
  • libcfa/prelude/builtins.c

    r9ef5516 r6d2af204  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug 14 08:45:54 2021
    13 // Update Count     : 133
     12// Last Modified On : Thu Feb  2 11:33:56 2023
     13// Update Count     : 135
    1414//
    1515
     
    6464static inline void ^?{}(generator$ &) {}
    6565
    66 trait is_generator(T &) {
     66forall( T & )
     67trait is_generator {
    6768      void main(T & this);
    6869      generator$ * get_generator(T & this);
  • libcfa/prelude/prelude-gen.cc

    r9ef5516 r6d2af204  
    1010// Created On       : Sat Feb 16 08:44:58 2019
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Apr  2 17:18:24 2019
    13 // Update Count     : 37
     12// Last Modified On : Thu Feb  2 11:40:01 2023
     13// Update Count     : 38
    1414//
    1515
     
    159159int main() {
    160160        cout << "# 2 \"prelude.cfa\"  // needed for error messages from this file" << endl;
    161         cout << "trait sized(T &) {};" << endl;
     161        cout << "forall( T & ) trait sized {};" << endl;
    162162
    163163        cout << "//////////////////////////" << endl;
  • libcfa/src/bits/containers.hfa

    r9ef5516 r6d2af204  
    1010// Created On       : Tue Oct 31 16:38:50 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan 15 07:42:35 2020
    13 // Update Count     : 28
     12// Last Modified On : Thu Feb  2 11:33:08 2023
     13// Update Count     : 29
    1414
    1515#pragma once
     
    6969
    7070#ifdef __cforall
    71         trait is_node(T &) {
     71        forall( T & )
     72        trait is_node {
    7273                T *& get_next( T & );
    7374        };
  • libcfa/src/concurrency/actor.hfa

    r9ef5516 r6d2af204  
     1#pragma once
     2
    13#include <locks.hfa>
    24#include <limits.hfa>
    35#include <list.hfa>
     6#include <kernel.hfa>
    47
    58#ifdef __CFA_DEBUG__
     
    2124// Define if executor is created in a separate cluster
    2225#define __DEFAULT_EXECUTOR_SEPCLUS__ false
     26
     27// when you flip this make sure to recompile compiler and flip the appropriate flag there too in Actors.cpp
     28#define __ALLOC 0
    2329
    2430// forward decls
     
    3844P9_EMBEDDED( request, dlink(request) )
    3945
    40 void ?{}( request & this ) { this.stop = true; } // default ctor makes a sentinel
    41 void ?{}( request & this, actor * receiver, message * msg, __receive_fn fn ) {
     46static inline void ?{}( request & this ) { this.stop = true; } // default ctor makes a sentinel
     47static inline void ?{}( request & this, actor * receiver, message * msg, __receive_fn fn ) {
    4248    this.receiver = receiver;
    4349    this.msg = msg;
     
    4551    this.stop = false;
    4652}
    47 
     53static inline void ?{}( request & this, request & copy ) {
     54    this.receiver = copy.receiver;
     55    this.msg = copy.msg;
     56    this.fn = copy.fn;
     57    this.stop = copy.stop;
     58}
     59
     60// hybrid data structure. Copies until buffer is full and then allocates for intrusive list
     61struct copy_queue {
     62    dlist( request ) list;
     63    #if ! __ALLOC
     64    request * buffer;
     65    size_t count, buffer_size, index;
     66    #endif
     67};
     68static inline void ?{}( copy_queue & this ) {}
     69static inline void ?{}( copy_queue & this, size_t buf_size ) with(this) {
     70    list{};
     71    #if ! __ALLOC
     72    buffer_size = buf_size;
     73    buffer = aalloc( buffer_size );
     74    count = 0;
     75    index = 0;
     76    #endif
     77}
     78static inline void ^?{}( copy_queue & this ) with(this) {
     79    #if ! __ALLOC
     80    adelete(buffer);
     81    #endif
     82}
     83
     84static inline void insert( copy_queue & this, request & elem ) with(this) {
     85    #if ! __ALLOC
     86    if ( count < buffer_size ) { // fast path ( no alloc )
     87        buffer[count]{ elem };
     88        count++;
     89        return;
     90    }
     91    request * new_elem = alloc();
     92    (*new_elem){ elem };
     93    insert_last( list, *new_elem );
     94    #else
     95    insert_last( list, elem );
     96    #endif
     97}
     98
     99// once you start removing you need to remove all elements
     100// it is not supported to call insert() before the list is fully empty
     101// should_delete is an output param
     102static inline request & remove( copy_queue & this, bool & should_delete ) with(this) {
     103    #if ! __ALLOC
     104    if ( count > 0 ) {
     105        count--;
     106        should_delete = false;
     107        size_t old_idx = index;
     108        index = count == 0 ? 0 : index + 1;
     109        return buffer[old_idx];
     110    }
     111    #endif
     112    should_delete = true;
     113    return try_pop_front( list );
     114}
     115
     116static inline bool isEmpty( copy_queue & this ) with(this) {
     117    #if ! __ALLOC
     118    return count == 0 && list`isEmpty;
     119    #else
     120    return list`isEmpty;
     121    #endif
     122}
     123
     124static size_t __buffer_size = 10; // C_TODO: rework this to be passed from executor through ctors (no need for global)
    48125struct work_queue {
    49     futex_mutex mutex_lock;
    50     dlist( request ) input;                                             // unbounded list of work requests
     126    __spinlock_t mutex_lock;
     127    copy_queue owned_queue;
     128    copy_queue * c_queue; // C_TODO: try putting this on the stack with ptr juggling
     129
    51130}; // work_queue
    52 void ?{}( work_queue & this ) with(this) { input{}; mutex_lock{}; }
    53 
    54 void insert( work_queue & this, request & elem ) with(this) {
    55     lock( mutex_lock );
    56     insert_last( input, elem );
     131static inline void ?{}( work_queue & this ) with(this) {
     132    // c_queue = alloc();
     133    // (*c_queue){ __buffer_size };
     134    owned_queue{ __buffer_size };
     135    c_queue = &owned_queue;
     136}
     137// static inline void ^?{}( work_queue & this ) with(this) { delete( c_queue ); }
     138
     139static inline void insert( work_queue & this, request & elem ) with(this) {
     140    lock( mutex_lock __cfaabi_dbg_ctx2 );
     141    insert( *c_queue, elem );
    57142    unlock( mutex_lock );
    58143} // insert
    59144
    60 void transfer( work_queue & this, dlist(request) & transferTo ) with(this) {
    61     lock( mutex_lock );
    62 
    63     //C_TODO CHANGE
    64     // transferTo->transfer( input );              // transfer input to output
    65 
    66     // this is awfully inefficient but Ill use it until transfer is implemented
    67     request * r;
    68     while ( ! input`isEmpty ) {
    69         r = &try_pop_front( input );
    70         if ( r ) insert_last( transferTo, *r );
    71     }
    72 
    73     // transfer( input, transferTo );
    74 
     145static inline void transfer( work_queue & this, copy_queue ** transfer_to ) with(this) {
     146    lock( mutex_lock __cfaabi_dbg_ctx2 );
     147    // swap copy queue ptrs
     148    copy_queue * temp = *transfer_to;
     149    *transfer_to = c_queue;
     150    c_queue = temp;
    75151    unlock( mutex_lock );
    76152} // transfer
    77153
    78154thread worker {
     155    copy_queue owned_queue;
    79156    work_queue * request_queues;
    80     dlist( request ) current_queue;
     157    copy_queue * current_queue;
    81158        request & req;
    82159    unsigned int start, range;
     
    86163    ((thread &)this){ clu };
    87164    this.request_queues = request_queues;
    88     this.current_queue{};
     165    // this.current_queue = alloc();
     166    // (*this.current_queue){ __buffer_size };
     167    this.owned_queue{ __buffer_size };
     168    this.current_queue = &this.owned_queue;
    89169    this.start = start;
    90170    this.range = range;
    91171}
     172// static inline void ^?{}( worker & mutex this ) with(this) { delete( current_queue ); }
    92173
    93174struct executor {
     
    100181}; // executor
    101182
    102 static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues, bool seperate_clus ) with(this) {
     183static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues, bool seperate_clus, size_t buf_size ) with(this) {
    103184    if ( nrqueues < nworkers ) abort( "nrqueues needs to be >= nworkers\n" );
     185    __buffer_size = buf_size;
    104186    this.nprocessors = nprocessors;
    105187    this.nworkers = nworkers;
     
    127209    } // for
    128210}
    129 
     211static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues, bool seperate_clus ) { this{ nprocessors, nworkers, nrqueues, seperate_clus, __buffer_size }; }
    130212static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers, unsigned int nrqueues ) { this{ nprocessors, nworkers, nrqueues, __DEFAULT_EXECUTOR_SEPCLUS__ }; }
    131213static inline void ?{}( executor & this, unsigned int nprocessors, unsigned int nworkers ) { this{ nprocessors, nworkers, __DEFAULT_EXECUTOR_RQUEUES__ }; }
     
    147229    } // for
    148230
    149     delete( workers );
    150     delete( request_queues );
    151     delete( processors );
     231    adelete( workers );
     232    adelete( request_queues );
     233    adelete( processors );
    152234    if ( seperate_clus ) delete( cluster );
    153235}
     
    170252};
    171253
    172 void ?{}( actor & this ) {
     254static inline void ?{}( actor & this ) {
    173255    // Once an actor is allocated it must be sent a message or the actor system cannot stop. Hence, its receive
    174256    // member must be called to end it
     
    178260    __atomic_fetch_add( &__num_actors_, 1, __ATOMIC_SEQ_CST );
    179261}
    180 void ^?{}( actor & this ) {}
     262static inline void ^?{}( actor & this ) {}
    181263
    182264static inline void check_actor( actor & this ) {
     
    204286};
    205287
    206 void ?{}( message & this ) { this.allocation_ = Nodelete; }
    207 void ?{}( message & this, Allocation allocation ) { this.allocation_ = allocation; }
    208 void ^?{}( message & this ) {}
     288static inline void ?{}( message & this ) { this.allocation_ = Nodelete; }
     289static inline void ?{}( message & this, Allocation allocation ) { this.allocation_ = allocation; }
     290static inline void ^?{}( message & this ) {}
    209291
    210292static inline void check_message( message & this ) {
     
    217299}
    218300
    219 void deliver_request( request & this ) {
     301static inline void deliver_request( request & this ) {
    220302    Allocation actor_allocation = this.fn( *this.receiver, *this.msg );
    221303    this.receiver->allocation_ = actor_allocation;
     
    225307
    226308void main( worker & this ) with(this) {
     309    bool should_delete;
    227310    Exit:
    228311    for ( unsigned int i = 0;; i = (i + 1) % range ) { // cycle through set of request buffers
    229         transfer( request_queues[i + start], current_queue );
    230         while ( ! current_queue`isEmpty ) {
    231             &req = &try_pop_front( current_queue );
     312        // C_TODO: potentially check queue count instead of immediately trying to transfer
     313        transfer( request_queues[i + start], &current_queue );
     314        while ( ! isEmpty( *current_queue ) ) {
     315            &req = &remove( *current_queue, should_delete );
    232316            if ( !&req ) continue; // possibly add some work stealing/idle sleep here
    233317            if ( req.stop ) break Exit;
    234318            deliver_request( req );
    235319
    236             delete( &req );
     320            if ( should_delete ) delete( &req );
    237321        } // while
    238322    } // for
     
    250334    __actor_executor_thd = active_thread();
    251335    __actor_executor_ = alloc();
    252     (*__actor_executor_){ 0, num_thds, num_thds * 16 };
     336    (*__actor_executor_){ 0, num_thds, num_thds == 1 ? 1 : num_thds * 16 };
    253337}
    254338
  • libcfa/src/concurrency/coroutine.hfa

    r9ef5516 r6d2af204  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jan  6 16:33:16 2022
    13 // Update Count     : 12
     12// Last Modified On : Thu Feb  2 11:31:42 2023
     13// Update Count     : 13
    1414//
    1515
     
    3838// Anything that implements this trait can be resumed.
    3939// Anything that is resumed is a coroutine.
    40 trait is_coroutine(T & | IS_RESUMPTION_EXCEPTION(CoroutineCancelled(T))) {
     40forall( T & | IS_RESUMPTION_EXCEPTION(CoroutineCancelled(T)) )
     41trait is_coroutine {
    4142        void main(T & this);
    4243        coroutine$ * get_coroutine(T & this);
  • libcfa/src/concurrency/locks.hfa

    r9ef5516 r6d2af204  
    640640//-----------------------------------------------------------------------------
    641641// is_blocking_lock
    642 trait is_blocking_lock(L & | sized(L)) {
     642forall( L & | sized(L) )
     643trait is_blocking_lock {
    643644        // For synchronization locks to use when acquiring
    644645        void on_notify( L &, struct thread$ * );
  • libcfa/src/concurrency/monitor.hfa

    r9ef5516 r6d2af204  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec  4 07:55:32 2019
    13 // Update Count     : 11
     12// Last Modified On : Thu Feb  2 11:29:21 2023
     13// Update Count     : 12
    1414//
    1515
     
    2222#include "stdlib.hfa"
    2323
    24 trait is_monitor(T &) {
     24forall( T & )
     25trait is_monitor {
    2526        monitor$ * get_monitor( T & );
    2627        void ^?{}( T & mutex );
  • libcfa/src/concurrency/mutex.hfa

    r9ef5516 r6d2af204  
    1212// Created On       : Fri May 25 01:24:09 2018
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Wed Dec  4 09:16:53 2019
    15 // Update Count     : 1
     14// Last Modified On : Thu Feb  2 11:46:08 2023
     15// Update Count     : 2
    1616//
    1717
     
    7070void unlock(recursive_mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
    7171
    72 trait is_lock(L & | sized(L)) {
     72forall( L & | sized(L) )
     73trait is_lock {
    7374        void lock  (L &);
    7475        void unlock(L &);
  • libcfa/src/concurrency/thread.hfa

    r9ef5516 r6d2af204  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov 22 22:18:34 2022
    13 // Update Count     : 35
     12// Last Modified On : Thu Feb  2 11:27:59 2023
     13// Update Count     : 37
    1414//
    1515
     
    2727//-----------------------------------------------------------------------------
    2828// thread trait
    29 trait is_thread(T &) {
     29forall( T & )
     30trait is_thread {
    3031        void ^?{}(T& mutex this);
    3132        void main(T& this);
  • libcfa/src/containers/list.hfa

    r9ef5516 r6d2af204  
    99// Author           : Michael Brooks
    1010// Created On       : Wed Apr 22 18:00:00 2020
    11 // Last Modified By : Michael Brooks
    12 // Last Modified On : Wed Apr 22 18:00:00 2020
    13 // Update Count     : 1
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Feb  2 11:32:26 2023
     13// Update Count     : 2
    1414//
    1515
     
    2323};
    2424
    25 trait embedded( tOuter &, tMid &, tInner & ) {
     25forall( tOuter &, tMid &, tInner & )
     26trait embedded {
    2627    tytagref( tMid, tInner ) ?`inner( tOuter & );
    2728};
  • libcfa/src/containers/vector.hfa

    r9ef5516 r6d2af204  
    1010// Created On       : Tue Jul  5 18:00:07 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 17 11:02:46 2020
    13 // Update Count     : 4
     12// Last Modified On : Thu Feb  2 11:41:24 2023
     13// Update Count     : 5
    1414//
    1515
     
    5050//------------------------------------------------------------------------------
    5151//Declaration
    52 trait allocator_c(T, allocator_t)
    53 {
     52forall( T, allocator_t )
     53trait allocator_c {
    5454        void realloc_storage(allocator_t*, size_t);
    5555        T* data(allocator_t*);
  • libcfa/src/exception.h

    r9ef5516 r6d2af204  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:11:00 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Apr  8 15:20:00 2021
    13 // Update Count     : 12
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Feb  2 11:20:19 2023
     13// Update Count     : 13
    1414//
    1515
     
    101101// implemented in the .c file either so they all have to be inline.
    102102
    103 trait is_exception(exceptT &, virtualT &) {
     103forall( exceptT &, virtualT & )
     104trait is_exception {
    104105        /* The first field must be a pointer to a virtual table.
    105106         * That virtual table must be a decendent of the base exception virtual table.
     
    109110};
    110111
    111 trait is_termination_exception(exceptT &, virtualT & | is_exception(exceptT, virtualT)) {
     112forall( exceptT &, virtualT & | is_exception(exceptT, virtualT) )
     113trait is_termination_exception {
    112114        void defaultTerminationHandler(exceptT &);
    113115};
    114116
    115 trait is_resumption_exception(exceptT &, virtualT & | is_exception(exceptT, virtualT)) {
     117forall( exceptT &, virtualT & | is_exception(exceptT, virtualT) )
     118trait is_resumption_exception {
    116119        void defaultResumptionHandler(exceptT &);
    117120};
  • libcfa/src/iostream.hfa

    r9ef5516 r6d2af204  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 10 10:02:07 2021
    13 // Update Count     : 407
     12// Last Modified On : Thu Feb  2 11:25:39 2023
     13// Update Count     : 410
    1414//
    1515
     
    2222
    2323
    24 trait basic_ostream( ostype & ) {
     24forall( ostype & )
     25trait basic_ostream {
    2526        // private
    2627        bool sepPrt$( ostype & );                                                       // get separator state (on/off)
     
    5152}; // basic_ostream
    5253       
    53 trait ostream( ostype & | basic_ostream( ostype ) ) {
     54forall( ostype & | basic_ostream( ostype ) )
     55trait ostream {
    5456        bool fail( ostype & );                                                          // operation failed?
    5557        void clear( ostype & );
     
    6062}; // ostream
    6163
    62 // trait writeable( T ) {
     64// forall( T )
     65// trait writeable {
    6366//      forall( ostype & | ostream( ostype ) ) ostype & ?|?( ostype &, T );
    6467// }; // writeable
    6568
    66 trait writeable( T, ostype & | ostream( ostype ) ) {
     69forall( T, ostype & | ostream( ostype ) )
     70        trait writeable {
    6771        ostype & ?|?( ostype &, T );
    6872}; // writeable
     
    290294
    291295
    292 trait basic_istream( istype & ) {
     296forall( istype & )
     297trait basic_istream {
    293298        // private
    294299        bool getANL$( istype & );                                                       // get scan newline (on/off)
     
    302307}; // basic_istream
    303308
    304 trait istream( istype & | basic_istream( istype ) ) {
     309forall( istype & | basic_istream( istype ) )
     310trait istream {
    305311        bool fail( istype & );
    306312        void clear( istype & );
     
    310316}; // istream
    311317
    312 trait readable( T ) {
     318forall( T )
     319trait readable {
    313320        forall( istype & | istream( istype ) ) istype & ?|?( istype &, T );
    314321}; // readable
  • libcfa/src/iterator.hfa

    r9ef5516 r6d2af204  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul  7 08:37:25 2017
    13 // Update Count     : 10
     12// Last Modified On : Thu Feb  2 11:21:50 2023
     13// Update Count     : 11
    1414//
    1515
     
    1717
    1818// An iterator can be used to traverse a data structure.
    19 trait iterator( iterator_type, elt_type ) {
     19forall( iterator_type, elt_type )
     20trait iterator {
    2021        // point to the next element
    2122//      iterator_type ?++( iterator_type & );
     
    3132};
    3233
    33 trait iterator_for( iterator_type, collection_type, elt_type | iterator( iterator_type, elt_type ) ) {
     34forall( iterator_type, collection_type, elt_type | iterator( iterator_type, elt_type ) )
     35        trait iterator_for {
    3436//      [ iterator_type begin, iterator_type end ] get_iterators( collection_type );
    3537        iterator_type begin( collection_type );
  • libcfa/src/math.trait.hfa

    r9ef5516 r6d2af204  
    1010// Created On       : Fri Jul 16 15:40:52 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul 20 17:47:19 2021
    13 // Update Count     : 19
     12// Last Modified On : Thu Feb  2 11:36:56 2023
     13// Update Count     : 20
    1414//
    1515
    1616#pragma once
    1717
    18 trait Not( U ) {
     18forall( U )
     19trait Not {
    1920        void ?{}( U &, zero_t );
    2021        int !?( U );
    2122}; // Not
    2223
    23 trait Equality( T | Not( T ) ) {
     24forall( T | Not( T ) )
     25trait Equality {
    2426        int ?==?( T, T );
    2527        int ?!=?( T, T );
    2628}; // Equality
    2729
    28 trait Relational( U | Equality( U ) ) {
     30forall( U | Equality( U ) )
     31trait Relational {
    2932        int ?<?( U, U );
    3033        int ?<=?( U, U );
     
    3336}; // Relational
    3437
    35 trait Signed( T ) {
     38forall ( T )
     39trait Signed {
    3640        T +?( T );
    3741        T -?( T );
     
    3943}; // Signed
    4044
    41 trait Additive( U | Signed( U ) ) {
     45forall( U | Signed( U ) )
     46trait Additive {
    4247        U ?+?( U, U );
    4348        U ?-?( U, U );
     
    4651}; // Additive
    4752
    48 trait Incdec( T | Additive( T ) ) {
     53forall( T | Additive( T ) )
     54trait Incdec {
    4955        void ?{}( T &, one_t );
    5056        // T ?++( T & );
     
    5460}; // Incdec
    5561
    56 trait Multiplicative( U | Incdec( U ) ) {
     62forall( U | Incdec( U ) )
     63trait Multiplicative {
    5764        U ?*?( U, U );
    5865        U ?/?( U, U );
     
    6168}; // Multiplicative
    6269
    63 trait Arithmetic( T | Relational( T ) | Multiplicative( T ) ) {
     70forall( T | Relational( T ) | Multiplicative( T ) )
     71trait Arithmetic {
    6472}; // Arithmetic
    6573
  • libcfa/src/stdlib.hfa

    r9ef5516 r6d2af204  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Dec 11 18:25:53 2022
    13 // Update Count     : 765
     12// Last Modified On : Thu Feb  2 11:30:04 2023
     13// Update Count     : 766
    1414//
    1515
     
    404404//   calls( sprng );
    405405
    406 trait basic_prng( PRNG &, R ) {
     406forall( PRNG &, R )
     407trait basic_prng {
    407408        void set_seed( PRNG & prng, R seed );                           // set seed
    408409        R get_seed( PRNG & prng );                                                      // get seed
  • src/Common/ScopedMap.h

    r9ef5516 r6d2af204  
    3737                template<typename N>
    3838                Scope(N && n) : map(), note(std::forward<N>(n)) {}
    39                
     39
    4040                Scope() = default;
    4141                Scope(const Scope &) = default;
     
    4646        typedef std::vector< Scope > ScopeList;
    4747
    48         ScopeList scopes; ///< scoped list of maps
     48        /// Scoped list of maps.
     49        ScopeList scopes;
    4950public:
    5051        typedef typename MapType::key_type key_type;
     
    5859        typedef typename MapType::const_pointer const_pointer;
    5960
    60         class iterator : public std::iterator< std::bidirectional_iterator_tag, value_type > {
    61         friend class ScopedMap;
    62         friend class const_iterator;
    63                 typedef typename ScopedMap::MapType::iterator wrapped_iterator;
    64                 typedef typename ScopedMap::ScopeList scope_list;
    65                 typedef typename scope_list::size_type size_type;
    66 
    67                 /// Checks if this iterator points to a valid item
    68                 bool is_valid() const {
    69                         return it != (*scopes)[level].map.end();
    70                 }
    71 
    72                 /// Increments on invalid
    73                 iterator & next_valid() {
    74                         if ( ! is_valid() ) { ++(*this); }
    75                         return *this;
    76                 }
    77 
    78                 /// Decrements on invalid
    79                 iterator & prev_valid() {
    80                         if ( ! is_valid() ) { --(*this); }
    81                         return *this;
    82                 }
    83 
    84                 iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel)
    85                         : scopes(&_scopes), it(_it), level(inLevel) {}
    86         public:
    87                 iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
    88                 iterator & operator= (const iterator & that) {
    89                         scopes = that.scopes; level = that.level; it = that.it;
    90                         return *this;
    91                 }
    92 
    93                 reference operator* () { return *it; }
    94                 pointer operator-> () const { return it.operator->(); }
    95 
    96                 iterator & operator++ () {
    97                         if ( it == (*scopes)[level].map.end() ) {
    98                                 if ( level == 0 ) return *this;
    99                                 --level;
    100                                 it = (*scopes)[level].map.begin();
    101                         } else {
    102                                 ++it;
    103                         }
    104                         return next_valid();
    105                 }
    106                 iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
    107 
    108                 iterator & operator-- () {
    109                         // may fail if this is the begin iterator; allowed by STL spec
    110                         if ( it == (*scopes)[level].map.begin() ) {
    111                                 ++level;
    112                                 it = (*scopes)[level].map.end();
    113                         }
    114                         --it;
    115                         return prev_valid();
    116                 }
    117                 iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
    118 
    119                 bool operator== (const iterator & that) const {
    120                         return scopes == that.scopes && level == that.level && it == that.it;
    121                 }
    122                 bool operator!= (const iterator & that) const { return !( *this == that ); }
    123 
    124                 size_type get_level() const { return level; }
    125 
    126                 Note & get_note() { return (*scopes)[level].note; }
    127                 const Note & get_note() const { return (*scopes)[level].note; }
    128 
    129         private:
    130                 scope_list *scopes;
    131                 wrapped_iterator it;
    132                 size_type level;
    133         };
    134 
    135         class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
    136                                                      value_type > {
    137         friend class ScopedMap;
    138                 typedef typename ScopedMap::MapType::iterator wrapped_iterator;
    139                 typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
    140                 typedef typename ScopedMap::ScopeList scope_list;
    141                 typedef typename scope_list::size_type size_type;
    142 
    143                 /// Checks if this iterator points to a valid item
    144                 bool is_valid() const {
    145                         return it != (*scopes)[level].map.end();
    146                 }
    147 
    148                 /// Increments on invalid
    149                 const_iterator & next_valid() {
    150                         if ( ! is_valid() ) { ++(*this); }
    151                         return *this;
    152                 }
    153 
    154                 /// Decrements on invalid
    155                 const_iterator & prev_valid() {
    156                         if ( ! is_valid() ) { --(*this); }
    157                         return *this;
    158                 }
    159 
    160                 const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
    161                         : scopes(&_scopes), it(_it), level(inLevel) {}
    162         public:
    163                 const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
    164                 const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
    165                 const_iterator & operator= (const iterator & that) {
    166                         scopes = that.scopes; level = that.level; it = that.it;
    167                         return *this;
    168                 }
    169                 const_iterator & operator= (const const_iterator & that) {
    170                         scopes = that.scopes; level = that.level; it = that.it;
    171                         return *this;
    172                 }
    173 
    174                 const_reference operator* () { return *it; }
    175                 const_pointer operator-> () { return it.operator->(); }
    176 
    177                 const_iterator & operator++ () {
    178                         if ( it == (*scopes)[level].map.end() ) {
    179                                 if ( level == 0 ) return *this;
    180                                 --level;
    181                                 it = (*scopes)[level].map.begin();
    182                         } else {
    183                                 ++it;
    184                         }
    185                         return next_valid();
    186                 }
    187                 const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
    188 
    189                 const_iterator & operator-- () {
    190                         // may fail if this is the begin iterator; allowed by STL spec
    191                         if ( it == (*scopes)[level].map.begin() ) {
    192                                 ++level;
    193                                 it = (*scopes)[level].map.end();
    194                         }
    195                         --it;
    196                         return prev_valid();
    197                 }
    198                 const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
    199 
    200                 bool operator== (const const_iterator & that) const {
    201                         return scopes == that.scopes && level == that.level && it == that.it;
    202                 }
    203                 bool operator!= (const const_iterator & that) const { return !( *this == that ); }
    204 
    205                 size_type get_level() const { return level; }
    206 
    207                 const Note & get_note() const { return (*scopes)[level].note; }
    208 
    209         private:
    210                 scope_list const *scopes;
    211                 wrapped_const_iterator it;
    212                 size_type level;
    213         };
     61        // Both iterator types are complete bidrectional iterators, see below.
     62        class iterator;
     63        class const_iterator;
    21464
    21565        /// Starts a new scope
     
    297147        }
    298148
    299         template< typename value_type_t >
    300         std::pair< iterator, bool > insert( iterator at, value_type_t && value ) {
    301                 MapType & scope = (*at.scopes)[ at.level ].map;
    302                 std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
    303                 return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) );
    304         }
    305 
    306149        template< typename value_t >
    307150        std::pair< iterator, bool > insert( const Key & key, value_t && value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); }
     
    324167        }
    325168
    326         iterator erase( iterator pos ) {
    327                 MapType & scope = (*pos.scopes)[ pos.level ].map;
    328                 const typename iterator::wrapped_iterator & new_it = scope.erase( pos.it );
    329                 iterator it( *pos.scopes, new_it, pos.level );
    330                 return it.next_valid();
     169        /// Erases element with key in the innermost scope that has it.
     170        size_type erase( const Key & key ) {
     171                for ( auto it = scopes.rbegin() ; it != scopes.rend() ; ++it ) {
     172                        if ( size_type i = it->map.erase( key ) ; 0 != i ) return i;
     173                }
     174                return 0;
    331175        }
    332176
     
    343187                return c;
    344188        }
     189
     190        bool contains( const Key & key ) const {
     191                return find( key ) != cend();
     192        }
     193};
     194
     195template<typename Key, typename Value, typename Note>
     196class ScopedMap<Key, Value, Note>::iterator :
     197                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     198        friend class ScopedMap;
     199        friend class const_iterator;
     200        typedef typename ScopedMap::MapType::iterator wrapped_iterator;
     201        typedef typename ScopedMap::ScopeList scope_list;
     202        typedef typename scope_list::size_type size_type;
     203
     204        /// Checks if this iterator points to a valid item
     205        bool is_valid() const {
     206                return it != (*scopes)[level].map.end();
     207        }
     208
     209        /// Increments on invalid
     210        iterator & next_valid() {
     211                if ( ! is_valid() ) { ++(*this); }
     212                return *this;
     213        }
     214
     215        /// Decrements on invalid
     216        iterator & prev_valid() {
     217                if ( ! is_valid() ) { --(*this); }
     218                return *this;
     219        }
     220
     221        iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel)
     222                : scopes(&_scopes), it(_it), level(inLevel) {}
     223public:
     224        iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     225        iterator & operator= (const iterator & that) {
     226                scopes = that.scopes; level = that.level; it = that.it;
     227                return *this;
     228        }
     229
     230        reference operator* () { return *it; }
     231        pointer operator-> () const { return it.operator->(); }
     232
     233        iterator & operator++ () {
     234                if ( it == (*scopes)[level].map.end() ) {
     235                        if ( level == 0 ) return *this;
     236                        --level;
     237                        it = (*scopes)[level].map.begin();
     238                } else {
     239                        ++it;
     240                }
     241                return next_valid();
     242        }
     243        iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
     244
     245        iterator & operator-- () {
     246                // may fail if this is the begin iterator; allowed by STL spec
     247                if ( it == (*scopes)[level].map.begin() ) {
     248                        ++level;
     249                        it = (*scopes)[level].map.end();
     250                }
     251                --it;
     252                return prev_valid();
     253        }
     254        iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
     255
     256        bool operator== (const iterator & that) const {
     257                return scopes == that.scopes && level == that.level && it == that.it;
     258        }
     259        bool operator!= (const iterator & that) const { return !( *this == that ); }
     260
     261        size_type get_level() const { return level; }
     262
     263        Note & get_note() { return (*scopes)[level].note; }
     264        const Note & get_note() const { return (*scopes)[level].note; }
     265
     266private:
     267        scope_list *scopes;
     268        wrapped_iterator it;
     269        size_type level;
     270};
     271
     272template<typename Key, typename Value, typename Note>
     273class ScopedMap<Key, Value, Note>::const_iterator :
     274                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     275        friend class ScopedMap;
     276        typedef typename ScopedMap::MapType::iterator wrapped_iterator;
     277        typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
     278        typedef typename ScopedMap::ScopeList scope_list;
     279        typedef typename scope_list::size_type size_type;
     280
     281        /// Checks if this iterator points to a valid item
     282        bool is_valid() const {
     283                return it != (*scopes)[level].map.end();
     284        }
     285
     286        /// Increments on invalid
     287        const_iterator & next_valid() {
     288                if ( ! is_valid() ) { ++(*this); }
     289                return *this;
     290        }
     291
     292        /// Decrements on invalid
     293        const_iterator & prev_valid() {
     294                if ( ! is_valid() ) { --(*this); }
     295                return *this;
     296        }
     297
     298        const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
     299                : scopes(&_scopes), it(_it), level(inLevel) {}
     300public:
     301        const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     302        const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     303        const_iterator & operator= (const iterator & that) {
     304                scopes = that.scopes; level = that.level; it = that.it;
     305                return *this;
     306        }
     307        const_iterator & operator= (const const_iterator & that) {
     308                scopes = that.scopes; level = that.level; it = that.it;
     309                return *this;
     310        }
     311
     312        const_reference operator* () { return *it; }
     313        const_pointer operator-> () { return it.operator->(); }
     314
     315        const_iterator & operator++ () {
     316                if ( it == (*scopes)[level].map.end() ) {
     317                        if ( level == 0 ) return *this;
     318                        --level;
     319                        it = (*scopes)[level].map.begin();
     320                } else {
     321                        ++it;
     322                }
     323                return next_valid();
     324        }
     325        const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
     326
     327        const_iterator & operator-- () {
     328                // may fail if this is the begin iterator; allowed by STL spec
     329                if ( it == (*scopes)[level].map.begin() ) {
     330                        ++level;
     331                        it = (*scopes)[level].map.end();
     332                }
     333                --it;
     334                return prev_valid();
     335        }
     336        const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
     337
     338        bool operator== (const const_iterator & that) const {
     339                return scopes == that.scopes && level == that.level && it == that.it;
     340        }
     341        bool operator!= (const const_iterator & that) const { return !( *this == that ); }
     342
     343        size_type get_level() const { return level; }
     344
     345        const Note & get_note() const { return (*scopes)[level].note; }
     346
     347private:
     348        scope_list const *scopes;
     349        wrapped_const_iterator it;
     350        size_type level;
    345351};
    346352
  • src/Common/SemanticError.h

    r9ef5516 r6d2af204  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May  4 14:08:26 2022
    13 // Update Count     : 35
     12// Last Modified On : Thu Feb  2 10:59:10 2023
     13// Update Count     : 36
    1414//
    1515
     
    5454
    5555constexpr WarningData WarningFormats[] = {
    56         {"self-assign"            , Severity::Warn    , "self assignment of expression: %s"                          },
    57         {"reference-conversion"   , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
    58         {"qualifiers-zero_t-one_t", Severity::Warn    , "questionable use of type qualifier %s with %s"              },
    59         {"aggregate-forward-decl" , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
    60         {"superfluous-decl"       , Severity::Warn    , "declaration does not allocate storage: %s"                  },
    61         {"superfluous-else"       , Severity::Warn    , "else clause never executed for empty loop conditional"      },
    62         {"gcc-attributes"         , Severity::Warn    , "invalid attribute: %s"                                      },
    63         {"c++-like-copy"          , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
     56        {"self-assign"              , Severity::Warn    , "self assignment of expression: %s"                          },
     57        {"reference-conversion"     , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
     58        {"qualifiers-zero_t-one_t"  , Severity::Warn    , "questionable use of type qualifier %s with %s"              },
     59        {"aggregate-forward-decl"   , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
     60        {"superfluous-decl"         , Severity::Warn    , "declaration does not allocate storage: %s"                  },
     61        {"superfluous-else"         , Severity::Warn    , "else clause never executed for empty loop conditional"      },
     62        {"gcc-attributes"           , Severity::Warn    , "invalid attribute: %s"                                      },
     63        {"c++-like-copy"            , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
     64        {"depreciated-trait-syntax" , Severity::Warn    , "trait type-parameters are now specified using the forall clause" },
    6465};
    6566
     
    7374        GccAttributes,
    7475        CppCopy,
     76        DeprecTraitSyntax,
    7577        NUMBER_OF_WARNINGS, // This MUST be the last warning
    7678};
  • src/Concurrency/Actors.cpp

    r9ef5516 r6d2af204  
    2121#include "AST/TranslationUnit.hpp"
    2222#include "AST/Expr.hpp"
     23#include <algorithm>
    2324using namespace ast;
     25using namespace std;
    2426
    2527namespace Concurrency {
    2628
    2729struct CollectactorStructDecls : public ast::WithGuards {
    28     std::map<const StructDecl *, int> & actorStructDecls;
    29     std::map<const StructDecl *, int>  & messageStructDecls;
     30    unordered_set<const StructDecl *> & actorStructDecls;
     31    unordered_set<const StructDecl *>  & messageStructDecls;
    3032    const StructDecl ** requestDecl;
    3133    const EnumDecl ** allocationDecl;
     
    3436    StructDecl * parentDecl;
    3537    bool insideStruct = false;
    36 
     38    bool namedDecl = false;
     39
     40    // finds and sets a ptr to the Allocation enum, which is needed in the next pass
    3741    void previsit( const EnumDecl * decl ) {
    3842        if( decl->name == "Allocation" ) *allocationDecl = decl;
    3943    }
    4044
     45    // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
    4146    void previsit( const StructDecl * decl ) {
    4247        GuardValue(insideStruct);
     
    4550        if( decl->name == "actor" ) *actorDecl = decl;
    4651        if( decl->name == "message" ) *msgDecl = decl;
    47         if( decl->name == "request" ) *requestDecl = decl;       
     52        if( decl->name == "request" ) *requestDecl = decl;
    4853        }
    4954
     55    // this catches structs of the form:
     56    //     struct dummy_actor { actor a; };
     57    // since they should be:
     58    //     struct dummy_actor { inline actor; };
     59    void previsit ( const ObjectDecl * decl ) {
     60        if ( insideStruct && ! decl->name.empty() ) {
     61            GuardValue(namedDecl);
     62            namedDecl = true;
     63        }
     64    }
     65
     66    // this collects the valid actor and message struct decl pts
    5067    void postvisit( const StructInstType * node ) {
    5168        if ( ! *actorDecl || ! *msgDecl ) return;
    52         if ( insideStruct ) {
     69        if ( insideStruct && !namedDecl ) {
    5370            if ( node->aggr() == *actorDecl ) {
    54                 actorStructDecls.insert({parentDecl, 1});
     71                actorStructDecls.insert( parentDecl );
    5572            } else if ( node->aggr() == *msgDecl ) {
    56                 messageStructDecls.insert({parentDecl, 1});
     73                messageStructDecls.insert( parentDecl );
    5774            }
    5875        }
     
    6077
    6178  public:
    62     CollectactorStructDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
     79    CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    6380        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl )
    6481        : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ),
     
    6683};
    6784
     85// keeps track of all fwdDecls of message routines so that we can hoist them to right after the appropriate decls
     86class FwdDeclTable {
     87
     88    // tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
     89    struct FwdDeclData {
     90        const StructDecl * actorDecl;
     91        const StructDecl * msgDecl;
     92        FunctionDecl * fwdDecl;
     93        bool actorFound;
     94        bool msgFound;
     95
     96        bool readyToInsert() { return actorFound && msgFound; }
     97        bool foundActor() { actorFound = true; return readyToInsert(); }
     98        bool foundMsg() { msgFound = true; return readyToInsert(); }
     99
     100        FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
     101            actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
     102    };
     103
     104    // map indexed by actor struct ptr
     105    // value is map of all FwdDeclData that contains said actor struct ptr
     106    // inner map is indexed by the message struct ptr of FwdDeclData
     107    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
     108
     109    // this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
     110    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
     111
     112    void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
     113        auto iter = map.find( decl );
     114        if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
     115            iter->second.emplace( make_pair( otherDecl, data ) );
     116        } else { // else create inner map for key
     117            map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) );
     118        }
     119    }
     120
     121  public:
     122    // insert decl into table so that we can fwd declare it later (average cost: O(1))
     123    void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
     124        FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
     125        insert( actorDecl, msgDecl, actorMap, declToInsert );
     126        insert( msgDecl, actorDecl, msgMap, declToInsert );
     127    }
     128
     129    // returns list of decls to insert after current struct decl
     130    // Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
     131    list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
     132        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
     133        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
     134        auto iter = map.find( decl );
     135        list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
     136        if ( iter == map.end() ) return toInsertAfter;
     137       
     138        // iterate over inner map
     139        unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
     140        for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
     141            FwdDeclData * currentDatum = innerIter->second;
     142            bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
     143            if ( ! readyToInsert ) { ++innerIter; continue; }
     144           
     145            // readyToInsert is true so we are good to insert the forward decl of the message fn
     146            toInsertAfter.push_back( currentDatum->fwdDecl );
     147
     148            // need to remove from other map before deleting
     149            // find inner map in other map ( other map is actor map if original is msg map and vice versa )
     150            const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
     151            auto otherMapIter = otherMap.find( otherDecl );
     152
     153            unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
     154
     155            // find the FwdDeclData we need to remove in the other inner map
     156            auto otherInnerIter = otherInnerMap.find( decl );
     157
     158            // remove references to deleted FwdDeclData from current inner map
     159            innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
     160
     161            // remove references to deleted FwdDeclData from other inner map
     162            otherInnerMap.erase( otherInnerIter );
     163           
     164            // if other inner map is now empty, remove key from other outer map
     165            if ( otherInnerMap.empty() )
     166                otherMap.erase( otherDecl );
     167
     168            // now we are safe to delete the FwdDeclData since we are done with it
     169            // and we have removed all references to it from our data structures
     170            delete currentDatum;
     171        }
     172
     173        // if current inner map is now empty, remove key from outer map.
     174        // Have to do this after iterating for safety
     175        if ( currInnerMap.empty() )
     176            map.erase( decl );
     177
     178        return toInsertAfter;
     179    }
     180};
     181
     182#define __ALLOC 0 // C_TODO: complete swap to no-alloc version
     183
    68184struct GenReceiveDecls : public ast::WithDeclsToAdd<> {
    69     std::map<const StructDecl *, int> & actorStructDecls;
    70     std::map<const StructDecl *, int>  & messageStructDecls;
     185    unordered_set<const StructDecl *> & actorStructDecls;
     186    unordered_set<const StructDecl *>  & messageStructDecls;
    71187    const StructDecl ** requestDecl;
    72188    const EnumDecl ** allocationDecl;
    73189    const StructDecl ** actorDecl;
    74190    const StructDecl ** msgDecl;
    75     std::vector<FunctionDecl *> & forwardDecls;
     191    FwdDeclTable & forwardDecls;
    76192
    77193        void postvisit( const FunctionDecl * decl ) {
     
    90206
    91207        // If the struct instances are derived actor and message types then generate the message send routine
    92         if ( actorStructDecls.count( arg1InstType->aggr() ) && messageStructDecls.count( arg2InstType->aggr() ) ) {
     208        auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
     209        auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
     210        if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
    93211
    94212            // check that we have found all the decls we need from <actor.hfa>
     
    107225                    return receiver;
    108226                }
    109             */
     227            */ // C_TODO: update this with new no alloc version
    110228            CompoundStmt * sendBody = new CompoundStmt( decl->location );
    111229
     230            #if __ALLOC
    112231            // Generates: request * new_req = alloc();
    113232            sendBody->push_back( new DeclStmt(
     
    120239                )
    121240            ));
     241            #else
     242            // Generates: request new_req;
     243            sendBody->push_back( new DeclStmt(
     244                decl->location,
     245                new ObjectDecl(
     246                    decl->location,
     247                    "new_req",
     248                    new StructInstType( *requestDecl )
     249                )
     250            ));
     251            #endif
    122252           
    123253            // Function type is: Allocation (*)( derived_actor &, derived_msg & )
     
    160290            ));
    161291
     292            #if __ALLOC
    162293            // Generates: (*new_req){ &receiver, &msg, fn };
    163294            sendBody->push_back( new ExprStmt(
     
    189320                                )
    190321                        ));
     322            #else
     323            // Generates: new_req{ &receiver, &msg, fn };
     324            sendBody->push_back( new ExprStmt(
     325                decl->location,
     326                                new UntypedExpr (
     327                    decl->location,
     328                                        new NameExpr( decl->location, "?{}" ),
     329                                        {
     330                                                new NameExpr( decl->location, "new_req" ),
     331                        new AddressExpr( new NameExpr( decl->location, "receiver" ) ),
     332                        new AddressExpr( new NameExpr( decl->location, "msg" ) ),
     333                        new NameExpr( decl->location, "fn" )
     334                                        }
     335                                )
     336                        ));
     337
     338            // Generates: send( receiver, new_req );
     339            sendBody->push_back( new ExprStmt(
     340                decl->location,
     341                                new UntypedExpr (
     342                    decl->location,
     343                                        new NameExpr( decl->location, "send" ),
     344                                        {
     345                                                {
     346                            new NameExpr( decl->location, "receiver" ),
     347                            new NameExpr( decl->location, "new_req" )
     348                        }
     349                                        }
     350                                )
     351                        ));
     352            #endif
    191353           
    192354            // Generates: return receiver;
     
    225387           
    226388            // forward decls to resolve use before decl problem for '|' routines
    227             forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
     389            forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
     390            // forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
    228391
    229392            sendOperatorFunction->stmts = sendBody;
     
    233396
    234397  public:
    235     GenReceiveDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
     398    GenReceiveDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    236399        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl,
    237         std::vector<FunctionDecl *> & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     400        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    238401        requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
    239402};
    240403
    241404struct GenFwdDecls : public ast::WithDeclsToAdd<> {
    242     std::map<const StructDecl *, int> & actorStructDecls;
    243     std::map<const StructDecl *, int>  & messageStructDecls;
    244     std::vector<FunctionDecl *> & forwardDecls;
    245     bool done;
    246 
    247     void postvisit( const FunctionDecl * decl ) {
    248         if ( done ) return;
    249         // return if not of the form receive( param1, param2 ) or if it is a forward decl
    250         if ( decl->name != "receive" || decl->params.size() != 2 || !decl->stmts ) return;
    251 
    252         // the params should be references
    253         const ReferenceType * derivedActorRef = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type());
    254         const ReferenceType * derivedMsgRef = dynamic_cast<const ReferenceType *>(decl->params.at(1)->get_type());
    255         if ( !derivedActorRef || !derivedMsgRef ) return;
    256 
    257         // the references should be to struct instances
    258         const StructInstType * arg1InstType = dynamic_cast<const StructInstType *>(derivedActorRef->base.get());
    259         const StructInstType * arg2InstType = dynamic_cast<const StructInstType *>(derivedMsgRef->base.get());
    260         if ( !arg1InstType || !arg2InstType ) return;
    261 
    262         // If the struct instances are derived actor and message types then generate the message send routine
    263         if ( actorStructDecls.count( arg1InstType->aggr() ) && messageStructDecls.count( arg2InstType->aggr() ) ) {
    264             done = true;
    265             for ( const auto & func : forwardDecls ) {
    266                 declsToAddBefore.push_back( func );
    267             }
     405    unordered_set<const StructDecl *> & actorStructDecls;
     406    unordered_set<const StructDecl *>  & messageStructDecls;
     407    FwdDeclTable & forwardDecls;
     408
     409    void postvisit( const StructDecl * decl ) {
     410        list<FunctionDecl *> toAddAfter;
     411        auto actorIter = actorStructDecls.find( decl );
     412        if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
     413            // get list of fwd decls that we can now insert
     414            toAddAfter = forwardDecls.updateDecl( decl, false );
     415
     416            // get rid of decl from actorStructDecls since we no longer need it
     417            actorStructDecls.erase( actorIter );
     418        } else {
     419            auto messageIter = messageStructDecls.find( decl );
     420            if ( messageIter == messageStructDecls.end() ) return;
     421
     422            toAddAfter = forwardDecls.updateDecl( decl, true );
     423
     424            // get rid of decl from messageStructDecls since we no longer need it
     425            messageStructDecls.erase( messageIter );
     426        }
     427
     428        // add the fwd decls to declsToAddAfter
     429        for ( FunctionDecl * func : toAddAfter ) {
     430            declsToAddAfter.push_back( func );
    268431        }
    269432    }
    270433
    271434  public:
    272     GenFwdDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
    273         std::vector<FunctionDecl *> & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    274         forwardDecls(forwardDecls), done(false) {}
     435    GenFwdDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     436        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     437        forwardDecls(forwardDecls) {}
    275438};
    276439
    277440void implementActors( TranslationUnit & translationUnit ) {
    278     // maps to collect all derived actor and message types
    279     std::map<const StructDecl *, int> actorStructDecls;
    280     std::map<const StructDecl *, int> messageStructDecls;
    281     std::vector<FunctionDecl *> forwardDecls;
     441    // unordered_maps to collect all derived actor and message types
     442    unordered_set<const StructDecl *> actorStructDecls;
     443    unordered_set<const StructDecl *> messageStructDecls;
     444    FwdDeclTable forwardDecls;
    282445
    283446    // for storing through the passes
  • src/GenPoly/Box.cc

    r9ef5516 r6d2af204  
    488488                                for ( FunctionType const * const funType : functions ) {
    489489                                        std::string mangleName = mangleAdapterName( funType, scopeTyVars );
    490                                         if ( adapters.find( mangleName ) == adapters.end() ) {
     490                                        if ( !adapters.contains( mangleName ) ) {
    491491                                                std::string adapterName = makeAdapterName( mangleName );
    492492                                                adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), nullptr ) ) );
     
    14871487                                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
    14881488                                                // do not try to monomorphize generic parameters
    1489                                                 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() && ! genericParams.count( typeInst->name ) ) {
     1489                                                if ( scopeTyVars.contains( typeInst->get_name() ) && ! genericParams.count( typeInst->name ) ) {
    14901490                                                        // polymorphic aggregate members should be converted into monomorphic members.
    14911491                                                        // Using char[size_T] here respects the expected sizing rules of an aggregate type.
     
    16961696
    16971697                        if ( auto typeInst = dynamic_cast< TypeInstType const * >( ty ) ) {
    1698                                 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
     1698                                if ( scopeTyVars.contains( typeInst->get_name() ) ) {
    16991699                                        // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
    17001700                                        return true;
     
    17041704                                // check if this type already has a layout generated for it
    17051705                                std::string typeName = mangleType( ty );
    1706                                 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     1706                                if ( knownLayouts.contains( typeName ) ) return true;
    17071707
    17081708                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     
    17411741                                // check if this type already has a layout generated for it
    17421742                                std::string typeName = mangleType( ty );
    1743                                 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     1743                                if ( knownLayouts.contains( typeName ) ) return true;
    17441744
    17451745                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     
    18321832                        } else {
    18331833                                std::string offsetName = offsetofName( mangleType( ty ) );
    1834                                 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
     1834                                if ( knownOffsets.contains( offsetName ) ) {
    18351835                                        // use the already-generated offsets for this type
    18361836                                        ret = new NameExpr( offsetName );
  • src/GenPoly/ErasableScopedMap.h

    r9ef5516 r6d2af204  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ScopedMap.h --
     7// ErasableScopedMap.h --
    88//
    99// Author           : Aaron B. Moss
     
    5151        typedef typename Scope::const_pointer const_pointer;
    5252
    53         // Both iterator types are complete bidirection iterators, defined below.
     53        // Both iterator types are complete bidirectional iterators, see below.
    5454        class iterator;
    5555        class const_iterator;
     
    118118        std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); }
    119119
     120        Value& operator[] ( const Key &key ) {
     121                iterator slot = find( key );
     122                if ( slot != end() ) return slot->second;
     123                return insert( key, Value() ).first->second;
     124        }
     125
    120126        /// Marks the given element as erased from this scope inward; returns 1 for erased an element, 0 otherwise
    121127        size_type erase( const Key &key ) {
     
    130136        }
    131137
    132         Value& operator[] ( const Key &key ) {
    133                 iterator slot = find( key );
    134                 if ( slot != end() ) return slot->second;
    135                 return insert( key, Value() ).first->second;
     138        bool contains( const Key & key ) const {
     139                return find( key ) != cend();
    136140        }
    137141};
  • src/GenPoly/GenPoly.cc

    r9ef5516 r6d2af204  
    172172
    173173                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
    174                         if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
     174                        if ( tyVars.contains( typeInst->get_name() ) ) {
    175175                                return type;
    176176                        }
     
    189189
    190190                if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    191                         return tyVars.find(typeInst->typeString()) != tyVars.end() ? type : nullptr;
     191                        if ( tyVars.contains( typeInst->typeString() ) ) return type;
    192192                } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
    193193                        return isPolyType( arrayType->base, env );
     
    205205
    206206        if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    207                 if ( typeVars.find( *inst ) != typeVars.end() ) return type;
     207                if ( typeVars.contains( *inst ) ) return type;
    208208        } else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) {
    209209                return isPolyType( array->base, subst );
     
    393393
    394394                if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {
    395                         if ( tyVars.find( typeInstType->get_name() ) != tyVars.end() ) {
     395                        if ( tyVars.contains( typeInstType->get_name() ) ) {
    396396                                return true;
    397397                        }
  • src/GenPoly/ScopedSet.h

    r9ef5516 r6d2af204  
    2121
    2222namespace GenPoly {
    23         /// A set where the items are placed into nested scopes;
    24         /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
    25         template<typename Value>
    26         class ScopedSet {
    27                 typedef std::set< Value > Scope;
    28                 typedef std::vector< Scope > ScopeList;
    29 
    30                 ScopeList scopes; ///< scoped list of sets
    31         public:
    32                 typedef typename Scope::key_type key_type;
    33                 typedef typename Scope::value_type value_type;
    34                 typedef typename ScopeList::size_type size_type;
    35                 typedef typename ScopeList::difference_type difference_type;
    36                 typedef typename Scope::reference reference;
    37                 typedef typename Scope::const_reference const_reference;
    38                 typedef typename Scope::pointer pointer;
    39                 typedef typename Scope::const_pointer const_pointer;
    40 
    41                 class iterator : public std::iterator< std::bidirectional_iterator_tag,
    42                                                        value_type > {
    43                 friend class ScopedSet;
    44                 friend class const_iterator;
    45                         typedef typename std::set< Value >::iterator wrapped_iterator;
    46                         typedef typename std::vector< std::set< Value > > scope_list;
    47                         typedef typename scope_list::size_type size_type;
    48 
    49                         /// Checks if this iterator points to a valid item
    50                         bool is_valid() const {
    51                                 return it != (*scopes)[i].end();
    52                         }
    53 
    54                         /// Increments on invalid
    55                         iterator& next_valid() {
    56                                 if ( ! is_valid() ) { ++(*this); }
    57                                 return *this;
    58                         }
    59 
    60                         /// Decrements on invalid
    61                         iterator& prev_valid() {
    62                                 if ( ! is_valid() ) { --(*this); }
    63                                 return *this;
    64                         }
    65 
    66                         iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
    67                                 : scopes(&_scopes), it(_it), i(_i) {}
    68                 public:
    69                         iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    70                         iterator& operator= (const iterator &that) {
    71                                 scopes = that.scopes; i = that.i; it = that.it;
    72                                 return *this;
    73                         }
    74 
    75                         reference operator* () { return *it; }
    76                         pointer operator-> () { return it.operator->(); }
    77 
    78                         iterator& operator++ () {
    79                                 if ( it == (*scopes)[i].end() ) {
    80                                         if ( i == 0 ) return *this;
    81                                         --i;
    82                                         it = (*scopes)[i].begin();
    83                                 } else {
    84                                         ++it;
    85                                 }
    86                                 return next_valid();
    87                         }
    88                         iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
    89 
    90                         iterator& operator-- () {
    91                                 // may fail if this is the begin iterator; allowed by STL spec
    92                                 if ( it == (*scopes)[i].begin() ) {
    93                                         ++i;
    94                                         it = (*scopes)[i].end();
    95                                 }
    96                                 --it;
    97                                 return prev_valid();
    98                         }
    99                         iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
    100 
    101                         bool operator== (const iterator &that) {
    102                                 return scopes == that.scopes && i == that.i && it == that.it;
    103                         }
    104                         bool operator!= (const iterator &that) { return !( *this == that ); }
    105 
    106                         size_type get_level() const { return i; }
    107 
    108                 private:
    109                         scope_list const *scopes;
    110                         wrapped_iterator it;
    111                         size_type i;
    112                 };
    113 
    114                 class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
    115                                                              value_type > {
    116                 friend class ScopedSet;
    117                         typedef typename std::set< Value >::iterator wrapped_iterator;
    118                         typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
    119                         typedef typename std::vector< std::set< Value > > scope_list;
    120                         typedef typename scope_list::size_type size_type;
    121 
    122                         /// Checks if this iterator points to a valid item
    123                         bool is_valid() const {
    124                                 return it != (*scopes)[i].end();
    125                         }
    126 
    127                         /// Increments on invalid
    128                         const_iterator& next_valid() {
    129                                 if ( ! is_valid() ) { ++(*this); }
    130                                 return *this;
    131                         }
    132 
    133                         /// Decrements on invalid
    134                         const_iterator& prev_valid() {
    135                                 if ( ! is_valid() ) { --(*this); }
    136                                 return *this;
    137                         }
    138 
    139                         const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
    140                                 : scopes(&_scopes), it(_it), i(_i) {}
    141                 public:
    142                         const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    143                         const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    144                         const_iterator& operator= (const iterator &that) {
    145                                 scopes = that.scopes; i = that.i; it = that.it;
    146                                 return *this;
    147                         }
    148                         const_iterator& operator= (const const_iterator &that) {
    149                                 scopes = that.scopes; i = that.i; it = that.it;
    150                                 return *this;
    151                         }
    152 
    153                         const_reference operator* () { return *it; }
    154                         const_pointer operator-> () { return it.operator->(); }
    155 
    156                         const_iterator& operator++ () {
    157                                 if ( it == (*scopes)[i].end() ) {
    158                                         if ( i == 0 ) return *this;
    159                                         --i;
    160                                         it = (*scopes)[i].begin();
    161                                 } else {
    162                                         ++it;
    163                                 }
    164                                 return next_valid();
    165                         }
    166                         const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
    167 
    168                         const_iterator& operator-- () {
    169                                 // may fail if this is the begin iterator; allowed by STL spec
    170                                 if ( it == (*scopes)[i].begin() ) {
    171                                         ++i;
    172                                         it = (*scopes)[i].end();
    173                                 }
    174                                 --it;
    175                                 return prev_valid();
    176                         }
    177                         const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
    178 
    179                         bool operator== (const const_iterator &that) {
    180                                 return scopes == that.scopes && i == that.i && it == that.it;
    181                         }
    182                         bool operator!= (const const_iterator &that) { return !( *this == that ); }
    183 
    184                         size_type get_level() const { return i; }
    185 
    186                 private:
    187                         scope_list const *scopes;
    188                         wrapped_const_iterator it;
    189                         size_type i;
    190                 };
    191 
    192                 /// Starts a new scope
    193                 void beginScope() {
    194                         Scope scope;
    195                         scopes.push_back(scope);
    196                 }
    197 
    198                 /// Ends a scope; invalidates any iterators pointing to elements of that scope
    199                 void endScope() {
    200                         scopes.pop_back();
    201                 }
    202 
    203                 /// Default constructor initializes with one scope
    204                 ScopedSet() { beginScope(); }
    205 
    206                 iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    207                 const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    208                 const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    209                 iterator end() { return iterator(scopes, scopes[0].end(), 0); }
    210                 const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
    211                 const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
    212 
    213                 /// Gets the index of the current scope (counted from 1)
    214                 size_type currentScope() const { return scopes.size(); }
    215 
    216                 /// Finds the given key in the outermost scope it occurs; returns end() for none such
    217                 iterator find( const Value &key ) {
    218                         for ( size_type i = scopes.size() - 1; ; --i ) {
    219                                 typename Scope::iterator val = scopes[i].find( key );
    220                                 if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    221                                 if ( i == 0 ) break;
    222                         }
    223                         return end();
    224                 }
    225                 const_iterator find( const Value &key ) const {
    226                         return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
    227                 }
    228 
    229                 /// Finds the given key in the outermost scope inside the given scope where it occurs
    230                 iterator findNext( const_iterator &it, const Value &key ) {
    231                         if ( it.i == 0 ) return end();
     23
     24/// A set where the items are placed into nested scopes;
     25/// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
     26template<typename Value>
     27class ScopedSet {
     28        typedef std::set< Value > Scope;
     29        typedef std::vector< Scope > ScopeList;
     30
     31        /// Scoped list of sets.
     32        ScopeList scopes;
     33public:
     34        typedef typename Scope::key_type key_type;
     35        typedef typename Scope::value_type value_type;
     36        typedef typename ScopeList::size_type size_type;
     37        typedef typename ScopeList::difference_type difference_type;
     38        typedef typename Scope::reference reference;
     39        typedef typename Scope::const_reference const_reference;
     40        typedef typename Scope::pointer pointer;
     41        typedef typename Scope::const_pointer const_pointer;
     42
     43        // Both iterator types are complete bidirectional iterators, see below.
     44        class iterator;
     45        class const_iterator;
     46
     47        /// Starts a new scope
     48        void beginScope() {
     49                Scope scope;
     50                scopes.push_back(scope);
     51        }
     52
     53        /// Ends a scope; invalidates any iterators pointing to elements of that scope
     54        void endScope() {
     55                scopes.pop_back();
     56        }
     57
     58        /// Default constructor initializes with one scope
     59        ScopedSet() { beginScope(); }
     60
     61        iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     62        const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     63        const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     64        iterator end() { return iterator(scopes, scopes[0].end(), 0); }
     65        const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
     66        const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
     67
     68        /// Gets the index of the current scope (counted from 1)
     69        size_type currentScope() const { return scopes.size(); }
     70
     71        /// Finds the given key in the outermost scope it occurs; returns end() for none such
     72        iterator find( const Value &key ) {
     73                for ( size_type i = scopes.size() - 1; ; --i ) {
     74                        typename Scope::iterator val = scopes[i].find( key );
     75                        if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     76                        if ( i == 0 ) break;
     77                }
     78                return end();
     79        }
     80        const_iterator find( const Value &key ) const {
     81                return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
     82        }
     83
     84        /// Finds the given key in the outermost scope inside the given scope where it occurs
     85        iterator findNext( const_iterator &it, const Value &key ) {
     86                if ( it.i == 0 ) return end();
    23287                        for ( size_type i = it.i - 1; ; --i ) {
    233                                 typename Scope::iterator val = scopes[i].find( key );
    234                                 if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    235                                 if ( i == 0 ) break;
    236                         }
    237                         return end();
    238                 }
    239                 const_iterator findNext( const_iterator &it, const Value &key ) const {
    240                         return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
    241                 }
    242 
    243                 /// Inserts the given value into the outermost scope
    244                 std::pair< iterator, bool > insert( const value_type &value ) {
    245                         std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
    246                         return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
    247                 }
    248 
    249         };
     88                        typename Scope::iterator val = scopes[i].find( key );
     89                        if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     90                        if ( i == 0 ) break;
     91                }
     92                return end();
     93        }
     94        const_iterator findNext( const_iterator &it, const Value &key ) const {
     95                return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
     96        }
     97
     98        /// Inserts the given value into the outermost scope
     99        std::pair< iterator, bool > insert( const value_type &value ) {
     100                std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
     101                return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
     102        }
     103
     104        bool contains( const Value & key ) const {
     105                return find( key ) != cend();
     106        }
     107};
     108
     109template<typename Value>
     110class ScopedSet<Value>::iterator :
     111                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     112        friend class ScopedSet;
     113        friend class const_iterator;
     114        typedef typename std::set< Value >::iterator wrapped_iterator;
     115        typedef typename std::vector< std::set< Value > > scope_list;
     116        typedef typename scope_list::size_type size_type;
     117
     118        /// Checks if this iterator points to a valid item
     119        bool is_valid() const {
     120                return it != (*scopes)[i].end();
     121        }
     122
     123        /// Increments on invalid
     124        iterator& next_valid() {
     125                if ( ! is_valid() ) { ++(*this); }
     126                return *this;
     127        }
     128
     129        /// Decrements on invalid
     130        iterator& prev_valid() {
     131                if ( ! is_valid() ) { --(*this); }
     132                return *this;
     133        }
     134
     135        iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
     136                : scopes(&_scopes), it(_it), i(_i) {}
     137public:
     138        iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     139        iterator& operator= (const iterator &that) {
     140                scopes = that.scopes; i = that.i; it = that.it;
     141                return *this;
     142        }
     143
     144        reference operator* () { return *it; }
     145        pointer operator-> () { return it.operator->(); }
     146
     147        iterator& operator++ () {
     148                if ( it == (*scopes)[i].end() ) {
     149                        if ( i == 0 ) return *this;
     150                        --i;
     151                        it = (*scopes)[i].begin();
     152                } else {
     153                        ++it;
     154                }
     155                return next_valid();
     156        }
     157        iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
     158
     159        iterator& operator-- () {
     160                // may fail if this is the begin iterator; allowed by STL spec
     161                if ( it == (*scopes)[i].begin() ) {
     162                        ++i;
     163                        it = (*scopes)[i].end();
     164                }
     165                --it;
     166                return prev_valid();
     167        }
     168        iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
     169
     170        bool operator== (const iterator &that) {
     171                return scopes == that.scopes && i == that.i && it == that.it;
     172        }
     173        bool operator!= (const iterator &that) { return !( *this == that ); }
     174
     175        size_type get_level() const { return i; }
     176
     177private:
     178        scope_list const *scopes;
     179        wrapped_iterator it;
     180        size_type i;
     181};
     182
     183template<typename Value>
     184class ScopedSet<Value>::const_iterator :
     185                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     186        friend class ScopedSet;
     187        typedef typename std::set< Value >::iterator wrapped_iterator;
     188        typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
     189        typedef typename std::vector< std::set< Value > > scope_list;
     190        typedef typename scope_list::size_type size_type;
     191
     192        /// Checks if this iterator points to a valid item
     193        bool is_valid() const {
     194                return it != (*scopes)[i].end();
     195        }
     196
     197        /// Increments on invalid
     198        const_iterator& next_valid() {
     199                if ( ! is_valid() ) { ++(*this); }
     200                return *this;
     201        }
     202
     203        /// Decrements on invalid
     204        const_iterator& prev_valid() {
     205                if ( ! is_valid() ) { --(*this); }
     206                return *this;
     207        }
     208
     209        const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
     210                : scopes(&_scopes), it(_it), i(_i) {}
     211public:
     212        const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     213        const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     214        const_iterator& operator= (const iterator &that) {
     215                scopes = that.scopes; i = that.i; it = that.it;
     216                return *this;
     217        }
     218        const_iterator& operator= (const const_iterator &that) {
     219                scopes = that.scopes; i = that.i; it = that.it;
     220                return *this;
     221        }
     222
     223        const_reference operator* () { return *it; }
     224        const_pointer operator-> () { return it.operator->(); }
     225
     226        const_iterator& operator++ () {
     227                if ( it == (*scopes)[i].end() ) {
     228                        if ( i == 0 ) return *this;
     229                        --i;
     230                        it = (*scopes)[i].begin();
     231                } else {
     232                        ++it;
     233                }
     234                return next_valid();
     235        }
     236        const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
     237
     238        const_iterator& operator-- () {
     239                // may fail if this is the begin iterator; allowed by STL spec
     240                if ( it == (*scopes)[i].begin() ) {
     241                        ++i;
     242                        it = (*scopes)[i].end();
     243                }
     244                --it;
     245                return prev_valid();
     246        }
     247        const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
     248
     249        bool operator== (const const_iterator &that) {
     250                return scopes == that.scopes && i == that.i && it == that.it;
     251        }
     252        bool operator!= (const const_iterator &that) { return !( *this == that ); }
     253
     254        size_type get_level() const { return i; }
     255
     256private:
     257        scope_list const *scopes;
     258        wrapped_const_iterator it;
     259        size_type i;
     260};
     261
    250262} // namespace GenPoly
    251263
  • src/GenPoly/ScrubTyVars.cc

    r9ef5516 r6d2af204  
    178178
    179179ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
     180        ast::TypeDecl::Kind kind;
    180181        // This implies that mode == ScrubMode::All.
    181182        if ( !typeVars ) {
    182                 if ( ast::TypeDecl::Ftype == type->kind ) {
    183                         return new ast::PointerType(
    184                                 new ast::FunctionType( ast::FixedArgs ) );
    185                 } else {
    186                         return new ast::PointerType(
    187                                 new ast::VoidType( type->qualifiers ) );
    188                 }
    189         }
    190 
    191         auto typeVar = typeVars->find( *type );
    192         if ( typeVar == typeVars->end() ) {
    193                 return type;
    194         }
    195 
    196         switch ( typeVar->second.kind ) {
    197         case ::TypeDecl::Dtype:
    198         case ::TypeDecl::Ttype:
     183                kind = type->kind;
     184        } else {
     185                // Otherwise, only scrub the type var if it is in map.
     186                auto typeVar = typeVars->find( *type );
     187                if ( typeVar == typeVars->end() ) {
     188                        return type;
     189                }
     190                kind = typeVar->second.kind;
     191        }
     192
     193        switch ( kind ) {
     194        case ast::TypeDecl::Dtype:
     195        case ast::TypeDecl::Ttype:
    199196                return new ast::PointerType(
    200197                        new ast::VoidType( type->qualifiers ) );
    201         case ::TypeDecl::Ftype:
     198        case ast::TypeDecl::Ftype:
    202199                return new ast::PointerType(
    203200                        new ast::FunctionType( ast::VariableArgs ) );
    204201        default:
    205                 assertf( false,
    206                         "Unhandled type variable kind: %d", typeVar->second.kind );
     202                assertf( false, "Unhandled type variable kind: %d", kind );
    207203                throw; // Just in case the assert is removed, stop here.
    208204        }
  • src/Parser/parser.yy

    r9ef5516 r6d2af204  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan 30 20:47:27 2023
    13 // Update Count     : 5859
     12// Last Modified On : Thu Feb  2 21:36:16 2023
     13// Update Count     : 5865
    1414//
    1515
     
    20802080                { $$ = DeclarationNode::newTypeQualifier( Type::Atomic ); }
    20812081        | forall
     2082                { $$ = DeclarationNode::newForall( $1 ); }
    20822083        ;
    20832084
    20842085forall:
    20852086        FORALL '(' type_parameter_list ')'                                      // CFA
    2086                 { $$ = DeclarationNode::newForall( $3 ); }
     2087                { $$ = $3; }
    20872088        ;
    20882089
     
    29782979trait_specifier:                                                                                // CFA
    29792980        TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}'
    2980                 { $$ = DeclarationNode::newTrait( $2, $4, nullptr ); }
    2981         | FORALL '(' type_parameter_list ')' TRAIT identifier_or_type_name '{' '}' // alternate
    2982                 { $$ = DeclarationNode::newTrait( $6, $3, nullptr ); }
     2981                {
     2982                        SemanticWarning( yylloc, Warning::DeprecTraitSyntax, "" );
     2983                        $$ = DeclarationNode::newTrait( $2, $4, nullptr );
     2984                }
     2985        | forall TRAIT identifier_or_type_name '{' '}'          // alternate
     2986                { $$ = DeclarationNode::newTrait( $3, $1, nullptr ); }
    29832987        | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
    2984                 { $$ = DeclarationNode::newTrait( $2, $4, $8 ); }
    2985         | FORALL '(' type_parameter_list ')' TRAIT identifier_or_type_name '{' push trait_declaration_list pop '}' // alternate
    2986                 { $$ = DeclarationNode::newTrait( $6, $3, $9 ); }
     2988                {
     2989                        SemanticWarning( yylloc, Warning::DeprecTraitSyntax, "" );
     2990                        $$ = DeclarationNode::newTrait( $2, $4, $8 );
     2991                }
     2992        | forall TRAIT identifier_or_type_name '{' push trait_declaration_list pop '}' // alternate
     2993                { $$ = DeclarationNode::newTrait( $3, $1, $6 ); }
    29872994        ;
    29882995
  • src/SymTab/Validate.cc

    r9ef5516 r6d2af204  
    863863
    864864        void ReplaceTypedef::premutate( TypeDecl * typeDecl ) {
    865                 TypedefMap::iterator i = typedefNames.find( typeDecl->name );
    866                 if ( i != typedefNames.end() ) {
    867                         typedefNames.erase( i ) ;
    868                 } // if
    869 
     865                typedefNames.erase( typeDecl->name );
    870866                typedeclNames.insert( typeDecl->name, typeDecl );
    871867        }
  • src/Validate/ReplaceTypedef.cpp

    r9ef5516 r6d2af204  
    186186
    187187void ReplaceTypedefCore::previsit( ast::TypeDecl const * decl ) {
    188         TypedefMap::iterator iter = typedefNames.find( decl->name );
    189         if ( iter != typedefNames.end() ) {
    190                 typedefNames.erase( iter );
    191         }
     188        typedefNames.erase( decl->name );
    192189        typedeclNames.insert( decl->name, decl );
    193190}
  • tests/.expect/forall.txt

    r9ef5516 r6d2af204  
    1 forall.cfa:244:25: warning: Compiled
     11
     2f
     397
     4f
     5g
     6f
     7f
     8g
     9fT
     10fT
     11fT
     12fTU
     13fTU
     14fTU
     151 2
     162 1
     171, 2
     18@ 0 2 0 4 6.4 6.4 6.4 6.4+3.i 4
     193. 3.
     2045
     2112 3
  • tests/Makefile.am

    r9ef5516 r6d2af204  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Sat Jun  5 14:49:25 2021
    14 ## Update Count     : 92
     13## Last Modified On : Fri Feb  3 23:06:44 2023
     14## Update Count     : 94
    1515###############################################################################
    1616
     
    8989        meta/fork+exec.hfa \
    9090        concurrent/unified_locking/mutex_test.hfa \
    91     concurrent/channels/parallel_harness.hfa
     91        concurrent/channels/parallel_harness.hfa
    9292
    9393dist-hook:
     
    183183CFACOMPILE_SYNTAX = $(CFACOMPILETEST) -Wno-unused-variable -Wno-unused-label -c -fsyntax-only -o $(abspath ${@})
    184184
    185 SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator forall \
     185SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator \
    186186        init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment
    187187$(SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN)
  • tests/concurrent/actors/matrix.cfa

    r9ef5516 r6d2af204  
    55#include <stdio.h>
    66
    7 unsigned int xr = 100, xc = 100, yc = 100, Processors = 1; // default values
     7unsigned int xr = 500, xc = 500, yc = 500, Processors = 1; // default values
    88
    99struct derived_actor {
  • tests/concurrent/actors/types.cfa

    r9ef5516 r6d2af204  
    55#include <stdio.h>
    66#include <mutex_stmt.hfa>
     7
     8struct dummy_actor { actor a; }; // this won't work since the actor isn't inlined
    79
    810struct derived_actor {
     
    2628}
    2729
     30Allocation receive( derived_actor & receiver, d_msg & msg ) {
     31    return receive( receiver, msg.num );
     32}
     33
    2834struct derived_actor2 {
     35    struct nested { int i; }; // testing nested before inline
    2936    inline actor;
    3037};
    3138static inline void ?{}( derived_actor2 & this ) { ((actor &)this){}; }
     39
     40Allocation receive( derived_actor2 & receiver, d_msg & msg ) {
     41    mutex(sout) sout | msg.num;
     42    return Finished;
     43}
    3244
    3345struct derived_actor3 {
     
    4153};
    4254static inline void ?{}( d_msg2 & this ) { ((message &)this){}; }
    43 
    44 Allocation receive( derived_actor2 & receiver, d_msg & msg ) {
    45     mutex(sout) sout | msg.num;
    46     return Finished;
    47 }
    48 
    49 Allocation receive( derived_actor & receiver, d_msg & msg ) {
    50     return receive( receiver, msg.num );
    51 }
    5255
    5356Allocation receive( derived_actor3 & receiver, d_msg & msg ) {
  • tests/forall.cfa

    r9ef5516 r6d2af204  
    1010// Created On       : Wed May  9 08:48:15 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun  5 10:06:08 2021
    13 // Update Count     : 36
    14 //
     12// Last Modified On : Sun Feb  5 07:54:43 2023
     13// Update Count     : 90
     14//
     15
     16#include <fstream.hfa>
    1517
    1618void g1() {
    17         forall( T ) T f( T ) {};
    18         void f( int ) {};
    19         void h( void (*p)(void) ) {};
    20 
    21         int x;
    22         void (*y)(void);
    23         char z;
    24         float w;
     19        forall( T ) T f( T p ) { sout | 'f'; return p;  };
     20        void f( int p ) { sout | p; };
     21        void g( void ) { sout | 'g'; };
     22        void h( void (*p)(void) ) { p(); };
     23
     24        int x = 1;
     25        void (*y)(void) = g;
     26        char z = 'a';
     27        float w = 3.5;
    2528
    2629        f( x );
     
    2831        f( z );
    2932        f( w );
     33        h( y );
     34        f( y );
    3035        h( f( y ) );
    3136}
    3237
    3338void g2() {
    34         forall( T ) void f( T, T ) {}
    35         forall( T, U ) void f( T, U ) {}
     39        forall( T ) void f( T, T ) { sout | "fT"; }
     40        forall( T, U ) void f( T, U ) { sout | "fTU"; }
    3641
    3742        int x;
    3843        float y;
    39         int *z;
    40         float *w;
    41 
     44        int * z;
     45        float * w;
     46
     47        f( x, x );
     48        f( y, y );
     49        f( w, w );
    4250        f( x, y );
    4351        f( z, w );
     
    5058
    5159forall( T )
    52 void swap( T left, T right ) {
    53         T temp = left;
    54         left = right;
    55         right = temp;
    56 }
    57 
    58 trait sumable( T ) {
     60void swap( T & left, T & right ) {                                              // by reference
     61    T temp = left;
     62    left = right;
     63    right = temp;
     64}
     65
     66forall( T )
     67[ T, T ] swap( T i, T j ) {                                                             // by value
     68    return [ j, i ];
     69}
     70
     71forall( T ) trait sumable {
    5972        void ?{}( T &, zero_t );                                                        // 0 literal constructor
    6073        T ?+?( T, T );                                                                          // assortment of additions
     
    6477}; // sumable
    6578
    66 forall( T | sumable( T ) )                                              // use trait
     79forall( T | sumable( T ) )                                                              // use trait
    6780T sum( size_t size, T a[] ) {
    6881        T total = 0;                                                                            // initialize by 0 constructor
     
    7285} // sum
    7386
    74 forall( T | { T ?+?( T, T ); T ?++( T & ); [T] ?+=?( T &,T ); } )
     87forall( T | { T ?+?( T, T ); T ?++( T & ); [T] ?+=?( T &, T ); } )
    7588T twice( T t ) {
    7689        return t + t;
     
    8295}
    8396
    84 int fred() {
    85         int x = 1, y = 2, a[10];
     97void fred() {
     98        int x = 1, y = 2, a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    8699        float f;
    87100
     101        sout | x | y;
    88102        swap( x, y );
    89         twice( x );
     103        sout | x | y | nl | swap( x, y );
     104        // [ x, y ] = swap( y, x );
     105        sout | twice( ' ' ) | ' ' | twice( 0hh ) | twice( 1h ) | twice( 0n ) | twice( 2 )
     106                 | twice( 3.2f ) | twice( 3.2 ) | twice( 3.2d ) | twice( 3.2+1.5i ) | twice( x );
    90107        f = min( 4.0, 3.0 );
    91         sum( 10, a );
     108        sout | f | min( 4.0, 3.0 );
     109        sout | sum( 10, a );
    92110}
    93111
     
    186204
    187205forall( T ) {
    188         extern "C" {
     206//      extern "C" {
    189207                struct SS { T t; };
    190                 T foo( T ) {}
    191         }
     208                T foo( T p ) { return p; }
     209//      }
    192210}
    193211
     
    195213W(int,int) w;
    196214
    197 int jane() {
     215void jane() {
    198216//      int j = bar( 3, 4 );
    199217        int k = baz( 3, 4, 5 );
    200218        int i = foo( 3 );
     219        sout | k | i;
    201220}
    202221
     
    211230        T t;
    212231        T t2 = t;
     232        sout | &tr | tp;
    213233}
    214234
     
    242262
    243263int main( void ) {
    244     #pragma GCC warning "Compiled"                      // force non-empty .expect file, NO TABS!!!
     264        g1();
     265        g2();
     266        fred();
     267        jane();
    245268}
    246269
Note: See TracChangeset for help on using the changeset viewer.