Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CurrentObject.cc

    rc6b4432 r2908f08  
    4141
    4242namespace ast {
    43         /// Iterates members of a type by initializer.
    44         class MemberIterator {
    45         public:
    46                 virtual ~MemberIterator() {}
    47 
    48                 /// Internal set position based on iterator ranges.
    49                 virtual void setPosition(
    50                         std::deque< ptr< Expr > >::const_iterator it,
    51                         std::deque< ptr< Expr > >::const_iterator end ) = 0;
    52 
    53                 /// Walks the current object using the given designators as a guide.
    54                 void setPosition( const std::deque< ptr< Expr > > & designators ) {
    55                         setPosition( designators.begin(), designators.end() );
    56                 }
    57 
    58                 /// Retrieve the list of possible (Type,Designation) pairs for the
    59                 /// current position in the current object.
    60                 virtual std::deque< InitAlternative > operator* () const = 0;
    61 
    62                 /// True if the iterator is not currently at the end.
    63                 virtual operator bool() const = 0;
    64 
    65                 /// Moves the iterator by one member in the current object.
    66                 virtual MemberIterator & bigStep() = 0;
    67 
    68                 /// Moves the iterator by one member in the current subobject.
    69                 virtual MemberIterator & smallStep() = 0;
    70 
    71                 /// The type of the current object.
    72                 virtual const Type * getType() = 0;
    73 
    74                 /// The type of the current subobject.
    75                 virtual const Type * getNext() = 0;
    76 
    77                 /// Helper for operator*; aggregates must add designator to each init
    78                 /// alternative, but adding designators in operator* creates duplicates.
    79                 virtual std::deque< InitAlternative > first() const = 0;
    80         };
    81 
    82         /// create a new MemberIterator that traverses a type correctly
    83         MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
    84 
    85         /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
    86         class SimpleIterator final : public MemberIterator {
    87                 CodeLocation location;
    88                 const Type * type = nullptr;
    89         public:
    90                 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
    91 
    92                 void setPosition(
    93                         std::deque< ptr< Expr > >::const_iterator begin,
    94                         std::deque< ptr< Expr > >::const_iterator end
    95                 ) override {
    96                         if ( begin != end ) {
    97                                 SemanticError( location, "Un-designated initializer given non-empty designator" );
    98                         }
    99                 }
    100 
    101                 std::deque< InitAlternative > operator* () const override { return first(); }
    102 
    103                 operator bool() const override { return type; }
    104 
    105                 SimpleIterator & bigStep() override { return smallStep(); }
    106                 SimpleIterator & smallStep() override {
    107                         type = nullptr;  // empty on increment because no members
    108                         return *this;
    109                 }
    110 
    111                 const Type * getType() override { return type; }
    112 
    113                 const Type * getNext() override { return type; }
    114 
    115                 std::deque< InitAlternative > first() const override {
    116                         if ( type ) return { InitAlternative{ type, new Designation{ location } } };
    117                         return {};
    118                 }
    119         };
    120 
    121         /// Iterates over an indexed type:
    122         class IndexIterator : public MemberIterator {
    123         protected:
    124                 CodeLocation location;
    125                 size_t index = 0;
    126                 size_t size = 0;
    127                 std::unique_ptr<MemberIterator> memberIter;
    128         public:
    129                 IndexIterator( const CodeLocation & loc, size_t size ) :
    130                         location( loc ), size( size )
    131                 {}
    132 
    133                 void setPosition( const Expr * expr ) {
    134                         // need to permit integer-constant-expressions, including: integer constants,
    135                         // enumeration constants, character constants, sizeof expressions, alignof expressions,
    136                         // cast expressions
    137 
    138                         auto arg = eval( expr );
    139                         assertf( arg.hasKnownValue, "Non-evaluable expression made it to IndexIterator" );
    140                         index = arg.knownValue;
    141 
    142                         // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
    143                         //      try {
    144                         //              index = constExpr->intValue();
    145                         //      } catch ( SemanticErrorException & ) {
    146                         //              SemanticError( expr, "Constant expression of non-integral type in array designator: " );
    147                         //      }
    148                         // } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
    149                         //      setPosition( castExpr->arg );
    150                         // } else if ( dynamic_cast< const SizeofExpr * >( expr ) || dynamic_cast< const AlignofExpr * >( expr ) ) {
    151                         //      index = 0;
    152                         // } else {
    153                         //      assertf( false, "2 bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
    154                         // }
    155                 }
    156 
    157                 void setPosition(
    158                         std::deque<ast::ptr<ast::Expr>>::const_iterator begin,
    159                         std::deque<ast::ptr<ast::Expr>>::const_iterator end
    160                 ) override {
    161                         if ( begin == end ) return;
    162 
    163                         setPosition( *begin );
    164                         memberIter->setPosition( ++begin, end );
    165                 }
    166 
    167                 std::deque< InitAlternative > operator* () const override { return first(); }
    168 
    169                 operator bool() const override { return index < size; }
    170         };
    171 
    172         /// Iterates over the members of array types:
    173         class ArrayIterator final : public IndexIterator {
    174                 const ArrayType * array = nullptr;
    175                 const Type * base = nullptr;
    176 
    177                 size_t getSize( const Expr * expr ) {
    178                         auto res = eval( expr );
    179                         if ( !res.hasKnownValue ) {
    180                                 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
    181                         }
    182                         return res.knownValue;
    183                 }
    184 
    185         public:
    186                 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) :
    187                                 IndexIterator( loc, getSize( at->dimension) ),
    188                                 array( at ), base( at->base ) {
    189                         PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    190                         memberIter.reset( createMemberIterator( loc, base ) );
    191                         if ( at->isVarLen ) {
    192                                 SemanticError( location, at, "VLA initialization does not support @=: " );
    193                         }
    194                 }
    195 
    196                 ArrayIterator & bigStep() override {
    197                         PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    198                         ++index;
    199                         memberIter.reset( index < size ? createMemberIterator( location, base ) : nullptr );
    200                         return *this;
    201                 }
    202 
    203                 ArrayIterator & smallStep() override {
    204                         PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    205                         if ( memberIter ) {
    206                                 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
    207                                 memberIter->smallStep();
    208                                 if ( *memberIter ) {
    209                                         PRINT( std::cerr << "has valid member iter" << std::endl; )
    210                                         return *this;
    211                                 }
    212                         }
    213                         return bigStep();
    214                 }
    215 
    216                 const Type * getType() override { return array; }
    217 
    218                 const Type * getNext() override { return base; }
    219 
    220                 std::deque< InitAlternative > first() const override {
    221                         PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    222                         if ( memberIter && *memberIter ) {
    223                                 std::deque< InitAlternative > ret = memberIter->first();
    224                                 for ( InitAlternative & alt : ret ) {
    225                                         alt.designation.get_and_mutate()->designators.emplace_front( ConstantExpr::from_ulong( location, index ) );
    226                                 }
    227                                 return ret;
    228                         }
    229                         return {};
    230                 }
    231         };
    232 
    233         class AggregateIterator : public MemberIterator {
    234         protected:
    235                 using MemberList = std::vector< ptr< Decl > >;
    236 
    237                 CodeLocation location;
    238                 std::string kind;  // for debug
    239                 std::string name;
    240                 const Type * inst;
    241                 const MemberList & members;
    242                 MemberList::const_iterator curMember;
    243                 bool atbegin = true;  // false at first {small,big}Step
    244                 const Type * curType = nullptr;
    245                 std::unique_ptr< MemberIterator > memberIter = nullptr;
    246                 TypeSubstitution sub;
    247 
    248                 bool init() {
    249                         PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
    250                         if ( curMember != members.end() ) {
    251                                 if ( auto field = curMember->as< ObjectDecl >() ) {
    252                                         PRINT( std::cerr << "incremented to field: " << field << std::endl; )
    253                                         curType = field->get_type();
    254                                         memberIter.reset( createMemberIterator( location, curType ) );
    255                                         return true;
    256                                 }
    257                         }
    258                         return false;
    259                 }
    260 
    261                 AggregateIterator(
    262                         const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
    263                         const MemberList & ms )
    264                 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
    265                   sub( genericSubstitution( i ) ) {
    266                         PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
    267                         init();
    268                 }
    269 
    270         public:
    271                 void setPosition(
    272                         std::deque< ptr< Expr > >::const_iterator begin,
    273                         std::deque< ptr< Expr > >::const_iterator end
    274                 ) final {
    275                         if ( begin == end ) return;
    276 
    277                         if ( auto varExpr = begin->as< VariableExpr >() ) {
    278                                 for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
    279                                         if ( *curMember != varExpr->var ) continue;
    280 
    281                                         ++begin;
    282 
    283                                         memberIter.reset( createMemberIterator( location, varExpr->result ) );
    284                                         curType = varExpr->result;
    285                                         atbegin = curMember == members.begin() && begin == end;
    286                                         memberIter->setPosition( begin, end );
    287                                         return;
    288                                 }
    289                                 assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    290                         } else {
    291                                 assertf( false, "1 bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
    292                         }
    293                 }
    294 
    295                 std::deque< InitAlternative > operator* () const final {
    296                         if ( memberIter && *memberIter ) {
    297                                 std::deque< InitAlternative > ret = memberIter->first();
    298                                 PRINT( std::cerr << "sub: " << sub << std::endl; )
    299                                 for ( InitAlternative & alt : ret ) {
    300                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    301                                         alt.designation.get_and_mutate()->designators.emplace_front(
    302                                                 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    303                                         // need to substitute for generic types so that casts are to concrete types
    304                                         alt.type = shallowCopy(alt.type.get());
    305                                         PRINT( std::cerr << "  type is: " << alt.type; )
    306                                         sub.apply( alt.type ); // also apply to designation??
    307                                         PRINT( std::cerr << " ==> " << alt.type << std::endl; )
    308                                 }
    309                                 return ret;
    310                         }
    311                         return {};
    312                 }
    313 
    314                 AggregateIterator & smallStep() final {
    315                         PRINT( std::cerr << "smallStep in " << kind << std::endl; )
    316                         atbegin = false;
    317                         if ( memberIter ) {
    318                                 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
    319                                 memberIter->smallStep();
    320                                 if ( *memberIter ) {
    321                                         PRINT( std::cerr << "success!" << std::endl; )
    322                                         return *this;
    323                                 }
    324                         }
    325                         return bigStep();
    326                 }
    327 
    328                 AggregateIterator & bigStep() override = 0;
    329 
    330                 const Type * getType() final { return inst; }
    331 
    332                 const Type * getNext() final {
    333                         bool hasMember = memberIter && *memberIter;
    334                         return hasMember ? memberIter->getType() : nullptr;
    335                 }
    336 
    337                 std::deque< InitAlternative > first() const final {
    338                         std::deque< InitAlternative > ret;
    339                         PRINT( std::cerr << "first " << kind << std::endl; )
    340                         if ( memberIter && *memberIter ) {
    341                                 PRINT( std::cerr << "adding children" << std::endl; )
    342                                 ret = memberIter->first();
    343                                 for ( InitAlternative & alt : ret ) {
    344                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    345                                         alt.designation.get_and_mutate()->designators.emplace_front(
    346                                                 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    347                                 }
    348                         }
    349                         if ( atbegin ) {
    350                                 // only add self if at the very beginning of the structure
    351                                 PRINT( std::cerr << "adding self" << std::endl; )
    352                                 ret.emplace_front( inst, new Designation{ location } );
     43
     44/// Iterates members of a type by initializer.
     45class MemberIterator {
     46public:
     47        virtual ~MemberIterator() {}
     48
     49        /// Internal set position based on iterator ranges.
     50        virtual void setPosition(
     51                std::deque< ptr< Expr > >::const_iterator it,
     52                std::deque< ptr< Expr > >::const_iterator end ) = 0;
     53
     54        /// Walks the current object using the given designators as a guide.
     55        void setPosition( const std::deque< ptr< Expr > > & designators ) {
     56                setPosition( designators.begin(), designators.end() );
     57        }
     58
     59        /// Retrieve the list of possible (Type,Designation) pairs for the
     60        /// current position in the current object.
     61        virtual std::deque< InitAlternative > operator* () const = 0;
     62
     63        /// True if the iterator is not currently at the end.
     64        virtual operator bool() const = 0;
     65
     66        /// Moves the iterator by one member in the current object.
     67        virtual MemberIterator & bigStep() = 0;
     68
     69        /// Moves the iterator by one member in the current subobject.
     70        virtual MemberIterator & smallStep() = 0;
     71
     72        /// The type of the current object.
     73        virtual const Type * getType() = 0;
     74
     75        /// The type of the current subobject.
     76        virtual const Type * getNext() = 0;
     77
     78        /// Helper for operator*; aggregates must add designator to each init
     79        /// alternative, but adding designators in operator* creates duplicates.
     80        virtual std::deque< InitAlternative > first() const = 0;
     81};
     82
     83namespace {
     84
     85/// create a new MemberIterator that traverses a type correctly
     86MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
     87
     88/// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
     89class SimpleIterator final : public MemberIterator {
     90        CodeLocation location;
     91        const Type * type = nullptr;
     92public:
     93        SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
     94
     95        void setPosition(
     96                std::deque< ptr< Expr > >::const_iterator begin,
     97                std::deque< ptr< Expr > >::const_iterator end
     98        ) override {
     99                if ( begin != end ) {
     100                        SemanticError( location, "Un-designated initializer given non-empty designator" );
     101                }
     102        }
     103
     104        std::deque< InitAlternative > operator* () const override { return first(); }
     105
     106        operator bool() const override { return type; }
     107
     108        SimpleIterator & bigStep() override { return smallStep(); }
     109        SimpleIterator & smallStep() override {
     110                type = nullptr;  // empty on increment because no members
     111                return *this;
     112        }
     113
     114        const Type * getType() override { return type; }
     115
     116        const Type * getNext() override { return type; }
     117
     118        std::deque< InitAlternative > first() const override {
     119                if ( type ) return { InitAlternative{ type, new Designation{ location } } };
     120                return {};
     121        }
     122};
     123
     124/// Iterates over an indexed type:
     125class IndexIterator : public MemberIterator {
     126protected:
     127        CodeLocation location;
     128        size_t index = 0;
     129        size_t size = 0;
     130        std::unique_ptr<MemberIterator> memberIter;
     131public:
     132        IndexIterator( const CodeLocation & loc, size_t size ) :
     133                location( loc ), size( size )
     134        {}
     135
     136        void setPosition( const Expr * expr ) {
     137                // need to permit integer-constant-expressions, including: integer constants,
     138                // enumeration constants, character constants, sizeof expressions, alignof expressions,
     139                // cast expressions
     140
     141                auto arg = eval( expr );
     142                assertf( arg.hasKnownValue, "Non-evaluable expression made it to IndexIterator" );
     143                index = arg.knownValue;
     144
     145                // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
     146                //      try {
     147                //              index = constExpr->intValue();
     148                //      } catch ( SemanticErrorException & ) {
     149                //              SemanticError( expr, "Constant expression of non-integral type in array designator: " );
     150                //      }
     151                // } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
     152                //      setPosition( castExpr->arg );
     153                // } else if ( dynamic_cast< const SizeofExpr * >( expr ) || dynamic_cast< const AlignofExpr * >( expr ) ) {
     154                //      index = 0;
     155                // } else {
     156                //      assertf( false, "2 bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
     157                // }
     158        }
     159
     160        void setPosition(
     161                std::deque<ast::ptr<ast::Expr>>::const_iterator begin,
     162                std::deque<ast::ptr<ast::Expr>>::const_iterator end
     163        ) override {
     164                if ( begin == end ) return;
     165
     166                setPosition( *begin );
     167                memberIter->setPosition( ++begin, end );
     168        }
     169
     170        std::deque< InitAlternative > operator* () const override { return first(); }
     171
     172        operator bool() const override { return index < size; }
     173};
     174
     175/// Iterates over the members of array types:
     176class ArrayIterator final : public IndexIterator {
     177        const ArrayType * array = nullptr;
     178        const Type * base = nullptr;
     179
     180        size_t getSize( const Expr * expr ) {
     181                auto res = eval( expr );
     182                if ( !res.hasKnownValue ) {
     183                        SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
     184                }
     185                return res.knownValue;
     186        }
     187
     188public:
     189        ArrayIterator( const CodeLocation & loc, const ArrayType * at ) :
     190                        IndexIterator( loc, getSize( at->dimension) ),
     191                        array( at ), base( at->base ) {
     192                PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
     193                memberIter.reset( createMemberIterator( loc, base ) );
     194                if ( at->isVarLen ) {
     195                        SemanticError( location, at, "VLA initialization does not support @=: " );
     196                }
     197        }
     198
     199        ArrayIterator & bigStep() override {
     200                PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
     201                ++index;
     202                memberIter.reset( index < size ? createMemberIterator( location, base ) : nullptr );
     203                return *this;
     204        }
     205
     206        ArrayIterator & smallStep() override {
     207                PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
     208                if ( memberIter ) {
     209                        PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
     210                        memberIter->smallStep();
     211                        if ( *memberIter ) {
     212                                PRINT( std::cerr << "has valid member iter" << std::endl; )
     213                                return *this;
     214                        }
     215                }
     216                return bigStep();
     217        }
     218
     219        const Type * getType() override { return array; }
     220
     221        const Type * getNext() override { return base; }
     222
     223        std::deque< InitAlternative > first() const override {
     224                PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
     225                if ( memberIter && *memberIter ) {
     226                        std::deque< InitAlternative > ret = memberIter->first();
     227                        for ( InitAlternative & alt : ret ) {
     228                                alt.designation.get_and_mutate()->designators.emplace_front( ConstantExpr::from_ulong( location, index ) );
    353229                        }
    354230                        return ret;
    355231                }
    356         };
    357 
    358         class StructIterator final : public AggregateIterator {
    359         public:
    360                 StructIterator( const CodeLocation & loc, const StructInstType * inst )
    361                 : AggregateIterator( loc, "StructIterator", inst->name, inst, inst->base->members ) {}
    362 
    363                 operator bool() const override {
    364                         return curMember != members.end() || (memberIter && *memberIter);
    365                 }
    366 
    367                 StructIterator & bigStep() override {
    368                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    369                         atbegin = false;
    370                         memberIter = nullptr;
    371                         curType = nullptr;
    372                         while ( curMember != members.end() ) {
    373                                 ++curMember;
    374                                 if ( init() ) return *this;
    375                         }
    376                         return *this;
    377                 }
    378         };
    379 
    380         class UnionIterator final : public AggregateIterator {
    381         public:
    382                 UnionIterator( const CodeLocation & loc, const UnionInstType * inst )
    383                 : AggregateIterator( loc, "UnionIterator", inst->name, inst, inst->base->members ) {}
    384 
    385                 operator bool() const override { return memberIter && *memberIter; }
    386 
    387                 UnionIterator & bigStep() override {
    388                         // unions only initialize one member
    389                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    390                         atbegin = false;
    391                         memberIter = nullptr;
    392                         curType = nullptr;
    393                         curMember = members.end();
    394                         return *this;
    395                 }
    396         };
    397 
    398         /// Iterates across the positions in a tuple:
    399         class TupleIterator final : public IndexIterator {
    400                 ast::TupleType const * const tuple;
    401 
    402                 const ast::Type * typeAtIndex() const {
    403                         assert( index < size );
    404                         return tuple->types[ index ].get();
    405                 }
    406 
    407         public:
    408                 TupleIterator( const CodeLocation & loc, const TupleType * type )
    409                 : IndexIterator( loc, type->size() ), tuple( type ) {
    410                         PRINT( std::cerr << "Creating tuple iterator: " << type << std::endl; )
    411                         memberIter.reset( createMemberIterator( loc, typeAtIndex() ) );
    412                 }
    413 
    414                 TupleIterator & bigStep() override {
    415                         ++index;
    416                         memberIter.reset( index < size ?
    417                                 createMemberIterator( location, typeAtIndex() ) : nullptr );
    418                         return *this;
    419                 }
    420 
    421                 TupleIterator & smallStep() override {
    422                         if ( memberIter ) {
    423                                 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
    424                                 memberIter->smallStep();
    425                                 if ( !memberIter ) {
    426                                         PRINT( std::cerr << "has valid member iter" << std::endl; )
    427                                         return *this;
    428                                 }
    429                         }
    430                         return bigStep();
    431                 }
    432 
    433                 const ast::Type * getType() override {
    434                         return tuple;
    435                 }
    436 
    437                 const ast::Type * getNext() override {
    438                         bool hasMember = memberIter && *memberIter;
    439                         return hasMember ? memberIter->getType() : nullptr;
    440                 }
    441 
    442                 std::deque< InitAlternative > first() const override {
    443                         PRINT( std::cerr << "first in TupleIterator (" << index << "/" << size << ")" << std::endl; )
    444                         if ( memberIter && *memberIter ) {
    445                                 std::deque< InitAlternative > ret = memberIter->first();
    446                                 for ( InitAlternative & alt : ret ) {
    447                                         alt.designation.get_and_mutate()->designators.emplace_front(
    448                                                 ConstantExpr::from_ulong( location, index ) );
    449                                 }
    450                                 return ret;
    451                         }
    452                         return {};
    453                 }
    454         };
    455 
    456         MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
    457                 if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) {
    458                         if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
    459                                 assert( sit->base );
    460                                 return new StructIterator{ loc, sit };
    461                         } else if ( auto uit = dynamic_cast< const UnionInstType * >( aggr ) ) {
    462                                 assert( uit->base );
    463                                 return new UnionIterator{ loc, uit };
    464                         } else {
    465                                 assertf(
    466                                         dynamic_cast< const EnumInstType * >( type )
    467                                                 || dynamic_cast< const TypeInstType * >( type ),
    468                                         "Encountered unhandled BaseInstType in createMemberIterator: %s",
    469                                                 toString( type ).c_str() );
    470                                 return new SimpleIterator{ loc, type };
    471                         }
    472                 } else if ( auto at = dynamic_cast< const ArrayType * >( type ) ) {
    473                         return new ArrayIterator{ loc, at };
    474                 } else if ( auto tt = dynamic_cast< const TupleType * >( type ) ) {
    475                         return new TupleIterator{ loc, tt };
     232                return {};
     233        }
     234};
     235
     236class AggregateIterator : public MemberIterator {
     237protected:
     238        using MemberList = std::vector< ptr< Decl > >;
     239
     240        CodeLocation location;
     241        std::string kind;  // for debug
     242        std::string name;
     243        const Type * inst;
     244        const MemberList & members;
     245        MemberList::const_iterator curMember;
     246        bool atbegin = true;  // false at first {small,big}Step
     247        const Type * curType = nullptr;
     248        std::unique_ptr< MemberIterator > memberIter = nullptr;
     249        TypeSubstitution sub;
     250
     251        bool init() {
     252                PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
     253                if ( curMember != members.end() ) {
     254                        if ( auto field = curMember->as< ObjectDecl >() ) {
     255                                PRINT( std::cerr << "incremented to field: " << field << std::endl; )
     256                                curType = field->get_type();
     257                                memberIter.reset( createMemberIterator( location, curType ) );
     258                                return true;
     259                        }
     260                }
     261                return false;
     262        }
     263
     264        AggregateIterator(
     265                const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
     266                const MemberList & ms )
     267        : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
     268          sub( genericSubstitution( i ) ) {
     269                PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
     270                init();
     271        }
     272
     273public:
     274        void setPosition(
     275                std::deque< ptr< Expr > >::const_iterator begin,
     276                std::deque< ptr< Expr > >::const_iterator end
     277        ) final {
     278                if ( begin == end ) return;
     279
     280                if ( auto varExpr = begin->as< VariableExpr >() ) {
     281                        for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
     282                                if ( *curMember != varExpr->var ) continue;
     283
     284                                ++begin;
     285
     286                                memberIter.reset( createMemberIterator( location, varExpr->result ) );
     287                                curType = varExpr->result;
     288                                atbegin = curMember == members.begin() && begin == end;
     289                                memberIter->setPosition( begin, end );
     290                                return;
     291                        }
     292                        assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    476293                } else {
     294                        assertf( false, "1 bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
     295                }
     296        }
     297
     298        std::deque< InitAlternative > operator* () const final {
     299                if ( memberIter && *memberIter ) {
     300                        std::deque< InitAlternative > ret = memberIter->first();
     301                        PRINT( std::cerr << "sub: " << sub << std::endl; )
     302                        for ( InitAlternative & alt : ret ) {
     303                                PRINT( std::cerr << "iterating and adding designators" << std::endl; )
     304                                alt.designation.get_and_mutate()->designators.emplace_front(
     305                                        new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
     306                                // need to substitute for generic types so that casts are to concrete types
     307                                alt.type = shallowCopy(alt.type.get());
     308                                PRINT( std::cerr << "  type is: " << alt.type; )
     309                                sub.apply( alt.type ); // also apply to designation??
     310                                PRINT( std::cerr << " ==> " << alt.type << std::endl; )
     311                        }
     312                        return ret;
     313                }
     314                return {};
     315        }
     316
     317        AggregateIterator & smallStep() final {
     318                PRINT( std::cerr << "smallStep in " << kind << std::endl; )
     319                atbegin = false;
     320                if ( memberIter ) {
     321                        PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
     322                        memberIter->smallStep();
     323                        if ( *memberIter ) {
     324                                PRINT( std::cerr << "success!" << std::endl; )
     325                                return *this;
     326                        }
     327                }
     328                return bigStep();
     329        }
     330
     331        AggregateIterator & bigStep() override = 0;
     332
     333        const Type * getType() final { return inst; }
     334
     335        const Type * getNext() final {
     336                bool hasMember = memberIter && *memberIter;
     337                return hasMember ? memberIter->getType() : nullptr;
     338        }
     339
     340        std::deque< InitAlternative > first() const final {
     341                std::deque< InitAlternative > ret;
     342                PRINT( std::cerr << "first " << kind << std::endl; )
     343                if ( memberIter && *memberIter ) {
     344                        PRINT( std::cerr << "adding children" << std::endl; )
     345                        ret = memberIter->first();
     346                        for ( InitAlternative & alt : ret ) {
     347                                PRINT( std::cerr << "iterating and adding designators" << std::endl; )
     348                                alt.designation.get_and_mutate()->designators.emplace_front(
     349                                        new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
     350                        }
     351                }
     352                if ( atbegin ) {
     353                        // only add self if at the very beginning of the structure
     354                        PRINT( std::cerr << "adding self" << std::endl; )
     355                        ret.emplace_front( inst, new Designation{ location } );
     356                }
     357                return ret;
     358        }
     359};
     360
     361class StructIterator final : public AggregateIterator {
     362public:
     363        StructIterator( const CodeLocation & loc, const StructInstType * inst )
     364        : AggregateIterator( loc, "StructIterator", inst->name, inst, inst->base->members ) {}
     365
     366        operator bool() const override {
     367                return curMember != members.end() || (memberIter && *memberIter);
     368        }
     369
     370        StructIterator & bigStep() override {
     371                PRINT( std::cerr << "bigStep in " << kind << std::endl; )
     372                atbegin = false;
     373                memberIter = nullptr;
     374                curType = nullptr;
     375                while ( curMember != members.end() ) {
     376                        ++curMember;
     377                        if ( init() ) return *this;
     378                }
     379                return *this;
     380        }
     381};
     382
     383class UnionIterator final : public AggregateIterator {
     384public:
     385        UnionIterator( const CodeLocation & loc, const UnionInstType * inst )
     386        : AggregateIterator( loc, "UnionIterator", inst->name, inst, inst->base->members ) {}
     387
     388        operator bool() const override { return memberIter && *memberIter; }
     389
     390        UnionIterator & bigStep() override {
     391                // unions only initialize one member
     392                PRINT( std::cerr << "bigStep in " << kind << std::endl; )
     393                atbegin = false;
     394                memberIter = nullptr;
     395                curType = nullptr;
     396                curMember = members.end();
     397                return *this;
     398        }
     399};
     400
     401/// Iterates across the positions in a tuple:
     402class TupleIterator final : public IndexIterator {
     403        ast::TupleType const * const tuple;
     404
     405        const ast::Type * typeAtIndex() const {
     406                assert( index < size );
     407                return tuple->types[ index ].get();
     408        }
     409
     410public:
     411        TupleIterator( const CodeLocation & loc, const TupleType * type )
     412        : IndexIterator( loc, type->size() ), tuple( type ) {
     413                PRINT( std::cerr << "Creating tuple iterator: " << type << std::endl; )
     414                memberIter.reset( createMemberIterator( loc, typeAtIndex() ) );
     415        }
     416
     417        TupleIterator & bigStep() override {
     418                ++index;
     419                memberIter.reset( index < size ?
     420                        createMemberIterator( location, typeAtIndex() ) : nullptr );
     421                return *this;
     422        }
     423
     424        TupleIterator & smallStep() override {
     425                if ( memberIter ) {
     426                        PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
     427                        memberIter->smallStep();
     428                        if ( !memberIter ) {
     429                                PRINT( std::cerr << "has valid member iter" << std::endl; )
     430                                return *this;
     431                        }
     432                }
     433                return bigStep();
     434        }
     435
     436        const ast::Type * getType() override {
     437                return tuple;
     438        }
     439
     440        const ast::Type * getNext() override {
     441                bool hasMember = memberIter && *memberIter;
     442                return hasMember ? memberIter->getType() : nullptr;
     443        }
     444
     445        std::deque< InitAlternative > first() const override {
     446                PRINT( std::cerr << "first in TupleIterator (" << index << "/" << size << ")" << std::endl; )
     447                if ( memberIter && *memberIter ) {
     448                        std::deque< InitAlternative > ret = memberIter->first();
     449                        for ( InitAlternative & alt : ret ) {
     450                                alt.designation.get_and_mutate()->designators.emplace_front(
     451                                        ConstantExpr::from_ulong( location, index ) );
     452                        }
     453                        return ret;
     454                }
     455                return {};
     456        }
     457};
     458
     459MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
     460        if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) {
     461                if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
     462                        assert( sit->base );
     463                        return new StructIterator{ loc, sit };
     464                } else if ( auto uit = dynamic_cast< const UnionInstType * >( aggr ) ) {
     465                        assert( uit->base );
     466                        return new UnionIterator{ loc, uit };
     467                } else {
     468                        assertf(
     469                                dynamic_cast< const EnumInstType * >( type )
     470                                        || dynamic_cast< const TypeInstType * >( type ),
     471                                "Encountered unhandled BaseInstType in createMemberIterator: %s",
     472                                        toString( type ).c_str() );
    477473                        return new SimpleIterator{ loc, type };
    478474                }
    479         }
    480 
    481         CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
    482                 objStack.emplace_back( new SimpleIterator{ loc, type } );
    483         }
    484 
    485         const Designation * CurrentObject::findNext( const Designation * designation ) {
    486                 using DesignatorChain = std::deque< ptr< Expr > >;
    487                 PRINT( std::cerr << "___findNext" << std::endl; )
    488 
    489                 // find all the d's
    490                 std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
    491                 std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes;
    492                 for ( const Expr * expr : designation->designators ) {
    493                         PRINT( std::cerr << "____untyped: " << expr << std::endl; )
    494                         auto dit = desigAlts.begin();
    495 
    496                         for ( const Type * t : curTypes ) {
    497                                 assert( dit != desigAlts.end() );
    498                                 DesignatorChain & d = *dit;
    499                                 if ( auto nexpr = dynamic_cast< const NameExpr *>( expr ) ) {
    500                                         PRINT( std::cerr << "____actual: " << t << std::endl; )
    501                                         if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) {
    502                                                 // concatenate identical field names
    503                                                 for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
    504                                                         if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
    505                                                                 PRINT( std::cerr << "____alt: " << field->type << std::endl; )
    506                                                                 DesignatorChain d2 = d;
    507                                                                 d2.emplace_back( new VariableExpr{ expr->location, field } );
    508                                                                 newDesigAlts.emplace_back( std::move( d2 ) );
    509                                                                 newTypes.emplace_back( field->type );
    510                                                         }
    511                                                 }
    512                                         } else if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
    513                                                 auto nexpr = dynamic_cast< const NameExpr *>( expr );
    514                                                 for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
    515                                                         if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
    516                                                                 DesignatorChain d2 = d;
    517                                                                 d2.emplace_back( new VariableExpr{ expr->location, field } );
    518                                                                 newDesigAlts.emplace_back( std::move( d2 ) );
    519                                                                 newTypes.emplace_back( at->base );
    520                                                         }
     475        } else if ( auto at = dynamic_cast< const ArrayType * >( type ) ) {
     476                return new ArrayIterator{ loc, at };
     477        } else if ( auto tt = dynamic_cast< const TupleType * >( type ) ) {
     478                return new TupleIterator{ loc, tt };
     479        } else {
     480                return new SimpleIterator{ loc, type };
     481        }
     482}
     483
     484} // namespace
     485
     486CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
     487        objStack.emplace_back( new SimpleIterator{ loc, type } );
     488}
     489
     490const Designation * CurrentObject::findNext( const Designation * designation ) {
     491        using DesignatorChain = std::deque< ptr< Expr > >;
     492        PRINT( std::cerr << "___findNext" << std::endl; )
     493
     494        // find all the d's
     495        std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
     496        std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes;
     497        for ( const Expr * expr : designation->designators ) {
     498                PRINT( std::cerr << "____untyped: " << expr << std::endl; )
     499                auto dit = desigAlts.begin();
     500
     501                for ( const Type * t : curTypes ) {
     502                        assert( dit != desigAlts.end() );
     503                        DesignatorChain & d = *dit;
     504                        if ( auto nexpr = dynamic_cast< const NameExpr *>( expr ) ) {
     505                                PRINT( std::cerr << "____actual: " << t << std::endl; )
     506                                if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) {
     507                                        // concatenate identical field names
     508                                        for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
     509                                                if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
     510                                                        PRINT( std::cerr << "____alt: " << field->type << std::endl; )
     511                                                        DesignatorChain d2 = d;
     512                                                        d2.emplace_back( new VariableExpr{ expr->location, field } );
     513                                                        newDesigAlts.emplace_back( std::move( d2 ) );
     514                                                        newTypes.emplace_back( field->type );
    521515                                                }
    522516                                        }
    523 
    524                                         ++dit;
    525                                 } else {
    526                                         if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
    527                                                 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
    528                                                 d.emplace_back( expr );
    529                                                 newDesigAlts.emplace_back( d );
    530                                                 newTypes.emplace_back( at->base );
     517                                } else if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
     518                                        auto nexpr = dynamic_cast< const NameExpr *>( expr );
     519                                        for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
     520                                                if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
     521                                                        DesignatorChain d2 = d;
     522                                                        d2.emplace_back( new VariableExpr{ expr->location, field } );
     523                                                        newDesigAlts.emplace_back( std::move( d2 ) );
     524                                                        newTypes.emplace_back( at->base );
     525                                                }
    531526                                        }
    532527                                }
    533                         }
    534 
    535                         // reset queue
    536                         desigAlts = std::move( newDesigAlts );
    537                         newDesigAlts.clear();
    538                         curTypes = std::move( newTypes );
    539                         newTypes.clear();
    540                         assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
    541                 }
    542 
    543                 if ( desigAlts.size() > 1 ) {
    544                         SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
    545                 } else if ( desigAlts.empty() ) {
    546                         SemanticError( designation, "No reasonable alternatives for designation: " );
    547                 }
    548 
    549                 DesignatorChain & d = desigAlts.back();
    550                 PRINT( for ( Expression * expr : d ) {
    551                         std::cerr << "____desig: " << expr << std::endl;
    552                 } ) // for
    553                 assertf( ! curTypes.empty(), "empty designator chosen");
    554 
    555                 // set new designators
    556                 assertf( ! objStack.empty(), "empty object stack when setting designation" );
    557                 Designation * actualDesignation =
    558                         new Designation{ designation->location, DesignatorChain{d} };
    559                 objStack.back()->setPosition( d ); // destroys d
    560                 return actualDesignation;
    561         }
    562 
    563         void CurrentObject::setNext( const Designation * designation ) {
    564                 PRINT( std::cerr << "____setNext" << designation << std::endl; )
    565                 assertf( ! objStack.empty(), "obj stack empty in setNext" );
    566                 objStack.back()->setPosition( designation->designators );
    567         }
    568 
    569         void CurrentObject::increment() {
    570                 PRINT( std::cerr << "____increment" << std::endl; )
    571                 if ( objStack.empty() ) return;
     528
     529                                ++dit;
     530                        } else {
     531                                if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
     532                                        PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
     533                                        d.emplace_back( expr );
     534                                        newDesigAlts.emplace_back( d );
     535                                        newTypes.emplace_back( at->base );
     536                                }
     537                        }
     538                }
     539
     540                // reset queue
     541                desigAlts = std::move( newDesigAlts );
     542                newDesigAlts.clear();
     543                curTypes = std::move( newTypes );
     544                newTypes.clear();
     545                assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
     546        }
     547
     548        if ( desigAlts.size() > 1 ) {
     549                SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
     550        } else if ( desigAlts.empty() ) {
     551                SemanticError( designation, "No reasonable alternatives for designation: " );
     552        }
     553
     554        DesignatorChain & d = desigAlts.back();
     555        PRINT( for ( Expression * expr : d ) {
     556                std::cerr << "____desig: " << expr << std::endl;
     557        } ) // for
     558        assertf( ! curTypes.empty(), "empty designator chosen");
     559
     560        // set new designators
     561        assertf( ! objStack.empty(), "empty object stack when setting designation" );
     562        Designation * actualDesignation =
     563                new Designation{ designation->location, DesignatorChain{d} };
     564        objStack.back()->setPosition( d ); // destroys d
     565        return actualDesignation;
     566}
     567
     568void CurrentObject::setNext( const Designation * designation ) {
     569        PRINT( std::cerr << "____setNext" << designation << std::endl; )
     570        assertf( ! objStack.empty(), "obj stack empty in setNext" );
     571        objStack.back()->setPosition( designation->designators );
     572}
     573
     574void CurrentObject::increment() {
     575        PRINT( std::cerr << "____increment" << std::endl; )
     576        if ( objStack.empty() ) return;
     577        PRINT( std::cerr << *objStack.back() << std::endl; )
     578        objStack.back()->smallStep();
     579}
     580
     581void CurrentObject::enterListInit( const CodeLocation & loc ) {
     582        PRINT( std::cerr << "____entering list init" << std::endl; )
     583        assertf( ! objStack.empty(), "empty obj stack entering list init" );
     584        const ast::Type * type = objStack.back()->getNext();
     585        assert( type );
     586        objStack.emplace_back( createMemberIterator( loc, type ) );
     587}
     588
     589void CurrentObject::exitListInit() {
     590        PRINT( std::cerr << "____exiting list init" << std::endl; )
     591        assertf( ! objStack.empty(), "objstack empty" );
     592        objStack.pop_back();
     593        if ( ! objStack.empty() ) {
    572594                PRINT( std::cerr << *objStack.back() << std::endl; )
    573                 objStack.back()->smallStep();
    574         }
    575 
    576         void CurrentObject::enterListInit( const CodeLocation & loc ) {
    577                 PRINT( std::cerr << "____entering list init" << std::endl; )
    578                 assertf( ! objStack.empty(), "empty obj stack entering list init" );
    579                 const ast::Type * type = objStack.back()->getNext();
    580                 assert( type );
    581                 objStack.emplace_back( createMemberIterator( loc, type ) );
    582         }
    583 
    584         void CurrentObject::exitListInit() {
    585                 PRINT( std::cerr << "____exiting list init" << std::endl; )
    586                 assertf( ! objStack.empty(), "objstack empty" );
    587                 objStack.pop_back();
    588                 if ( ! objStack.empty() ) {
    589                         PRINT( std::cerr << *objStack.back() << std::endl; )
    590                         objStack.back()->bigStep();
    591                 }
    592         }
    593 
    594         std::deque< InitAlternative > CurrentObject::getOptions() {
    595                 PRINT( std::cerr << "____getting current options" << std::endl; )
    596                 assertf( ! objStack.empty(), "objstack empty in getOptions" );
    597                 return **objStack.back();
    598         }
    599 
    600         const Type * CurrentObject::getCurrentType() {
    601                 PRINT( std::cerr << "____getting current type" << std::endl; )
    602                 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
    603                 return objStack.back()->getNext();
    604         }
    605 }
     595                objStack.back()->bigStep();
     596        }
     597}
     598
     599std::deque< InitAlternative > CurrentObject::getOptions() {
     600        PRINT( std::cerr << "____getting current options" << std::endl; )
     601        assertf( ! objStack.empty(), "objstack empty in getOptions" );
     602        return **objStack.back();
     603}
     604
     605const Type * CurrentObject::getCurrentType() {
     606        PRINT( std::cerr << "____getting current type" << std::endl; )
     607        assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
     608        return objStack.back()->getNext();
     609}
     610
     611} // namespace ast
    606612
    607613// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.