Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CurrentObject.cc

    r2d11663 ra16764a6  
    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
    2120#include <string>                      // for string, operator<<, allocator
    2221
    23 #include "AST/Expr.hpp"                // for InitAlternative
    24 #include "AST/GenericSubstitution.hpp" // for genericSubstitution
    25 #include "AST/Init.hpp"                // for Designation
    26 #include "AST/Node.hpp"                // for readonly
    27 #include "AST/Type.hpp"
    2822#include "Common/Indenter.h"           // for Indenter, operator<<
    2923#include "Common/SemanticError.h"      // for SemanticError
     
    145139                ArrayIterator( ArrayType * at ) : array( at ) {
    146140                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    147                         base = at->base;
     141                        base = at->get_base();
    148142                        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() );
    151145                }
    152146
     
    156150
    157151        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                                }
    162169                        } 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
    164171                        }
    165172                }
     
    585592} // namespace ResolvExpr
    586593
    587 namespace ast {
    588         /// create a new MemberIterator that traverses a type correctly
    589         MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
    590 
    591         /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
    592         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 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 {
    622                         if ( type ) return { InitAlternative{ type, new Designation{ location } } };
    623                         return {};
    624                 }
    625         };
    626 
    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 
    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's
    953                 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 names
    966                                                 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 queue
    994                         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                 } ) // for
    1011                 assertf( ! curTypes.empty(), "empty designator chosen");
    1012 
    1013                 // set new designators
    1014                 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 d
    1018                 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 
    1065594// Local Variables: //
    1066595// tab-width: 4 //
Note: See TracChangeset for help on using the changeset viewer.