Ignore:
Timestamp:
Jun 17, 2019, 3:55:21 PM (5 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
e6faef4
Parents:
6e55240
Message:

Implemented new versions of Tuples/Explode?.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/Explode.h

    r6e55240 rb910d15  
    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
     
    138138        }
    139139
     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 * expr, const ResolvExpr::Candidate & arg,
     177        const ast::SymbolTable & symtab, Output && out
     178) {
     179}
     180
    140181/// helper function used by explode
    141182template< typename Output >
    142 void explodeUnique( 
    143         const ast::Expr * expr, const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab,
    144         Output && out, bool isTupleAssign
     183void explodeUnique(
     184        const ast::ptr< ast::Expr > & expr, const ResolvExpr::Candidate & arg,
     185        const ast::SymbolTable & symtab, Output && out, bool isTupleAssign
    145186) {
    146         #warning unimplemented
    147         (void)expr; (void)arg; (void)symtab; (void)out; (void)isTupleAssign;
    148         assert(false);
     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->location, 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        }
    149229}
    150230
    151231/// expands a tuple-valued candidate into multiple candidates, each with a non-tuple type
    152232template< typename Output >
    153 void explode( 
    154         const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out, 
     233void explode(
     234        const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out,
    155235        bool isTupleAssign = false
    156236) {
Note: See TracChangeset for help on using the changeset viewer.