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:
parent
c62dbdf811
commit
de6a68911a
8 changed files with 143 additions and 32 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)))
|
||||
{
|
||||
|
|
|
@ -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 += ")";
|
||||
|
|
|
@ -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, ¶ms, &commas, BfToken_RParen);
|
||||
auto closeNode = ParseMethodParams(delegateTypeRef, ¶ms, &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, ¶ms, &commas, BfToken_RBracket);
|
||||
auto endToken = ParseMethodParams(indexerDeclaration, ¶ms, &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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue