Changeset 28f3a19 for src/ResolvExpr/Unify.cc
- Timestamp:
- Jun 27, 2018, 3:28:41 PM (6 years ago)
- Branches:
- new-env, with_gc
- Children:
- b21c77a
- Parents:
- 0182bfa (diff), 63238a4 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
r0182bfa r28f3a19 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:27:10 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Mar 16 16:22:54 201713 // Update Count : 4 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 18 11:58:00 2018 13 // Update Count : 43 14 14 // 15 15 … … 122 122 } 123 123 124 bool isFtype( Type *type ) {125 if ( dynamic_cast< FunctionType* >( type ) ) {126 return true;127 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {128 return typeInst->get_isFtype();129 } // if130 return false;131 }132 133 bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {134 switch ( data.kind ) {135 case TypeDecl::Dtype:136 // to bind to an object type variable, the type must not be a function type.137 // if the type variable is specified to be a complete type then the incoming138 // type must also be complete139 // xxx - should this also check that type is not a tuple type and that it's not a ttype?140 return ! isFtype( type ) && (! data.isComplete || type->isComplete() );141 case TypeDecl::Ftype:142 return isFtype( type );143 case TypeDecl::Ttype:144 // ttype unifies with any tuple type145 return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );146 } // switch147 return false;148 }149 150 bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {151 // remove references from other, so that type variables can only bind to value types152 other = other->stripReferences();153 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );154 assert( tyvar != openVars.end() );155 if ( ! tyVarCompatible( tyvar->second, other ) ) {156 return false;157 } // if158 if ( occurs( other, typeInst->get_name(), env ) ) {159 return false;160 } // if161 if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) {162 if ( curClass->type ) {163 Type *common = 0;164 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to165 Type* newType = curClass->type->clone();166 newType->get_qualifiers() = typeInst->get_qualifiers();167 if ( unifyInexact( newType, other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {168 if ( common ) {169 common->get_qualifiers() = Type::Qualifiers();170 EqvClass newClass = *curClass;171 newClass.type = common;172 env.add( std::move(newClass) );173 } // if174 return true;175 } else {176 return false;177 } // if178 } else {179 EqvClass newClass = *curClass;180 newClass.type = other->clone();181 newClass.type->get_qualifiers() = Type::Qualifiers();182 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;183 env.add( std::move(newClass) );184 } // if185 } else {186 EqvClass newClass;187 newClass.vars.insert( typeInst->get_name() );188 newClass.type = other->clone();189 newClass.type->get_qualifiers() = Type::Qualifiers();190 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;191 newClass.data = data;192 env.add( newClass );193 } // if194 return true;195 }196 197 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {198 bool result = true;199 const EqvClass *class1 = env.lookup( var1->get_name() );200 const EqvClass *class2 = env.lookup( var2->get_name() );201 bool widen1 = false, widen2 = false;202 Type *type1 = nullptr, *type2 = nullptr;203 204 if ( class1 ) {205 if ( class1->type ) {206 if ( occurs( class1->type, var2->get_name(), env ) ) {207 return false;208 } // if209 type1 = class1->type->clone();210 } // if211 widen1 = widenMode.widenFirst && class1->allowWidening;212 } // if213 if ( class2 ) {214 if ( class2->type ) {215 if ( occurs( class2->type, var1->get_name(), env ) ) {216 return false;217 } // if218 type2 = class2->type->clone();219 } // if220 widen2 = widenMode.widenSecond && class2->allowWidening;221 } // if222 223 if ( type1 && type2 ) {224 // std::cerr << "has type1 && type2" << std::endl;225 WidenMode newWidenMode ( widen1, widen2 );226 Type *common = 0;227 if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {228 EqvClass newClass1 = *class1;229 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );230 newClass1.allowWidening = widen1 && widen2;231 if ( common ) {232 common->get_qualifiers() = Type::Qualifiers();233 newClass1.type = common;234 } // if235 env.add( std::move(newClass1) );236 } else {237 result = false;238 } // if239 } else if ( class1 && class2 ) {240 if ( type1 ) {241 EqvClass newClass1 = *class1;242 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );243 newClass1.allowWidening = widen1;244 env.add( std::move(newClass1) );245 } else {246 EqvClass newClass2 = *class2;247 newClass2.vars.insert( class1->vars.begin(), class1->vars.end() );248 newClass2.allowWidening = widen2;249 env.add( std::move(newClass2) );250 } // if251 } else if ( class1 ) {252 EqvClass newClass1 = *class1;253 newClass1.vars.insert( var2->get_name() );254 newClass1.allowWidening = widen1;255 env.add( std::move(newClass1) );256 } else if ( class2 ) {257 EqvClass newClass2 = *class2;258 newClass2.vars.insert( var1->get_name() );259 newClass2.allowWidening = widen2;260 env.add( std::move(newClass2) );261 } else {262 EqvClass newClass;263 newClass.vars.insert( var1->get_name() );264 newClass.vars.insert( var2->get_name() );265 newClass.allowWidening = widen1 && widen2;266 newClass.data = data;267 env.add( newClass );268 } // if269 return result;270 }271 272 124 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 273 125 OpenVarSet closedVars; … … 307 159 308 160 if ( isopen1 && isopen2 && entry1->second == entry2->second ) { 309 result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );161 result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 310 162 } else if ( isopen1 ) { 311 result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );163 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 312 164 } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped? 313 result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );165 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 314 166 } else { 315 167 PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
Note: See TracChangeset
for help on using the changeset viewer.