- File:
-
- 1 edited
-
src/ResolvExpr/CurrentObject.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CurrentObject.cc
r60aaa51d r2b59f55 16 16 #include <stddef.h> // for size_t 17 17 #include <cassert> // for assertf, assert, safe_dynamic_... 18 #include <deque>19 18 #include <iostream> // for ostream, operator<<, basic_ost... 20 19 #include <stack> // for stack … … 22 21 23 22 #include "AST/Expr.hpp" // for InitAlternative 24 #include "AST/GenericSubstitution.hpp" // for genericSubstitution25 23 #include "AST/Init.hpp" // for Designation 26 24 #include "AST/Node.hpp" // for readonly 27 #include "AST/Type.hpp"28 25 #include "Common/Indenter.h" // for Indenter, operator<< 29 26 #include "Common/SemanticError.h" // for SemanticError … … 586 583 587 584 namespace 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 }; 590 600 591 601 /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry … … 596 606 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {} 597 607 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 { 622 612 if ( type ) return { InitAlternative{ type, new Designation{ location } } }; 623 613 return {}; … … 625 615 }; 626 616 627 /// Iterates array types628 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 expressions660 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 end683 ) 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 debug738 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}Step743 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 end773 ) 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 types805 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 structure850 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 member888 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->members902 ) {}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 944 617 CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() { 945 618 objStack.emplace_back( new SimpleIterator{ loc, type } ); 946 619 } 947 620 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() { 980 622 PRINT( std::cerr << "____getting current options" << std::endl; ) 981 623 assertf( ! objStack.empty(), "objstack empty in getOptions" ); 982 624 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();989 625 } 990 626 }
Note:
See TracChangeset
for help on using the changeset viewer.