1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

New function/delegate casting rules, similar to tuple rules

This commit is contained in:
Brian Fiete 2020-03-31 07:46:01 -07:00
parent c62dbdf811
commit de6a68911a
8 changed files with 143 additions and 32 deletions

View file

@ -7024,6 +7024,7 @@ void BfCompiler::GenerateAutocompleteInfo()
int dispParamIdx = 0;
StringT<64> paramName;
for (int paramIdx = 0; paramIdx < (int)methodInstance->GetParamCount(); paramIdx++)
{
auto paramKind = methodInstance->GetParamKind(paramIdx);
@ -7083,8 +7084,12 @@ void BfCompiler::GenerateAutocompleteInfo()
}
else
methodText += bfModule->TypeToString(type, BfTypeNameFlag_ResolveGenericParamNames, genericMethodNameOverridesPtr);
methodText += " ";
methodText += methodInstance->GetParamName(paramIdx);
methodInstance->GetParamName(paramIdx, paramName);
if (!paramName.IsEmpty())
{
methodText += " ";
methodText += paramName;
}
if (paramInitializer != NULL)
{

View file

@ -12444,6 +12444,9 @@ void BfModule::CreateDIRetVal()
void BfModule::CheckVariableDef(BfLocalVariable* variableDef)
{
if (variableDef->mName.IsEmpty())
return;
BfLocalVarEntry* localVarEntryPtr = NULL;
if ((mCurMethodState != NULL) && (mCurMethodState->mLocalVarSet.TryGet(BfLocalVarEntry(variableDef), &localVarEntryPtr)))
{

View file

@ -9530,6 +9530,62 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
return BfTypedValue();
}
// Function->Function and Delegate->Delegate where type is compatible but not exact
if (((typedVal.mType->IsDelegate()) || (typedVal.mType->IsFunction())) &&
((typedVal.mType->IsDelegate()) == (toType->IsDelegate())) &&
((typedVal.mType->IsFunction()) == (toType->IsFunction())))
{
auto fromDelegateType = (BfDelegateType*)typedVal.mType->ToTypeInstance();
auto toDelegateType = (BfDelegateType*)toType;
if (fromDelegateType->mReturnType == toDelegateType->mReturnType)
{
auto fromMethodInst = GetRawMethodByName(fromDelegateType, "Invoke");
auto toMethodInst = GetRawMethodByName(toDelegateType, "Invoke");
if ((fromMethodInst->mMethodDef->mCallingConvention == toMethodInst->mMethodDef->mCallingConvention) &&
(fromMethodInst->mReturnType == toMethodInst->mReturnType) &&
(fromMethodInst->GetParamCount() == toMethodInst->GetParamCount()))
{
bool matched = true;
StringT<64> fromParamName;
StringT<64> toParamName;
for (int paramIdx = 0; paramIdx < (int)fromMethodInst->GetParamCount(); paramIdx++)
{
bool nameMatches = true;
if (!explicitCast)
{
fromMethodInst->GetParamName(paramIdx, fromParamName);
toMethodInst->GetParamName(paramIdx, toParamName);
if ((!fromParamName.IsEmpty()) && (!toParamName.IsEmpty()))
nameMatches = fromParamName == toParamName;
}
if ((fromMethodInst->GetParamKind(paramIdx) == toMethodInst->GetParamKind(paramIdx)) &&
(fromMethodInst->GetParamType(paramIdx) == toMethodInst->GetParamType(paramIdx)) &&
(nameMatches))
{
// Matched, required for implicit/explicit
}
else
{
matched = false;
break;
}
}
if (matched)
{
BfTypedValue loadedVal = LoadValue(typedVal);
return BfTypedValue(mBfIRBuilder->CreateBitCast(loadedVal.mValue, mBfIRBuilder->MapType(toType)), toType);
}
}
}
}
// Struct truncate
if ((typedVal.mType->IsStruct()) && (toType->IsStruct()))
{
@ -10012,6 +10068,16 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
auto methodDef = delegateType->mTypeDef->mMethods[0];
switch (methodDef->mCallingConvention)
{
case BfCallingConvention_Stdcall:
str += "[StdCall] ";
break;
case BfCallingConvention_Fastcall:
str += "[FastCall] ";
break;
}
if (resolvedType->IsDelegateFromTypeRef())
str += "delegate ";
else
@ -10024,13 +10090,14 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
str += ", ";
auto paramDef = methodDef->mParams[paramIdx];
BfTypeNameFlags innerFlags = (BfTypeNameFlags)(typeNameFlags & ~(BfTypeNameFlag_OmitNamespace | BfTypeNameFlag_OmitOuterType));
//TODO: Why was this necessary? It made some errors show incorrectly
// if (delegateType->mIsUnspecializedTypeVariation)
// innerFlags = (BfTypeNameFlags)(innerFlags & ~BfTypeNameFlag_ResolveGenericParamNames);
DoTypeToString(str, delegateType->mParams[paramIdx], innerFlags, genericMethodNameOverrides);
str += " ";
str += paramDef->mName;
if (!paramDef->mName.IsEmpty())
{
str += " ";
str += paramDef->mName;
}
}
str += ")";

View file

@ -4602,7 +4602,7 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
BfDeferredAstSizedArray<BfParameterDeclaration*> params(delegateTypeRef->mParams, mAlloc);
BfDeferredAstSizedArray<BfTokenNode*> commas(delegateTypeRef->mCommas, mAlloc);
auto closeNode = ParseMethodParams(delegateTypeRef, &params, &commas, BfToken_RParen);
auto closeNode = ParseMethodParams(delegateTypeRef, &params, &commas, BfToken_RParen, false);
if (closeNode == NULL)
{
if (!params.empty())
@ -6523,7 +6523,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth)
if (openToken == NULL)
return indexerDeclaration;
MEMBER_SET(indexerDeclaration, mOpenBracket, openToken);
auto endToken = ParseMethodParams(indexerDeclaration, &params, &commas, BfToken_RBracket);
auto endToken = ParseMethodParams(indexerDeclaration, &params, &commas, BfToken_RBracket, true);
if (endToken == NULL)
return indexerDeclaration;
MEMBER_SET(indexerDeclaration, mCloseBracket, endToken);
@ -8401,7 +8401,7 @@ BfCommentNode * BfReducer::FindDocumentation(BfAstNode* defNodeHead, BfAstNode*
return NULL;
}
BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfParameterDeclaration*>* params, SizedArrayImpl<BfTokenNode*>* commas, BfToken endToken)
BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfParameterDeclaration*>* params, SizedArrayImpl<BfTokenNode*>* commas, BfToken endToken, bool requireNames)
{
BfAstNode* nameAfterNode = node;
@ -8713,18 +8713,29 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
if (paramDecl->mNameNode == NULL)
{
auto nameIdentifierNode = ExpectIdentifierAfter(node, "parameter name");
if (nameIdentifierNode == NULL)
BfAstNode* nameIdentifierNode;
if (requireNames)
{
if (!allowNameFail)
return NULL;
nameIdentifierNode = ExpectIdentifierAfter(node, "parameter name");
if (nameIdentifierNode == NULL)
{
if (!allowNameFail)
return NULL;
}
}
else
{
nameIdentifierNode = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext());
if (nameIdentifierNode != NULL)
mVisitorPos.MoveNext();
}
if (nameIdentifierNode != NULL)
{
paramDecl->mNameNode = nameIdentifierNode;
MoveNode(nameIdentifierNode, paramDecl);
nameAfterNode = nameIdentifierNode;
}
nameAfterNode = nameIdentifierNode;
}
}
}
@ -8770,7 +8781,7 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm
methodDeclaration->mOpenParen = tokenNode;
MoveNode(methodDeclaration->mOpenParen, methodDeclaration);
methodDeclaration->mCloseParen = ParseMethodParams(methodDeclaration, params, commas, BfToken_RParen);
methodDeclaration->mCloseParen = ParseMethodParams(methodDeclaration, params, commas, BfToken_RParen, true);
// RParen
if (methodDeclaration->mCloseParen == NULL)

View file

@ -179,7 +179,7 @@ public:
BfExpression* CheckBinaryOperatorPrecedence(BfBinaryOperatorExpression* binOpExpression);
BfExpression* ApplyToFirstExpression(BfUnaryOperatorExpression* unaryOp, BfExpression* target);
BfIdentifierNode* ExtractExplicitInterfaceRef(BfAstNode* memberDeclaration, BfIdentifierNode* nameIdentifier, BfTypeReference** outExplicitInterface, BfTokenNode** outExplicitInterfaceDotToken);
BfTokenNode* ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfParameterDeclaration*>* params, SizedArrayImpl<BfTokenNode*>* commas, BfToken endToken);
BfTokenNode* ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfParameterDeclaration*>* params, SizedArrayImpl<BfTokenNode*>* commas, BfToken endToken, bool requireNames);
BfTokenNode* ReadArguments(BfAstNode* parentNode, BfAstNode* afterNode, SizedArrayImpl<BfExpression*>* arguments, SizedArrayImpl<BfTokenNode*>* commas, BfToken endToken, bool allowSkippedArgs = false, CreateExprFlags createExprFlags = CreateExprFlags_None);
void ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, BfBlock* block);
BfAstNode* ReadTypeMember(BfTokenNode* node, int depth = 0);

View file

@ -676,18 +676,22 @@ int BfMethodInstance::GetImplicitParamCount()
return 0;
}
String BfMethodInstance::GetParamName(int paramIdx)
void BfMethodInstance::GetParamName(int paramIdx, StringImpl& name)
{
if (paramIdx == -1)
{
BF_ASSERT(!mMethodDef->mIsStatic);
return "this";
name = "this";
return;
}
if ((mMethodInfoEx != NULL) && (mMethodInfoEx->mClosureInstanceInfo != NULL) && (mMethodDef->mIsLocalMethod))
{
if (paramIdx < (int)mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries.size())
return mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries[paramIdx].mName;
{
name = mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries[paramIdx].mName;
return;
}
}
BfMethodParam* methodParam = &mParams[paramIdx];
@ -696,11 +700,19 @@ String BfMethodInstance::GetParamName(int paramIdx)
{
BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke();
if (methodParam->mDelegateParamNameCombine)
return paramDef->mName + "__" + invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx);
name = paramDef->mName + "__" + invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx);
else
return invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx);
invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx, name);
return;
}
return paramDef->mName;
name = paramDef->mName;
}
String BfMethodInstance::GetParamName(int paramIdx)
{
String paramName;
GetParamName(paramIdx, paramName);
return paramName;
}
BfType* BfMethodInstance::GetParamType(int paramIdx, bool useResolvedType)
@ -2644,11 +2656,6 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
BfTypeReference* fieldType = param->mTypeRef;
hashVal = ((hashVal ^ (Hash(fieldType, ctx, BfHashFlag_AllowRef))) << 5) - hashVal;
hashVal = ((hashVal ^ (HashNode(param->mNameNode))) << 5) - hashVal;
if (param->mNameNode == NULL)
{
ctx->mFailed = true;
}
}
return hashVal;
@ -3158,7 +3165,11 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext*
{
if (!Equals(lhsInvokeMethodInstance->GetParamType(paramIdx), rhsDelegateType->mParams[paramIdx]->mTypeRef, ctx))
return false;
if (lhsInvokeMethodInstance->GetParamName(paramIdx) != rhsDelegateType->mParams[paramIdx]->mNameNode->ToString())
StringView rhsParamName;
if (rhsDelegateType->mParams[paramIdx]->mNameNode != NULL)
rhsParamName = rhsDelegateType->mParams[paramIdx]->mNameNode->ToStringView();
if (lhsInvokeMethodInstance->GetParamName(paramIdx) != rhsParamName)
return false;
}
return true;

View file

@ -817,7 +817,8 @@ public:
bool IsTestMethod();
int GetParamCount();
int GetImplicitParamCount();
String GetParamName(int paramIdx);
void GetParamName(int paramIdx, StringImpl& name);
String GetParamName(int paramIdx);
BfType* GetParamType(int paramIdx, bool useResolvedType = true);
bool GetParamIsSplat(int paramIdx);
BfParamKind GetParamKind(int paramIdx);

View file

@ -1,3 +1,5 @@
#pragma warning disable 168
using System;
namespace Tests
@ -137,5 +139,16 @@ namespace Tests
ClassA ca = scope .();
ca.TestLambda();
}
public static void TestCasting()
{
delegate int(int, int) dlg0 = null;
delegate int(int a, int b) dlg1 = dlg0;
delegate int(int a2, int b2) dlg2 = (.)dlg1;
function int(int, int) func0 = null;
function int(int a, int b) func1 = func0;
function int(int a2, int b2) func2 = (.)func1;
}
}
}