Changeset 29702ad


Ignore:
Timestamp:
Nov 22, 2022, 10:18:04 AM (17 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, master
Children:
20cf96d
Parents:
1553a55 (diff), d41735a (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
2 deleted
38 edited
9 moved

Legend:

Unmodified
Added
Removed
  • libcfa/src/bits/random.hfa

    r1553a55 r29702ad  
    1010// Created On       : Fri Jan 14 07:18:11 2022
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jan 14 07:18:58 2022
    13 // Update Count     : 1
     12// Last Modified On : Mon Nov 21 17:50:12 2022
     13// Update Count     : 15
    1414//
    1515
     
    1717
    1818#include <stdint.h>
     19
     20// Set default PRNG for architecture size.
     21#ifdef __x86_64__                                                                               // 64-bit architecture
     22#define LEHMER64
     23#else                                                                                                   // 32-bit architecture
     24#define XORSHIFT_6_21_7
     25#endif // __x86_64__
     26
     27// C/CFA PRNG name and random-state.
     28#ifdef LEHMER64
     29#define PRNG_NAME lehmer64
     30#define PRNG_ARG_T __uint128_t
     31#endif // LEHMER64
     32
     33#ifdef XORSHIFT_6_21_7
     34#define PRNG_NAME xorshift_6_21_7
     35#define PRNG_ARG_T uint32_t
     36#endif // XORSHIFT_6_21_7
     37
     38#ifdef __cforall                                                                                // don't include in C code (invoke.h)
    1939
    2040// Pipelined to allow out-of-order overlap with reduced dependencies. Critically, the current random state is returned
     
    6181//--------------------------------------------------
    6282typedef struct {
    63   uint32_t a, b, c, d;
    64   uint32_t counter;
     83        uint32_t a, b, c, d;
     84        uint32_t counter;
    6585} xorwow__state_t;
    6686
     
    116136#undef C
    117137#undef D
     138
     139#endif // __cforall
  • libcfa/src/concurrency/invoke.h

    r1553a55 r29702ad  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jan  9 19:06:45 2022
    13 // Update Count     : 48
     12// Last Modified On : Mon Nov 21 17:40:24 2022
     13// Update Count     : 55
    1414//
    1515
     
    1717#include "bits/defs.hfa"
    1818#include "bits/locks.hfa"
     19#include "bits/random.hfa"
    1920#include "kernel/fwd.hfa"
    2021
     
    222223                struct processor * last_proc;
    223224
    224                 uint32_t random_state;                                                  // fast random numbers
     225                PRNG_ARG_T random_state;                                                // fast random numbers
    225226
    226227                #if defined( __CFA_WITH_VERIFY__ )
  • libcfa/src/concurrency/kernel/fwd.hfa

    r1553a55 r29702ad  
    120120
    121121                // Yield: yield N times
    122                 static inline void yield( unsigned times ) {
     122                static inline void yield( size_t times ) {
    123123                        for( times ) {
    124124                                yield();
  • libcfa/src/concurrency/kernel/startup.cfa

    r1553a55 r29702ad  
    3939#include "limits.hfa"
    4040#include "math.hfa"
     41#include "bits/random.hfa"                                                              // prng
    4142
    4243#define CFA_PROCESSOR_USE_MMAP 0
     
    107108extern void __wake_proc(processor *);
    108109extern int cfa_main_returned;                                                   // from interpose.cfa
    109 uint32_t __global_random_prime = 4_294_967_291u, __global_random_mask = false;
     110PRNG_ARG_T __global_random_prime = 4_294_967_291u;
     111bool __global_random_mask = false;
    110112
    111113//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/thread.cfa

    r1553a55 r29702ad  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 12 15:24:18 2022
    13 // Update Count     : 66
     12// Last Modified On : Sun Nov 20 17:17:50 2022
     13// Update Count     : 80
    1414//
    1515
     
    2626#include "invoke.h"
    2727
    28 extern uint32_t __global_random_seed, __global_random_prime, __global_random_mask;
     28extern PRNG_ARG_T __global_random_seed, __global_random_prime;
     29extern bool __global_random_mask;
    2930
    3031#pragma GCC visibility push(default)
     
    225226
    226227//-----------------------------------------------------------------------------
    227 #define GENERATOR LCG
    228 
    229 void set_seed( uint32_t seed ) {
    230         uint32_t & state = active_thread()->random_state;
     228
     229void set_seed( uint64_t seed ) {
     230        PRNG_ARG_T & state = active_thread()->random_state;
    231231        state = __global_random_seed = seed;
    232         GENERATOR( state );
     232        (void)PRNG_NAME( state );                                                       // prime PRNG
    233233        __global_random_prime = state;
    234234        __global_random_mask = true;
    235235} // set_seed
    236236
    237 uint32_t prng( void ) {                                                                 // [0,UINT_MAX]
    238         uint32_t & state = active_thread()->random_state;
    239         return GENERATOR( state );
     237uint64_t prng( void ) {                                                                 // [0,UINT_MAX]
     238        PRNG_ARG_T & state = active_thread()->random_state;
     239        return PRNG_NAME( state );
    240240} // prng
    241241
  • libcfa/src/concurrency/thread.hfa

    r1553a55 r29702ad  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb 11 16:34:07 2022
    13 // Update Count     : 20
     12// Last Modified On : Sat Nov 19 16:41:27 2022
     13// Update Count     : 30
    1414//
    1515
     
    2323#include "monitor.hfa"
    2424#include "exception.hfa"
     25#include "bits/random.hfa"
    2526
    2627//-----------------------------------------------------------------------------
     
    142143// prng
    143144static inline {
    144         uint32_t prng( thread$ & th ) __attribute__(( warn_unused_result )) { return LCG( th.random_state ); } // [0,UINT_MAX]
    145         uint32_t prng( thread$ & th, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th ) % u; } // [0,u)
    146         uint32_t prng( thread$ & th, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th, u - l + 1 ) + l; } // [l,u]
     145        uint64_t prng( thread$ & th ) __attribute__(( warn_unused_result )) { return PRNG_NAME( th.random_state ); } // [0,UINT_MAX]
     146        uint64_t prng( thread$ & th, uint64_t u ) __attribute__(( warn_unused_result )) { return prng( th ) % u; } // [0,u)
     147        uint64_t prng( thread$ & th, uint64_t l, uint64_t u ) __attribute__(( warn_unused_result )) { return prng( th, u - l + 1 ) + l; } // [l,u]
    147148        forall( T & | is_thread(T) ) {
    148                 uint32_t prng( T & th ) __attribute__(( warn_unused_result )) { return prng( (thread &)th ); } // [0,UINT_MAX]
    149                 uint32_t prng( T & th, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th ) % u; } // [0,u)
    150                 uint32_t prng( T & th, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th, u - l + 1 ) + l; } // [l,u]
     149                uint64_t prng( T & th ) __attribute__(( warn_unused_result )) { return prng( (thread &)th ); } // [0,UINT_MAX]
     150                uint64_t prng( T & th, uint64_t u ) __attribute__(( warn_unused_result )) { return prng( th ) % u; } // [0,u)
     151                uint64_t prng( T & th, uint64_t l, uint64_t u ) __attribute__(( warn_unused_result )) { return prng( th, u - l + 1 ) + l; } // [l,u]
    151152        } // distribution
    152153} // distribution
  • libcfa/src/startup.cfa

    r1553a55 r29702ad  
    1010// Created On       : Tue Jul 24 16:21:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Oct  6 13:51:57 2022
    13 // Update Count     : 57
     12// Last Modified On : Sun Nov 20 21:26:40 2022
     13// Update Count     : 59
    1414//
    1515
     
    1818#include <stdlib.h>                                                                             // getenv
    1919#include "bits/defs.hfa"                                                                // rdtscl
     20#include "bits/random.hfa"                                                              // rdtscl
    2021#include "startup.hfa"
    2122
    22 extern uint32_t __global_random_seed;                                   // sequential/concurrent
    23 extern uint32_t __global_random_state;                                  // sequential
     23extern PRNG_ARG_T __global_random_seed;                                 // sequential/concurrent
     24extern PRNG_ARG_T __global_random_state;                                // sequential
    2425
    2526extern "C" {
  • libcfa/src/stdlib.cfa

    r1553a55 r29702ad  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Aug 25 22:41:14 2022
    13 // Update Count     : 604
     12// Last Modified On : Sat Nov 19 16:42:26 2022
     13// Update Count     : 612
    1414//
    1515
     
    225225//---------------------------------------
    226226
    227 #define GENERATOR LCG
    228 
    229227// would be cool to make hidden but it's needed for libcfathread
    230 __attribute__((visibility("default"))) uint32_t __global_random_seed;                                                   // sequential/concurrent
    231 __attribute__((visibility("hidden"))) uint32_t __global_random_state;                                                   // sequential only
    232 
    233 void set_seed( PRNG & prng, uint32_t seed_ ) with( prng ) { state = seed = seed_; GENERATOR( state ); } // set seed
    234 
    235 void set_seed( uint32_t seed ) { __global_random_state = __global_random_seed = seed; GENERATOR( __global_random_state ); }
    236 uint32_t get_seed() { return __global_random_seed; }
    237 uint32_t prng( void ) { return GENERATOR( __global_random_state ); } // [0,UINT_MAX]
     228__attribute__((visibility("default"))) PRNG_ARG_T __global_random_seed; // sequential/concurrent
     229__attribute__((visibility("hidden"))) PRNG_ARG_T __global_random_state; // sequential only
     230
     231void set_seed( uint64_t seed ) { __global_random_state = __global_random_seed = seed; PRNG_NAME( __global_random_state ); }
     232uint64_t get_seed() { return __global_random_seed; }
     233uint64_t prng( void ) { return PRNG_NAME( __global_random_state ); } // [0,UINT_MAX]
    238234
    239235//---------------------------------------
  • libcfa/src/stdlib.hfa

    r1553a55 r29702ad  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Aug 25 18:07:06 2022
    13 // Update Count     : 645
     12// Last Modified On : Sun Nov 20 17:12:37 2022
     13// Update Count     : 730
    1414//
    1515
     
    404404//   calls( sprng );
    405405
    406 struct PRNG {
     406trait basic_prng( PRNG &, S, R ) {
     407        void set_seed( PRNG & prng, S seed );                           // set seed
     408        S get_seed( PRNG & prng );                                                      // get seed
     409        R prng( PRNG & prng );
     410        void ?{}( PRNG & prng );                                                        // random seed
     411        void ?{}( PRNG & prng, S seed );                                        // fixed seed
     412}; // basic_prng
     413
     414static inline forall( PRNG &, S, R | basic_prng( PRNG, S, R ) | { R ?%?( R, R ); } ) {
     415        R prng( PRNG & prng, R u ) { return prng( prng ) % u; } // [0,u)
     416}
     417static inline forall( PRNG &, S, R | basic_prng( PRNG, S, R ) | { R ?+?( R, R ); R ?-?( R, R ); R ?%?( R, R ); void ?{}( R &, one_t ); } ) {
     418        R prng( PRNG & prng, R l, R u ) { return prng( prng, u - l + (R){1} ) + l; } // [l,u]
     419}
     420
     421struct PRNG32 {
    407422        uint32_t callcnt;                                                                       // call count
    408423        uint32_t seed;                                                                          // current seed
    409         uint32_t state;                                                                         // random state
     424        PRNG_ARG_T state;                                                                       // random state
    410425}; // PRNG
    411426
    412 void set_seed( PRNG & prng, uint32_t seed_ );
    413 static inline {
    414         void ?{}( PRNG & prng ) with( prng ) { callcnt = 0; set_seed( prng, rdtscl() ); } // random seed
    415         void ?{}( PRNG & prng, uint32_t seed ) with( prng ) { callcnt = 0; set_seed( prng, seed ); } // fixed seed
    416         uint32_t get_seed( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { return seed; } // get seed
    417         uint32_t prng( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { callcnt += 1; return LCG( state ); } // [0,UINT_MAX]
    418         uint32_t prng( PRNG & prng, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( prng ) % u; } // [0,u)
    419         uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( prng, u - l + 1 ) + l; } // [l,u]
    420         uint32_t calls( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { return callcnt; }
     427static inline {
     428        void set_seed( PRNG32 & prng, uint32_t seed_ ) with( prng ) { state = seed = seed_; PRNG_NAME( state ); } // set seed
     429        uint32_t get_seed( PRNG32 & prng ) __attribute__(( warn_unused_result )) with( prng ) { return seed; } // get seed
     430        uint32_t prng( PRNG32 & prng ) __attribute__(( warn_unused_result )) with( prng ) { callcnt += 1; return PRNG_NAME( state ); } // [0,UINT_MAX]
     431        uint32_t calls( PRNG32 & prng ) __attribute__(( warn_unused_result )) with( prng ) { return callcnt; }
     432        void ?{}( PRNG32 & prng ) with( prng ) { callcnt = 0; set_seed( prng, rdtscl() ); } // random seed
     433        void ?{}( PRNG32 & prng, uint32_t seed ) with( prng ) { callcnt = 0; set_seed( prng, seed ); } // fixed seed
     434} // distribution
     435
     436struct PRNG64 {
     437        uint64_t callcnt;                                                                       // call count
     438        uint64_t seed;                                                                          // current seed
     439        PRNG_ARG_T state;                                                                       // random state
     440}; // PRNG
     441
     442static inline {
     443        void set_seed( PRNG64 & prng, uint64_t seed_ ) with( prng ) { state = seed = seed_; PRNG_NAME( state ); } // set seed
     444        uint64_t get_seed( PRNG64 & prng ) __attribute__(( warn_unused_result )) with( prng ) { return seed; } // get seed
     445        uint64_t prng( PRNG64 & prng ) __attribute__(( warn_unused_result )) with( prng ) { callcnt += 1; return PRNG_NAME( state ); } // [0,UINT_MAX]
     446        uint64_t calls( PRNG64 & prng ) __attribute__(( warn_unused_result )) with( prng ) { return callcnt; }
     447        void ?{}( PRNG64 & prng ) with( prng ) { callcnt = 0; set_seed( prng, rdtscl() ); } // random seed
     448        void ?{}( PRNG64 & prng, uint64_t seed ) with( prng ) { callcnt = 0; set_seed( prng, seed ); } // fixed seed
    421449} // distribution
    422450
     
    435463//   prng( 5, 21 );
    436464
    437 void set_seed( uint32_t seed_ ) OPTIONAL_THREAD;
    438 uint32_t get_seed() __attribute__(( warn_unused_result ));
    439 uint32_t prng( void ) __attribute__(( warn_unused_result )) OPTIONAL_THREAD; // [0,UINT_MAX]
    440 static inline {
    441         uint32_t prng( uint32_t u ) __attribute__(( warn_unused_result )) { return prng() % u; } // [0,u)
    442         uint32_t prng( uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( u - l + 1 ) + l; } // [l,u]
     465// Harmonize with concurrency/thread.hfa.
     466void set_seed( uint64_t seed_ ) OPTIONAL_THREAD;
     467uint64_t get_seed() __attribute__(( warn_unused_result ));
     468uint64_t prng( void ) __attribute__(( warn_unused_result )) OPTIONAL_THREAD; // [0,UINT_MAX]
     469static inline {
     470        uint64_t prng( uint64_t u ) __attribute__(( warn_unused_result )) { return prng() % u; } // [0,u)
     471        uint64_t prng( uint64_t l, uint64_t u ) __attribute__(( warn_unused_result )) { return prng( u - l + 1 ) + l; } // [l,u]
    443472} // distribution
    444473
  • src/AST/Convert.cpp

    r1553a55 r29702ad  
    236236        }
    237237
    238         // InlineValueDecl vanish after EnumAndPointerDecay pass so no necessary to implement NewToOld
    239         const ast::DeclWithType * visit( const ast::InlineValueDecl * node ) override final {   
     238        // InlineMemberDecl vanish after EnumAndPointerDecay pass so no necessary to implement NewToOld
     239        const ast::DeclWithType * visit( const ast::InlineMemberDecl * node ) override final { 
    240240                assert( false );
    241241                (void) node;
     
    17641764                        { old->linkage.val },
    17651765                        GET_ACCEPT_1(base, Type),
     1766                        old->hide == EnumDecl::EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible,
    17661767                        old->enumValues
    17671768                );
     
    18691870        }
    18701871
    1871         virtual void visit( const InlineValueDecl * old ) override final {
     1872        virtual void visit( const InlineMemberDecl * old ) override final {
    18721873                if ( inCache( old ) ) {
    18731874                        return;
     
    18751876                auto&& type = GET_ACCEPT_1(type, Type);
    18761877                auto&& attr = GET_ACCEPT_V(attributes, Attribute);
    1877  
    1878                 auto decl = new ast::InlineValueDecl(
     1878
     1879                auto decl = new ast::InlineMemberDecl(
    18791880                        old->location,
    18801881                        old->name,
  • src/AST/Decl.hpp

    r1553a55 r29702ad  
    315315        // enum (type_optional) Name {...}
    316316        ptr<Type> base; // if isTyped == true && base.get() == nullptr, it is a "void" type enum
    317 
    318         EnumDecl( const CodeLocation& loc, const std::string& name, bool isTyped = false,
     317        enum class EnumHiding { Visible, Hide } hide;
     318
     319        EnumDecl( const CodeLocation& loc, const std::string& name, bool isTyped = false,
    319320                std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall,
    320                 Type const * base = nullptr,
     321                Type const * base = nullptr, EnumHiding hide = EnumHiding::Hide,
    321322                std::unordered_map< std::string, long long > enumValues = std::unordered_map< std::string, long long >() )
    322         : AggregateDecl( loc, name, std::move(attrs), linkage ), isTyped(isTyped), base(base), enumValues(enumValues) {}
     323        : AggregateDecl( loc, name, std::move(attrs), linkage ), isTyped(isTyped), base(base), hide(hide), enumValues(enumValues) {}
    323324
    324325        /// gets the integer value for this enumerator, returning true iff value found
     
    397398};
    398399
     400/// Static Assertion `_Static_assert( ... , ... );`
    399401class StaticAssertDecl : public Decl {
    400402public:
     
    411413};
    412414
    413 class InlineValueDecl final : public DeclWithType {
     415/// Inline Member Declaration `inline TypeName;`
     416class InlineMemberDecl final : public DeclWithType {
    414417public:
    415418        ptr<Type> type;
    416419
    417         InlineValueDecl( const CodeLocation & loc, const std::string & name, const Type * type,
     420        InlineMemberDecl( const CodeLocation & loc, const std::string & name, const Type * type,
    418421                Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
    419422                std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {} )
     
    425428        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
    426429private:
    427         InlineValueDecl * clone() const override { return new InlineValueDecl{ *this }; }
    428         MUTATE_FRIEND
    429 };
     430        InlineMemberDecl * clone() const override { return new InlineMemberDecl{ *this }; }
     431        MUTATE_FRIEND
     432};
     433
    430434}
    431435
  • src/AST/Fwd.hpp

    r1553a55 r29702ad  
    3737class DirectiveDecl;
    3838class StaticAssertDecl;
    39 class InlineValueDecl;
     39class InlineMemberDecl;
    4040
    4141class Stmt;
  • src/AST/Pass.hpp

    r1553a55 r29702ad  
    141141        const ast::DirectiveDecl *    visit( const ast::DirectiveDecl        * ) override final;
    142142        const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl     * ) override final;
    143         const ast::DeclWithType *     visit( const ast::InlineValueDecl      * ) override final;
     143        const ast::DeclWithType *     visit( const ast::InlineMemberDecl     * ) override final;
    144144        const ast::CompoundStmt *     visit( const ast::CompoundStmt         * ) override final;
    145145        const ast::Stmt *             visit( const ast::ExprStmt             * ) override final;
  • src/AST/Pass.impl.hpp

    r1553a55 r29702ad  
    686686
    687687        if ( __visit_children() ) {
    688                 // unlike structs, traits, and unions, enums inject their members into the global scope
    689                 maybe_accept( node, &EnumDecl::base );
    690                 maybe_accept( node, &EnumDecl::params     );
    691                 maybe_accept( node, &EnumDecl::members    );
    692                 maybe_accept( node, &EnumDecl::attributes );
     688                if ( node->hide == ast::EnumDecl::EnumHiding::Hide ) {
     689                        guard_symtab guard { *this };
     690                        maybe_accept( node, &EnumDecl::base );
     691                        maybe_accept( node, &EnumDecl::params     );
     692                        maybe_accept( node, &EnumDecl::members    );
     693                        maybe_accept( node, &EnumDecl::attributes );
     694                } else {
     695                        maybe_accept( node, &EnumDecl::base );
     696                        maybe_accept( node, &EnumDecl::params     );
     697                        maybe_accept( node, &EnumDecl::members    );
     698                        maybe_accept( node, &EnumDecl::attributes );
     699                }
    693700        }
    694701
     
    803810
    804811//--------------------------------------------------------------------------
    805 // DeclWithType
    806 template< typename core_t >
    807 const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::InlineValueDecl * node ) {
    808         VISIT_START( node );
    809 
    810         if ( __visit_children() ) {
    811                 {
    812                         guard_symtab guard { *this };
    813                         maybe_accept( node, &InlineValueDecl::type );
     812// InlineMemberDecl
     813template< typename core_t >
     814const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::InlineMemberDecl * node ) {
     815        VISIT_START( node );
     816
     817        if ( __visit_children() ) {
     818                {
     819                        guard_symtab guard { *this };
     820                        maybe_accept( node, &InlineMemberDecl::type );
    814821                }
    815822        }
  • src/AST/Print.cpp

    r1553a55 r29702ad  
    401401        }
    402402
    403         virtual const ast::DeclWithType * visit( const ast::InlineValueDecl * node ) override final {
     403        virtual const ast::DeclWithType * visit( const ast::InlineMemberDecl * node ) override final {
    404404                os << "inline ";
    405405                if ( ! node->name.empty() ) os << node->name;
  • src/AST/Visitor.hpp

    r1553a55 r29702ad  
    3333    virtual const ast::DirectiveDecl *    visit( const ast::DirectiveDecl        * ) = 0;
    3434    virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl     * ) = 0;
    35     virtual const ast::DeclWithType *     visit( const ast::InlineValueDecl      * ) = 0;
     35    virtual const ast::DeclWithType *     visit( const ast::InlineMemberDecl     * ) = 0;
    3636    virtual const ast::CompoundStmt *     visit( const ast::CompoundStmt         * ) = 0;
    3737    virtual const ast::Stmt *             visit( const ast::ExprStmt             * ) = 0;
  • src/CodeGen/CodeGenerator.cc

    r1553a55 r29702ad  
    290290                                        if ( obj->get_init() ) {
    291291                                                obj->get_init()->accept( *visitor );
    292                                                 last_val = ((ConstantExpr *)(((SingleInit *)(obj->init))->value))->constant.get_ival();
     292                                                Expression* expr = ((SingleInit *)(obj->init))->value;
     293                                                while ( auto temp = dynamic_cast<CastExpr *>(expr) ) {
     294                                                        expr = temp->arg;
     295                                                }
     296                                                last_val = ((ConstantExpr *)expr)->constant.get_ival();
    293297                                        } else {
    294298                                                output << ++last_val;
  • src/Common/CodeLocationTools.cpp

    r1553a55 r29702ad  
    111111    macro(DirectiveDecl, DirectiveDecl) \
    112112    macro(StaticAssertDecl, StaticAssertDecl) \
    113     macro(InlineValueDecl, DeclWithType) \
     113    macro(InlineMemberDecl, DeclWithType) \
    114114    macro(CompoundStmt, CompoundStmt) \
    115115    macro(ExprStmt, Stmt) \
  • src/Common/PassVisitor.h

    r1553a55 r29702ad  
    8181        virtual void visit( StaticAssertDecl * assertDecl ) override final;
    8282        virtual void visit( const StaticAssertDecl * assertDecl ) override final;
    83         virtual void visit( InlineValueDecl * valueDecl ) override final;
    84         virtual void visit( const InlineValueDecl * valueDecl ) override final;
     83        virtual void visit( InlineMemberDecl * valueDecl ) override final;
     84        virtual void visit( const InlineMemberDecl * valueDecl ) override final;
    8585
    8686        virtual void visit( CompoundStmt * compoundStmt ) override final;
     
    275275        virtual DirectiveDecl * mutate( DirectiveDecl * directiveDecl ) override final;
    276276        virtual StaticAssertDecl * mutate( StaticAssertDecl * assertDecl ) override final;
    277         virtual DeclarationWithType * mutate( InlineValueDecl * valueDecl ) override final;
     277        virtual DeclarationWithType * mutate( InlineMemberDecl * valueDecl ) override final;
    278278
    279279        virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override final;
  • src/Common/PassVisitor.impl.h

    r1553a55 r29702ad  
    10471047
    10481048//--------------------------------------------------------------------------
    1049 // InlineValueDecl
    1050 template< typename pass_type >
    1051 void PassVisitor< pass_type >::visit( InlineValueDecl * node ) {
     1049// InlineMemberDecl
     1050template< typename pass_type >
     1051void PassVisitor< pass_type >::visit( InlineMemberDecl * node ) {
    10521052        VISIT_START( node );
    10531053
     
    10581058
    10591059template< typename pass_type >
    1060 void PassVisitor< pass_type >::visit( const InlineValueDecl * node ) {
     1060void PassVisitor< pass_type >::visit( const InlineMemberDecl * node ) {
    10611061        VISIT_START( node );
    10621062
     
    10671067
    10681068template< typename pass_type >
    1069 DeclarationWithType * PassVisitor< pass_type >::mutate( InlineValueDecl * node ) {
     1069DeclarationWithType * PassVisitor< pass_type >::mutate( InlineMemberDecl * node ) {
    10701070        MUTATE_START( node );
    10711071
  • src/Common/utility.h

    r1553a55 r29702ad  
    461461        Iterables iterables;
    462462
     463        // Getting the iterator and value types this way preserves const.
    463464        template<size_t I> using Iter = decltype(std::get<I>(iterables).begin());
    464465        template<size_t I> using Data = decltype(*std::get<I>(iterables).begin());
    465466        template<typename> struct base_iterator;
    466467
    467         template<std::size_t... Is>
    468         struct base_iterator<std::integer_sequence<std::size_t, Is...>> {
    469                 using value_type = std::tuple< Data<Is>... >;
    470                 std::tuple<Iter<Is>...> iterators;
    471 
    472                 base_iterator( Iter<Is>... is ) : iterators( is... ) {}
     468        // This inner template puts the sequence of `0, 1, ... sizeof...(Args)-1`
     469        // into a pack. These are the indexes into the tuples, so unpacking can
     470        // go over each element of the tuple.
     471        // The std::integer_sequence is just used to build that sequence.
     472        // A library reference will probably explain it better than I can.
     473        template<std::size_t... Indices>
     474        struct base_iterator<std::integer_sequence<std::size_t, Indices...>> {
     475                using value_type = std::tuple< Data<Indices>... >;
     476                std::tuple<Iter<Indices>...> iterators;
     477
     478                base_iterator( Iter<Indices>... is ) : iterators( is... ) {}
    473479                base_iterator operator++() {
    474                         return base_iterator( ++std::get<Is>( iterators )... );
     480                        return base_iterator( ++std::get<Indices>( iterators )... );
    475481                }
    476482                bool operator!=( const base_iterator& other ) const {
     
    478484                }
    479485                value_type operator*() const {
    480                         return std::tie( *std::get<Is>( iterators )... );
     486                        return std::tie( *std::get<Indices>( iterators )... );
    481487                }
    482488
    483489                static base_iterator make_begin( Iterables & data ) {
    484                         return base_iterator( std::get<Is>( data ).begin()... );
     490                        return base_iterator( std::get<Indices>( data ).begin()... );
    485491                }
    486492                static base_iterator make_end( Iterables & data ) {
    487                         return base_iterator( std::get<Is>( data ).end()... );
     493                        return base_iterator( std::get<Indices>( data ).end()... );
    488494                }
    489495        };
  • src/GenPoly/ErasableScopedMap.h

    r1553a55 r29702ad  
    2323
    2424namespace GenPoly {
    25         /// A map where the items are placed into nested scopes;
    26         /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward;
    27         /// erasing a key means that find() will no longer report any instance of the key in a scope further
    28         /// out, but the erasure itself is scoped. Key erasure works by inserting a sentinal value into the
    29         /// value field, and thus only works for Value types where a meaningful sentinal can be chosen.
    30         template<typename Key, typename Value>
    31         class ErasableScopedMap {
    32                 typedef std::map< Key, Value > Scope;
    33                 typedef std::vector< Scope > ScopeList;
    34 
    35                 ScopeList scopes; ///< scoped list of maps
    36                 Value erased;     ///< sentinal value for erased keys
    37         public:
    38                 typedef typename Scope::key_type key_type;
    39                 typedef typename Scope::mapped_type mapped_type;
    40                 typedef typename Scope::value_type value_type;
    41                 typedef typename ScopeList::size_type size_type;
    42                 typedef typename ScopeList::difference_type difference_type;
    43                 typedef typename Scope::reference reference;
    44                 typedef typename Scope::const_reference const_reference;
    45                 typedef typename Scope::pointer pointer;
    46                 typedef typename Scope::const_pointer const_pointer;
    47 
    48                 class iterator : public std::iterator< std::bidirectional_iterator_tag,
    49                                                        value_type > {
    50                 friend class ErasableScopedMap;
    51                 friend class const_iterator;
    52                         typedef typename std::map< Key, Value >::iterator wrapped_iterator;
    53                         typedef typename std::vector< std::map< Key, Value > > scope_list;
    54                         typedef typename scope_list::size_type size_type;
    55 
    56                         /// Checks if this iterator points to a valid item
    57                         bool is_valid() const {
    58                                 return it != map->scopes[i].end() && it->second != map->erased;
     25
     26/// A map where the items are placed into nested scopes.
     27/// Inserted items are placed into the innermost scope, lookup looks from the
     28/// innermost scope outward. Erasing a key means that find() will no longer
     29/// report any instance of the key in a scope further out, but the erasure
     30/// itself is scoped. Key erasure works by inserting a sentinal value into
     31/// the value field, and thus only works for Value types where a meaningful
     32/// sentinal can be chosen.
     33template<typename Key, typename Value>
     34class ErasableScopedMap {
     35        typedef std::map< Key, Value > Scope;
     36        typedef std::vector< Scope > ScopeList;
     37
     38        /// Scoped list of maps.
     39        ScopeList scopes;
     40        /// Sentinal value for erased keys.
     41        Value erased;
     42public:
     43        typedef typename Scope::key_type key_type;
     44        typedef typename Scope::mapped_type mapped_type;
     45        typedef typename Scope::value_type value_type;
     46        typedef typename ScopeList::size_type size_type;
     47        typedef typename ScopeList::difference_type difference_type;
     48        typedef typename Scope::reference reference;
     49        typedef typename Scope::const_reference const_reference;
     50        typedef typename Scope::pointer pointer;
     51        typedef typename Scope::const_pointer const_pointer;
     52
     53        // Both iterator types are complete bidirection iterators, defined below.
     54        class iterator;
     55        class const_iterator;
     56
     57        /// Starts a new scope
     58        void beginScope() {
     59                Scope scope;
     60                scopes.push_back(scope);
     61        }
     62
     63        /// Ends a scope; invalidates any iterators pointing to elements of that scope
     64        void endScope() {
     65                scopes.pop_back();
     66                assert( ! scopes.empty() );
     67        }
     68
     69        /// Default constructor initializes with one scope
     70        ErasableScopedMap( const Value &erased_ ) : erased( erased_ ) { beginScope(); }
     71
     72        iterator begin() { return iterator(*this, scopes.back().begin(), scopes.size()-1).next_valid(); }
     73        const_iterator begin() const { return const_iterator(*this, scopes.back().begin(), scopes.size()-1).next_valid(); }
     74        const_iterator cbegin() const { return const_iterator(*this, scopes.back().begin(), scopes.size()-1).next_valid(); }
     75        iterator end() { return iterator(*this, scopes[0].end(), 0); }
     76        const_iterator end() const { return const_iterator(*this, scopes[0].end(), 0); }
     77        const_iterator cend() const { return const_iterator(*this, scopes[0].end(), 0); }
     78
     79        /// Gets the index of the current scope (counted from 1)
     80        size_type currentScope() const { return scopes.size(); }
     81
     82        /// Finds the given key in the outermost scope it occurs; returns end() for none such
     83        iterator find( const Key &key ) {
     84                for ( size_type i = scopes.size() - 1; ; --i ) {
     85                        typename Scope::iterator val = scopes[i].find( key );
     86                        if ( val != scopes[i].end() ) {
     87                                return val->second == erased ? end() : iterator( *this, val, i );
    5988                        }
    60 
    61                         /// Increments on invalid
    62                         iterator& next_valid() {
    63                                 if ( ! is_valid() ) { ++(*this); }
    64                                 return *this;
     89                        if ( i == 0 ) break;
     90                }
     91                return end();
     92        }
     93        const_iterator find( const Key &key ) const {
     94                return const_iterator( const_cast< ErasableScopedMap< Key, Value >* >(this)->find( key ) );
     95        }
     96
     97        /// Finds the given key in the outermost scope inside the given scope where it occurs
     98        iterator findNext( const_iterator &it, const Key &key ) {
     99                if ( it.i == 0 ) return end();
     100                for ( size_type i = it.i - 1; ; --i ) {
     101                        typename Scope::iterator val = scopes[i].find( key );
     102                        if ( val != scopes[i].end() ) {
     103                                return val->second == erased ? end() : iterator( *this, val, i );
    65104                        }
    66 
    67                         /// Decrements on invalid
    68                         iterator& prev_valid() {
    69                                 if ( ! is_valid() ) { --(*this); }
    70                                 return *this;
    71                         }
    72                        
    73                         iterator(ErasableScopedMap< Key, Value > const &_map, const wrapped_iterator &_it, size_type _i)
    74                                         : map(&_map), it(_it), i(_i) {}
    75                        
    76                 public:
    77                         iterator(const iterator &that) : map(that.map), it(that.it), i(that.i) {}
    78                         iterator& operator= (const iterator &that) {
    79                                 map = that.map; i = that.i; it = that.it;
    80                                 return *this;
    81                         }
    82 
    83                         reference operator* () { return *it; }
    84                         pointer operator-> () { return it.operator->(); }
    85 
    86                         iterator& operator++ () {
    87                                 if ( it == map->scopes[i].end() ) {
    88                                         if ( i == 0 ) return *this;
    89                                         --i;
    90                                         it = map->scopes[i].begin();
    91                                 } else {
    92                                         ++it;
    93                                 }
    94                                 return next_valid();
    95                         }
    96                         iterator& operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
    97 
    98                         iterator& operator-- () {
    99                                 // may fail if this is the begin iterator; allowed by STL spec
    100                                 if ( it == map->scopes[i].begin() ) {
    101                                         ++i;
    102                                         it = map->scopes[i].end();
    103                                 }
    104                                 --it;
    105                                 return prev_valid();
    106                         }
    107                         iterator& operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
    108 
    109                         bool operator== (const iterator &that) {
    110                                 return map == that.map && i == that.i && it == that.it;
    111                         }
    112                         bool operator!= (const iterator &that) { return !( *this == that ); }
    113 
    114                 private:
    115                         ErasableScopedMap< Key, Value > const *map;
    116                         wrapped_iterator it;
    117                         size_type i;
    118                 };
    119 
    120                 class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
    121                                                              value_type > {
    122                 friend class ErasableScopedMap;
    123                         typedef typename std::map< Key, Value >::iterator wrapped_iterator;
    124                         typedef typename std::map< Key, Value >::const_iterator wrapped_const_iterator;
    125                         typedef typename std::vector< std::map< Key, Value > > scope_list;
    126                         typedef typename scope_list::size_type size_type;
    127 
    128                         /// Checks if this iterator points to a valid item
    129                         bool is_valid() const {
    130                                 return it != map->scopes[i].end() && it->second != map->erased;
    131                         }
    132 
    133                         /// Increments on invalid
    134                         const_iterator& next_valid() {
    135                                 if ( ! is_valid() ) { ++(*this); }
    136                                 return *this;
    137                         }
    138 
    139                         /// Decrements on invalid
    140                         const_iterator& prev_valid() {
    141                                 if ( ! is_valid() ) { --(*this); }
    142                                 return *this;
    143                         }
    144                        
    145                         const_iterator(ErasableScopedMap< Key, Value > const &_map, const wrapped_const_iterator &_it, size_type _i)
    146                                         : map(&_map), it(_it), i(_i) {}
    147                 public:
    148                         const_iterator(const iterator &that) : map(that.map), it(that.it), i(that.i) {}
    149                         const_iterator(const const_iterator &that) : map(that.map), it(that.it), i(that.i) {}
    150                         const_iterator& operator= (const iterator &that) {
    151                                 map = that.map; i = that.i; it = that.it;
    152                                 return *this;
    153                         }
    154                         const_iterator& operator= (const const_iterator &that) {
    155                                 map = that.map; i = that.i; it = that.it;
    156                                 return *this;
    157                         }
    158 
    159                         const_reference operator* () { return *it; }
    160                         const_pointer operator-> () { return it.operator->(); }
    161 
    162                         const_iterator& operator++ () {
    163                                 if ( it == map->scopes[i].end() ) {
    164                                         if ( i == 0 ) return *this;
    165                                         --i;
    166                                         it = map->scopes[i].begin();
    167                                 } else {
    168                                         ++it;
    169                                 }
    170                                 return next_valid();
    171                         }
    172                         const_iterator& operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
    173 
    174                         const_iterator& operator-- () {
    175                                 // may fail if this is the begin iterator; allowed by STL spec
    176                                 if ( it == map->scopes[i].begin() ) {
    177                                         ++i;
    178                                         it = map->scopes[i].end();
    179                                 }
    180                                 --it;
    181                                 return prev_valid();
    182                         }
    183                         const_iterator& operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
    184 
    185                         bool operator== (const const_iterator &that) {
    186                                 return map == that.map && i == that.i && it == that.it;
    187                         }
    188                         bool operator!= (const const_iterator &that) { return !( *this == that ); }
    189 
    190                 private:
    191                         ErasableScopedMap< Key, Value > const *map;
    192                         wrapped_const_iterator it;
    193                         size_type i;
    194                 };
    195 
    196                 /// Starts a new scope
    197                 void beginScope() {
    198                         Scope scope;
    199                         scopes.push_back(scope);
    200                 }
    201 
    202                 /// Ends a scope; invalidates any iterators pointing to elements of that scope
    203                 void endScope() {
    204                         scopes.pop_back();
    205                         assert( ! scopes.empty() );
    206                 }
    207 
    208                 /// Default constructor initializes with one scope
    209                 ErasableScopedMap( const Value &erased_ ) : erased( erased_ ) { beginScope(); }
    210 
    211                 iterator begin() { return iterator(*this, scopes.back().begin(), scopes.size()-1).next_valid(); }
    212                 const_iterator begin() const { return const_iterator(*this, scopes.back().begin(), scopes.size()-1).next_valid(); }
    213                 const_iterator cbegin() const { return const_iterator(*this, scopes.back().begin(), scopes.size()-1).next_valid(); }
    214                 iterator end() { return iterator(*this, scopes[0].end(), 0); }
    215                 const_iterator end() const { return const_iterator(*this, scopes[0].end(), 0); }
    216                 const_iterator cend() const { return const_iterator(*this, scopes[0].end(), 0); }
    217 
    218                 /// Gets the index of the current scope (counted from 1)
    219                 size_type currentScope() const { return scopes.size(); }
    220 
    221                 /// Finds the given key in the outermost scope it occurs; returns end() for none such
    222                 iterator find( const Key &key ) {
    223                         for ( size_type i = scopes.size() - 1; ; --i ) {
    224                                 typename Scope::iterator val = scopes[i].find( key );
    225                                 if ( val != scopes[i].end() ) {
    226                                         return val->second == erased ? end() : iterator( *this, val, i );
    227                                 }
    228                                 if ( i == 0 ) break;
    229                         }
    230                         return end();
    231                 }
    232                 const_iterator find( const Key &key ) const {
    233                                 return const_iterator( const_cast< ErasableScopedMap< Key, Value >* >(this)->find( key ) );
    234                 }
    235 
    236                 /// Finds the given key in the outermost scope inside the given scope where it occurs
    237                 iterator findNext( const_iterator &it, const Key &key ) {
    238                         if ( it.i == 0 ) return end();
    239                         for ( size_type i = it.i - 1; ; --i ) {
    240                                 typename Scope::iterator val = scopes[i].find( key );
    241                                 if ( val != scopes[i].end() ) {
    242                                         return val->second == erased ? end() : iterator( *this, val, i );
    243                                 }
    244                                 if ( i == 0 ) break;
    245                         }
    246                         return end();
    247                 }
    248                 const_iterator findNext( const_iterator &it, const Key &key ) const {
    249                                 return const_iterator( const_cast< ErasableScopedMap< Key, Value >* >(this)->findNext( it, key ) );
    250                 }
    251 
    252                 /// Inserts the given key-value pair into the outermost scope
    253                 std::pair< iterator, bool > insert( const value_type &value ) {
    254                         std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
    255                         return std::make_pair( iterator(*this, res.first, scopes.size()-1), res.second );
    256                 }
    257                 std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); }
    258 
    259                 /// Marks the given element as erased from this scope inward; returns 1 for erased an element, 0 otherwise
    260                 size_type erase( const Key &key ) {
    261                         typename Scope::iterator val = scopes.back().find( key );
    262                         if ( val != scopes.back().end() ) {
    263                                 val->second = erased;
    264                                 return 1;
    265                         } else {
    266                                 scopes.back().insert( val, std::make_pair( key, erased ) );
    267                                 return 0;
    268                         }
    269                 }
    270 
    271                 Value& operator[] ( const Key &key ) {
    272                         iterator slot = find( key );
    273                         if ( slot != end() ) return slot->second;
    274                         return insert( key, Value() ).first->second;
    275                 }
    276         };
     105                        if ( i == 0 ) break;
     106                }
     107                return end();
     108        }
     109        const_iterator findNext( const_iterator &it, const Key &key ) const {
     110                return const_iterator( const_cast< ErasableScopedMap< Key, Value >* >(this)->findNext( it, key ) );
     111        }
     112
     113        /// Inserts the given key-value pair into the outermost scope
     114        std::pair< iterator, bool > insert( const value_type &value ) {
     115                std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
     116                return std::make_pair( iterator(*this, res.first, scopes.size()-1), res.second );
     117        }
     118        std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); }
     119
     120        /// Marks the given element as erased from this scope inward; returns 1 for erased an element, 0 otherwise
     121        size_type erase( const Key &key ) {
     122                typename Scope::iterator val = scopes.back().find( key );
     123                if ( val != scopes.back().end() ) {
     124                        val->second = erased;
     125                        return 1;
     126                } else {
     127                        scopes.back().insert( val, std::make_pair( key, erased ) );
     128                        return 0;
     129                }
     130        }
     131
     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;
     136        }
     137};
     138
     139template<typename Key, typename Value>
     140class ErasableScopedMap<Key, Value>::iterator :
     141                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     142        friend class ErasableScopedMap;
     143        typedef typename std::map< Key, Value >::iterator wrapped_iterator;
     144        typedef typename std::vector< std::map< Key, Value > > scope_list;
     145        typedef typename scope_list::size_type size_type;
     146
     147        /// Checks if this iterator points to a valid item
     148        bool is_valid() const {
     149                return it != map->scopes[i].end() && it->second != map->erased;
     150        }
     151
     152        /// Increments on invalid
     153        iterator& next_valid() {
     154                if ( ! is_valid() ) { ++(*this); }
     155                return *this;
     156        }
     157
     158        /// Decrements on invalid
     159        iterator& prev_valid() {
     160                if ( ! is_valid() ) { --(*this); }
     161                return *this;
     162        }
     163
     164        iterator(ErasableScopedMap< Key, Value > const &_map, const wrapped_iterator &_it, size_type _i)
     165                        : map(&_map), it(_it), i(_i) {}
     166
     167public:
     168        iterator(const iterator &that) : map(that.map), it(that.it), i(that.i) {}
     169        iterator& operator= (const iterator &that) {
     170                map = that.map; i = that.i; it = that.it;
     171                return *this;
     172        }
     173
     174        reference operator* () { return *it; }
     175        pointer operator-> () { return it.operator->(); }
     176
     177        iterator& operator++ () {
     178                if ( it == map->scopes[i].end() ) {
     179                        if ( i == 0 ) return *this;
     180                        --i;
     181                        it = map->scopes[i].begin();
     182                } else {
     183                        ++it;
     184                }
     185                return next_valid();
     186        }
     187
     188        iterator& operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
     189
     190        iterator& operator-- () {
     191                // may fail if this is the begin iterator; allowed by STL spec
     192                if ( it == map->scopes[i].begin() ) {
     193                        ++i;
     194                        it = map->scopes[i].end();
     195                }
     196                --it;
     197                return prev_valid();
     198        }
     199        iterator& operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
     200
     201        bool operator== (const iterator &that) {
     202                return map == that.map && i == that.i && it == that.it;
     203        }
     204        bool operator!= (const iterator &that) { return !( *this == that ); }
     205
     206private:
     207        ErasableScopedMap< Key, Value > const *map;
     208        wrapped_iterator it;
     209        size_type i;
     210};
     211
     212template<typename Key, typename Value>
     213class ErasableScopedMap<Key, Value>::const_iterator :
     214                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     215        friend class ErasableScopedMap;
     216        typedef typename std::map< Key, Value >::iterator wrapped_iterator;
     217        typedef typename std::map< Key, Value >::const_iterator wrapped_const_iterator;
     218        typedef typename std::vector< std::map< Key, Value > > scope_list;
     219        typedef typename scope_list::size_type size_type;
     220
     221        /// Checks if this iterator points to a valid item
     222        bool is_valid() const {
     223                return it != map->scopes[i].end() && it->second != map->erased;
     224        }
     225
     226        /// Increments on invalid
     227        const_iterator& next_valid() {
     228                if ( ! is_valid() ) { ++(*this); }
     229                return *this;
     230        }
     231
     232        /// Decrements on invalid
     233        const_iterator& prev_valid() {
     234                if ( ! is_valid() ) { --(*this); }
     235                return *this;
     236        }
     237
     238        const_iterator(ErasableScopedMap< Key, Value > const &_map, const wrapped_const_iterator &_it, size_type _i)
     239                        : map(&_map), it(_it), i(_i) {}
     240public:
     241        const_iterator(const iterator &that) : map(that.map), it(that.it), i(that.i) {}
     242        const_iterator(const const_iterator &that) : map(that.map), it(that.it), i(that.i) {}
     243        const_iterator& operator= (const iterator &that) {
     244                map = that.map; i = that.i; it = that.it;
     245                return *this;
     246        }
     247        const_iterator& operator= (const const_iterator &that) {
     248                map = that.map; i = that.i; it = that.it;
     249                return *this;
     250        }
     251
     252        const_reference operator* () { return *it; }
     253        const_pointer operator-> () { return it.operator->(); }
     254
     255        const_iterator& operator++ () {
     256                if ( it == map->scopes[i].end() ) {
     257                        if ( i == 0 ) return *this;
     258                        --i;
     259                        it = map->scopes[i].begin();
     260                } else {
     261                        ++it;
     262                }
     263                return next_valid();
     264        }
     265        const_iterator& operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
     266
     267        const_iterator& operator-- () {
     268                // may fail if this is the begin iterator; allowed by STL spec
     269                if ( it == map->scopes[i].begin() ) {
     270                        ++i;
     271                        it = map->scopes[i].end();
     272                }
     273                --it;
     274                return prev_valid();
     275        }
     276        const_iterator& operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
     277
     278        bool operator== (const const_iterator &that) {
     279                return map == that.map && i == that.i && it == that.it;
     280        }
     281        bool operator!= (const const_iterator &that) { return !( *this == that ); }
     282
     283private:
     284        ErasableScopedMap< Key, Value > const *map;
     285        wrapped_const_iterator it;
     286        size_type i;
     287};
     288
    277289} // namespace GenPoly
    278290
  • src/Parser/DeclarationNode.cc

    r1553a55 r29702ad  
    2727#include "SynTree/LinkageSpec.h"   // for Spec, linkageName, Cforall
    2828#include "SynTree/Attribute.h"     // for Attribute
    29 #include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, InlineValueDecl, Declaration
     29#include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, InlineMemberDecl, Declaration
    3030#include "SynTree/Expression.h"    // for Expression, ConstantExpr
    3131#include "SynTree/Statement.h"     // for AsmStmt
     
    254254} // DeclarationNode::newAggregate
    255255
    256 DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base) {
     256DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base, EnumHiding hiding ) {
    257257        DeclarationNode * newnode = new DeclarationNode;
    258258        newnode->type = new TypeData( TypeData::Enum );
     
    262262        newnode->type->enumeration.anon = name == nullptr;
    263263        newnode->type->enumeration.typed = typed;
     264        newnode->type->enumeration.hiding = hiding;
    264265        if ( base && base->type)  {
    265266                newnode->type->base = base->type;
     
    11661167        } // if
    11671168        if ( enumInLine ) {
    1168                 return new InlineValueDecl( *name, storageClasses, linkage, nullptr );
     1169                return new InlineMemberDecl( *name, storageClasses, linkage, nullptr );
    11691170        } // if
    11701171        assertf( name, "ObjectDecl must a have name\n" );
  • src/Parser/ParseNode.h

    r1553a55 r29702ad  
    239239        static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    240240        static DeclarationNode * newAggregate( AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
    241         static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base = nullptr );
     241        static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base = nullptr, EnumHiding hiding = EnumHiding::Visible );
    242242        static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );
    243243        static DeclarationNode * newEnumValueGeneric( const std::string * name, InitializerNode * init );
  • src/Parser/TypeData.cc

    r1553a55 r29702ad  
    923923        buildList( td->enumeration.constants, ret->get_members() );
    924924        list< Declaration * >::iterator members = ret->get_members().begin();
     925        ret->hide = td->enumeration.hiding == EnumHiding::Hide ? EnumDecl::EnumHiding::Hide : EnumDecl::EnumHiding::Visible;
    925926        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) {
    926927                if ( cur->enumInLine ) {
  • src/Parser/TypeData.h

    r1553a55 r29702ad  
    6060                bool anon;
    6161                bool typed;
     62                EnumHiding hiding;
    6263        };
    6364
  • src/Parser/parser.yy

    r1553a55 r29702ad  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Nov  2 21:31:21 2022
    13 // Update Count     : 5810
     12// Last Modified On : Mon Nov 21 22:34:30 2022
     13// Update Count     : 5848
    1414//
    1515
     
    383383%type<ifctl> conditional_declaration
    384384%type<fctl> for_control_expression              for_control_expression_list
    385 %type<compop> updown updowneq downupdowneq
     385%type<compop> upupeq updown updowneq downupdowneq
    386386%type<en> subrange
    387387%type<decl> asm_name_opt
     
    489489%type<decl> type_parameter type_parameter_list type_initializer_opt
    490490
    491 %type<en> type_parameters_opt type_list
     491%type<en> type_parameters_opt type_list array_type_list
    492492
    493493%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
     
    25582558                { typedefTable.makeTypedef( *$3 ); }
    25592559          hide_opt '{' enumerator_list comma_opt '}'
    2560           { $$ = DeclarationNode::newEnum( $3, $7, true, false )->addQualifiers( $2 ); }
     2560                { $$ = DeclarationNode::newEnum( $3, $7, true, false, nullptr, $5 )->addQualifiers( $2 ); }
    25612561        | ENUM attribute_list_opt typedef_name                          // unqualified type name
    25622562          hide_opt '{' enumerator_list comma_opt '}'
    2563                 { $$ = DeclarationNode::newEnum( $3->name, $6, true, false )->addQualifiers( $2 ); }
     2563                { $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); }
    25642564        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
    25652565                {
     
    25802580          hide_opt '{' enumerator_list comma_opt '}'
    25812581                {
    2582                         $$ = DeclarationNode::newEnum( $6, $11, true, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2582                        $$ = DeclarationNode::newEnum( $6, $11, true, true, $3, $9 )->addQualifiers( $5 )->addQualifiers( $7 );
    25832583                }
    25842584        | ENUM '(' ')' attribute_list_opt identifier attribute_list_opt
    25852585          hide_opt '{' enumerator_list comma_opt '}'
    25862586                {
    2587                         $$ = DeclarationNode::newEnum( $5, $9, true, true, nullptr )->addQualifiers( $4 )->addQualifiers( $6 );
     2587                        $$ = DeclarationNode::newEnum( $5, $9, true, true, nullptr, $7 )->addQualifiers( $4 )->addQualifiers( $6 );
    25882588                }
    25892589        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt typedef_name attribute_list_opt
    25902590          hide_opt '{' enumerator_list comma_opt '}'
    25912591                {
    2592                         $$ = DeclarationNode::newEnum( $6->name, $10, true, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2592                        $$ = DeclarationNode::newEnum( $6->name, $10, true, true, $3, $8 )->addQualifiers( $5 )->addQualifiers( $7 );
    25932593                }
    25942594        | ENUM '(' ')' attribute_list_opt typedef_name attribute_list_opt
    25952595          hide_opt '{' enumerator_list comma_opt '}'
    25962596                {
    2597                         $$ = DeclarationNode::newEnum( $5->name, $9, true, true, nullptr )->addQualifiers( $4 )->addQualifiers( $6 );
     2597                        $$ = DeclarationNode::newEnum( $5->name, $9, true, true, nullptr, $7 )->addQualifiers( $4 )->addQualifiers( $6 );
    25982598                }
    25992599        | enum_type_nobody
     
    36533653        | '[' ']' multi_array_dimension
    36543654                { $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $3 ); }
    3655         | '[' push assignment_expression pop ',' comma_expression ']'
     3655                // Cannot use constant_expression because of tuples => semantic check
     3656        | '[' push assignment_expression pop ',' comma_expression ']' // CFA
    36563657                { $$ = DeclarationNode::newArray( $3, 0, false )->addArray( DeclarationNode::newArray( $6, 0, false ) ); }
    36573658                // { SemanticError( yylloc, "New array dimension is currently unimplemented." ); $$ = nullptr; }
     3659        | '[' push array_type_list pop ']'                                      // CFA
     3660                { SemanticError( yylloc, "Type array dimension is currently unimplemented." ); $$ = nullptr; }
    36583661        | multi_array_dimension
    36593662        ;
     3663
     3664array_type_list:
     3665        basic_type_name
     3666                { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
     3667        | type_name
     3668                { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
     3669        | assignment_expression upupeq assignment_expression
     3670        | array_type_list ',' basic_type_name
     3671                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
     3672        | array_type_list ',' type_name
     3673                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
     3674        | array_type_list ',' assignment_expression upupeq assignment_expression
     3675        ;
     3676
     3677upupeq:
     3678        '~'
     3679                { $$ = OperKinds::LThan; }
     3680        | ErangeUpEq
     3681                { $$ = OperKinds::LEThan; }
     3682        ;
    36603683
    36613684multi_array_dimension:
  • src/SynTree/Declaration.h

    r1553a55 r29702ad  
    340340        bool isTyped;
    341341        Type * base;
     342        enum EnumHiding { Visible, Hide } hide;
    342343
    343344        EnumDecl( const std::string & name,
     
    345346          bool isTyped = false, LinkageSpec::Spec linkage = LinkageSpec::Cforall,
    346347          Type * baseType = nullptr )
    347           : Parent( name, attributes, linkage ),isTyped(isTyped), base( baseType ) {}
     348          : Parent( name, attributes, linkage ), isTyped(isTyped), base( baseType ) {}
    348349        EnumDecl( const EnumDecl & other )
    349350          : Parent( other ), isTyped( other.isTyped), base( other.base ) {}
     
    450451
    451452
    452 class InlineValueDecl : public DeclarationWithType {
     453class InlineMemberDecl : public DeclarationWithType {
    453454        typedef DeclarationWithType Parent;
    454455  public:
    455456        Type * type;
    456457
    457         InlineValueDecl( const std::string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage, Type * type,
     458        InlineMemberDecl( const std::string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage, Type * type,
    458459                                const std::list< Attribute * > attributes = std::list< Attribute * >(), Type::FuncSpecifiers fs = Type::FuncSpecifiers() );
    459         InlineValueDecl( const InlineValueDecl & other );
    460         virtual ~InlineValueDecl();
     460        InlineMemberDecl( const InlineMemberDecl & other );
     461        virtual ~InlineMemberDecl();
    461462
    462463        virtual Type * get_type() const override { return type; }
    463464        virtual void set_type(Type * newType) override { type = newType; }
    464465
    465         static InlineValueDecl * newInlineValueDecl( const std::string & name, Type * type );
    466 
    467         virtual InlineValueDecl * clone() const override { return new InlineValueDecl( *this ); }
     466        static InlineMemberDecl * newInlineMemberDecl( const std::string & name, Type * type );
     467
     468        virtual InlineMemberDecl * clone() const override { return new InlineMemberDecl( *this ); }
    468469        virtual void accept( Visitor & v ) override { v.visit( this ); }
    469470        virtual void accept( Visitor & v ) const override { v.visit( this ); }
  • src/SynTree/InlineMemberDecl.cc

    r1553a55 r29702ad  
    99#include "Type.h"                // for Type, Type::StorageClasses, Type::Fu...
    1010
    11 InlineValueDecl::InlineValueDecl( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage,
     11InlineMemberDecl::InlineMemberDecl( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage,
    1212Type * type, const std::list< Attribute * >attributes, Type::FuncSpecifiers fs)
    1313    : Parent( name, scs, linkage, attributes, fs ), type( type ) {}
    1414
    15 InlineValueDecl::InlineValueDecl( const InlineValueDecl &other)
     15InlineMemberDecl::InlineMemberDecl( const InlineMemberDecl &other)
    1616    : Parent( other), type( maybeClone( other.type ) ) {}
    1717
    18 InlineValueDecl::~InlineValueDecl() { delete type; }
     18InlineMemberDecl::~InlineMemberDecl() { delete type; }
    1919
    20 InlineValueDecl * InlineValueDecl::newInlineValueDecl( const std::string &name, Type * type ) {
    21     return new InlineValueDecl( name, Type::StorageClasses(), LinkageSpec::C, type );
     20InlineMemberDecl * InlineMemberDecl::newInlineMemberDecl( const std::string &name, Type * type ) {
     21    return new InlineMemberDecl( name, Type::StorageClasses(), LinkageSpec::C, type );
    2222}
    2323
    24 void InlineValueDecl::print( std::ostream &os, Indenter indent ) const {
     24void InlineMemberDecl::print( std::ostream &os, Indenter indent ) const {
    2525    if ( name != "" ) os << name << ": ";
    2626
     
    4444}
    4545
    46 void InlineValueDecl::printShort( std::ostream &os, Indenter indent ) const {
     46void InlineMemberDecl::printShort( std::ostream &os, Indenter indent ) const {
    4747    if ( name != "" ) os << name << ": ";
    4848
  • src/SynTree/Mutator.h

    r1553a55 r29702ad  
    3636        virtual DirectiveDecl * mutate( DirectiveDecl * directiveDecl ) = 0;
    3737        virtual StaticAssertDecl * mutate( StaticAssertDecl * assertDecl ) = 0;
    38         virtual DeclarationWithType * mutate( InlineValueDecl * inlineValueDecl ) = 0;
     38        virtual DeclarationWithType * mutate( InlineMemberDecl * InlineMemberDecl ) = 0;
    3939
    4040        virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) = 0;
  • src/SynTree/SynTree.h

    r1553a55 r29702ad  
    3838class DirectiveDecl;
    3939class StaticAssertDecl;
    40 class InlineValueDecl;
     40class InlineMemberDecl;
    4141
    4242class Statement;
  • src/SynTree/Visitor.h

    r1553a55 r29702ad  
    4949        virtual void visit( StaticAssertDecl * node ) { visit( const_cast<const StaticAssertDecl *>(node) ); }
    5050        virtual void visit( const StaticAssertDecl * assertDecl ) = 0;
    51         virtual void visit( InlineValueDecl * node ) { visit( const_cast<const InlineValueDecl *>(node) ); }
    52         virtual void visit( const InlineValueDecl * valueDecl ) = 0;
     51        virtual void visit( InlineMemberDecl * node ) { visit( const_cast<const InlineMemberDecl *>(node) ); }
     52        virtual void visit( const InlineMemberDecl * valueDecl ) = 0;
    5353
    5454        virtual void visit( CompoundStmt * node ) { visit( const_cast<const CompoundStmt *>(node) ); }
  • src/SynTree/module.mk

    r1553a55 r29702ad  
    4242      SynTree/Initializer.cc \
    4343      SynTree/Initializer.h \
    44       SynTree/InlineValueDecl.cc \
     44      SynTree/InlineMemberDecl.cc \
    4545      SynTree/Label.h \
    4646      SynTree/LinkageSpec.cc \
  • src/Validate/EnumAndPointerDecay.cpp

    r1553a55 r29702ad  
    4141        auto mut = ast::mutate( decl );
    4242        std::vector<ast::ptr<ast::Decl>> buffer;
    43         for ( auto it = decl->members.begin(); it != decl->members.end(); ++it ) {
    44                 if ( ast::ObjectDecl const * object = (*it).as<ast::ObjectDecl>() ) {
    45                         buffer.push_back( ast::mutate_field( object, &ast::ObjectDecl::type, new ast::EnumInstType( decl, ast::CV::Const ) ) );
    46                 } else if ( ast::InlineValueDecl const * value = (*it).as<ast::InlineValueDecl>() ) {
     43        for ( auto member : decl->members ) {
     44                if ( ast::ObjectDecl const * object = member.as<ast::ObjectDecl>() ) {
     45                        buffer.push_back( ast::mutate_field( object,
     46                                &ast::ObjectDecl::type,
     47                                new ast::EnumInstType( decl, ast::CV::Const ) ) );
     48                } else if ( auto value = member.as<ast::InlineMemberDecl>() ) {
    4749                        if ( auto targetEnum = symtab.lookupEnum( value->name ) ) {
    48                                 for ( auto singleMember : targetEnum->members ) {
    49                                         auto copyingMember = singleMember.as<ast::ObjectDecl>();
     50                                for ( auto enumMember : targetEnum->members ) {
     51                                        auto enumObject = enumMember.strict_as<ast::ObjectDecl>();
    5052                                        buffer.push_back( new ast::ObjectDecl(
    51                                                 value->location, // use the "inline" location
    52                                                 copyingMember->name,
     53                                                // Get the location from the "inline" declaration.
     54                                                value->location,
     55                                                enumObject->name,
     56                                                // Construct a new EnumInstType as the type.
    5357                                                new ast::EnumInstType( decl, ast::CV::Const ),
    54                                                 // Construct a new EnumInstType as the type
    55                                                 copyingMember->init,
    56                                                 copyingMember->storage,
    57                                                 copyingMember->linkage,
    58                                                 copyingMember->bitfieldWidth,
     58                                                enumObject->init,
     59                                                enumObject->storage,
     60                                                enumObject->linkage,
     61                                                enumObject->bitfieldWidth,
    5962                                                {},
    60                                                 copyingMember->funcSpec
     63                                                enumObject->funcSpec
    6164                                        ) );
    6265                                }
  • tests/PRNG.cfa

    r1553a55 r29702ad  
    88// Created On       : Wed Dec 29 09:38:12 2021
    99// Last Modified By : Peter A. Buhr
    10 // Last Modified On : Sat Apr  9 15:21:14 2022
    11 // Update Count     : 344
     10// Last Modified On : Sun Nov 20 22:17:35 2022
     11// Update Count     : 377
    1212//
    1313
     
    2222#include <mutex_stmt.hfa>
    2323
     24#ifdef __x86_64__                                                                               // 64-bit architecture
     25#define PRNG PRNG64
     26#else                                                                                                   // 32-bit architecture
     27#define PRNG PRNG32
     28#endif // __x86_64__
     29
    2430#ifdef TIME                                                                                             // use -O2 -nodebug
    2531#define STARTTIME start = timeHiRes()
     
    5460
    5561
    56 uint32_t seed = 1009;
     62unsigned int seed = 1009;
    5763
    5864thread T1 {};
     
    158164#if 1
    159165        PRNG prng;
     166
    160167        if ( seed != 0 ) set_seed( prng, seed );
    161168
     
    164171        for ( 20 ) {
    165172                sout | wd(13, prng( prng )) | nonl;                             // cascading => side-effect functions called in arbitary order
    166                 sout | wd(10, prng( prng, 5 )) | nonl;
    167                 sout | wd(13, prng( prng, 0, 5 ));
     173                sout | wd(10, prng( prng, 5z )) | nonl;
     174                sout | wd(13, prng( prng, 0, 5z ));
    168175        } // for
    169176        sout | sepEnable;
     
    199206        for ( 20 ) {
    200207                sout | wd(13, prng()) | nonl;                                   // cascading => side-effect functions called in arbitary order
    201                 sout | wd(10, prng( 5 )) | nonl;
    202                 sout | wd(13, prng( 0, 5 ));
     208                sout | wd(10, prng( 5z )) | nonl;
     209                sout | wd(13, prng( 0, 5z ));
    203210        } // for
    204211        sout | sepEnable;
     
    235242        for ( 20 ) {
    236243                sout | wd(13, prng( th )) | nonl;                               // cascading => side-effect functions called in arbitary order
    237                 sout | wd(10, prng( th, 5 )) | nonl;
    238                 sout | wd(13, prng( th, 0, 5 ));
     244                sout | wd(10, prng( th, 5z )) | nonl;
     245                sout | wd(13, prng( th, 0, 5z ));
    239246        } // for
    240247        sout | sepEnable;
  • tests/concurrent/barrier/generation.cfa

    r1553a55 r29702ad  
    3737                for(c; 'A' ~= 'Z') {
    3838                        // Yield for chaos
    39                         yield(prng(this, 10));
     39                        yield( prng(this, 10) );
    4040
    4141                        // Print the generation, no newline because
     
    4343
    4444                        // Yield again for more chaos
    45                         yield(prng(this, 10));
     45                        yield( prng(this, 10) );
    4646
    4747                        // Block on the barrier
  • tests/concurrent/barrier/order.cfa

    r1553a55 r29702ad  
    3737        for(l; NUM_LAPS) {
    3838                // Yield for chaos
    39                 yield(prng(this, 10));
     39                yield( prng(this, 10) );
    4040
    4141                // Block and what order we arrived
  • tests/concurrent/once.cfa

    r1553a55 r29702ad  
    3030
    3131                // sometime yields
    32                 yield(prng(this, 3));
     32                yield( prng(this, 3) );
    3333        }
    3434}
  • tests/concurrent/readyQ/leader_spin.cfa

    r1553a55 r29702ad  
    2626}
    2727
    28 PRNG lead_rng;
     28PRNG64 lead_rng;
    2929volatile unsigned leader;
    3030volatile size_t lead_idx;
    3131
    32 const unsigned nthreads = 17;
    33 const unsigned stop_count = 327;
     32const uint64_t nthreads = 17;
     33const uint64_t stop_count = 327;
    3434
    3535thread$ * the_main;
Note: See TracChangeset for help on using the changeset viewer.