1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-11 04:52:21 +02:00

Added 'visibleProjectSet', changed visibility rules for generics

This commit is contained in:
Brian Fiete 2020-07-01 12:06:28 -07:00
parent 6021518343
commit 75dd1a4213
6 changed files with 100 additions and 25 deletions

View file

@ -612,11 +612,6 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
bool prevChainSkip = (prevMethodInstance->mChainType == BfMethodChainType_ChainMember) || (prevMethodInstance->mChainType == BfMethodChainType_ChainSkip); bool prevChainSkip = (prevMethodInstance->mChainType == BfMethodChainType_ChainMember) || (prevMethodInstance->mChainType == BfMethodChainType_ChainSkip);
RETURN_BETTER_OR_WORSE(!chainSkip, !prevChainSkip); RETURN_BETTER_OR_WORSE(!chainSkip, !prevChainSkip);
// If one of these methods is local to the current extension then choose that one
auto activeDef = mModule->GetActiveTypeDef();
RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType == activeDef, prevMethodDef->mDeclaringType == activeDef);
RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType->IsExtension(), prevMethodDef->mDeclaringType->IsExtension());
if ((!isBetter) && (!isWorse)) if ((!isBetter) && (!isWorse))
{ {
bool betterByGenericParam = false; bool betterByGenericParam = false;
@ -948,6 +943,11 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
RETURN_BETTER_OR_WORSE(newMethodDef->mCheckedKind == mCheckedKind, prevMethodDef->mCheckedKind == mCheckedKind); RETURN_BETTER_OR_WORSE(newMethodDef->mCheckedKind == mCheckedKind, prevMethodDef->mCheckedKind == mCheckedKind);
RETURN_BETTER_OR_WORSE(newMethodDef->mCommutableKind != BfCommutableKind_Reverse, prevMethodDef->mCommutableKind != BfCommutableKind_Reverse); RETURN_BETTER_OR_WORSE(newMethodDef->mCommutableKind != BfCommutableKind_Reverse, prevMethodDef->mCommutableKind != BfCommutableKind_Reverse);
// If one of these methods is local to the current extension then choose that one
auto activeDef = mModule->GetActiveTypeDef();
RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType == activeDef, prevMethodDef->mDeclaringType == activeDef);
RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType->IsExtension(), prevMethodDef->mDeclaringType->IsExtension());
RETURN_RESULTS; RETURN_RESULTS;
} }
@ -1878,6 +1878,11 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
int checkInterfaceIdx = 0; int checkInterfaceIdx = 0;
if (mMethodName == "Handle")
{
NOP;
}
bool targetIsBase = target.IsBase(); bool targetIsBase = target.IsBase();
bool checkExtensionBase = false; bool checkExtensionBase = false;
if (targetIsBase) if (targetIsBase)
@ -1915,6 +1920,7 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
{ {
bool allowExplicitInterface = curTypeInst->IsInterface() && mBypassVirtual; bool allowExplicitInterface = curTypeInst->IsInterface() && mBypassVirtual;
auto activeTypeDef = mModule->GetActiveTypeDef(); auto activeTypeDef = mModule->GetActiveTypeDef();
auto visibleProjectSet = mModule->GetVisibleProjectSet();
bool isDelegate = typeInstance->IsDelegate(); bool isDelegate = typeInstance->IsDelegate();
auto checkMethod = nextMethodDef; auto checkMethod = nextMethodDef;
@ -1970,7 +1976,7 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
if (!isDelegate) if (!isDelegate)
{ {
if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) || if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) ||
(!curTypeInst->IsTypeMemberAccessible(checkMethod->mDeclaringType, activeTypeDef))) (!curTypeInst->IsTypeMemberAccessible(checkMethod->mDeclaringType, visibleProjectSet)))
continue; continue;
} }
@ -5353,9 +5359,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (!target) if (!target)
{ {
FinishDeferredEvals(argValues); FinishDeferredEvals(argValues);
mModule->Fail(StrFormat("An instance reference is required to %s the non-static method '%s'", auto error = mModule->Fail(StrFormat("An instance reference is required to %s the non-static method '%s'",
(prevBindResult.mPrevVal != NULL) ? "bind" : "invoke", (prevBindResult.mPrevVal != NULL) ? "bind" : "invoke",
mModule->MethodToString(methodInstance).c_str()), targetSrc); mModule->MethodToString(methodInstance).c_str()), targetSrc);
if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
return mModule->GetDefaultTypedValue(returnType); return mModule->GetDefaultTypedValue(returnType);
} }
@ -6023,6 +6031,7 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
BfProtectionCheckFlags protectionCheckFlags = BfProtectionCheckFlag_None; BfProtectionCheckFlags protectionCheckFlags = BfProtectionCheckFlag_None;
auto activeTypeDef = mModule->GetActiveTypeDef(); auto activeTypeDef = mModule->GetActiveTypeDef();
auto visibleProjectSet = mModule->GetVisibleProjectSet();
bool isFailurePass = false; bool isFailurePass = false;
for (int pass = 0; pass < 2; pass++) for (int pass = 0; pass < 2; pass++)
{ {
@ -6047,7 +6056,7 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
if (!mModule->IsInSpecializedSection()) if (!mModule->IsInSpecializedSection())
{ {
if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) || if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) ||
(!curTypeInst->IsTypeMemberAccessible(checkMethod->mDeclaringType, activeTypeDef))) (!curTypeInst->IsTypeMemberAccessible(checkMethod->mDeclaringType, visibleProjectSet)))
continue; continue;
} }
@ -7252,9 +7261,6 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
isFailurePass = false; isFailurePass = false;
curTypeInst = methodMatcher.mBestMethodTypeInstance; curTypeInst = methodMatcher.mBestMethodTypeInstance;
methodDef = methodMatcher.mBestMethodDef; methodDef = methodMatcher.mBestMethodDef;
// Extension check must check all possible extensions, no early bailout
if (!wantsExtensionCheck)
break;
} }
} }
} }
@ -7274,9 +7280,6 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
isFailurePass = false; isFailurePass = false;
curTypeInst = methodMatcher.mBestMethodTypeInstance; curTypeInst = methodMatcher.mBestMethodTypeInstance;
methodDef = methodMatcher.mBestMethodDef; methodDef = methodMatcher.mBestMethodDef;
// Extension check must check all possible extensions, no early bailout
if (!wantsExtensionCheck)
break;
} }
} }
} }
@ -13324,16 +13327,20 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
if (!target) if (!target)
{ {
mModule->Fail(StrFormat("An instance reference is required to invoke the non-static mixin '%s'", BfError* error = mModule->Fail(StrFormat("An instance reference is required to invoke the non-static mixin '%s'",
mModule->MethodToString(methodInstance).c_str()), targetSrc); mModule->MethodToString(methodInstance).c_str()), targetSrc);
if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
} }
} }
else else
{ {
if (target) if (target)
{ {
mModule->Fail(StrFormat("Mixin '%s' cannot be accessed with an instance reference; qualify it with a type name instead", BfError* error = mModule->Fail(StrFormat("Mixin '%s' cannot be accessed with an instance reference; qualify it with a type name instead",
mModule->MethodToString(methodInstance).c_str()), targetSrc); mModule->MethodToString(methodInstance).c_str()), targetSrc);
if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
} }
} }
@ -13354,14 +13361,14 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
if ((int)args.size() < explicitParamCount) if ((int)args.size() < explicitParamCount)
{ {
BfError* error = mModule->Fail(StrFormat("Not enough arguments specified, expected %d more.", explicitParamCount - (int)arguments.size()), targetSrc); BfError* error = mModule->Fail(StrFormat("Not enough arguments specified, expected %d more.", explicitParamCount - (int)arguments.size()), targetSrc);
if ((error != NULL) && (methodInstance->mMethodDef->mMethodDeclaration != NULL)) if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode()); mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
return; return;
} }
else if ((int)args.size() > explicitParamCount) else if ((int)args.size() > explicitParamCount)
{ {
BfError* error = mModule->Fail(StrFormat("Too many arguments specified, expected %d fewer.", (int)arguments.size() - explicitParamCount), targetSrc); BfError* error = mModule->Fail(StrFormat("Too many arguments specified, expected %d fewer.", (int)arguments.size() - explicitParamCount), targetSrc);
if ((error != NULL) && (methodInstance->mMethodDef->mMethodDeclaration != NULL)) if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode()); mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
return; return;
} }

View file

@ -2204,6 +2204,62 @@ void BfModule::ValueScopeEnd(BfIRValue valueScopeStart)
mBfIRBuilder->CreateValueScopeHardEnd(valueScopeStart); mBfIRBuilder->CreateValueScopeHardEnd(valueScopeStart);
} }
BfProjectSet* BfModule::GetVisibleProjectSet()
{
if (mCurMethodState == NULL)
return NULL;
if (mCurMethodState->mVisibleProjectSet.IsEmpty())
{
HashSet<BfType*> seenTypes;
std::function<void(BfProject* project)> _AddProject = [&](BfProject* project)
{
if (mCurMethodState->mVisibleProjectSet.Add(project))
{
for (auto dep : project->mDependencies)
_AddProject(dep);
}
};
std::function<void(BfType* type)> _AddType = [&](BfType* type)
{
auto typeInstance = type->ToTypeInstance();
if (typeInstance == NULL)
return;
_AddProject(typeInstance->mTypeDef->mProject);
if (typeInstance->mGenericTypeInfo == NULL)
return;
for (auto type : typeInstance->mGenericTypeInfo->mTypeGenericArguments)
{
if (seenTypes.Add(type))
_AddType(type);
}
};
if (mCurTypeInstance != NULL)
_AddType(mCurTypeInstance);
auto methodState = mCurMethodState;
while (methodState != NULL)
{
if (methodState->mMethodInstance != NULL)
{
_AddProject(methodState->mMethodInstance->mMethodDef->mDeclaringType->mProject);
if (methodState->mMethodInstance->mMethodInfoEx != NULL)
{
for (auto type : methodState->mMethodInstance->mMethodInfoEx->mMethodGenericArguments)
_AddType(type);
}
}
methodState = methodState->mPrevMethodState;
}
}
return &mCurMethodState->mVisibleProjectSet;
}
BfFileInstance* BfModule::GetFileFromNode(BfAstNode* astNode) BfFileInstance* BfModule::GetFileFromNode(BfAstNode* astNode)
{ {
auto bfParser = astNode->GetSourceData()->ToParserData(); auto bfParser = astNode->GetSourceData()->ToParserData();

View file

@ -895,6 +895,7 @@ public:
Array<BfLambdaInstance*> mDeferredLambdaInstances; Array<BfLambdaInstance*> mDeferredLambdaInstances;
Array<BfIRValue> mSplatDecompAddrs; Array<BfIRValue> mSplatDecompAddrs;
BfDeferredLocalAssignData* mDeferredLocalAssignData; BfDeferredLocalAssignData* mDeferredLocalAssignData;
BfProjectSet mVisibleProjectSet;
int mDeferredLoopListCount; int mDeferredLoopListCount;
int mDeferredLoopListEntryCount; int mDeferredLoopListEntryCount;
HashSet<int> mSkipObjectAccessChecks; // Indexed by BfIRValue value id HashSet<int> mSkipObjectAccessChecks; // Indexed by BfIRValue value id
@ -1468,6 +1469,7 @@ public:
void SaveStackState(BfScopeData* scope); void SaveStackState(BfScopeData* scope);
BfIRValue ValueScopeStart(); BfIRValue ValueScopeStart();
void ValueScopeEnd(BfIRValue valueScopeStart); void ValueScopeEnd(BfIRValue valueScopeStart);
BfProjectSet* GetVisibleProjectSet();
void AddBasicBlock(BfIRBlock bb, bool activate = true); void AddBasicBlock(BfIRBlock bb, bool activate = true);
void VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEvaluator = NULL, BfEmbeddedStatementFlags flags = BfEmbeddedStatementFlags_None); void VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEvaluator = NULL, BfEmbeddedStatementFlags flags = BfEmbeddedStatementFlags_None);

View file

@ -1698,6 +1698,13 @@ bool BfTypeInstance::IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProje
return curProject->ContainsReference(declaringTypeDef->mProject); return curProject->ContainsReference(declaringTypeDef->mProject);
} }
bool BfTypeInstance::IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProjectSet* visibleProjectSet)
{
if (visibleProjectSet == NULL)
return false;
return visibleProjectSet->Contains(declaringTypeDef->mProject);
}
bool BfTypeInstance::WantsGCMarking() bool BfTypeInstance::WantsGCMarking()
{ {
if (IsObjectOrInterface()) if (IsObjectOrInterface())

View file

@ -553,6 +553,7 @@ public:
virtual bool IsTypeMemberIncluded(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef = NULL, BfModule* module = NULL) { return true; } // May be 'false' only for generic extensions with constraints virtual bool IsTypeMemberIncluded(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef = NULL, BfModule* module = NULL) { return true; } // May be 'false' only for generic extensions with constraints
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef) { return true; } virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef) { return true; }
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProject* curProject) { return true; } virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProject* curProject) { return true; }
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProjectSet* visibleProjectSet) { return true; }
virtual void ReportMemory(MemReporter* memReporter); virtual void ReportMemory(MemReporter* memReporter);
}; };
@ -1836,6 +1837,7 @@ public:
virtual bool HasPackingHoles() override { return mHasPackingHoles; } virtual bool HasPackingHoles() override { return mHasPackingHoles; }
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef) override; virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef) override;
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProject* curProject) override; virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProject* curProject) override;
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProjectSet* visibleProjectSet) override;
virtual bool WantsGCMarking() override; virtual bool WantsGCMarking() override;
virtual bool GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCode = NULL, BfTypeCode* outTypeCode2 = NULL) override; virtual bool GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCode = NULL, BfTypeCode* outTypeCode2 = NULL) override;

View file

@ -44,6 +44,7 @@ class BfProject;
struct BfTypeDefMapFuncs; struct BfTypeDefMapFuncs;
typedef MultiHashSet<BfTypeDef*, BfTypeDefMapFuncs> BfTypeDefMap; typedef MultiHashSet<BfTypeDef*, BfTypeDefMapFuncs> BfTypeDefMap;
typedef HashSet<BfProject*> BfProjectSet;
class BfAtom class BfAtom
{ {