Ignore:
Timestamp:
Dec 22, 2016, 4:07:58 PM (7 years ago)
Author:
Rob Schluntz <rschlunt@…>
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:
1e3d5b6
Parents:
907eccb
Message:

allow construction, destruction, and assignment for empty tuples, allow matching a ttype parameter with an empty tuple, fix specialization to work with empty tuples and void functions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleAssignment.cc

    r907eccb r4c8621ac  
    4242          private:
    4343                void match();
     44                void handleEmptyTuple( const ResolvExpr::AltList & alts );
    4445
    4546                struct Matcher {
     
    130131                                                }
    131132                                                match();
     133                                        } else {
     134                                                // handle empty case specially. It is easy to cause conflicts for tuple assignment when we consider any expression with Tuple type to be a tuple.
     135                                                // Instead, only tuple expressions and expressions with at least 2 results are considered tuples for tuple assignment. This most obviously leaves out the
     136                                                // nullary and unary cases. The unary case is handled nicely by the alternative finder as is. For example, an expression of type [int] will be exploded
     137                                                // into a list of one element (combined with the RHS elements), which will easily allow for intrinsic construction. This seems like a best case scenario anyway,
     138                                                // since intrinsic construction is much simpler from a code-gen perspective than tuple construction is.
     139                                                // This leaves the empty case, which is not easily handled by existing alternative finder logic. Instead, it seems simple enough to hanlde here that if the left
     140                                                // side is an empty tuple, then the right side is allowed to be either an empty tuple or an empty list. Fortunately, these cases are identical when exploded.
     141                                                handleEmptyTuple( *ali );
    132142                                        }
    133143                                }
     
    248258                static UniqueName lhsNamer( "__massassign_L" );
    249259                static UniqueName rhsNamer( "__massassign_R" );
    250                 assert ( ! lhs.empty() && rhs.size() <= 1);
     260                assert( ! lhs.empty() && rhs.size() <= 1 );
    251261
    252262                ObjectDecl * rtmp = rhs.size() == 1 ? newObject( rhsNamer, rhs.front().expr ) : nullptr;
     
    278288                }
    279289        }
     290
     291        // empty case is okay when right side is also "empty" (empty explosion handles no argument case as well as empty tuple case)
     292        void TupleAssignSpotter::handleEmptyTuple( const ResolvExpr::AltList & alts ) {
     293                assert( ! alts.empty() );
     294                Expression * lhs = alts.front().expr;
     295                if ( PointerType * ptrType = dynamic_cast< PointerType * >( lhs->get_result() ) ) {
     296                        if ( TupleType * tupleType = dynamic_cast< TupleType * >( ptrType->get_base() ) ) {
     297                                if ( tupleType->size() == 0 ) {
     298                                        ResolvExpr::AltList rhs;
     299                                        explode( std::next(alts.begin(), 1), alts.end(), currentFinder.get_indexer(), back_inserter(rhs) );
     300                                        if ( rhs.empty() ) {
     301                                                // okay, no other case is allowed
     302                                                ResolvExpr::TypeEnvironment compositeEnv;
     303                                                simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
     304                                                currentFinder.get_alternatives().push_front( ResolvExpr::Alternative( new TupleAssignExpr( std::list< Expression * >(), std::list< ObjectDecl * >() ), compositeEnv, ResolvExpr::sumCost( alts ) ) );
     305                                        }
     306                                }
     307                        }
     308                }
     309        }
    280310} // namespace Tuples
    281311
Note: See TracChangeset for help on using the changeset viewer.