瀏覽代碼

Added improved invocation rules with extension methods / fields / props

Brian Fiete 4 年之前
父節點
當前提交
10d4047d01
共有 1 個文件被更改,包括 164 次插入146 次删除
  1. 164 146
      IDEHelper/Compiler/BfExprEvaluator.cpp

+ 164 - 146
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -1328,8 +1328,7 @@ BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, B
 				}
 
 				auto prevBlock = mModule->mBfIRBuilder->GetInsertBlock();
-
-				
+								
 				BfExprEvaluator exprEvaluator(mModule);									
 				exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowIntUnknown | BfEvalExprFlags_NoAutoComplete);
 				if ((resolvedArg.mArgFlags & BfArgFlag_ParamsExpr) != 0)
@@ -1599,7 +1598,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
 		else
 		{
 			// Being in autocomplete mode is the only excuse for not having the virtual method table slotted
-			if ((!mModule->mCompiler->IsAutocomplete()) && (!targetTypeInstance->mTypeFailed))
+			if ((!mModule->mCompiler->IsAutocomplete()) && (!targetTypeInstance->mTypeFailed) && (!targetTypeInstance->IsUnspecializedTypeVariation()))
 			{
 				mModule->AssertErrorState();
 			}
@@ -8113,6 +8112,9 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 
 	bool skipThis = false;
 
+	BfTypedValue fieldVal;
+	bool hasFieldVal = false;
+
 	// Fail, check for delegate field invocation
 	if ((methodDef == NULL) && ((methodGenericArguments == NULL) || (methodGenericArguments->size() == 0)))
 	{
@@ -8145,8 +8147,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 			}
 			return enumResult;
 		}
-
-		BfTypedValue fieldVal;
+		
 		if (allowImplicitThis)
 		{			
 			auto identifierNode = BfNodeDynCast<BfIdentifierNode>(targetSrc);
@@ -8159,148 +8160,23 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 			fieldVal = LookupField(targetSrc, target, methodName);
 		}
 
-		if (mPropDef != NULL)
-			fieldVal = GetResult();
-
 		if (fieldVal)
-		{			
-			if (fieldVal.mType->IsGenericParam())
-			{
-				bool delegateFailed = true;
-				auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)fieldVal.mType);
-				BfTypeInstance* typeInstConstraint = NULL;
-				if (genericParamInstance->mTypeConstraint != NULL)
-					typeInstConstraint = genericParamInstance->mTypeConstraint->ToTypeInstance();
-				if ((typeInstConstraint != NULL) &&
-					((typeInstConstraint->mTypeDef == mModule->mCompiler->mDelegateTypeDef) || (typeInstConstraint->mTypeDef == mModule->mCompiler->mFunctionTypeDef)))
-				{
-					MarkResultUsed();
-					
-// 					if (argValues.mResolvedArgs.size() > 0)
-// 					{
-// 						if ((argValues.mResolvedArgs[0].mArgFlags & BfArgFlag_FromParamComposite) != 0)
-// 							delegateFailed = false;
-// 					}
-// 					else 
-						
-					if (argValues.mArguments->size() == 1)
-					{
-						BfExprEvaluator exprEvaluator(mModule);
-						exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_AllowParamsExpr;
-						exprEvaluator.Evaluate((*argValues.mArguments)[0]);
-						if ((mModule->mCurMethodState != NULL) && (exprEvaluator.mResultLocalVar != NULL) && (exprEvaluator.mResultLocalVarRefNode != NULL))
-						{	
-							/*if (exprEvaluator.mResult.mKind != BfTypedValueKind_Params)
-								mModule->Warn(0, "'params' token expected", (*argValues.mArguments)[0]);*/
-
-							auto localVar = exprEvaluator.mResultLocalVar;
-							if ((localVar->mCompositeCount >= 0) && (localVar->mResolvedType == fieldVal.mType))
-							{
-								delegateFailed = false;
-								if (mModule->mCurMethodInstance->mIsUnspecialized)
-								{
-									auto retTypeType = mModule->CreateModifiedTypeType(fieldVal.mType, BfToken_RetType);
-									return mModule->GetFakeTypedValue(retTypeType);
-								}
-							}
-						}
-					}
-					
-					if (delegateFailed)
-					{
-						mModule->Fail(StrFormat("Generic delegates can only be invoked with 'params %s' composite parameters", mModule->TypeToString(fieldVal.mType).c_str()), targetSrc);
-						return BfTypedValue();
-					}
-				}				
-			}
-
-			if (fieldVal.mType->IsTypeInstance())
-			{
-				prevBindResult.Restore();
-				auto fieldTypeInst = fieldVal.mType->ToTypeInstance();				
-				MarkResultUsed();
-				return MatchMethod(targetSrc, NULL, fieldVal, false, false, "Invoke", argValues, methodGenericArguments, checkedKind);				
-			}					
-			if (fieldVal.mType->IsVar())			
-				return BfTypedValue(mModule->GetDefaultValue(fieldVal.mType), fieldVal.mType);		
-			if (fieldVal.mType->IsGenericParam())
-			{					
-				auto genericParam = mModule->GetGenericParamInstance((BfGenericParamType*)fieldVal.mType);
-				BfType* typeConstraint = genericParam->mTypeConstraint;
-
-				if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
-				{
-					for (int genericParamIdx = (int)mModule->mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
-						genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
-					{
-						auto genericParam = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
-						if ((genericParam->mExternType == fieldVal.mType) && (genericParam->mTypeConstraint != NULL))
-							typeConstraint = genericParam->mTypeConstraint;
-					}
-				}
-				
-				if ((typeConstraint != NULL) &&
-					((typeConstraint->IsDelegate()) || (typeConstraint->IsFunction())))
-				{
-					BfMethodInstance* invokeMethodInstance = mModule->GetRawMethodInstanceAtIdx(typeConstraint->ToTypeInstance(), 0, "Invoke");
-
-					methodDef = invokeMethodInstance->mMethodDef;
-					methodMatcher.mBestMethodInstance = invokeMethodInstance;
-					methodMatcher.mBestMethodTypeInstance = invokeMethodInstance->GetOwner();
-					methodMatcher.mBestMethodDef = invokeMethodInstance->mMethodDef;
-					target = mModule->GetDefaultTypedValue(methodMatcher.mBestMethodTypeInstance);
-					isFailurePass = false;
-					isIndirectMethodCall = true;
-				}
-			}
-			else if (fieldVal.mType->IsMethodRef())
-			{
-				auto functionBindResults = prevBindResult.mPrevVal;
-				if (functionBindResults != NULL)
-				{
-					functionBindResults->mOrigTarget = fieldVal;										
-				}
-				origTarget = fieldVal;
-				
-				auto methodRefType = (BfMethodRefType*)fieldVal.mType;
-				BfMethodInstance* methodInstance = methodRefType->mMethodRef;
-				methodDef = methodInstance->mMethodDef;
-				if (methodDef->mIsLocalMethod)
-				{
-					methodMatcher.mBestMethodInstance = mModule->ReferenceExternalMethodInstance(methodInstance);
-				}
-				else
-				{					
-					BfTypeVector methodGenericArguments;
-					if (methodInstance->mMethodInfoEx != NULL)
-						methodGenericArguments = methodInstance->mMethodInfoEx->mMethodGenericArguments;
-					methodMatcher.mBestMethodInstance = mModule->GetMethodInstance(methodInstance->GetOwner(), methodInstance->mMethodDef, methodGenericArguments);
-				}
-				methodMatcher.mBestMethodTypeInstance = methodInstance->GetOwner();
-				if (methodInstance->HasThis())
-				{
-					bool failed = false;
-					target = DoImplicitArgCapture(targetSrc, methodInstance, -1, failed, BfImplicitParamKind_General, origTarget);
-				}
-				else if (!methodDef->mIsStatic)
-				{
-					auto thisType = methodInstance->GetParamType(-1);
-					BF_ASSERT(thisType->IsValuelessType());
-					target = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), methodMatcher.mBestMethodTypeInstance);
-				}
-				else
-					target = BfTypedValue(methodMatcher.mBestMethodTypeInstance);
-				methodMatcher.mBypassVirtual = true;
-				bypassVirtual = true;
-				isFailurePass = false;
-				isIndirectMethodCall = true;
-			}
+		{
+			hasFieldVal = true;
+			wantsExtensionCheck = !fieldVal.mType->IsDelegate() && !fieldVal.mType->IsFunction();
+		}
+		else if (mPropDef != NULL)
+		{
+			hasFieldVal = true;
 
-			if (methodDef == NULL)
+			BfMethodDef* matchedMethod = GetPropertyMethodDef(mPropDef, BfMethodType_PropertyGetter, mPropCheckedKind, mPropTarget);
+			if (matchedMethod != NULL)
 			{
-				mModule->Fail(StrFormat("Cannot perform invocation on type '%s'", mModule->TypeToString(fieldVal.mType).c_str()), targetSrc);
-				return BfTypedValue();
-			}
+				auto getMethodInstance = mModule->GetRawMethodInstance(mPropTarget.mType->ToTypeInstance(), matchedMethod);
+				if ((getMethodInstance != NULL) &&
+					((getMethodInstance->mReturnType->IsDelegate()) || (getMethodInstance->mReturnType->IsFunction())))
+					wantsExtensionCheck = false;
+			}						
 		}
 	}
 
@@ -8488,6 +8364,143 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 		}
 	}
 
+	if ((methodDef == NULL) && (hasFieldVal))
+	{
+		if (mPropDef != NULL)
+			fieldVal = GetResult();
+
+		if (fieldVal)
+		{
+			if (fieldVal.mType->IsGenericParam())
+			{
+				bool delegateFailed = true;
+				auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)fieldVal.mType);
+				BfTypeInstance* typeInstConstraint = NULL;
+				if (genericParamInstance->mTypeConstraint != NULL)
+					typeInstConstraint = genericParamInstance->mTypeConstraint->ToTypeInstance();
+				if ((typeInstConstraint != NULL) &&
+					((typeInstConstraint->mTypeDef == mModule->mCompiler->mDelegateTypeDef) || (typeInstConstraint->mTypeDef == mModule->mCompiler->mFunctionTypeDef)))
+				{
+					MarkResultUsed();
+
+					if (argValues.mArguments->size() == 1)
+					{
+						BfExprEvaluator exprEvaluator(mModule);
+						exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_AllowParamsExpr;
+						exprEvaluator.Evaluate((*argValues.mArguments)[0]);
+						if ((mModule->mCurMethodState != NULL) && (exprEvaluator.mResultLocalVar != NULL) && (exprEvaluator.mResultLocalVarRefNode != NULL))
+						{
+							auto localVar = exprEvaluator.mResultLocalVar;
+							if ((localVar->mCompositeCount >= 0) && (localVar->mResolvedType == fieldVal.mType))
+							{
+								delegateFailed = false;
+								if (mModule->mCurMethodInstance->mIsUnspecialized)
+								{
+									auto retTypeType = mModule->CreateModifiedTypeType(fieldVal.mType, BfToken_RetType);
+									return mModule->GetFakeTypedValue(retTypeType);
+								}
+							}
+						}
+					}
+
+					if (delegateFailed)
+					{
+						mModule->Fail(StrFormat("Generic delegates can only be invoked with 'params %s' composite parameters", mModule->TypeToString(fieldVal.mType).c_str()), targetSrc);
+						return BfTypedValue();
+					}
+				}
+			}
+
+			if (fieldVal.mType->IsTypeInstance())
+			{
+				prevBindResult.Restore();
+				auto fieldTypeInst = fieldVal.mType->ToTypeInstance();
+				MarkResultUsed();
+				return MatchMethod(targetSrc, NULL, fieldVal, false, false, "Invoke", argValues, methodGenericArguments, checkedKind);
+			}
+			if (fieldVal.mType->IsVar())
+				return BfTypedValue(mModule->GetDefaultValue(fieldVal.mType), fieldVal.mType);
+			if (fieldVal.mType->IsGenericParam())
+			{
+				auto genericParam = mModule->GetGenericParamInstance((BfGenericParamType*)fieldVal.mType);
+				BfType* typeConstraint = genericParam->mTypeConstraint;
+
+				if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
+				{
+					for (int genericParamIdx = (int)mModule->mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
+						genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
+					{
+						auto genericParam = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
+						if ((genericParam->mExternType == fieldVal.mType) && (genericParam->mTypeConstraint != NULL))
+							typeConstraint = genericParam->mTypeConstraint;
+					}
+				}
+
+				if ((typeConstraint != NULL) &&
+					((typeConstraint->IsDelegate()) || (typeConstraint->IsFunction())))
+				{
+					BfMethodInstance* invokeMethodInstance = mModule->GetRawMethodInstanceAtIdx(typeConstraint->ToTypeInstance(), 0, "Invoke");
+
+					methodDef = invokeMethodInstance->mMethodDef;
+					methodMatcher.mBestMethodInstance = invokeMethodInstance;
+					methodMatcher.mBestMethodTypeInstance = invokeMethodInstance->GetOwner();
+					methodMatcher.mBestMethodDef = invokeMethodInstance->mMethodDef;
+					target = mModule->GetDefaultTypedValue(methodMatcher.mBestMethodTypeInstance);
+					isFailurePass = false;
+					isIndirectMethodCall = true;
+				}
+			}
+			else if (fieldVal.mType->IsMethodRef())
+			{
+				auto functionBindResults = prevBindResult.mPrevVal;
+				if (functionBindResults != NULL)
+				{
+					functionBindResults->mOrigTarget = fieldVal;
+				}
+				origTarget = fieldVal;
+
+				auto methodRefType = (BfMethodRefType*)fieldVal.mType;
+				BfMethodInstance* methodInstance = methodRefType->mMethodRef;
+				methodDef = methodInstance->mMethodDef;
+				if (methodDef->mIsLocalMethod)
+				{
+					methodMatcher.mBestMethodInstance = mModule->ReferenceExternalMethodInstance(methodInstance);
+				}
+				else
+				{
+					BfTypeVector methodGenericArguments;
+					if (methodInstance->mMethodInfoEx != NULL)
+						methodGenericArguments = methodInstance->mMethodInfoEx->mMethodGenericArguments;
+					methodMatcher.mBestMethodInstance = mModule->GetMethodInstance(methodInstance->GetOwner(), methodInstance->mMethodDef, methodGenericArguments);
+				}
+				methodMatcher.mBestMethodTypeInstance = methodInstance->GetOwner();
+				if (methodInstance->HasThis())
+				{
+					bool failed = false;
+					target = DoImplicitArgCapture(targetSrc, methodInstance, -1, failed, BfImplicitParamKind_General, origTarget);
+				}
+				else if (!methodDef->mIsStatic)
+				{
+					auto thisType = methodInstance->GetParamType(-1);
+					BF_ASSERT(thisType->IsValuelessType());
+					target = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), methodMatcher.mBestMethodTypeInstance);
+				}
+				else
+					target = BfTypedValue(methodMatcher.mBestMethodTypeInstance);
+				methodMatcher.mBypassVirtual = true;
+				bypassVirtual = true;
+				isFailurePass = false;
+				isIndirectMethodCall = true;
+			}
+
+			if (methodDef == NULL)
+			{
+				mModule->Fail(StrFormat("Cannot perform invocation on type '%s'", mModule->TypeToString(fieldVal.mType).c_str()), targetSrc);
+				return BfTypedValue();
+			}
+		}
+	}
+
 	// This will flush out any new ambiguity errors from extension methods
 	methodMatcher.FlushAmbiguityError();
 
@@ -10474,8 +10487,13 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
 	}
 	else if ((!targetType->IsInterface()) && (!mModule->TypeIsSubTypeOf(targetTypeInstance, srcTypeInstance)))
 	{
-		mModule->Fail(StrFormat("Cannot convert type '%s' to '%s' via any conversion", 
-			mModule->TypeToString(targetValue.mType).c_str(), mModule->TypeToString(targetTypeInstance).c_str()), dynCastExpr->mAsToken);
+		if (!mModule->IsInSpecializedSection())
+		{
+			mModule->Fail(StrFormat("Cannot convert type '%s' to '%s' via any conversion",
+				mModule->TypeToString(targetValue.mType).c_str(), mModule->TypeToString(targetTypeInstance).c_str()), dynCastExpr->mAsToken);
+		}
+		mResult = mModule->GetDefaultTypedValue(targetType);
+		return;
 	}
 
 	if (autoComplete != NULL)