Changeset d286cf68 for src/ResolvExpr/Unify.cc
- Timestamp:
- Jun 26, 2018, 5:16:19 PM (6 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, with_gc
- Children:
- 63238a4
- Parents:
- 270fdcf
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
r270fdcf rd286cf68 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 … … 129 129 } 130 130 131 bool isFtype( Type *type ) {132 if ( dynamic_cast< FunctionType* >( type ) ) {133 return true;134 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {135 return typeInst->get_isFtype();136 } // if137 return false;138 }139 140 bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {141 switch ( data.kind ) {142 case TypeDecl::Dtype:143 // to bind to an object type variable, the type must not be a function type.144 // if the type variable is specified to be a complete type then the incoming145 // type must also be complete146 // xxx - should this also check that type is not a tuple type and that it's not a ttype?147 return ! isFtype( type ) && (! data.isComplete || type->isComplete() );148 case TypeDecl::Ftype:149 return isFtype( type );150 case TypeDecl::Ttype:151 // ttype unifies with any tuple type152 return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );153 } // switch154 return false;155 }156 157 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 ) {158 // remove references from other, so that type variables can only bind to value types159 other = other->stripReferences();160 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );161 assert( tyvar != openVars.end() );162 if ( ! tyVarCompatible( tyvar->second, other ) ) {163 return false;164 } // if165 if ( occurs( other, typeInst->get_name(), env ) ) {166 return false;167 } // if168 if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) {169 if ( curClass->type ) {170 Type *common = 0;171 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to172 std::unique_ptr< Type > newType( curClass->type->clone() );173 newType->get_qualifiers() = typeInst->get_qualifiers();174 if ( unifyInexact( newType.get(), other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {175 if ( common ) {176 common->get_qualifiers() = Type::Qualifiers();177 env.add( EqvClass{ *curClass, common } );178 } // if179 return true;180 } else {181 return false;182 } // if183 } else {184 EqvClass newClass { *curClass, other };185 newClass.type->get_qualifiers() = Type::Qualifiers();186 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;187 env.add( std::move(newClass) );188 } // if189 } else {190 EqvClass newClass;191 newClass.vars.insert( typeInst->get_name() );192 newClass.type = other->clone();193 newClass.type->get_qualifiers() = Type::Qualifiers();194 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;195 newClass.data = data;196 env.add( newClass );197 } // if198 return true;199 }200 201 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 ) {202 bool result = true;203 const EqvClass *class1 = env.lookup( var1->get_name() );204 const EqvClass *class2 = env.lookup( var2->get_name() );205 bool widen1 = false, widen2 = false;206 Type *type1 = nullptr, *type2 = nullptr;207 208 if ( class1 ) {209 if ( class1->type ) {210 if ( occurs( class1->type, var2->get_name(), env ) ) {211 return false;212 } // if213 type1 = class1->type->clone();214 } // if215 widen1 = widenMode.widenFirst && class1->allowWidening;216 } // if217 if ( class2 ) {218 if ( class2->type ) {219 if ( occurs( class2->type, var1->get_name(), env ) ) {220 return false;221 } // if222 type2 = class2->type->clone();223 } // if224 widen2 = widenMode.widenSecond && class2->allowWidening;225 } // if226 227 if ( type1 && type2 ) {228 // std::cerr << "has type1 && type2" << std::endl;229 WidenMode newWidenMode ( widen1, widen2 );230 Type *common = 0;231 if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {232 EqvClass newClass1 = *class1;233 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );234 newClass1.allowWidening = widen1 && widen2;235 if ( common ) {236 common->get_qualifiers() = Type::Qualifiers();237 delete newClass1.type;238 newClass1.type = common;239 } // if240 env.add( std::move(newClass1) );241 } else {242 result = false;243 } // if244 } else if ( class1 && class2 ) {245 if ( type1 ) {246 EqvClass newClass1 = *class1;247 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );248 newClass1.allowWidening = widen1;249 env.add( std::move(newClass1) );250 } else {251 EqvClass newClass2 = *class2;252 newClass2.vars.insert( class1->vars.begin(), class1->vars.end() );253 newClass2.allowWidening = widen2;254 env.add( std::move(newClass2) );255 } // if256 } else if ( class1 ) {257 EqvClass newClass1 = *class1;258 newClass1.vars.insert( var2->get_name() );259 newClass1.allowWidening = widen1;260 env.add( std::move(newClass1) );261 } else if ( class2 ) {262 EqvClass newClass2 = *class2;263 newClass2.vars.insert( var1->get_name() );264 newClass2.allowWidening = widen2;265 env.add( std::move(newClass2) );266 } else {267 EqvClass newClass;268 newClass.vars.insert( var1->get_name() );269 newClass.vars.insert( var2->get_name() );270 newClass.allowWidening = widen1 && widen2;271 newClass.data = data;272 env.add( newClass );273 } // if274 delete type1;275 delete type2;276 return result;277 }278 279 131 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 280 132 OpenVarSet closedVars; … … 321 173 322 174 if ( isopen1 && isopen2 && entry1->second == entry2->second ) { 323 result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );175 result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 324 176 } else if ( isopen1 ) { 325 result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );177 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 326 178 } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped? 327 result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );179 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 328 180 } else { 329 181 PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
Note: See TracChangeset
for help on using the changeset viewer.