Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CurrentObject.cc

    r60aaa51d r2b59f55  
    1616#include <stddef.h>                    // for size_t
    1717#include <cassert>                     // for assertf, assert, safe_dynamic_...
    18 #include <deque>
    1918#include <iostream>                    // for ostream, operator<<, basic_ost...
    2019#include <stack>                       // for stack
     
    2221
    2322#include "AST/Expr.hpp"                // for InitAlternative
    24 #include "AST/GenericSubstitution.hpp" // for genericSubstitution
    2523#include "AST/Init.hpp"                // for Designation
    2624#include "AST/Node.hpp"                // for readonly
    27 #include "AST/Type.hpp"
    2825#include "Common/Indenter.h"           // for Indenter, operator<<
    2926#include "Common/SemanticError.h"      // for SemanticError
     
    586583
    587584namespace ast {
    588         /// create a new MemberIterator that traverses a type correctly
    589         MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
     585
     586        /// Iterates members of a type by initializer
     587        class MemberIterator {
     588        public:
     589                virtual ~MemberIterator() {}
     590
     591                /// retrieve the list of possible (Type,Designation) pairs for the current position in the
     592                /// current object
     593                virtual std::vector< InitAlternative > operator* () const = 0;
     594       
     595        protected:
     596                /// helper for operator*; aggregates must add designator to each init alternative, but
     597                /// adding designators in operator* creates duplicates
     598                virtual std::vector< InitAlternative > first() const = 0;
     599        };
    590600
    591601        /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
     
    596606                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
    597607
    598                 void setPosition(
    599                         std::deque< ptr< Expr > >::const_iterator begin,
    600                         std::deque< ptr< Expr > >::const_iterator end
    601                 ) override {
    602                         if ( begin != end ) {
    603                                 SemanticError( location, "Un-designated initializer given non-empty designator" );
    604                         }
    605                 }
    606 
    607                 std::deque< InitAlternative > operator* () const override { return first(); }
    608 
    609                 operator bool() const override { return type; }
    610 
    611                 SimpleIterator & bigStep() override { return smallStep(); }
    612                 SimpleIterator & smallStep() override {
    613                         type = nullptr;  // empty on increment because no members
    614                         return *this;
    615                 }
    616 
    617                 const Type * getType() override { return type; }
    618 
    619                 const Type * getNext() override { return type; }
    620 
    621                 std::deque< InitAlternative > first() const override {
     608                std::vector< InitAlternative > operator* () const override { return first(); }
     609
     610        protected:
     611                std::vector< InitAlternative > first() const override {
    622612                        if ( type ) return { InitAlternative{ type, new Designation{ location } } };
    623613                        return {};
     
    625615        };
    626616
    627         /// Iterates array types
    628         class ArrayIterator final : public MemberIterator {
    629                 CodeLocation location;
    630                 readonly< ArrayType > array = nullptr;
    631                 readonly< Type > base = nullptr;
    632                 size_t index = 0;
    633                 size_t size = 0;
    634                 std::unique_ptr< MemberIterator > memberIter;
    635 
    636                 void setSize( const Expr * expr ) {
    637                         auto res = eval(expr);
    638                         if ( ! res.second ) {
    639                                 SemanticError( location,
    640                                         toString("Array designator must be a constant expression: ", expr ) );
    641                         }
    642                         size = res.first;
    643                 }
    644 
    645         public:
    646                 ArrayIterator( const CodeLocation & loc, const ArrayType * at )
    647                 : location( loc ), array( at ), base( at->base ) {
    648                         PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    649                         memberIter.reset( createMemberIterator( loc, base ) );
    650                         if ( at->isVarLen ) {
    651                                 SemanticError( location, at, "VLA initialization does not support @=: " );
    652                         }
    653                         setSize( at->dimension );
    654                 }
    655 
    656                 void setPosition( const Expr * expr ) {
    657                         // need to permit integer-constant-expressions, including: integer constants,
    658                         // enumeration constants, character constants, sizeof expressions, alignof expressions,
    659                         // cast expressions
    660                         if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
    661                                 try {
    662                                         index = constExpr->intValue();
    663                                 } catch ( SemanticErrorException & ) {
    664                                         SemanticError( expr,
    665                                                 "Constant expression of non-integral type in array designator: " );
    666                                 }
    667                         } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
    668                                 setPosition( castExpr->arg );
    669                         } else if (
    670                                 dynamic_cast< const SizeofExpr * >( expr )
    671                                 || dynamic_cast< const AlignofExpr * >( expr )
    672                         ) {
    673                                 index = 0;
    674                         } else {
    675                                 assertf( false,
    676                                         "bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
    677                         }
    678                 }
    679 
    680                 void setPosition(
    681                         std::deque< ptr< Expr > >::const_iterator begin,
    682                         std::deque< ptr< Expr > >::const_iterator end
    683                 ) override {
    684                         if ( begin == end ) return;
    685 
    686                         setPosition( *begin );
    687                         memberIter->setPosition( ++begin, end );
    688                 }
    689 
    690                 std::deque< InitAlternative > operator* () const override { return first(); }
    691 
    692                 operator bool() const override { return index < size; }
    693 
    694                 ArrayIterator & bigStep() override {
    695                         PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    696                         ++index;
    697                         memberIter.reset( index < size ? createMemberIterator( location, base ) : nullptr );
    698                         return *this;
    699                 }
    700 
    701                 ArrayIterator & smallStep() override {
    702                         PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    703                         if ( memberIter ) {
    704                                 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
    705                                 memberIter->smallStep();
    706                                 if ( *memberIter ) {
    707                                         PRINT( std::cerr << "has valid member iter" << std::endl; )
    708                                         return *this;
    709                                 }
    710                         }
    711                         return bigStep();
    712                 }
    713 
    714                 const Type * getType() override { return array; }
    715 
    716                 const Type * getNext() override { return base; }
    717 
    718                 std::deque< InitAlternative > first() const override {
    719                         PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    720                         if ( memberIter && *memberIter ) {
    721                                 std::deque< InitAlternative > ret = memberIter->first();
    722                                 for ( InitAlternative & alt : ret ) {
    723                                         alt.designation.get_and_mutate()->designators.emplace_front(
    724                                                 ConstantExpr::from_ulong( location, index ) );
    725                                 }
    726                                 return ret;
    727                         }
    728                         return {};
    729                 }
    730         };
    731 
    732         class AggregateIterator : public MemberIterator {
    733         protected:
    734                 using MemberList = std::vector< ptr< Decl > >;
    735 
    736                 CodeLocation location;
    737                 std::string kind;  // for debug
    738                 std::string name;
    739                 const Type * inst;
    740                 const MemberList & members;
    741                 MemberList::const_iterator curMember;
    742                 bool atbegin = true;  // false at first {small,big}Step
    743                 const Type * curType = nullptr;
    744                 std::unique_ptr< MemberIterator > memberIter = nullptr;
    745                 TypeSubstitution sub;
    746 
    747                 bool init() {
    748                         PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
    749                         if ( curMember != members.end() ) {
    750                                 if ( auto field = curMember->as< ObjectDecl >() ) {
    751                                         PRINT( std::cerr << "incremented to field: " << field << std::endl; )
    752                                         curType = field->get_type();
    753                                         memberIter.reset( createMemberIterator( location, curType ) );
    754                                         return true;
    755                                 }
    756                         }
    757                         return false;
    758                 }
    759 
    760                 AggregateIterator(
    761                         const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
    762                         const MemberList & ms )
    763                 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
    764                   sub( genericSubstitution( i ) ) {
    765                         PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
    766                         init();
    767                 }
    768 
    769         public:
    770                 void setPosition(
    771                         std::deque< ptr< Expr > >::const_iterator begin,
    772                         std::deque< ptr< Expr > >::const_iterator end
    773                 ) final {
    774                         if ( begin == end ) return;
    775 
    776                         if ( auto varExpr = begin->as< VariableExpr >() ) {
    777                                 for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
    778                                         if ( *curMember != varExpr->var ) continue;
    779 
    780                                         ++begin;
    781 
    782                                         memberIter.reset( createMemberIterator( location, varExpr->result ) );
    783                                         curType = varExpr->result;
    784                                         atbegin = curMember == members.begin() && begin == end;
    785                                         memberIter->setPosition( begin, end );
    786                                         return;
    787                                 }
    788                                 assertf( false,
    789                                         "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    790                         } else {
    791                                 assertf( false,
    792                                         "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
    793                         }
    794                 }
    795 
    796                 std::deque< InitAlternative > operator* () const final {
    797                         if ( memberIter && *memberIter ) {
    798                                 std::deque< InitAlternative > ret = memberIter->first();
    799                                 PRINT( std::cerr << "sub: " << sub << std::endl; )
    800                                 for ( InitAlternative & alt : ret ) {
    801                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    802                                         alt.designation.get_and_mutate()->designators.emplace_front(
    803                                                 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    804                                         // need to substitute for generic types so that casts are to concrete types
    805                                         PRINT( std::cerr << "  type is: " << alt.type; )
    806                                         sub.apply( alt.type ); // also apply to designation??
    807                                         PRINT( std::cerr << " ==> " << alt.type << std::endl; )
    808                                 }
    809                                 return ret;
    810                         }
    811                         return {};
    812                 }
    813 
    814                 AggregateIterator & smallStep() final {
    815                         PRINT( std::cerr << "smallStep in " << kind << std::endl; )
    816                         atbegin = false;
    817                         if ( memberIter ) {
    818                                 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
    819                                 memberIter->smallStep();
    820                                 if ( *memberIter ) {
    821                                         PRINT( std::cerr << "success!" << std::endl; )
    822                                         return *this;
    823                                 }
    824                         }
    825                         return bigStep();
    826                 }
    827 
    828                 AggregateIterator & bigStep() override = 0;
    829 
    830                 const Type * getType() final { return inst; }
    831 
    832                 const Type * getNext() final {
    833                         return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr;
    834                 }
    835 
    836                 std::deque< InitAlternative > first() const final {
    837                         std::deque< InitAlternative > ret;
    838                         PRINT( std::cerr << "first " << kind << std::endl; )
    839                         if ( memberIter && *memberIter ) {
    840                                 PRINT( std::cerr << "adding children" << std::endl; )
    841                                 ret = memberIter->first();
    842                                 for ( InitAlternative & alt : ret ) {
    843                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    844                                         alt.designation.get_and_mutate()->designators.emplace_front(
    845                                                 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    846                                 }
    847                         }
    848                         if ( atbegin ) {
    849                                 // only add self if at the very beginning of the structure
    850                                 PRINT( std::cerr << "adding self" << std::endl; )
    851                                 ret.emplace_front( inst, new Designation{ location } );
    852                         }
    853                         return ret;
    854                 }
    855         };
    856 
    857         class StructIterator final : public AggregateIterator {
    858         public:
    859                 StructIterator( const CodeLocation & loc, const StructInstType * inst )
    860                 : AggregateIterator( loc, "StructIterator", inst->name, inst, inst->base->members ) {}
    861 
    862                 operator bool() const override {
    863                         return curMember != members.end() || (memberIter && *memberIter);
    864                 }
    865 
    866                 StructIterator & bigStep() override {
    867                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    868                         atbegin = false;
    869                         memberIter = nullptr;
    870                         curType = nullptr;
    871                         while ( curMember != members.end() ) {
    872                                 ++curMember;
    873                                 if ( init() ) return *this;
    874                         }
    875                         return *this;
    876                 }
    877         };
    878 
    879         class UnionIterator final : public AggregateIterator {
    880         public:
    881                 UnionIterator( const CodeLocation & loc, const UnionInstType * inst )
    882                 : AggregateIterator( loc, "UnionIterator", inst->name, inst, inst->base->members ) {}
    883 
    884                 operator bool() const override { return memberIter && *memberIter; }
    885 
    886                 UnionIterator & bigStep() override {
    887                         // unions only initialize one member
    888                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    889                         atbegin = false;
    890                         memberIter = nullptr;
    891                         curType = nullptr;
    892                         curMember = members.end();
    893                         return *this;
    894                 }
    895         };
    896 
    897         class TupleIterator final : public AggregateIterator {
    898         public:
    899                 TupleIterator( const CodeLocation & loc, const TupleType * inst )
    900                 : AggregateIterator(
    901                         loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members
    902                 ) {}
    903 
    904                 operator bool() const override {
    905                         return curMember != members.end() || (memberIter && *memberIter);
    906                 }
    907 
    908                 TupleIterator & bigStep() override {
    909                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    910                         atbegin = false;
    911                         memberIter = nullptr;
    912                         curType = nullptr;
    913                         while ( curMember != members.end() ) {
    914                                 ++curMember;
    915                                 if ( init() ) return *this;
    916                         }
    917                         return *this;
    918                 }
    919         };
    920 
    921         MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
    922                 if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {
    923                         if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
    924                                 return new StructIterator{ loc, sit };
    925                         } else if ( auto uit = dynamic_cast< const UnionInstType * >( aggr ) ) {
    926                                 return new UnionIterator{ loc, uit };
    927                         } else {
    928                                 assertf(
    929                                         dynamic_cast< const EnumInstType * >( aggr )
    930                                                 || dynamic_cast< const TypeInstType * >( aggr ),
    931                                         "Encountered unhandled ReferenceToType in createMemberIterator: %s",
    932                                                 toString( type ).c_str() );
    933                                 return new SimpleIterator{ loc, type };
    934                         }
    935                 } else if ( auto at = dynamic_cast< const ArrayType * >( type ) ) {
    936                         return new ArrayIterator{ loc, at };
    937                 } else if ( auto tt = dynamic_cast< const TupleType * >( type ) ) {
    938                         return new TupleIterator{ loc, tt };
    939                 } else {
    940                         return new SimpleIterator{ loc, type };
    941                 }
    942         }
    943 
    944617        CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
    945618                objStack.emplace_back( new SimpleIterator{ loc, type } );
    946619        }
    947620
    948         void CurrentObject::setNext( const ast::Designation * designation ) {
    949                 PRINT( std::cerr << "____setNext" << designation << std::endl; )
    950                 assertf( ! objStack.empty(), "obj stack empty in setNext" );
    951                 objStack.back()->setPosition( designation->designators );
    952         }
    953 
    954         void CurrentObject::increment() {
    955                 PRINT( std::cerr << "____increment" << std::endl; )
    956                 if ( objStack.empty() ) return;
    957                 PRINT( std::cerr << *objStack.back() << std::endl; )
    958                 objStack.back()->smallStep();
    959         }
    960 
    961         void CurrentObject::enterListInit( const CodeLocation & loc ) {
    962                 PRINT( std::cerr << "____entering list init" << std::endl; )
    963                 assertf( ! objStack.empty(), "empty obj stack entering list init" );
    964                 const ast::Type * type = objStack.back()->getNext();
    965                 assert( type );
    966                 objStack.emplace_back( createMemberIterator( loc, type ) );
    967         }
    968 
    969         void CurrentObject::exitListInit() {
    970                 PRINT( std::cerr << "____exiting list init" << std::endl; )
    971                 assertf( ! objStack.empty(), "objstack empty" );
    972                 objStack.pop_back();
    973                 if ( ! objStack.empty() ) {
    974                         PRINT( std::cerr << *objStack.back() << std::endl; )
    975                         objStack.back()->bigStep();
    976                 }
    977         }
    978 
    979         std::deque< InitAlternative > CurrentObject::getOptions() {
     621        std::vector< InitAlternative > CurrentObject::getOptions() {
    980622                PRINT( std::cerr << "____getting current options" << std::endl; )
    981623                assertf( ! objStack.empty(), "objstack empty in getOptions" );
    982624                return **objStack.back();
    983         }
    984 
    985         const Type * CurrentObject::getCurrentType() {
    986                 PRINT( std::cerr << "____getting current type" << std::endl; )
    987                 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
    988                 return objStack.back()->getNext();
    989625        }
    990626}
Note: See TracChangeset for help on using the changeset viewer.