bool asCModule::CanDeleteAllReferences(asCArray<asCModule*> &modules) { if( !isDiscarded ) return false; if( contextCount ) return false; modules.PushLast(this); // Check all bound functions for referenced modules for( asUINT n = 0; n < bindInformations.GetLength(); n++ ) { int funcID = bindInformations[n].importedFunction; asCModule *module = engine->GetModule(funcID); // If the module is already in the list don't check it again bool inList = false; for( asUINT m = 0; m < modules.GetLength(); m++ ) { if( modules[m] == module ) { inList = true; break; } } if( !inList ) { bool ret = module->CanDeleteAllReferences(modules); if( ret == false ) return false; } } // If no module has external references then all can be deleted return true; }
// internal bool asCModule::AreTypesEqual(const asCDataType &a, const asCDataType &b, asCArray<sObjectTypePair> &equals) { if( !a.IsEqualExceptInterfaceType(b) ) return false; asCObjectType *ai = a.GetObjectType(); asCObjectType *bi = b.GetObjectType(); if( ai && ai->IsInterface() ) { // If the interface is in the equals list, then the pair must match the pair in the list bool found = false; unsigned int e; for( e = 0; e < equals.GetLength(); e++ ) { if( equals[e].a == ai ) { found = true; break; } } if( found ) { // Do the pairs match? if( equals[e].b != bi ) return false; } else { // Assume they are equal from now on sObjectTypePair pair = {ai, bi}; equals.PushLast(pair); } } return true; }
// internal bool asCModule::AreInterfacesEqual(asCObjectType *a, asCObjectType *b, asCArray<sObjectTypePair> &equals) { // An interface is considered equal to another if the following criterias apply: // // - The interface names are equal // - The number of methods is equal // - All the methods are equal // - The order of the methods is equal // - If a method returns or takes an interface by handle or reference, both interfaces must be equal // ------------ // TODO: Study the possiblity of allowing interfaces where methods are declared in different orders to // be considered equal. The compiler and VM can handle this, but it complicates the comparison of interfaces // where multiple methods take different interfaces as parameters (or return values). Example: // // interface A // { // void f(B, C); // void f(B); // void f(C); // } // // If 'void f(B)' in module A is compared against 'void f(C)' in module B, then the code will assume // interface B in module A equals interface C in module B. Thus 'void f(B, C)' in module A won't match // 'void f(C, B)' in module B. // ------------ // Are both interfaces? if( !a->IsInterface() || !b->IsInterface() ) return false; // Are the names equal? if( a->name != b->name ) return false; // Are the number of methods equal? if( a->methods.GetLength() != b->methods.GetLength() ) return false; // Keep the number of equals in the list so we can restore it later if necessary int prevEquals = (int)equals.GetLength(); // Are the methods equal to each other? bool match = true; for( unsigned int n = 0; n < a->methods.GetLength(); n++ ) { match = false; asCScriptFunction *funcA = (asCScriptFunction*)engine->GetFunctionDescriptorById(a->methods[n]); asCScriptFunction *funcB = (asCScriptFunction*)engine->GetFunctionDescriptorById(b->methods[n]); // funcB can be null if the module that created the interface has been // discarded but the type has not yet been released by the engine. if( funcB == 0 ) break; // The methods must have the same name and the same number of parameters if( funcA->name != funcB->name || funcA->parameterTypes.GetLength() != funcB->parameterTypes.GetLength() ) break; // The return types must be equal. If the return type is an interface the interfaces must match. if( !AreTypesEqual(funcA->returnType, funcB->returnType, equals) ) break; match = true; for( unsigned int p = 0; p < funcA->parameterTypes.GetLength(); p++ ) { if( !AreTypesEqual(funcA->parameterTypes[p], funcB->parameterTypes[p], equals) || funcA->inOutFlags[p] != funcB->inOutFlags[p] ) { match = false; break; } } if( !match ) break; } // For each of the new interfaces that we're assuming to be equal, we need to validate this if( match ) { for( unsigned int n = prevEquals; n < equals.GetLength(); n++ ) { if( !AreInterfacesEqual(equals[n].a, equals[n].b, equals) ) { match = false; break; } } } if( !match ) { // The interfaces doesn't match. // Restore the list of previous equals before we go on, so // the caller can continue comparing with another interface equals.SetLength(prevEquals); } return match; }