Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/Explode.h

    r490ff5c3 r7870799  
    99// Author           : Rob Schluntz
    1010// Created On       : Wed Nov 9 13:12:24 2016
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:55:16 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun 17 14:36:00 2019
     13// Update Count     : 4
    1414//
    1515
     
    1919#include <utility>                      // for forward
    2020
     21#include "AST/Expr.hpp"
    2122#include "ResolvExpr/Alternative.h"     // for Alternative, AltList
     23#include "ResolvExpr/Candidate.hpp"     // for Candidate, CandidateList
    2224#include "ResolvExpr/ExplodedActual.h"  // for ExplodedActual
     25#include "ResolvExpr/ExplodedArg.hpp"   // for ExplodedArg
    2326#include "SynTree/Expression.h"         // for Expression, UniqueExpr, AddressExpr
    2427#include "SynTree/Type.h"               // for TupleType, Type
    2528#include "Tuples.h"                     // for maybeImpure
     29
     30namespace ast {
     31        class SymbolTable;
     32}
    2633
    2734namespace SymTab {
     
    4451        template<typename OutputIterator>
    4552        void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
     53                        const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need,
    4654                        const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
    47                 *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };
     55                *out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost };
    4856        }
    4957
    5058        /// Append alternative to an ExplodedActual
    5159        static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,
    52                         const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
     60                        const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&,
     61                        const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
    5362                ea.exprs.emplace_back( expr );
    54                 /// xxx -- merge environment, cost?
     63                /// xxx -- merge environment, openVars, need, cost?
    5564        }
    5665
     
    6877                                        // distribute reference cast over all components
    6978                                        append( std::forward<Output>(out), distributeReference( alt.release_expr() ),
    70                                                 alt.env, alt.cost, alt.cvtCost );
     79                                                alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost );
    7180                                }
    7281                                // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives)
     
    102111                } else {
    103112                        // atomic (non-tuple) type - output a clone of the expression in a new alternative
    104                         append( std::forward<Output>(out), expr->clone(), alt.env, alt.cost, alt.cvtCost );
     113                        append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need,
     114                                alt.cost, alt.cvtCost );
    105115                }
    106116        }
     
    127137                explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign );
    128138        }
     139
     140const ast::Expr * distributeReference( const ast::Expr * );
     141
     142/// Append candidate to an OutputIterator of Candidates.
     143template<typename OutputIterator>
     144void append( OutputIterator out, const ast::Expr * expr, const ast::TypeEnvironment & env,
     145                const ast::OpenVarSet & open, const ast::AssertionList & need,
     146                const ResolvExpr::Cost & cost, const ResolvExpr::Cost & cvtCost ) {
     147        ast::TypeEnvironment copyEnv = env;
     148        ast::OpenVarSet copyOpen = open;
     149        ast::AssertionSet set;
     150        mergeAssertionSet( set, need );
     151        *out++ = std::make_shared<ResolvExpr::Candidate>( expr, std::move( copyEnv ),
     152                std::move( copyOpen ), std::move( set ), cost, cvtCost );
     153}
     154
     155/// Append candidate to an ExplodedArg.
     156static inline void append( ResolvExpr::ExplodedArg& ea, const ast::Expr * expr,
     157                const ast::TypeEnvironment&, const ast::OpenVarSet&,
     158                const ast::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
     159        // I'm not sure why most of the arguments are unused. But they were in the old version.
     160        ea.exprs.emplace_back( expr );
     161}
     162
     163/// Check if the expression is a cast to a reference type, return it if it is.
     164static inline const ast::CastExpr * isReferenceCast( const ast::Expr * expr ) {
     165        if ( const ast::CastExpr * cast = dynamic_cast< const ast::CastExpr * >( expr ) ) {
     166                if ( dynamic_cast< const ast::ReferenceType * >( cast->result.get() ) ) {
     167                        return cast;
     168                }
     169        }
     170        return nullptr;
     171}
     172
     173/// helper function (indirectely) used by explode
     174template< typename Output >
     175void explodeRecursive(
     176        const ast::CastExpr *, const ResolvExpr::Candidate &,
     177        const ast::SymbolTable &, Output &&
     178) {
     179}
     180
     181/// helper function used by explode
     182template< typename Output >
     183void explodeUnique(
     184        const ast::ptr< ast::Expr > & expr, const ResolvExpr::Candidate & arg,
     185        const ast::SymbolTable & symtab, Output && out, bool isTupleAssign
     186) {
     187        // Tuple assignment can use a faster method if it is cast. Uses recursive exploding.
     188        if ( isTupleAssign ) if ( const ast::CastExpr * castExpr = isReferenceCast( expr ) ) {
     189                ResolvExpr::CandidateList candidates;
     190                explodeUnique( castExpr->arg, arg, symtab, back_inserter( candidates ), true );
     191                for ( ResolvExpr::CandidateRef & cand : candidates ) {
     192                        // Distribute the reference cast over all components of the candidate.
     193                        append( std::forward<Output>(out), distributeReference( cand->expr ), cand->env,
     194                                cand->open, cand->need, cand->cost, cand->cvtCost );
     195                }
     196                return;
     197        }
     198        const ast::Type * res = expr->result->stripReferences();
     199        if ( const ast::TupleType * tupleType = dynamic_cast< const ast::TupleType * >( res ) ) {
     200                if ( const ast::ptr< ast::TupleExpr > & tupleExpr = expr.as< ast::TupleExpr >() ) {
     201                        // Open the tuple expr and continue on its components.
     202                        for ( const ast::Expr * expr : tupleExpr->exprs ) {
     203                                explodeUnique( expr, arg, symtab, std::forward<Output>(out), isTupleAssign );
     204                        }
     205                } else {
     206                        ast::ptr< ast::Expr > local = expr;
     207                        // Expressions which may have side effects require a single unique instance.
     208                        if ( Tuples::maybeImpureIgnoreUnique( local ) ) {
     209                                local = new ast::UniqueExpr( local->location, local );
     210                        }
     211                        // Cast a reference away to a value-type to allow further explosion.
     212                        if ( dynamic_cast< const ast::ReferenceType *>( local->result.get() ) ) {
     213                                local = new ast::CastExpr{ local, tupleType };
     214                        }
     215                        // Now we have to go across the tuple via indexing.
     216                        for ( unsigned int i = 0 ; i < tupleType->size() ; ++i ) {
     217                                ast::TupleIndexExpr * idx = new ast::TupleIndexExpr( local->location, local, i );
     218                                explodeUnique( idx, arg, symtab, std::forward<Output>(out), isTupleAssign );
     219                                // TODO: We need more input to figure out the exact lifetimes of these types.
     220                                // delete idx;
     221                        }
     222                        // delete local;
     223                }
     224        } else {
     225                // For atomic/non-tuple types, no explosion is used.
     226                append( std::forward<Output>(out), expr, arg.env, arg.open, arg.need, arg.cost,
     227                        arg.cvtCost );
     228        }
     229}
     230
     231/// expands a tuple-valued candidate into multiple candidates, each with a non-tuple type
     232template< typename Output >
     233void explode(
     234        const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out,
     235        bool isTupleAssign = false
     236) {
     237        explodeUnique( arg.expr, arg, symtab, std::forward< Output >( out ), isTupleAssign );
     238}
     239
     240/// explode list of candidates into flattened list of candidates
     241template< typename Output >
     242void explode(
     243        const ResolvExpr::CandidateList & cands, const ast::SymbolTable & symtab, Output && out,
     244        bool isTupleAssign = false
     245) {
     246        for ( const ResolvExpr::CandidateRef & cand : cands ) {
     247                explode( *cand, symtab, std::forward< Output >( out ), isTupleAssign );
     248        }
     249}
     250
    129251} // namespace Tuples
    130252
Note: See TracChangeset for help on using the changeset viewer.