Changeset 65197c2


Ignore:
Timestamp:
Dec 5, 2017, 2:17:17 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
971d9f2, a85e44c, c13e8dc8
Parents:
12d2dc8 (diff), 866f560 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
2 added
26 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    r12d2dc8 r65197c2  
    10121012        }
    10131013
     1014        void CodeGenerator::postvisit( WithStmt * with ) {
     1015                if ( ! genC ) {
     1016                        output << "with ( ";
     1017                        genCommaList( with->exprs.begin(), with->exprs.end() );
     1018                        output << " ) ";
     1019                }
     1020                with->stmt->accept( *visitor );
     1021        }
    10141022
    10151023        void CodeGenerator::postvisit( WhileStmt * whileStmt ) {
  • src/CodeGen/CodeGenerator.h

    r12d2dc8 r65197c2  
    102102                void postvisit( CatchStmt * );
    103103                void postvisit( WaitForStmt * );
     104                void postvisit( WithStmt * );
    104105                void postvisit( WhileStmt * );
    105106                void postvisit( ForStmt * );
  • src/Common/PassVisitor.h

    r12d2dc8 r65197c2  
    8181        virtual void visit( FinallyStmt * finallyStmt ) override final;
    8282        virtual void visit( WaitForStmt * waitforStmt ) override final;
     83        virtual void visit( WithStmt * withStmt ) override final;
    8384        virtual void visit( NullStmt * nullStmt ) override final;
    8485        virtual void visit( DeclStmt * declStmt ) override final;
     
    172173        virtual Statement * mutate( FinallyStmt * finallyStmt ) override final;
    173174        virtual Statement * mutate( WaitForStmt * waitforStmt ) override final;
     175        virtual Statement * mutate( WithStmt * withStmt ) override final;
    174176        virtual NullStmt * mutate( NullStmt * nullStmt ) override final;
    175177        virtual Statement * mutate( DeclStmt * declStmt ) override final;
     
    296298        void indexerAddUnionFwd ( UnionDecl           * node ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
    297299        void indexerAddTrait    ( TraitDecl           * node ) { indexer_impl_addTrait    ( pass, 0, node ); }
     300        void indexerAddWith     ( WithStmt            * node ) { indexer_impl_addWith    ( pass, 0, node ); }
     301
    298302
    299303        template< typename TreeType, typename VisitorType >
  • src/Common/PassVisitor.impl.h

    r12d2dc8 r65197c2  
    985985}
    986986
     987
     988
     989//--------------------------------------------------------------------------
     990// NullStmt
     991template< typename pass_type >
     992void PassVisitor< pass_type >::visit( WithStmt * node ) {
     993        VISIT_START( node );
     994        maybeAccept_impl( node->exprs, *this );
     995        {
     996                // catch statements introduce a level of scope (for the caught exception)
     997                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     998                indexerAddWith( node );
     999                maybeAccept_impl( node->stmt, *this );
     1000        }
     1001        VISIT_END( node );
     1002}
     1003
     1004template< typename pass_type >
     1005Statement * PassVisitor< pass_type >::mutate( WithStmt * node ) {
     1006        MUTATE_START( node );
     1007        maybeMutate_impl( node->exprs, *this );
     1008        {
     1009                // catch statements introduce a level of scope (for the caught exception)
     1010                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     1011                indexerAddWith( node );
     1012                maybeMutate_impl( node->stmt, *this );
     1013        }
     1014        MUTATE_END( Statement, node );
     1015}
     1016
    9871017//--------------------------------------------------------------------------
    9881018// NullStmt
  • src/Common/PassVisitor.proto.h

    r12d2dc8 r65197c2  
    208208INDEXER_FUNC( addUnion  , UnionDecl *           );
    209209INDEXER_FUNC( addTrait  , TraitDecl *           );
     210INDEXER_FUNC( addWith   , WithStmt *            );
    210211
    211212
  • src/GenPoly/InstantiateGeneric.cc

    r12d2dc8 r65197c2  
    453453                        return false;
    454454                }
    455 
    456                 AggregateDecl * getAggr( Type * t ) {
    457                         if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) {
    458                                 return inst->baseStruct;
    459                         } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
    460                                 return inst->baseUnion;
    461                         }
    462                         assertf( false, "Non-aggregate type: %s", toString( t ).c_str() );
    463                 }
    464455        }
    465456
     
    469460                if ( isGenericType( memberExpr->aggregate->result ) ) {
    470461                        // find the location of the member
    471                         AggregateDecl * aggr = getAggr( memberExpr->aggregate->result );
     462                        AggregateDecl * aggr = memberExpr->aggregate->result->getAggr();
    472463                        std::list< Declaration * > & members = aggr->members;
    473464                        memberIndex = std::distance( members.begin(), std::find( members.begin(), members.end(), memberExpr->member ) );
     
    479470                if ( memberIndex != -1 ) {
    480471                        // using the location from the generic type, find the member in the instantiation and rebuild the member expression
    481                         AggregateDecl * aggr = getAggr( memberExpr->aggregate->result );
     472                        AggregateDecl * aggr = memberExpr->aggregate->result->getAggr();
    482473                        assertf( memberIndex < (int)aggr->members.size(), "Instantiation somehow has fewer members than the generic type." );
    483474                        Declaration * member = *std::next( aggr->members.begin(), memberIndex );
  • src/Parser/DeclarationNode.cc

    r12d2dc8 r65197c2  
    717717}
    718718
    719 DeclarationNode * DeclarationNode::addFunctionBody( StatementNode * body ) {
     719DeclarationNode * DeclarationNode::addFunctionBody( StatementNode * body, StatementNode * with ) {
    720720        assert( type );
    721721        assert( type->kind == TypeData::Function );
    722722        assert( ! type->function.body );
     723        if ( with ) {
     724                // convert
     725                //  void f(S s) with (s) { x = 0; }
     726                // to
     727                //  void f(S s) { with(s) { x = 0; } }
     728                WithStmt * withStmt = strict_dynamic_cast< WithStmt * >( with->build() );
     729                withStmt->stmt = body->build();
     730                delete body;
     731                delete with;
     732                body = new StatementNode( new CompoundStmt( { withStmt } ) );
     733        }
    723734        type->function.body = body;
    724735        return this;
  • src/Parser/ParseNode.h

    r12d2dc8 r65197c2  
    6969
    7070        virtual void print( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const {}
    71         virtual void printList( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const {}
     71        virtual void printList( std::ostream &os, int indent = 0 ) const {
     72                print( os, indent );
     73                if ( next ) next->print( os, indent );
     74        }
    7275
    7376        static int indent_by;
     
    120123        ExpressionNode * set_extension( bool exten ) { extension = exten; return this; }
    121124
    122         virtual void print( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const override {}
     125        virtual void print( std::ostream &os, __attribute__((unused)) int indent = 0 ) const override {
     126                os << expr.get() << std::endl;
     127        }
    123128        void printOneLine( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const {}
    124129
     
    257262        DeclarationNode * addBitfield( ExpressionNode * size );
    258263        DeclarationNode * addVarArgs();
    259         DeclarationNode * addFunctionBody( StatementNode * body );
     264        DeclarationNode * addFunctionBody( StatementNode * body, StatementNode * with = nullptr );
    260265        DeclarationNode * addOldDeclList( DeclarationNode * list );
    261266        DeclarationNode * setBase( TypeData * newType );
     
    359364        virtual StatementNode * append_last_case( StatementNode * );
    360365
    361         virtual void print( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const override {}
    362         virtual void printList( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const override {}
     366        virtual void print( std::ostream &os, __attribute__((unused)) int indent = 0 ) const override {
     367                os << stmt.get() << std::endl;
     368        }
    363369  private:
    364370        std::unique_ptr<Statement> stmt;
     
    408414WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when );
    409415WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );
     416WithStmt * build_with( ExpressionNode * exprs, StatementNode * stmt );
    410417
    411418//##############################################################################
  • src/Parser/StatementNode.cc

    r12d2dc8 r65197c2  
    282282        node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    283283
    284         node->orelse.statement = maybeMoveBuild<Statement >( else_stmt );
     284        node->orelse.statement  = maybeMoveBuild<Statement >( else_stmt );
    285285        node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( else_when ) );
    286286
    287287        return node;
     288}
     289
     290WithStmt * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
     291        std::list< Expression * > e;
     292        buildMoveList( exprs, e );
     293        Statement * s = maybeMoveBuild<Statement>( stmt );
     294        return new WithStmt( e, s );
    288295}
    289296
  • src/Parser/parser.yy

    r12d2dc8 r65197c2  
    10581058with_statement:
    10591059        WITH '(' tuple_expression_list ')' statement
    1060                 { throw SemanticError("With clause is currently unimplemented."); $$ = nullptr; } // FIX ME
     1060                {
     1061                        $$ = new StatementNode( build_with( $3, $5 ) );
     1062                }
    10611063        ;
    10621064
     
    24102412                { $$ = nullptr; }
    24112413        | WITH '(' tuple_expression_list ')'
    2412                 { throw SemanticError("With clause is currently unimplemented."); $$ = nullptr; } // FIX ME
     2414                { $$ = new StatementNode( build_with( $3, nullptr ) ); }
    24132415        ;
    24142416
     
    24202422                        // Add the function body to the last identifier in the function definition list, i.e., foo3:
    24212423                        //   [const double] foo1(), foo2( int ), foo3( double ) { return 3.0; }
    2422                         $1->get_last()->addFunctionBody( $3 );
     2424                        $1->get_last()->addFunctionBody( $3, $2 );
    24232425                        $$ = $1;
    24242426                }
     
    24282430                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24292431                        typedefTable.leaveScope();
    2430                         $$ = $2->addFunctionBody( $4 )->addType( $1 );
     2432                        $$ = $2->addFunctionBody( $4, $3 )->addType( $1 );
    24312433                }
    24322434                // handles default int return type, OBSOLESCENT (see 1)
     
    24352437                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24362438                        typedefTable.leaveScope();
    2437                         $$ = $2->addFunctionBody( $4 )->addQualifiers( $1 );
     2439                        $$ = $2->addFunctionBody( $4, $3 )->addQualifiers( $1 );
    24382440                }
    24392441                // handles default int return type, OBSOLESCENT (see 1)
     
    24422444                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24432445                        typedefTable.leaveScope();
    2444                         $$ = $2->addFunctionBody( $4 )->addQualifiers( $1 );
     2446                        $$ = $2->addFunctionBody( $4, $3 )->addQualifiers( $1 );
    24452447                }
    24462448                // handles default int return type, OBSOLESCENT (see 1)
     
    24492451                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24502452                        typedefTable.leaveScope();
    2451                         $$ = $3->addFunctionBody( $5 )->addQualifiers( $2 )->addQualifiers( $1 );
     2453                        $$ = $3->addFunctionBody( $5, $4 )->addQualifiers( $2 )->addQualifiers( $1 );
    24522454                }
    24532455
     
    24582460                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24592461                        typedefTable.leaveScope();
    2460                         $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5 )->addType( $1 );
     2462                        $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addType( $1 );
    24612463                }
    24622464                // handles default int return type, OBSOLESCENT (see 1)
     
    24652467                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24662468                        typedefTable.leaveScope();
    2467                         $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5 )->addQualifiers( $1 );
     2469                        $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 );
    24682470                }
    24692471                // handles default int return type, OBSOLESCENT (see 1)
     
    24722474                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24732475                        typedefTable.leaveScope();
    2474                         $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5 )->addQualifiers( $1 );
     2476                        $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 );
    24752477                }
    24762478                // handles default int return type, OBSOLESCENT (see 1)
     
    24792481                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24802482                        typedefTable.leaveScope();
    2481                         $$ = $3->addOldDeclList( $4 )->addFunctionBody( $6 )->addQualifiers( $2 )->addQualifiers( $1 );
     2483                        $$ = $3->addOldDeclList( $4 )->addFunctionBody( $6, $5 )->addQualifiers( $2 )->addQualifiers( $1 );
    24822484                }
    24832485        ;
  • src/ResolvExpr/AlternativeFinder.cc

    r12d2dc8 r65197c2  
    8383        }
    8484
     85        void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) {
     86                Indenter indent = { Indenter::tabsize, indentAmt };
     87                for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
     88                        i->print( os, indent );
     89                        os << std::endl;
     90                }
     91        }
     92
    8593        namespace {
    86                 void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt = 0 ) {
    87                         Indenter indent = { Indenter::tabsize, indentAmt };
    88                         for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    89                                 i->print( os, indent );
    90                                 os << std::endl;
    91                         }
    92                 }
    93 
    9494                void makeExprList( const AltList &in, std::list< Expression* > &out ) {
    9595                        for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
     
    469469                        std::cerr << std::endl;
    470470                )
    471                 std::list< DeclarationWithType* > candidates;
     471                std::list< SymTab::Indexer::IdData > candidates;
    472472                decls.lookupId( curDecl->get_name(), candidates );
    473473///   if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; }
    474                 for ( std::list< DeclarationWithType* >::const_iterator candidate = candidates.begin(); candidate != candidates.end(); ++candidate ) {
     474                for ( const auto & data : candidates ) {
     475                        DeclarationWithType * candidate = data.id;
    475476                        PRINT(
    476477                                std::cerr << "inferRecursive: candidate is ";
    477                                 (*candidate)->print( std::cerr );
     478                                candidate->print( std::cerr );
    478479                                std::cerr << std::endl;
    479480                        )
     
    482483                        TypeEnvironment newEnv( newAlt.env );
    483484                        OpenVarSet newOpenVars( openVars );
    484                         Type *adjType = (*candidate)->get_type()->clone();
     485                        Type *adjType = candidate->get_type()->clone();
    485486                        adjustExprType( adjType, newEnv, indexer );
    486487                        adjType->accept( global_renamer );
     
    500501                                Alternative newerAlt( newAlt );
    501502                                newerAlt.env = newEnv;
    502                                 assertf( (*candidate)->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( *candidate ).c_str() );
    503                                 DeclarationWithType *candDecl = static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) );
     503                                assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    504504
    505505                                // everything with an empty idChain was pulled in by the current assertion.
     
    516516                                // DOESN'T WORK: grandchild nodes conflict with their cousins
    517517                                //if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue;
    518                                 Expression *varExpr = new VariableExpr( candDecl );
     518                                Expression *varExpr = data.combine();
    519519                                delete varExpr->get_result();
    520520                                varExpr->set_result( adjType->clone() );
     
    522522                                        std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
    523523                                        curDecl->print( std::cerr );
    524                                         std::cerr << " with declaration " << (*candidate)->get_uniqueId() << " ";
    525                                         (*candidate)->print( std::cerr );
     524                                        std::cerr << " with declaration " << candidate->get_uniqueId() << " ";
     525                                        candidate->print( std::cerr );
    526526                                        std::cerr << std::endl;
    527527                                )
     
    532532                                }
    533533                                // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
    534                                 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( (*candidate)->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
     534                                (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
    535535                                inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, /*newNeedParents,*/ level, indexer, out );
    536536                        } else {
     
    13171317
    13181318        void AlternativeFinder::visit( NameExpr *nameExpr ) {
    1319                 std::list< DeclarationWithType* > declList;
     1319                std::list< SymTab::Indexer::IdData > declList;
    13201320                indexer.lookupId( nameExpr->get_name(), declList );
    13211321                PRINT( std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl; )
    1322                 for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
    1323                         VariableExpr newExpr( *i );
    1324                         alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
     1322                for ( auto & data : declList ) {
     1323                        Expression * newExpr = data.combine();
     1324                        // xxx - add in extra cost for with-statement exprs?
     1325                        alternatives.push_back( Alternative( newExpr, env, Cost::zero ) );
    13251326                        PRINT(
    13261327                                std::cerr << "decl is ";
    1327                                 (*i)->print( std::cerr );
     1328                                data.id->print( std::cerr );
    13281329                                std::cerr << std::endl;
    13291330                                std::cerr << "newExpr is ";
    1330                                 newExpr.print( std::cerr );
     1331                                newExpr->print( std::cerr );
    13311332                                std::cerr << std::endl;
    13321333                        )
     
    14201421        }
    14211422
    1422         void AlternativeFinder::resolveAttr( DeclarationWithType *funcDecl, FunctionType *function, Type *argType, const TypeEnvironment &env ) {
    1423                 // assume no polymorphism
    1424                 // assume no implicit conversions
    1425                 assert( function->get_parameters().size() == 1 );
    1426                 PRINT(
    1427                         std::cerr << "resolvAttr: funcDecl is ";
    1428                         funcDecl->print( std::cerr );
    1429                         std::cerr << " argType is ";
    1430                         argType->print( std::cerr );
    1431                         std::cerr << std::endl;
    1432                 )
    1433                 if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
    1434                         alternatives.push_back( Alternative( new AttrExpr( new VariableExpr( funcDecl ), argType->clone() ), env, Cost::zero ) );
    1435                         for ( std::list< DeclarationWithType* >::iterator i = function->get_returnVals().begin(); i != function->get_returnVals().end(); ++i ) {
    1436                                 alternatives.back().expr->set_result( (*i)->get_type()->clone() );
    1437                         } // for
    1438                 } // if
     1423        namespace {
     1424                void resolveAttr( SymTab::Indexer::IdData data, FunctionType *function, Type *argType, const TypeEnvironment &env, AlternativeFinder & finder ) {
     1425                        // assume no polymorphism
     1426                        // assume no implicit conversions
     1427                        assert( function->get_parameters().size() == 1 );
     1428                        PRINT(
     1429                                std::cerr << "resolvAttr: funcDecl is ";
     1430                                data.id->print( std::cerr );
     1431                                std::cerr << " argType is ";
     1432                                argType->print( std::cerr );
     1433                                std::cerr << std::endl;
     1434                        )
     1435                        const SymTab::Indexer & indexer = finder.get_indexer();
     1436                        AltList & alternatives = finder.get_alternatives();
     1437                        if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
     1438                                alternatives.push_back( Alternative( new AttrExpr( data.combine(), argType->clone() ), env, Cost::zero ) );
     1439                                for ( DeclarationWithType * retVal : function->returnVals ) {
     1440                                        alternatives.back().expr->result = retVal->get_type()->clone();
     1441                                } // for
     1442                        } // if
     1443                }
    14391444        }
    14401445
     
    14431448                NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
    14441449                assert( nameExpr );
    1445                 std::list< DeclarationWithType* > attrList;
     1450                std::list< SymTab::Indexer::IdData > attrList;
    14461451                indexer.lookupId( nameExpr->get_name(), attrList );
    14471452                if ( attrExpr->get_isType() || attrExpr->get_expr() ) {
    1448                         for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
     1453                        for ( auto & data : attrList ) {
     1454                                DeclarationWithType * id = data.id;
    14491455                                // check if the type is function
    1450                                 if ( FunctionType *function = dynamic_cast< FunctionType* >( (*i)->get_type() ) ) {
     1456                                if ( FunctionType *function = dynamic_cast< FunctionType* >( id->get_type() ) ) {
    14511457                                        // assume exactly one parameter
    14521458                                        if ( function->get_parameters().size() == 1 ) {
    14531459                                                if ( attrExpr->get_isType() ) {
    1454                                                         resolveAttr( *i, function, attrExpr->get_type(), env );
     1460                                                        resolveAttr( data, function, attrExpr->get_type(), env, *this );
    14551461                                                } else {
    14561462                                                        AlternativeFinder finder( indexer, env );
     
    14581464                                                        for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
    14591465                                                                if ( choice->expr->get_result()->size() == 1 ) {
    1460                                                                         resolveAttr(*i, function, choice->expr->get_result(), choice->env );
     1466                                                                        resolveAttr(data, function, choice->expr->get_result(), choice->env, *this );
    14611467                                                                } // fi
    14621468                                                        } // for
     
    14661472                        } // for
    14671473                } else {
    1468                         for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
    1469                                 VariableExpr newExpr( *i );
    1470                                 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
     1474                        for ( auto & data : attrList ) {
     1475                                alternatives.push_back( Alternative( data.combine(), env, Cost::zero ) );
    14711476                                renameTypes( alternatives.back().expr );
    14721477                        } // for
  • src/ResolvExpr/AlternativeFinder.h

    r12d2dc8 r65197c2  
    142142                template< typename OutputIterator >
    143143                void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
    144                 void resolveAttr( DeclarationWithType *funcDecl, FunctionType *function, Type *argType, const TypeEnvironment &env );
    145144
    146145                const SymTab::Indexer &indexer;
     
    151150
    152151        Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env );
    153         void referenceToRvalueConversion( Expression *& expr );
    154152
    155153        template< typename InputIterator, typename OutputIterator >
     
    174172
    175173        Cost sumCost( const AltList &in );
     174        void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt = 0 );
    176175
    177176        template< typename InputIterator >
     
    181180                }
    182181        }
     182
    183183} // namespace ResolvExpr
    184184
  • src/ResolvExpr/Resolver.cc

    r12d2dc8 r65197c2  
    2626#include "Common/utility.h"              // for ValueGuard, group_iterate
    2727#include "CurrentObject.h"               // for CurrentObject
     28#include "InitTweak/GenInit.h"
    2829#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
    2930#include "RenameVars.h"                  // for RenameVars, global_renamer
     
    4041#include "SynTree/TypeSubstitution.h"    // for TypeSubstitution
    4142#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
     43#include "Tuples/Tuples.h"
    4244#include "typeops.h"                     // for extractResultType
    4345#include "Unify.h"                       // for unify
     
    4648
    4749namespace ResolvExpr {
    48         struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting {
     50        struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd {
    4951                Resolver() {}
    5052                Resolver( const SymTab::Indexer & other ) {
     
    7476                void previsit( CatchStmt *catchStmt );
    7577                void previsit( WaitForStmt * stmt );
     78                void previsit( WithStmt * withStmt );
    7679
    7780                void previsit( SingleInit *singleInit );
     
    571574        }
    572575
     576        bool isStructOrUnion( Type * t ) {
     577                t = t->stripReferences();
     578                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
     579        }
     580
     581        void Resolver::previsit( WithStmt * withStmt ) {
     582                for ( Expression *& expr : withStmt->exprs )  {
     583                        TypeEnvironment env;
     584                        AlternativeFinder finder( indexer, env );
     585                        finder.findWithAdjustment( expr );
     586
     587                        // only struct- and union-typed expressions are viable candidates
     588                        AltList candidates;
     589                        for ( Alternative & alt : finder.get_alternatives() ) {
     590                                if ( isStructOrUnion( alt.expr->result ) ) {
     591                                        candidates.push_back( std::move( alt ) );
     592                                }
     593                        }
     594
     595                        // choose the lowest cost expression among the candidates
     596                        AltList winners;
     597                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     598                        if ( winners.size() == 0 ) {
     599                                throw SemanticError( "No reasonable alternatives for with statement expression: ", expr );
     600                        } else if ( winners.size() != 1 ) {
     601                                std::ostringstream stream;
     602                                stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n";
     603                                expr->print( stream );
     604                                stream << "Alternatives are:\n";
     605                                printAlts( winners, stream, 1 );
     606                                throw SemanticError( stream.str() );
     607                        }
     608
     609                        // there is one unambiguous interpretation - move the expression into the with statement
     610                        Alternative & alt = winners.front();
     611                        finishExpr( alt.expr, alt.env, expr->env );
     612                        delete expr;
     613                        expr = alt.expr;
     614                        alt.expr = nullptr;
     615
     616                        // if with expression might be impure, create a temporary so that it is evaluated once
     617                        if ( Tuples::maybeImpure( expr ) ) {
     618                                static UniqueName tmpNamer( "_with_tmp_" );
     619                                ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
     620                                expr = new VariableExpr( tmp );
     621                                stmtsToAddBefore.push_back( new DeclStmt( tmp ) );
     622                                if ( InitTweak::isConstructable( tmp->type ) ) {
     623                                        // generate ctor/dtor and resolve them
     624                                        tmp->init = InitTweak::genCtorInit( tmp );
     625                                        tmp->accept( *visitor );
     626                                }
     627                        }
     628                }
     629        }
     630
    573631        template< typename T >
    574632        bool isCharType( T t ) {
  • src/ResolvExpr/typeops.h

    r12d2dc8 r65197c2  
    102102        bool occurs( Type *type, std::string varName, const TypeEnvironment &env );
    103103
     104        // in AlternativeFinder.cc
     105        void referenceToRvalueConversion( Expression *& expr );
     106
    104107        // flatten tuple type into list of types
    105108        template< typename OutputIterator >
  • src/SymTab/Indexer.cc

    r12d2dc8 r65197c2  
    4040
    4141namespace SymTab {
    42         typedef std::unordered_map< std::string, DeclarationWithType* > MangleTable;
     42        std::ostream & operator<<( std::ostream & out, const Indexer::IdData & data ) {
     43                return out << "(" << data.id << "," << data.baseExpr << ")";
     44        }
     45
     46        typedef std::unordered_map< std::string, Indexer::IdData > MangleTable;
    4347        typedef std::unordered_map< std::string, MangleTable > IdTable;
    4448        typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable;
     
    97101        }
    98102
    99         void Indexer::removeSpecialOverrides( const std::string &id, std::list< DeclarationWithType * > & out ) const {
     103        void Indexer::removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const {
    100104                // only need to perform this step for constructors, destructors, and assignment functions
    101105                if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
     
    104108                struct ValueType {
    105109                        struct DeclBall {
    106                                 FunctionDecl * decl;
     110                                IdData decl;
    107111                                bool isUserDefinedFunc; // properties for this particular decl
    108112                                bool isDefaultCtor;
     
    120124                        // another FunctionDecl for the current type was found - determine
    121125                        // if it has special properties and update data structure accordingly
    122                         ValueType & operator+=( FunctionDecl * function ) {
     126                        ValueType & operator+=( IdData data ) {
     127                                DeclarationWithType * function = data.id;
    123128                                bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->get_linkage() );
    124129                                bool isDefaultCtor = InitTweak::isDefaultConstructor( function );
    125130                                bool isDtor = InitTweak::isDestructor( function );
    126131                                bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() );
    127                                 decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
     132                                decls.push_back( DeclBall{ data, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
    128133                                existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc;
    129134                                existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && CodeGen::isConstructor( function->get_name() ) );
     
    135140                }; // ValueType
    136141
    137                 std::list< DeclarationWithType * > copy;
     142                std::list< IdData > copy;
    138143                copy.splice( copy.end(), out );
    139144
    140145                // organize discovered declarations by type
    141146                std::unordered_map< std::string, ValueType > funcMap;
    142                 for ( DeclarationWithType * decl : copy ) {
    143                         if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl ) ) {
     147                for ( auto decl : copy ) {
     148                        if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) {
    144149                                std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
    145150                                assert( ! params.empty() );
     
    147152                                Type * base = InitTweak::getPointerBase( params.front()->get_type() );
    148153                                assert( base );
    149                                 funcMap[ Mangler::mangle( base ) ] += function;
     154                                funcMap[ Mangler::mangle( base ) ] += decl;
    150155                        } else {
    151156                                out.push_back( decl );
     
    164169                                bool noUserDefinedFunc = ! val.existsUserDefinedFunc;
    165170                                bool isUserDefinedFunc = ball.isUserDefinedFunc;
    166                                 bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl->get_linkage() == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
     171                                bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl.id->get_linkage() == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
    167172                                bool isAcceptableCopyFunc = ! val.existsUserDefinedCopyFunc && ball.isCopyFunc; // handles copy ctor and assignment operator
    168173                                bool isAcceptableDtor = ! val.existsUserDefinedDtor && ball.isDtor;
     
    219224        }
    220225
    221         void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const {
     226        void Indexer::lookupId( const std::string &id, std::list< IdData > &out ) const {
    222227                std::unordered_set< std::string > foundMangleNames;
    223228
     
    289294                        const MangleTable &mangleTable = decls->second;
    290295                        MangleTable::const_iterator decl = mangleTable.find( mangleName );
    291                         if ( decl != mangleTable.end() ) return decl->second;
     296                        if ( decl != mangleTable.end() ) return decl->second.id;
    292297                }
    293298
     
    304309                        for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
    305310                                // check for C decls with the same name, skipping those with a compatible type (by mangleName)
    306                                 if ( ! LinkageSpec::isMangled( decl->second->get_linkage() ) && decl->first != mangleName ) return true;
     311                                if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first != mangleName ) return true;
    307312                        }
    308313                }
     
    321326                                // check for C decls with the same name, skipping
    322327                                // those with an incompatible type (by mangleName)
    323                                 if ( ! LinkageSpec::isMangled( decl->second->get_linkage() ) && decl->first == mangleName ) return true;
     328                                if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first == mangleName ) return true;
    324329                        }
    325330                }
     
    403408        }
    404409
    405         void Indexer::addId( DeclarationWithType *decl ) {
     410        void Indexer::addId( DeclarationWithType *decl, Expression * baseExpr ) {
    406411                debugPrint( "Adding Id " << decl->name << std::endl );
    407412                makeWritable();
     
    439444
    440445                // add to indexer
    441                 tables->idTable[ name ][ mangleName ] = decl;
     446                tables->idTable[ name ][ mangleName ] = { decl, baseExpr };
    442447                ++tables->size;
    443448        }
     
    563568                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
    564569                                existing->second = decl;
     570                        }
     571                }
     572        }
     573
     574        void Indexer::addWith( WithStmt * stmt ) {
     575                for ( Expression * expr : stmt->exprs ) {
     576                        if ( expr->result ) {
     577                                AggregateDecl * aggr = expr->result->stripReferences()->getAggr();
     578                                assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() );
     579
     580                                for ( Declaration * decl : aggr->members ) {
     581                                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
     582                                                addId( dwt, expr );
     583                                        }
     584                                }
    565585                        }
    566586                }
     
    645665
    646666        }
     667
     668        Expression * Indexer::IdData::combine() const {
     669                if ( baseExpr ) {
     670                        Expression * base = baseExpr->clone();
     671                        ResolvExpr::referenceToRvalueConversion( base );
     672                        Expression * ret = new MemberExpr( id, base );
     673                        // xxx - this introduces hidden environments, for now remove them.
     674                        // std::swap( base->env, ret->env );
     675                        delete base->env;
     676                        base->env = nullptr;
     677                        return ret;
     678                } else {
     679                        return new VariableExpr( id );
     680                }
     681        }
    647682} // namespace SymTab
    648683
  • src/SymTab/Indexer.h

    r12d2dc8 r65197c2  
    3939                void leaveScope();
    4040
     41                struct IdData {
     42                        DeclarationWithType * id;
     43                        Expression * baseExpr; // WithExpr
     44
     45                        Expression * combine() const;
     46                };
     47
    4148                /// Gets all declarations with the given ID
    42                 void lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const;
     49                void lookupId( const std::string &id, std::list< IdData > &out ) const;
    4350                /// Gets the top-most type declaration with the given ID
    4451                NamedTypeDecl *lookupType( const std::string &id ) const;
     
    6774                TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const;
    6875
    69                 void addId( DeclarationWithType *decl );
     76                void addId( DeclarationWithType *decl, Expression * baseExpr = nullptr );
    7077                void addType( NamedTypeDecl *decl );
    7178                void addStruct( const std::string &id );
     
    7582                void addUnion( UnionDecl *decl );
    7683                void addTrait( TraitDecl *decl );
     84
     85                /// adds all of the IDs from WithStmt exprs
     86                void addWith( WithStmt * );
    7787
    7888                /// convenience function for adding a list of Ids to the indexer
     
    100110                // so that they will not be selected
    101111                // void removeSpecialOverrides( FunctionDecl *decl );
    102                 void removeSpecialOverrides( const std::string &id, std::list< DeclarationWithType * > & out ) const;
     112                void removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const;
    103113
    104114                /// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope)
  • src/SynTree/Mutator.cc

    r12d2dc8 r65197c2  
    203203}
    204204
     205Statement * Mutator::mutate( WithStmt * withStmt ) {
     206        mutateAll( withStmt->exprs, *this );
     207        withStmt->stmt = maybeMutate( withStmt->stmt, *this );
     208        return withStmt;
     209}
     210
    205211NullStmt * Mutator::mutate( NullStmt *nullStmt ) {
    206212        return nullStmt;
  • src/SynTree/Mutator.h

    r12d2dc8 r65197c2  
    5050        virtual Statement * mutate( FinallyStmt * catchStmt );
    5151        virtual Statement * mutate( WaitForStmt * waitforStmt );
     52        virtual Statement * mutate( WithStmt * withStmt );
    5253        virtual NullStmt * mutate( NullStmt * nullStmt );
    5354        virtual Statement * mutate( DeclStmt * declStmt );
  • src/SynTree/ReferenceToType.cc

    r12d2dc8 r65197c2  
    7070bool StructInstType::isComplete() const { return baseStruct ? baseStruct->has_body() : false; }
    7171
     72AggregateDecl * StructInstType::getAggr() { return baseStruct; }
     73
    7274void StructInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
    7375        assert( baseStruct );
     
    101103
    102104bool UnionInstType::isComplete() const { return baseUnion ? baseUnion->has_body() : false; }
     105
     106AggregateDecl * UnionInstType::getAggr() { return baseUnion; }
    103107
    104108void UnionInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
  • src/SynTree/Statement.cc

    r12d2dc8 r65197c2  
    456456}
    457457
     458
     459WithStmt::WithStmt( const std::list< Expression * > & exprs, Statement * stmt ) : Statement(), exprs( exprs ), stmt( stmt ) {}
     460WithStmt::WithStmt( const WithStmt & other ) : Statement( other ), stmt( maybeClone( other.stmt ) ) {
     461        cloneAll( other.exprs, exprs );
     462}
     463WithStmt::~WithStmt() {
     464        deleteAll( exprs );
     465        delete stmt;
     466}
     467
     468void WithStmt::print( std::ostream & os, Indenter indent ) const {
     469        os << "With statement" << endl;
     470        os << indent << "... with statement:" << endl << indent+1;
     471        stmt->print( os, indent+1 );
     472}
     473
     474
    458475NullStmt::NullStmt( const std::list<Label> & labels ) : Statement( labels ) {
    459476}
  • src/SynTree/Statement.h

    r12d2dc8 r65197c2  
    431431};
    432432
     433class WithStmt : public Statement {
     434public:
     435        std::list< Expression * > exprs;
     436        Statement * stmt;
     437
     438        WithStmt( const std::list< Expression * > & exprs, Statement * stmt );
     439        WithStmt( const WithStmt & other );
     440        virtual ~WithStmt();
     441
     442        virtual WithStmt * clone() const override { return new WithStmt( *this ); }
     443        virtual void accept( Visitor & v ) override { v.visit( this ); }
     444        virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
     445        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     446};
     447
    433448
    434449// represents a declaration that occurs as part of a compound statement
  • src/SynTree/SynTree.h

    r12d2dc8 r65197c2  
    5555class FinallyStmt;
    5656class WaitForStmt;
     57class WithStmt;
    5758class NullStmt;
    5859class DeclStmt;
  • src/SynTree/Type.h

    r12d2dc8 r65197c2  
    178178        virtual bool isComplete() const { return true; }
    179179
     180        virtual AggregateDecl * getAggr() {     assertf( false, "Non-aggregate type: %s", toString( this ).c_str() ); }
     181
    180182        virtual Type *clone() const = 0;
    181183        virtual void accept( Visitor & v ) = 0;
     
    405407        virtual bool isComplete() const override;
    406408
     409        virtual AggregateDecl * getAggr() override;
     410
    407411        /// Looks up the members of this struct named "name" and places them into "foundDecls".
    408412        /// Clones declarations into "foundDecls", caller responsible for freeing
     
    436440
    437441        virtual bool isComplete() const override;
     442
     443        virtual AggregateDecl * getAggr() override;
    438444
    439445        /// looks up the members of this union named "name" and places them into "foundDecls"
  • src/SynTree/Visitor.cc

    r12d2dc8 r65197c2  
    174174}
    175175
    176 void Visitor::visit( __attribute__((unused)) NullStmt *nullStmt ) {
     176void Visitor::visit( WithStmt * withStmt ) {
     177        acceptAll( withStmt->exprs, *this );
     178        maybeAccept( withStmt->stmt, *this );
     179}
     180
     181void Visitor::visit( NullStmt * ) {
    177182}
    178183
  • src/SynTree/Visitor.h

    r12d2dc8 r65197c2  
    5252        virtual void visit( FinallyStmt * finallyStmt );
    5353        virtual void visit( WaitForStmt * waitforStmt );
     54        virtual void visit( WithStmt * withStmt );
    5455        virtual void visit( NullStmt * nullStmt );
    5556        virtual void visit( DeclStmt * declStmt );
  • src/tests/.expect/declarationErrors.txt

    r12d2dc8 r65197c2  
    77declarationErrors.c:19:1 error: duplicate static in declaration of x4: static const volatile instance of const volatile struct __anonymous0
    88  with members
     9    i: int
    910   with body
    1011
     
    1213declarationErrors.c:20:1 error: duplicate const, duplicate static, duplicate volatile in declaration of x5: static const volatile instance of const volatile struct __anonymous1
    1314  with members
     15    i: int
    1416   with body
    1517
Note: See TracChangeset for help on using the changeset viewer.