// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // CurrentObject.h -- // // Author : Rob Schluntz // Created On : Tue Jun 13 15:28:32 2017 // Last Modified By : Rob Schluntz // Last Modified On : Tue Jun 13 15:28:44 2017 // Update Count : 2 // #include // for size_t #include // for assertf, assert, safe_dynamic_... #include // for ostream, operator<<, basic_ost... #include // for stack #include // for string, operator<<, allocator #include "Common/Indenter.h" // for Indenter, operator<< #include "Common/SemanticError.h" // for SemanticError #include "Common/utility.h" // for toString #include "CurrentObject.h" #include "SynTree/Constant.h" // for Constant #include "SynTree/Declaration.h" // for ObjectDecl, Declaration, Struc... #include "SynTree/Expression.h" // for InitAlternative, VariableExpr #include "SynTree/Initializer.h" // for Designation, operator<< #include "SynTree/Type.h" // for Type, StructInstType, UnionIns... #include "SynTree/TypeSubstitution.h" // for TypeSubstitution #if 0 #define PRINT(x) x #else #define PRINT(x) #endif namespace ResolvExpr { template< typename AggrInst > TypeSubstitution makeGenericSubstitution( AggrInst * inst ) { assert( inst ); assert( inst->get_baseParameters() ); std::list< TypeDecl * > baseParams = *inst->get_baseParameters(); std::list< Expression * > typeSubs = inst->get_parameters(); TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() ); return subs; } TypeSubstitution makeGenericSubstitution( Type * type ) { if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) { return makeGenericSubstitution( inst ); } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) { return makeGenericSubstitution( inst ); } else { return TypeSubstitution(); } } class MemberIterator { public: virtual ~MemberIterator() {} /// walks the current object using the given designators as a guide virtual void setPosition( std::list< Expression * > & designators ) = 0; /// retrieve the list of possible Type/Designaton pairs for the current position in the currect object virtual std::list operator*() const = 0; /// true if the iterator is not currently at the end virtual operator bool() const = 0; /// moves the iterator by one member in the current object virtual MemberIterator & bigStep() = 0; /// moves the iterator by one member in the current subobject virtual MemberIterator & smallStep() = 0; /// the type of the current object virtual Type * getType() = 0; /// the type of the current subobject virtual Type * getNext() = 0; /// printing for debug virtual void print( std::ostream & out, Indenter indent ) const = 0; /// helper for operator*; aggregates must add designator to each init alternative, but /// adding designators in operator* creates duplicates. virtual std::list first() const = 0; // should be protected }; std::ostream & operator<<(std::ostream & out, const MemberIterator & it) { Indenter indenter; it.print( out, indenter ); return out; } /// create a new MemberIterator that traverses a type correctly MemberIterator * createMemberIterator( Type * type ); /// iterates "other" types, e.g. basic types, pointer types, etc. which do not change at list initializer entry class SimpleIterator : public MemberIterator { public: SimpleIterator( Type * type ) : type( type ) {} virtual void setPosition( std::list< Expression * > & designators ) { assertf( designators.empty(), "simple iterator given non-empty designator..." ); // xxx - might be semantic error } virtual std::list operator*() const { return first(); } virtual operator bool() const { return type; } // big step is the same as small step virtual MemberIterator & bigStep() { return smallStep(); } virtual MemberIterator & smallStep() { type = nullptr; // type is nullified on increment since SimpleIterators do not have members return *this; } virtual void print( std::ostream & out, __attribute__((unused)) Indenter indent ) const { out << "SimpleIterator(" << type << ")"; } virtual Type * getType() { return type; } virtual Type * getNext() { return type; } protected: virtual std::list first() const { if ( type ) return std::list{ { type->clone(), new Designation( {} ) } }; else return std::list{}; } private: Type * type = nullptr; }; class ArrayIterator : public MemberIterator { public: ArrayIterator( ArrayType * at ) : array( at ) { PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) base = at->get_base(); memberIter = createMemberIterator( base ); if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=" ); setSize( at->get_dimension() ); } ~ArrayIterator() { delete memberIter; } private: void setSize( Expression * expr ) { if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { try { size = constExpr->intValue(); PRINT( std::cerr << "array type with size: " << size << std::endl; ) } catch ( SemanticErrorException & ) { SemanticError( expr, "Constant expression of non-integral type in array dimension: " ); } } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { setSize( castExpr->get_arg() ); // xxx - need to perform the conversion specified by the cast } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { if ( EnumInstType * inst = dynamic_cast< EnumInstType * > ( varExpr->result ) ) { long long int value; if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { size = value; } } } else { 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 } } public: void setPosition( Expression * expr ) { // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { try { index = constExpr->intValue(); } catch( SemanticErrorException & ) { SemanticError( expr, "Constant expression of non-integral type in array designator: " ); } } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { setPosition( castExpr->get_arg() ); } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { EnumInstType * inst = dynamic_cast( varExpr->get_result() ); assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() ); long long int value; if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { index = value; } } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) { index = 0; // xxx - get actual sizeof/alignof value? } else { assertf( false, "bad designator given to ArrayIterator: %s", toString( expr ).c_str() ); } } virtual void setPosition( std::list< Expression * > & designators ) { if ( ! designators.empty() ) { setPosition( designators.front() ); designators.pop_front(); memberIter->setPosition( designators ); } } virtual std::list operator*() const { return first(); } virtual operator bool() const { return index < size; } virtual MemberIterator & bigStep() { PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; ) ++index; delete memberIter; if ( index < size ) memberIter = createMemberIterator( base ); else memberIter = nullptr; return *this; } virtual MemberIterator & smallStep() { PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; ) if ( memberIter ) { PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; ) memberIter->smallStep(); if ( *memberIter ) { PRINT( std::cerr << "has valid member iter" << std::endl; ) return *this; } } return bigStep(); } virtual Type * getType() { return array; } virtual Type * getNext() { return base; } virtual std::list first() const { PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; ) if ( memberIter && *memberIter ) { std::list ret = memberIter->first(); for ( InitAlternative & alt : ret ) { alt.designation->get_designators().push_front( new ConstantExpr( Constant::from_ulong( index ) ) ); } return ret; } return std::list(); } virtual void print( std::ostream & out, Indenter indent ) const { out << "ArrayIterator(Array of " << base << ")"; if ( memberIter ) { Indenter childIndent = indent+1; out << std::endl << childIndent; memberIter->print( out, childIndent ); } } private: ArrayType * array = nullptr; Type * base = nullptr; size_t index = 0; size_t size = 0; MemberIterator * memberIter = nullptr; }; class AggregateIterator : public MemberIterator { public: typedef std::list MemberList; typedef MemberList::const_iterator iterator; std::string kind = ""; // for debug std::string name; Type * inst = nullptr; const MemberList & members; iterator curMember; bool atbegin = true; // false at first {small,big}Step -- this aggr type is only added to the possibilities at the beginning Type * curType = nullptr; MemberIterator * memberIter = nullptr; mutable TypeSubstitution sub; AggregateIterator( const std::string & kind, const std::string & name, Type * inst, const MemberList & members ) : kind( kind ), name( name ), inst( inst ), members( members ), curMember( members.begin() ), sub( makeGenericSubstitution( inst ) ) { PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; ) init(); } virtual ~AggregateIterator() { delete memberIter; } bool init() { PRINT( std::cerr << "--init()--" << members.size() << std::endl; ) if ( curMember != members.end() ) { if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( *curMember ) ) { PRINT( std::cerr << "incremented to field: " << field << std::endl; ) curType = field->get_type(); memberIter = createMemberIterator( curType ); return true; } } return false; } virtual std::list operator*() const { if (memberIter && *memberIter) { std::list ret = memberIter->first(); PRINT( std::cerr << "sub: " << sub << std::endl; ) for ( InitAlternative & alt : ret ) { PRINT( std::cerr << "iterating and adding designators" << std::endl; ) alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) ); // need to substitute for generic types, so that casts are to concrete types PRINT( std::cerr << " type is: " << alt.type; ) sub.apply( alt.type ); // also apply to designation?? PRINT( std::cerr << " ==> " << alt.type << std::endl; ) } return ret; } return std::list(); } virtual void setPosition( std::list< Expression * > & designators ) { if ( ! designators.empty() ) { if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( designators.front() ) ) { for ( curMember = members.begin(); curMember != members.end(); ++curMember ) { if ( *curMember == varExpr->get_var() ) { designators.pop_front(); delete memberIter; memberIter = createMemberIterator( varExpr->get_result() ); curType = varExpr->get_result(); atbegin = curMember == members.begin() && designators.empty(); // xxx - is this the right condition for atbegin?? memberIter->setPosition( designators ); return; } // if } // for assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() ); } else { assertf( false, "bad designator given to %s: %s", kind.c_str(), toString( designators.front() ).c_str() ); } // if } // if } virtual MemberIterator & smallStep() { PRINT( std::cerr << "smallStep in " << kind << std::endl; ) atbegin = false; if ( memberIter ) { PRINT( std::cerr << "has member iter, incrementing..." << std::endl; ) memberIter->smallStep(); if ( *memberIter ) { PRINT( std::cerr << "success!" << std::endl; ) return *this; } } return bigStep(); } virtual Type * getType() { return inst; } virtual Type * getNext() { if ( memberIter && *memberIter ) return memberIter->getType(); // xxx - ??? recursive call??? return nullptr; } virtual std::list first() const { std::list ret; PRINT( std::cerr << "first " << kind << std::endl; ) if ( memberIter && *memberIter ) { // might not need *memberIter?? PRINT( std::cerr << "adding children" << std::endl; ) ret = memberIter->first(); for ( InitAlternative & alt : ret ) { PRINT( std::cerr << "iterating and adding designators" << std::endl; ) alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) ); } } if ( atbegin ) { // xxx - what about case of empty struct?? // only add self if at the very beginning of the structure PRINT( std::cerr << "adding self" << std::endl; ) ret.push_front( { inst->clone(), new Designation( {} ) } ); } return ret; } virtual void print( std::ostream & out, Indenter indent ) const { out << kind << "(" << name << ")"; if ( memberIter ) { Indenter childIndent = indent+1; out << std::endl << childIndent; memberIter->print( out, childIndent ); } } }; class UnionIterator : public AggregateIterator { public: UnionIterator( UnionInstType * inst ) : AggregateIterator( "UnionIterator", inst->get_name(), inst, inst->get_baseUnion()->get_members() ) {} virtual operator bool() const { return (memberIter && *memberIter); } virtual MemberIterator & bigStep() { // unions only initialize one member PRINT( std::cerr << "bigStep in " << kind << std::endl; ) atbegin = false; delete memberIter; memberIter = nullptr; curType = nullptr; curMember = members.end(); return *this; } }; class StructIterator : public AggregateIterator { public: StructIterator( StructInstType * inst ) : AggregateIterator( "StructIterator", inst->get_name(), inst, inst->get_baseStruct()->get_members() ) {} virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); } virtual MemberIterator & bigStep() { PRINT( std::cerr << "bigStep in " << kind << std::endl; ) atbegin = false; delete memberIter; memberIter = nullptr; curType = nullptr; for ( ; curMember != members.end(); ) { ++curMember; if ( init() ) { return *this; } } return *this; } }; class TupleIterator : public AggregateIterator { public: TupleIterator( TupleType * inst ) : AggregateIterator( "TupleIterator", toString("Tuple", inst->size()), inst, inst->get_members() ) {} virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); } virtual MemberIterator & bigStep() { PRINT( std::cerr << "bigStep in " << kind << std::endl; ) atbegin = false; delete memberIter; memberIter = nullptr; curType = nullptr; for ( ; curMember != members.end(); ) { ++curMember; if ( init() ) { return *this; } } return *this; } }; MemberIterator * createMemberIterator( Type * type ) { if ( ReferenceToType * aggr = dynamic_cast< ReferenceToType * >( type ) ) { if ( StructInstType * sit = dynamic_cast< StructInstType * >( aggr ) ) { return new StructIterator( sit ); } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( aggr ) ) { return new UnionIterator( uit ); } else { assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() ); return new SimpleIterator( type ); } } else if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { return new ArrayIterator( at ); } else if ( TupleType * tt = dynamic_cast< TupleType * >( type ) ) { return new TupleIterator( tt ); } else { return new SimpleIterator( type ); } } CurrentObject::CurrentObject() {} CurrentObject::CurrentObject( Type * type ) { objStack.push( new SimpleIterator( type ) ); } void CurrentObject::setNext( Designation * designation ) { assertf( ! objStack.empty(), "obj stack empty in setNext" ); PRINT( std::cerr << "____setNext" << designation << std::endl; ) objStack.top()->setPosition( designation->get_designators() ); } Designation * CurrentObject::findNext( Designation * designation ) { typedef std::list< Expression * > DesignatorChain; PRINT( std::cerr << "___findNext" << std::endl; ) // find all the d's std::list desigAlts{ { } }, newDesigAlts; std::list curTypes { (objStack.top())->getType() }, newTypes; for ( Expression * expr : designation->get_designators() ) { PRINT( std::cerr << "____untyped: " << expr << std::endl; ) std::list::iterator dit = desigAlts.begin(); if ( NameExpr * nexpr = dynamic_cast(expr) ) { for ( Type * t : curTypes ) { assert( dit != desigAlts.end() ); DesignatorChain & d = *dit; PRINT( std::cerr << "____actual: " << t << std::endl; ) ReferenceToType * refType = dynamic_cast(t); std::list members; if ( refType ) { refType->lookup( nexpr->get_name(), members ); // concatenate identical field name // xxx - need to also include anonymous members in this somehow... for ( Declaration * mem: members ) { if ( ObjectDecl * field = dynamic_cast(mem) ) { PRINT( std::cerr << "____alt: " << field->get_type() << std::endl; ) DesignatorChain newD = d; newD.push_back( new VariableExpr( field ) ); newDesigAlts.push_back( newD ); newTypes.push_back( field->get_type() ); } // if } // for } // if ++dit; } // for } else { for ( Type * t : curTypes ) { assert( dit != desigAlts.end() ); DesignatorChain & d = *dit; if ( ArrayType * at = dynamic_cast< ArrayType * > ( t ) ) { PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; ) d.push_back( expr ); newDesigAlts.push_back( d ); newTypes.push_back( at->get_base() ); } ++dit; } // for } // if desigAlts = newDesigAlts; newDesigAlts.clear(); curTypes = newTypes; newTypes.clear(); assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() ); } // for if ( desigAlts.size() > 1 ) { SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") ); } else if ( desigAlts.size() == 0 ) { SemanticError( designation, "No reasonable alternatives for designation: " ); } DesignatorChain & d = desigAlts.back(); PRINT( for ( Expression * expr : d ) { std::cerr << "____desig: " << expr << std::endl; } ) // for assertf( ! curTypes.empty(), "empty designator chosen"); // set new designators assertf( ! objStack.empty(), "empty object stack when setting designation" ); Designation * actualDesignation = new Designation( d ); objStack.top()->setPosition( d ); // destroys d return actualDesignation; } void CurrentObject::increment() { PRINT( std::cerr << "____increment" << std::endl; ) if ( ! objStack.empty() ) { PRINT( std::cerr << *objStack.top() << std::endl; ) objStack.top()->smallStep(); } } void CurrentObject::enterListInit() { PRINT( std::cerr << "____entering list init" << std::endl; ) assertf( ! objStack.empty(), "empty obj stack entering list init" ); Type * type = objStack.top()->getNext(); if ( type ) { objStack.push( createMemberIterator( type ) ); } else { assertf( false, "not sure about this case..." ); } } void CurrentObject::exitListInit() { PRINT( std::cerr << "____exiting list init" << std::endl; ) assertf( ! objStack.empty(), "objstack empty" ); delete objStack.top(); objStack.pop(); if ( ! objStack.empty() ) { PRINT( std::cerr << *objStack.top() << std::endl; ) objStack.top()->bigStep(); } } std::list< InitAlternative > CurrentObject::getOptions() { PRINT( std::cerr << "____getting current options" << std::endl; ) assertf( ! objStack.empty(), "objstack empty in getOptions" ); return **objStack.top(); } Type * CurrentObject::getCurrentType() { PRINT( std::cerr << "____getting current type" << std::endl; ) assertf( ! objStack.empty(), "objstack empty in getCurrentType" ); return objStack.top()->getNext(); } } // namespace ResolvExpr // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //