#include #include "InferContext.h" #include "QualSolver.h" #include "StaleBindings.h" void TreeListNode::constrainCall( const TypeListNode &formal, QualSolver &solver ) const { assert( arity() == formal.arity() ); for (unsigned sweep = formal.arity(); sweep--; ) child( sweep )->type()->weaklySubsumedBy( *formal.child( sweep ), solver ); } void TreeNode::constrainCall( const TypeNode &callee, QualSolver &solver ) const { args()->constrainCall( *callee.paramTypes(), solver ); } //////////////////////////////////////////////////////////////////////// void MethodCallAssignNode::infer( const InferContext &context ) { TreeNode *lhs; if (isRewrittenRHSOpOverload()) lhs = args()->child(0); else lhs = method()->object(); const TypeNode &dispatcher = *method()->accessedObjectType(); context.solver.subsumedBy( dispatcher, *method()->decl()->type() ); const TypeNode &target = *method()->type(); constrainCall( target, context.solver ); type()->identicalTo( *lhs->type(), context.solver ); target.returnType()->weaklySubsumedBy( *lhs->type(), context.solver ); } void MethodCallNode::infer( const InferContext &context ) { const TypeNode &dispatcher = *method()->accessedObjectType(); const TypeNode &target = *method()->type(); if (dispatcher.isTitaniumArrayType()) { // arity(), domain(), isLocal(), isContiguous(), creator(), regionOf() if( args()->arity() == 0 ) { type()->identicalTo( *target.returnType(), context.solver ); // PR655 return; } const string * const name = decl()->name(); const TypeNode &element = *dispatcher.elementType(); static const string * const copy = intern( "copy" ); if (name == copy) { assert( args()->arity() == 1 || args()->arity() == 2 ); const TypeNode &donor = *args()->child( 0 )->type(); donor.elementType()->identicalTo( element, context.solver ); type()->identicalTo( *target.returnType(), context.solver ); context.stale.push_back( this ); return; } static const string * const scatter = intern( "scatter" ); static const string * const gather = intern( "gather" ); if (name == scatter || name == gather) { assert( args()->arity() == 2 ); const TypeNode &packedArray = *args()->child( 0 )->type(); packedArray.elementType()->identicalTo( element, context.solver ); context.stale.push_back( this ); return; } static const string * const exchange = intern( "exchange" ); if (name == exchange) { assert( args()->arity() == 1 ); const TypeNode &donation = *args()->child( 0 )->type(); donation.weaklySubsumedBy( element, context.solver ); type()->identicalTo( *target.returnType(), context.solver ); context.stale.push_back( this ); return; } static const string * const inject = intern( "inject" ); static const string * const permute = intern( "permute" ); static const string * const project = intern( "project" ); static const string * const restr = intern( "restrict" ); static const string * const slice = intern( "slice" ); static const string * const translate = intern( "translate" ); if (name == inject || name == permute || name == project || name == restr || name == slice || name == translate) { type()->identicalTo( dispatcher, context.solver ); context.stale.push_back( this ); return; } } context.solver.subsumedBy( dispatcher, *method()->decl()->type() ); constrainCall( target, context.solver ); type()->identicalTo( *target.returnType(), context.solver ); } void SuperConstructorCallNode::infer( const InferContext &context ) { constrainCall( *decl()->type(), context.solver ); } void ThisConstructorCallNode::infer( const InferContext &context ) { constrainCall( *decl()->type(), context.solver ); }