Ignore:
Timestamp:
Dec 5, 2017, 2:17:17 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, 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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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 ) {
Note: See TracChangeset for help on using the changeset viewer.