Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    rbd4f2e9 r0a60c04  
    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 );
     
    369372                if ( throwStmt->get_expr() ) {
    370373                        StructDecl * exception_decl =
    371                                 indexer.lookupStruct( "__cfaehm__base_exception_t" );
     374                                indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" );
    372375                        assert( exception_decl );
    373376                        Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl ) );
     
    568571                        findSingleExpression( stmt->orelse.condition, this->indexer );
    569572                        stmt->orelse.statement->accept( *visitor );
     573                }
     574        }
     575
     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                        }
    570628                }
    571629        }
Note: See TracChangeset for help on using the changeset viewer.