- File:
-
- 1 edited
-
src/ResolvExpr/CurrentObject.cc (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CurrentObject.cc
r2d11663 ra16764a6 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 21 20 #include <string> // for string, operator<<, allocator 22 21 23 #include "AST/Expr.hpp" // for InitAlternative24 #include "AST/GenericSubstitution.hpp" // for genericSubstitution25 #include "AST/Init.hpp" // for Designation26 #include "AST/Node.hpp" // for readonly27 #include "AST/Type.hpp"28 22 #include "Common/Indenter.h" // for Indenter, operator<< 29 23 #include "Common/SemanticError.h" // for SemanticError … … 145 139 ArrayIterator( ArrayType * at ) : array( at ) { 146 140 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 147 base = at-> base;141 base = at->get_base(); 148 142 memberIter = createMemberIterator( base ); 149 if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @= :" );150 setSize( at-> dimension);143 if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=" ); 144 setSize( at->get_dimension() ); 151 145 } 152 146 … … 156 150 157 151 private: 158 void setSize( Expression * expr ) { // replace this logic with an eval call 159 auto res = eval(expr); 160 if (res.second) { 161 size = res.first; 152 void setSize( Expression * expr ) { 153 if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 154 try { 155 size = constExpr->intValue(); 156 PRINT( std::cerr << "array type with size: " << size << std::endl; ) 157 } catch ( SemanticErrorException & ) { 158 SemanticError( expr, "Constant expression of non-integral type in array dimension: " ); 159 } 160 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 161 setSize( castExpr->get_arg() ); // xxx - need to perform the conversion specified by the cast 162 } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 163 if ( EnumInstType * inst = dynamic_cast< EnumInstType * > ( varExpr->result ) ) { 164 long long int value; 165 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 166 size = value; 167 } 168 } 162 169 } else { 163 SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) );170 assertf( false, "unhandled expression in setSize: %s", toString( expr ).c_str() ); // xxx - if not a constant expression, it's not simple to determine how long the array actually is, which is necessary for initialization to be done correctly -- fix this 164 171 } 165 172 } … … 585 592 } // namespace ResolvExpr 586 593 587 namespace ast {588 /// create a new MemberIterator that traverses a type correctly589 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );590 591 /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry592 class SimpleIterator final : public MemberIterator {593 CodeLocation location;594 readonly< Type > type = nullptr;595 public:596 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}597 598 void setPosition(599 std::deque< ptr< Expr > >::const_iterator begin,600 std::deque< ptr< Expr > >::const_iterator end601 ) 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 members614 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 {622 if ( type ) return { InitAlternative{ type, new Designation{ location } } };623 return {};624 }625 };626 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 CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {945 objStack.emplace_back( new SimpleIterator{ loc, type } );946 }947 948 const Designation * CurrentObject::findNext( const Designation * designation ) {949 using DesignatorChain = std::deque< ptr< Expr > >;950 PRINT( std::cerr << "___findNext" << std::endl; )951 952 // find all the d's953 std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;954 std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes;955 for ( const Expr * expr : designation->designators ) {956 PRINT( std::cerr << "____untyped: " << expr << std::endl; )957 auto dit = desigAlts.begin();958 if ( auto nexpr = dynamic_cast< const NameExpr * >( expr ) ) {959 for ( const Type * t : curTypes ) {960 assert( dit != desigAlts.end() );961 962 DesignatorChain & d = *dit;963 PRINT( std::cerr << "____actual: " << t << std::endl; )964 if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {965 // concatenate identical field names966 for ( const Decl * mem : refType->lookup( nexpr->name ) ) {967 if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {968 PRINT( std::cerr << "____alt: " << field->type << std::endl; )969 DesignatorChain d2 = d;970 d2.emplace_back( new VariableExpr{ expr->location, field } );971 newDesigAlts.emplace_back( std::move( d2 ) );972 newTypes.emplace_back( field->type );973 }974 }975 }976 977 ++dit;978 }979 } else {980 for ( const Type * t : curTypes ) {981 assert( dit != desigAlts.end() );982 983 DesignatorChain & d = *dit;984 if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {985 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )986 d.emplace_back( expr );987 newDesigAlts.emplace_back( d );988 newTypes.emplace_back( at->base );989 }990 }991 }992 993 // reset queue994 desigAlts = std::move( newDesigAlts );995 newDesigAlts.clear();996 curTypes = std::move( newTypes );997 newTypes.clear();998 assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );999 }1000 1001 if ( desigAlts.size() > 1 ) {1002 SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );1003 } else if ( desigAlts.empty() ) {1004 SemanticError( designation, "No reasonable alternatives for designation: " );1005 }1006 1007 DesignatorChain & d = desigAlts.back();1008 PRINT( for ( Expression * expr : d ) {1009 std::cerr << "____desig: " << expr << std::endl;1010 } ) // for1011 assertf( ! curTypes.empty(), "empty designator chosen");1012 1013 // set new designators1014 assertf( ! objStack.empty(), "empty object stack when setting designation" );1015 Designation * actualDesignation =1016 new Designation{ designation->location, DesignatorChain{d} };1017 objStack.back()->setPosition( d ); // destroys d1018 return actualDesignation;1019 }1020 1021 void CurrentObject::setNext( const Designation * designation ) {1022 PRINT( std::cerr << "____setNext" << designation << std::endl; )1023 assertf( ! objStack.empty(), "obj stack empty in setNext" );1024 objStack.back()->setPosition( designation->designators );1025 }1026 1027 void CurrentObject::increment() {1028 PRINT( std::cerr << "____increment" << std::endl; )1029 if ( objStack.empty() ) return;1030 PRINT( std::cerr << *objStack.back() << std::endl; )1031 objStack.back()->smallStep();1032 }1033 1034 void CurrentObject::enterListInit( const CodeLocation & loc ) {1035 PRINT( std::cerr << "____entering list init" << std::endl; )1036 assertf( ! objStack.empty(), "empty obj stack entering list init" );1037 const ast::Type * type = objStack.back()->getNext();1038 assert( type );1039 objStack.emplace_back( createMemberIterator( loc, type ) );1040 }1041 1042 void CurrentObject::exitListInit() {1043 PRINT( std::cerr << "____exiting list init" << std::endl; )1044 assertf( ! objStack.empty(), "objstack empty" );1045 objStack.pop_back();1046 if ( ! objStack.empty() ) {1047 PRINT( std::cerr << *objStack.back() << std::endl; )1048 objStack.back()->bigStep();1049 }1050 }1051 1052 std::deque< InitAlternative > CurrentObject::getOptions() {1053 PRINT( std::cerr << "____getting current options" << std::endl; )1054 assertf( ! objStack.empty(), "objstack empty in getOptions" );1055 return **objStack.back();1056 }1057 1058 const Type * CurrentObject::getCurrentType() {1059 PRINT( std::cerr << "____getting current type" << std::endl; )1060 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );1061 return objStack.back()->getNext();1062 }1063 }1064 1065 594 // Local Variables: // 1066 595 // tab-width: 4 //
Note:
See TracChangeset
for help on using the changeset viewer.