- Timestamp:
- Dec 22, 2016, 4:07:58 PM (8 years ago)
- 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
- Location:
- src
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Specialize.cc
r907eccb r4c8621ac 32 32 #include "Common/utility.h" 33 33 #include "InitTweak/InitTweak.h" 34 #include "Tuples/Tuples.h" 34 35 35 36 namespace GenPoly { … … 211 212 // [begin, end) are the formal parameters. 212 213 // args is the list of arguments currently given to the actual function, the last of which needs to be restructured. 213 template< typename Iterator > 214 void fixLastArg( std::list< Expression * > & args, Iterator begin, Iterator end ) { 215 assertf( ! args.empty(), "Somehow args to tuple function are empty" ); // xxx - it's quite possible this will trigger for the nullary case... 216 Expression * last = args.back(); 214 template< typename Iterator, typename OutIterator > 215 void fixLastArg( Expression * last, Iterator begin, Iterator end, OutIterator out ) { 217 216 // safe_dynamic_cast for the assertion 218 217 safe_dynamic_cast< TupleType * >( last->get_result() ); // xxx - it's quite possible this will trigger for the unary case... 219 args.pop_back(); // replace last argument in the call with220 218 unsigned idx = 0; 221 219 for ( ; begin != end; ++begin ) { 222 220 DeclarationWithType * formal = *begin; 223 221 Type * formalType = formal->get_type(); 224 matchOneFormal( last, idx, formalType, back_inserter( args ));222 matchOneFormal( last, idx, formalType, out ); 225 223 } 226 224 delete last; … … 251 249 252 250 FunctionType * actualType = getFunctionType( actual->get_result() ); 253 std::list< DeclarationWithType * >::iterator begin = actualType->get_parameters().begin(); 254 std::list< DeclarationWithType * >::iterator end = actualType->get_parameters().end(); 255 251 std::list< DeclarationWithType * >::iterator actualBegin = actualType->get_parameters().begin(); 252 std::list< DeclarationWithType * >::iterator actualEnd = actualType->get_parameters().end(); 253 std::list< DeclarationWithType * >::iterator formalBegin = funType->get_parameters().begin(); 254 std::list< DeclarationWithType * >::iterator formalEnd = funType->get_parameters().end(); 255 256 Expression * last = nullptr; 256 257 for ( DeclarationWithType* param : thunkFunc->get_functionType()->get_parameters() ) { 257 258 // walk the parameters to the actual function alongside the parameters to the thunk to find the location where the ttype parameter begins to satisfy parameters in the actual function. 258 assert( begin != end );259 ++begin;260 261 // std::cerr << "thunk param: " << param << std::endl;262 // last param will always be a tuple type... expand it into the actual type(?)263 259 param->set_name( paramNamer.newName() ); 260 assertf( formalBegin != formalEnd, "Reached end of formal parameters before finding ttype parameter" ); 261 if ( Tuples::isTtype((*formalBegin)->get_type()) ) { 262 last = new VariableExpr( param ); 263 break; 264 } 265 assertf( actualBegin != actualEnd, "reached end of actual function's arguments before finding ttype parameter" ); 266 ++actualBegin; 267 ++formalBegin; 268 264 269 appExpr->get_args().push_back( new VariableExpr( param ) ); 265 270 } // for 266 fixLastArg( appExpr->get_args(), --begin, end ); 271 assert( last ); 272 fixLastArg( last, actualBegin, actualEnd, back_inserter( appExpr->get_args() ) ); 267 273 appExpr->set_env( maybeClone( env ) ); 268 274 if ( inferParams ) { -
src/ResolvExpr/AlternativeFinder.cc
r907eccb r4c8621ac 359 359 } 360 360 *out++ = new TupleExpr( exprs ); 361 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) { 362 // xxx - mixing default arguments with variadic?? 363 std::list< Expression * > exprs; 364 for ( ; actualIt != actualEnd; ++actualIt ) { 365 exprs.push_back( actualIt->expr->clone() ); 366 cost += actualIt->cost; 367 } 368 Expression * arg = nullptr; 369 if ( exprs.size() == 1 && Tuples::isTtype( exprs.front()->get_result() ) ) { 370 // the case where a ttype value is passed directly is special, e.g. for argument forwarding purposes 371 // xxx - what if passing multiple arguments, last of which is ttype? 372 // xxx - what would happen if unify was changed so that unifying tuple types flattened both before unifying lists? then pass in TupleType(ttype) below. 373 arg = exprs.front(); 374 } else { 375 arg = new TupleExpr( exprs ); 376 } 377 assert( arg && arg->get_result() ); 378 if ( ! unify( ttype, arg->get_result(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 379 return false; 380 } 381 *out++ = arg; 382 return true; 361 383 } else if ( actualIt != actualEnd ) { 362 if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {363 // xxx - mixing default arguments with variadic??364 if ( ! Tuples::isTtype( actualIt->expr->get_result() ) ) {365 // xxx - what if passing multiple arguments, last of which is ttype?366 367 // consume all remaining arguments, variadic style368 std::list< Expression * > exprs;369 for ( ; actualIt != actualEnd; ++actualIt ) {370 exprs.push_back( actualIt->expr->clone() );371 cost += actualIt->cost;372 }373 TupleExpr * arg = new TupleExpr( exprs );374 assert( arg->get_result() );375 // unification run for side effects376 bool unifyResult = unify( ttype, arg->get_result(), resultEnv, resultNeed, resultHave, openVars, indexer );377 assertf( unifyResult, "Somehow unifying ttype failed..." );378 *out++ = arg;379 return true;380 }381 }382 384 // both actualType and formalType are atomic (non-tuple) types - if they unify 383 385 // then accept actual as an argument, otherwise return false (fail to instantiate argument) -
src/ResolvExpr/Unify.cc
r907eccb r4c8621ac 517 517 } // if 518 518 } // for 519 if ( list1Begin != list1End || list2Begin != list2End ) { 520 return false; 519 // if ( list1Begin != list1End || list2Begin != list2End ) { 520 // return false; 521 if ( list1Begin != list1End ) { 522 // try unifying empty tuple type with ttype 523 Type * t1 = (*list1Begin)->get_type(); 524 if ( Tuples::isTtype( t1 ) ) { 525 Type * combinedType = combineTypes( list2Begin, list2End ); 526 return unifyExact( t1, combinedType, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 527 } else return false; 528 } else if ( list2Begin != list2End ) { 529 // try unifying empty tuple type with ttype 530 Type * t2 = (*list2Begin)->get_type(); 531 if ( Tuples::isTtype( t2 ) ) { 532 Type * combinedType = combineTypes( list1Begin, list1End ); 533 return unifyExact( combinedType, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 534 } else return false; 521 535 } else { 522 536 return true; -
src/Tuples/TupleAssignment.cc
r907eccb r4c8621ac 42 42 private: 43 43 void match(); 44 void handleEmptyTuple( const ResolvExpr::AltList & alts ); 44 45 45 46 struct Matcher { … … 130 131 } 131 132 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 ); 132 142 } 133 143 } … … 248 258 static UniqueName lhsNamer( "__massassign_L" ); 249 259 static UniqueName rhsNamer( "__massassign_R" ); 250 assert ( ! lhs.empty() && rhs.size() <= 1);260 assert( ! lhs.empty() && rhs.size() <= 1 ); 251 261 252 262 ObjectDecl * rtmp = rhs.size() == 1 ? newObject( rhsNamer, rhs.front().expr ) : nullptr; … … 278 288 } 279 289 } 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 } 280 310 } // namespace Tuples 281 311 -
src/Tuples/TupleExpansion.cc
r907eccb r4c8621ac 225 225 decl->get_parameters().push_back( tyParam ); 226 226 } 227 if ( tupleType->size() == 0 ) { 228 // empty structs are not standard C. Add a dummy field to empty tuples to silence warnings when a compound literal Tuple0 is created. 229 decl->get_members().push_back( new ObjectDecl( "dummy", DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) ); 230 } 227 231 typeMap[mangleName] = decl; 228 232 addDeclaration( decl );
Note: See TracChangeset
for help on using the changeset viewer.