mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Added constraints for operators, 'external' constraints for methods
This commit is contained in:
parent
00a92dd0a7
commit
8945a906f7
24 changed files with 1561 additions and 509 deletions
|
@ -340,6 +340,12 @@ namespace System
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(.Method)]
|
||||||
|
public struct CommutableAttribute : Attribute
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
[AttributeUsage(.Method | .Constructor)]
|
[AttributeUsage(.Method | .Constructor)]
|
||||||
public struct ErrorAttribute : Attribute
|
public struct ErrorAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,6 +96,11 @@ void BfStructuralVisitor::Visit(BfGenericParamsDeclaration* genericParams)
|
||||||
Visit(genericParams->ToBase());
|
Visit(genericParams->ToBase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfStructuralVisitor::Visit(BfGenericOperatorConstraint* genericConstraints)
|
||||||
|
{
|
||||||
|
Visit(genericConstraints->ToBase());
|
||||||
|
}
|
||||||
|
|
||||||
void BfStructuralVisitor::Visit(BfGenericConstraintsDeclaration* genericConstraints)
|
void BfStructuralVisitor::Visit(BfGenericConstraintsDeclaration* genericConstraints)
|
||||||
{
|
{
|
||||||
Visit(genericConstraints->ToBase());
|
Visit(genericConstraints->ToBase());
|
||||||
|
@ -1567,6 +1572,165 @@ const char* Beefy::BfGetOpName(BfUnaryOp unaryOp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfBinaryOp Beefy::BfTokenToBinaryOp(BfToken token)
|
||||||
|
{
|
||||||
|
switch (token)
|
||||||
|
{
|
||||||
|
case BfToken_Plus:
|
||||||
|
return BfBinaryOp_Add;
|
||||||
|
case BfToken_Minus:
|
||||||
|
return BfBinaryOp_Subtract;
|
||||||
|
case BfToken_Star:
|
||||||
|
return BfBinaryOp_Multiply;
|
||||||
|
case BfToken_ForwardSlash:
|
||||||
|
return BfBinaryOp_Divide;
|
||||||
|
case BfToken_Modulus:
|
||||||
|
return BfBinaryOp_Modulus;
|
||||||
|
case BfToken_Ampersand:
|
||||||
|
return BfBinaryOp_BitwiseAnd;
|
||||||
|
case BfToken_Bar:
|
||||||
|
return BfBinaryOp_BitwiseOr;
|
||||||
|
case BfToken_Carat:
|
||||||
|
return BfBinaryOp_ExclusiveOr;
|
||||||
|
case BfToken_LDblChevron:
|
||||||
|
return BfBinaryOp_LeftShift;
|
||||||
|
case BfToken_RDblChevron:
|
||||||
|
return BfBinaryOp_RightShift;
|
||||||
|
case BfToken_CompareEquals:
|
||||||
|
return BfBinaryOp_Equality;
|
||||||
|
case BfToken_CompareNotEquals:
|
||||||
|
return BfBinaryOp_InEquality;
|
||||||
|
case BfToken_RChevron:
|
||||||
|
return BfBinaryOp_GreaterThan;
|
||||||
|
case BfToken_LChevron:
|
||||||
|
return BfBinaryOp_LessThan;
|
||||||
|
case BfToken_GreaterEquals:
|
||||||
|
return BfBinaryOp_GreaterThanOrEqual;
|
||||||
|
case BfToken_LessEquals:
|
||||||
|
return BfBinaryOp_LessThanOrEqual;
|
||||||
|
case BfToken_Spaceship:
|
||||||
|
return BfBinaryOp_Compare;
|
||||||
|
case BfToken_DblAmpersand:
|
||||||
|
return BfBinaryOp_ConditionalAnd;
|
||||||
|
case BfToken_DblBar:
|
||||||
|
return BfBinaryOp_ConditionalOr;
|
||||||
|
case BfToken_DblQuestion:
|
||||||
|
return BfBinaryOp_NullCoalesce;
|
||||||
|
default:
|
||||||
|
return BfBinaryOp_None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BfUnaryOp Beefy::BfTokenToUnaryOp(BfToken token)
|
||||||
|
{
|
||||||
|
switch (token)
|
||||||
|
{
|
||||||
|
case BfToken_Star:
|
||||||
|
return BfUnaryOp_Dereference;
|
||||||
|
case BfToken_Ampersand:
|
||||||
|
return BfUnaryOp_AddressOf;
|
||||||
|
case BfToken_Minus:
|
||||||
|
return BfUnaryOp_Negate;
|
||||||
|
case BfToken_Bang:
|
||||||
|
return BfUnaryOp_Not;
|
||||||
|
case BfToken_Plus:
|
||||||
|
return BfUnaryOp_Positive;
|
||||||
|
case BfToken_Tilde:
|
||||||
|
return BfUnaryOp_InvertBits;
|
||||||
|
case BfToken_DblPlus:
|
||||||
|
return BfUnaryOp_Increment;
|
||||||
|
case BfToken_DblMinus:
|
||||||
|
return BfUnaryOp_Decrement;
|
||||||
|
case BfToken_Ref:
|
||||||
|
return BfUnaryOp_Ref;
|
||||||
|
case BfToken_Mut:
|
||||||
|
return BfUnaryOp_Mut;
|
||||||
|
case BfToken_Out:
|
||||||
|
return BfUnaryOp_Out;
|
||||||
|
case BfToken_Params:
|
||||||
|
return BfUnaryOp_Params;
|
||||||
|
default:
|
||||||
|
return BfUnaryOp_None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BfAssignmentOp Beefy::BfTokenToAssignmentOp(BfToken token)
|
||||||
|
{
|
||||||
|
switch (token)
|
||||||
|
{
|
||||||
|
case BfToken_AssignEquals:
|
||||||
|
return BfAssignmentOp_Assign;
|
||||||
|
case BfToken_PlusEquals:
|
||||||
|
return BfAssignmentOp_Add;
|
||||||
|
case BfToken_MinusEquals:
|
||||||
|
return BfAssignmentOp_Subtract;
|
||||||
|
case BfToken_MultiplyEquals:
|
||||||
|
return BfAssignmentOp_Multiply;
|
||||||
|
case BfToken_DivideEquals:
|
||||||
|
return BfAssignmentOp_Divide;
|
||||||
|
case BfToken_ModulusEquals:
|
||||||
|
return BfAssignmentOp_Modulus;
|
||||||
|
case BfToken_ShiftLeftEquals:
|
||||||
|
return BfAssignmentOp_ShiftLeft;
|
||||||
|
case BfToken_ShiftRightEquals:
|
||||||
|
return BfAssignmentOp_ShiftRight;
|
||||||
|
case BfToken_AndEquals:
|
||||||
|
return BfAssignmentOp_BitwiseAnd;
|
||||||
|
case BfToken_OrEquals:
|
||||||
|
return BfAssignmentOp_BitwiseOr;
|
||||||
|
case BfToken_XorEquals:
|
||||||
|
return BfAssignmentOp_ExclusiveOr;
|
||||||
|
default:
|
||||||
|
return BfAssignmentOp_None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BfBinaryOp Beefy::BfGetOppositeBinaryOp(BfBinaryOp origOp)
|
||||||
|
{
|
||||||
|
switch (origOp)
|
||||||
|
{
|
||||||
|
case BfBinaryOp_Equality:
|
||||||
|
return BfBinaryOp_InEquality;
|
||||||
|
case BfBinaryOp_InEquality:
|
||||||
|
return BfBinaryOp_Equality;
|
||||||
|
case BfBinaryOp_LessThan:
|
||||||
|
return BfBinaryOp_GreaterThanOrEqual;
|
||||||
|
case BfBinaryOp_LessThanOrEqual:
|
||||||
|
return BfBinaryOp_GreaterThan;
|
||||||
|
case BfBinaryOp_GreaterThan:
|
||||||
|
return BfBinaryOp_LessThanOrEqual;
|
||||||
|
case BfBinaryOp_GreaterThanOrEqual:
|
||||||
|
return BfBinaryOp_LessThan;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BfBinaryOp_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfBinaryOp Beefy::BfGetFlippedBinaryOp(BfBinaryOp origOp)
|
||||||
|
{
|
||||||
|
switch (origOp)
|
||||||
|
{
|
||||||
|
case BfBinaryOp_Equality:
|
||||||
|
return BfBinaryOp_Equality;
|
||||||
|
case BfBinaryOp_InEquality:
|
||||||
|
return BfBinaryOp_InEquality;
|
||||||
|
case BfBinaryOp_LessThan:
|
||||||
|
return BfBinaryOp_GreaterThan;
|
||||||
|
case BfBinaryOp_LessThanOrEqual:
|
||||||
|
return BfBinaryOp_GreaterThanOrEqual;
|
||||||
|
case BfBinaryOp_GreaterThan:
|
||||||
|
return BfBinaryOp_LessThan;
|
||||||
|
case BfBinaryOp_GreaterThanOrEqual:
|
||||||
|
return BfBinaryOp_LessThanOrEqual;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BfBinaryOp_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BfInlineAsmInstruction::AsmArg::AsmArg()
|
BfInlineAsmInstruction::AsmArg::AsmArg()
|
||||||
: mType(ARGTYPE_Immediate)
|
: mType(ARGTYPE_Immediate)
|
||||||
, mMemFlags(0)
|
, mMemFlags(0)
|
||||||
|
|
|
@ -347,6 +347,7 @@ class BfCollectionInitializerExpression;
|
||||||
class BfArraySizeSpecifier;
|
class BfArraySizeSpecifier;
|
||||||
class BfSizedArrayCreateExpression;
|
class BfSizedArrayCreateExpression;
|
||||||
class BfEmptyStatement;
|
class BfEmptyStatement;
|
||||||
|
class BfGenericOperatorConstraint;
|
||||||
class BfGenericConstraintsDeclaration;
|
class BfGenericConstraintsDeclaration;
|
||||||
class BfAttributeDirective;
|
class BfAttributeDirective;
|
||||||
class BfNullableTypeRef;
|
class BfNullableTypeRef;
|
||||||
|
@ -409,6 +410,7 @@ public:
|
||||||
|
|
||||||
virtual void Visit(BfAttributeDirective* attributeDirective);
|
virtual void Visit(BfAttributeDirective* attributeDirective);
|
||||||
virtual void Visit(BfGenericParamsDeclaration* genericParams);
|
virtual void Visit(BfGenericParamsDeclaration* genericParams);
|
||||||
|
virtual void Visit(BfGenericOperatorConstraint* genericConstraints);
|
||||||
virtual void Visit(BfGenericConstraintsDeclaration* genericConstraints);
|
virtual void Visit(BfGenericConstraintsDeclaration* genericConstraints);
|
||||||
virtual void Visit(BfGenericArgumentsNode* genericArgumentsNode);
|
virtual void Visit(BfGenericArgumentsNode* genericArgumentsNode);
|
||||||
|
|
||||||
|
@ -2762,15 +2764,26 @@ public:
|
||||||
BfTokenNode* mRight;
|
BfTokenNode* mRight;
|
||||||
}; BF_AST_DECL(BfTokenPairNode, BfAstNode);
|
}; BF_AST_DECL(BfTokenPairNode, BfAstNode);
|
||||||
|
|
||||||
|
class BfGenericOperatorConstraint : public BfAstNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BF_AST_TYPE(BfGenericOperatorConstraint, BfAstNode);
|
||||||
|
|
||||||
|
BfTokenNode* mOperatorToken;
|
||||||
|
BfTypeReference* mLeftType;
|
||||||
|
BfTokenNode* mOpToken;
|
||||||
|
BfTypeReference* mRightType;
|
||||||
|
}; BF_AST_DECL(BfGenericOperatorConstraint, BfAstNode);
|
||||||
|
|
||||||
class BfGenericConstraint : public BfAstNode
|
class BfGenericConstraint : public BfAstNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BF_AST_TYPE(BfGenericConstraint, BfAstNode);
|
BF_AST_TYPE(BfGenericConstraint, BfAstNode);
|
||||||
|
|
||||||
BfTokenNode* mWhereToken;
|
BfTokenNode* mWhereToken;
|
||||||
BfIdentifierNode* mGenericParamName;
|
BfTypeReference* mTypeRef;
|
||||||
BfTokenNode* mColonToken;
|
BfTokenNode* mColonToken;
|
||||||
BfSizedArray<ASTREF(BfAstNode*)> mConstraintTypes;
|
BfSizedArray<BfAstNode*> mConstraintTypes;
|
||||||
BfSizedArray<ASTREF(BfTokenNode*)> mCommas;
|
BfSizedArray<ASTREF(BfTokenNode*)> mCommas;
|
||||||
}; BF_AST_DECL(BfGenericConstraint, BfAstNode);
|
}; BF_AST_DECL(BfGenericConstraint, BfAstNode);
|
||||||
|
|
||||||
|
@ -2778,7 +2791,7 @@ class BfGenericConstraintsDeclaration : public BfAstNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BF_AST_TYPE(BfGenericConstraintsDeclaration, BfAstNode);
|
BF_AST_TYPE(BfGenericConstraintsDeclaration, BfAstNode);
|
||||||
BfSizedArray<ASTREF(BfGenericConstraint*)> mGenericConstraints;
|
BfSizedArray<BfGenericConstraint*> mGenericConstraints;
|
||||||
}; BF_AST_DECL(BfGenericConstraintsDeclaration, BfAstNode);
|
}; BF_AST_DECL(BfGenericConstraintsDeclaration, BfAstNode);
|
||||||
|
|
||||||
class BfMethodDeclaration : public BfMemberDeclaration
|
class BfMethodDeclaration : public BfMemberDeclaration
|
||||||
|
@ -3171,8 +3184,13 @@ public:
|
||||||
const char* BfTokenToString(BfToken token);
|
const char* BfTokenToString(BfToken token);
|
||||||
bool BfTokenIsKeyword(BfToken token);
|
bool BfTokenIsKeyword(BfToken token);
|
||||||
BfBinaryOp BfAssignOpToBinaryOp(BfAssignmentOp assignmentOp);
|
BfBinaryOp BfAssignOpToBinaryOp(BfAssignmentOp assignmentOp);
|
||||||
|
BfBinaryOp BfGetOppositeBinaryOp(BfBinaryOp origOp);
|
||||||
|
BfBinaryOp BfGetFlippedBinaryOp(BfBinaryOp origOp);
|
||||||
int BfGetBinaryOpPrecendence(BfBinaryOp binOp);
|
int BfGetBinaryOpPrecendence(BfBinaryOp binOp);
|
||||||
const char* BfGetOpName(BfBinaryOp binOp);
|
const char* BfGetOpName(BfBinaryOp binOp);
|
||||||
const char* BfGetOpName(BfUnaryOp unaryOp);
|
const char* BfGetOpName(BfUnaryOp unaryOp);
|
||||||
|
BfBinaryOp BfTokenToBinaryOp(BfToken token);
|
||||||
|
BfUnaryOp BfTokenToUnaryOp(BfToken token);
|
||||||
|
BfAssignmentOp BfTokenToAssignmentOp(BfToken token);
|
||||||
|
|
||||||
NS_BF_END
|
NS_BF_END
|
|
@ -1512,22 +1512,37 @@ bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken
|
||||||
}
|
}
|
||||||
|
|
||||||
// Statics, inner types
|
// Statics, inner types
|
||||||
//bool isStatic = (targetValue.mValue == NULL) && (!targetValue.mType->IsValuelessType());
|
|
||||||
|
|
||||||
auto checkType = targetValue.mType;
|
auto checkType = targetValue.mType;
|
||||||
|
|
||||||
if (checkType->IsGenericParam())
|
if (checkType->IsGenericParam())
|
||||||
{
|
{
|
||||||
auto genericParamType = (BfGenericParamType*)checkType;
|
auto genericParamType = (BfGenericParamType*)checkType;
|
||||||
auto genericParamInst = mModule->GetGenericParamInstance(genericParamType);
|
auto genericParamInstance = mModule->GetGenericParamInstance(genericParamType);
|
||||||
|
|
||||||
for (auto interfaceConstraint : genericParamInst->mInterfaceConstraints)
|
auto _HandleGenericParamInstance = [&](BfGenericParamInstance* genericParamInstance)
|
||||||
AddTypeMembers(interfaceConstraint, false, true, filter, interfaceConstraint, true, false);
|
{
|
||||||
|
for (auto interfaceConstraint : genericParamInstance->mInterfaceConstraints)
|
||||||
|
AddTypeMembers(interfaceConstraint, false, true, filter, interfaceConstraint, true, false);
|
||||||
|
|
||||||
if (genericParamInst->mTypeConstraint != NULL)
|
if (genericParamInstance->mTypeConstraint != NULL)
|
||||||
checkType = genericParamInst->mTypeConstraint;
|
checkType = genericParamInstance->mTypeConstraint;
|
||||||
else
|
else
|
||||||
checkType = mModule->mContext->mBfObjectType;
|
checkType = mModule->mContext->mBfObjectType;
|
||||||
|
};
|
||||||
|
_HandleGenericParamInstance(genericParamInstance);
|
||||||
|
|
||||||
|
// Check method generic constraints
|
||||||
|
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 == genericParamType)
|
||||||
|
_HandleGenericParamInstance(genericParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkType->IsPointer())
|
if (checkType->IsPointer())
|
||||||
|
|
|
@ -2697,7 +2697,8 @@ void BfCompiler::GenerateDynCastData()
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfCompiler::UpdateRevisedTypes()
|
void BfCompiler::UpdateRevisedTypes()
|
||||||
{
|
{
|
||||||
|
BfLogSysM("UpdateRevisedTypes\n");
|
||||||
BP_ZONE("BfCompiler::UpdateRevisedTypes");
|
BP_ZONE("BfCompiler::UpdateRevisedTypes");
|
||||||
|
|
||||||
// See if we have any name conflicts and remove those
|
// See if we have any name conflicts and remove those
|
||||||
|
@ -3251,13 +3252,25 @@ void BfCompiler::UpdateRevisedTypes()
|
||||||
mContext->ValidateDependencies();
|
mContext->ValidateDependencies();
|
||||||
}
|
}
|
||||||
mContext->RemoveInvalidWorkItems();
|
mContext->RemoveInvalidWorkItems();
|
||||||
|
|
||||||
|
//for (auto typeDef : mSystem->mTypeDefs)
|
||||||
|
//{
|
||||||
|
// auto latestTypeDef = typeDef->GetLatest();
|
||||||
|
// if ((latestTypeDef->mOuterType != NULL) && (latestTypeDef->mOuterType->mIsPartial) && (latestTypeDef->mIsCombinedPartial))
|
||||||
|
// //((!latestTypeDef->mIsPartial) || (latestTypeDef->mIsCombinedPartial)))
|
||||||
|
// latestTypeDef->mOuterType = mSystem->GetOuterTypeNonPartial(latestTypeDef);
|
||||||
|
|
||||||
for (auto typeDef : mSystem->mTypeDefs)
|
// /*String fullName = typeDef->mFullNameEx.ToString();
|
||||||
{
|
// if (fullName == "System.Collections.Generic.List`1.Enumerator`1")
|
||||||
auto latestTypeDef = typeDef->GetLatest();
|
// {
|
||||||
if ((latestTypeDef->mOuterType != NULL) && (latestTypeDef->mOuterType->mIsPartial))
|
// NOP;
|
||||||
latestTypeDef->mOuterType = mSystem->GetOuterTypeNonPartial(latestTypeDef);
|
// }
|
||||||
}
|
|
||||||
|
// if ((typeDef->mOuterType != NULL) && (!typeDef->mIsPartial) && (typeDef->mOuterType->mIsPartial) && (!typeDef->mOuterType->mIsCombinedPartial))
|
||||||
|
// {
|
||||||
|
// NOP;
|
||||||
|
// }*/
|
||||||
|
//}
|
||||||
|
|
||||||
mSystem->mNeedsTypesHandledByCompiler = false;
|
mSystem->mNeedsTypesHandledByCompiler = false;
|
||||||
|
|
||||||
|
@ -3767,8 +3780,9 @@ void BfCompiler::ProcessAutocompleteTempType()
|
||||||
{
|
{
|
||||||
auto genericParamDef = tempTypeDef->mGenericParamDefs[genericParamIdx];
|
auto genericParamDef = tempTypeDef->mGenericParamDefs[genericParamIdx];
|
||||||
|
|
||||||
auto genericParamInstance = new BfGenericTypeParamInstance(tempTypeDef, genericParamIdx);
|
auto genericParamInstance = new BfGenericTypeParamInstance(tempTypeDef, genericParamIdx);
|
||||||
module->ResolveGenericParamConstraints(genericParamInstance, tempTypeDef->mGenericParamDefs, genericParamIdx);
|
genericParamInstance->mExternType = module->GetGenericParamType(BfGenericParamKind_Type, genericParamIdx);
|
||||||
|
module->ResolveGenericParamConstraints(genericParamInstance, true);
|
||||||
delete genericParamInstance;
|
delete genericParamInstance;
|
||||||
|
|
||||||
for (auto nameNode : genericParamDef->mNameNodes)
|
for (auto nameNode : genericParamDef->mNameNodes)
|
||||||
|
@ -3937,10 +3951,14 @@ void BfCompiler::ProcessAutocompleteTempType()
|
||||||
auto genericParamType = module->GetGenericParamType(BfGenericParamKind_Method, genericParamIdx);
|
auto genericParamType = module->GetGenericParamType(BfGenericParamKind_Method, genericParamIdx);
|
||||||
methodInstance->GetMethodInfoEx()->mMethodGenericArguments.push_back(genericParamType);
|
methodInstance->GetMethodInfoEx()->mMethodGenericArguments.push_back(genericParamType);
|
||||||
|
|
||||||
auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx);
|
auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx);
|
||||||
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
|
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
|
||||||
|
}
|
||||||
|
|
||||||
//module->ResolveGenericParamConstraints(genericParamInstance, methodDef->mGenericParams[genericParamIdx]);
|
for (int externConstraintIdx = 0; externConstraintIdx < (int)methodDef->mExternalConstraints.size(); externConstraintIdx++)
|
||||||
|
{
|
||||||
|
auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, externConstraintIdx + (int)methodDef->mGenericParams.size());
|
||||||
|
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetAndRestoreValue<BfFilePosition> prevFilePos(module->mCurFilePosition);
|
SetAndRestoreValue<BfFilePosition> prevFilePos(module->mCurFilePosition);
|
||||||
|
@ -4187,8 +4205,18 @@ void BfCompiler::GetSymbolReferences()
|
||||||
|
|
||||||
for (auto genericParam : checkTypeDef->mGenericParamDefs)
|
for (auto genericParam : checkTypeDef->mGenericParamDefs)
|
||||||
{
|
{
|
||||||
for (auto constraint : genericParam->mInterfaceConstraints)
|
for (auto constraint : genericParam->mConstraints)
|
||||||
module->ResolveTypeRef(constraint, BfPopulateType_Identity);
|
{
|
||||||
|
if (auto constraintTypeRef = BfNodeDynCast<BfTypeReference>(constraint))
|
||||||
|
{
|
||||||
|
module->ResolveTypeRef(constraintTypeRef, BfPopulateType_Identity);
|
||||||
|
}
|
||||||
|
else if (auto opConstraint = BfNodeDynCast<BfGenericOperatorConstraint>(constraint))
|
||||||
|
{
|
||||||
|
module->ResolveTypeRef(opConstraint->mLeftType, BfPopulateType_Identity);
|
||||||
|
module->ResolveTypeRef(opConstraint->mRightType, BfPopulateType_Identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4230,8 +4258,6 @@ void BfCompiler::GetSymbolReferences()
|
||||||
BfGenericTypeParamInstance genericParamInstance(genericTypeInstance->mTypeDef, genericParamIdx);
|
BfGenericTypeParamInstance genericParamInstance(genericTypeInstance->mTypeDef, genericParamIdx);
|
||||||
auto genericParamDef = typeDef->mGenericParamDefs[genericParamIdx];
|
auto genericParamDef = typeDef->mGenericParamDefs[genericParamIdx];
|
||||||
|
|
||||||
//BfGenericMethodParamInstance genericParamInstance(rebuildMethodInstance->mMethodDef, genericParamIdx);
|
|
||||||
|
|
||||||
if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_TypeGenericParam)
|
if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_TypeGenericParam)
|
||||||
{
|
{
|
||||||
for (auto nameNode : genericParamDef->mNameNodes)
|
for (auto nameNode : genericParamDef->mNameNodes)
|
||||||
|
@ -4239,8 +4265,8 @@ void BfCompiler::GetSymbolReferences()
|
||||||
mResolvePassData->HandleTypeGenericParam(nameNode, typeDef, genericParamIdx);
|
mResolvePassData->HandleTypeGenericParam(nameNode, typeDef, genericParamIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, typeDef->mGenericParamDefs, genericParamIdx);
|
rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, genericTypeInstance->IsGenericTypeInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4372,7 +4398,7 @@ void BfCompiler::GetSymbolReferences()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebuildMethodInstance->mIgnoreBody)
|
if (rebuildMethodInstance->mIgnoreBody)
|
||||||
{
|
{
|
||||||
auto methodDeclaration = methodDef->GetMethodDeclaration();
|
auto methodDeclaration = methodDef->GetMethodDeclaration();
|
||||||
if (methodDeclaration != NULL)
|
if (methodDeclaration != NULL)
|
||||||
mResolvePassData->HandleMethodReference(methodDeclaration->mNameNode, typeDef, methodDef);
|
mResolvePassData->HandleMethodReference(methodDeclaration->mNameNode, typeDef, methodDef);
|
||||||
|
@ -4436,7 +4462,15 @@ void BfCompiler::GetSymbolReferences()
|
||||||
mResolvePassData->HandleMethodGenericParam(nameNode, typeDef, methodDef, genericParamIdx);
|
mResolvePassData->HandleMethodGenericParam(nameNode, typeDef, methodDef, genericParamIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, methodDef->mGenericParams, genericParamIdx);
|
rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, rebuildMethodInstance->mIsUnspecialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int externConstraintIdx = 0; externConstraintIdx < (int)methodDef->mExternalConstraints.size(); externConstraintIdx++)
|
||||||
|
{
|
||||||
|
BfGenericMethodParamInstance genericParamInstance(rebuildMethodInstance->mMethodDef, externConstraintIdx + (int)methodDef->mGenericParams.size());
|
||||||
|
auto& externConstraintDef = methodDef->mExternalConstraints[externConstraintIdx];
|
||||||
|
CheckSymbolReferenceTypeRef(module, externConstraintDef.mTypeRef);
|
||||||
|
rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, rebuildMethodInstance->mIsUnspecialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuildModule->ProcessMethod(rebuildMethodInstance);
|
rebuildModule->ProcessMethod(rebuildMethodInstance);
|
||||||
|
|
|
@ -181,7 +181,7 @@ bool BfDefBuilder::WantsNode(BfAstNode* wholeNode, BfAstNode* startNode, int add
|
||||||
|
|
||||||
static int sGenericParamIdx = 0;
|
static int sGenericParamIdx = 0;
|
||||||
|
|
||||||
void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsDecl, BfGenericConstraintsDeclaration* genericConstraints, Array<BfGenericParamDef*>& genericParams, int outerGenericSize)
|
void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsDecl, BfGenericConstraintsDeclaration* genericConstraints, Array<BfGenericParamDef*>& genericParams, Array<BfExternalConstraintDef>* externConstraintDefs, int outerGenericSize)
|
||||||
{
|
{
|
||||||
if (genericParamsDecl != NULL)
|
if (genericParamsDecl != NULL)
|
||||||
{
|
{
|
||||||
|
@ -203,7 +203,7 @@ void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsD
|
||||||
while (checkTypeDef != NULL)
|
while (checkTypeDef != NULL)
|
||||||
{
|
{
|
||||||
if (&genericParams != &checkTypeDef->mGenericParamDefs)
|
if (&genericParams != &checkTypeDef->mGenericParamDefs)
|
||||||
{
|
{
|
||||||
for (int checkParamsIdx = 0; checkParamsIdx < (int)checkTypeDef->mGenericParamDefs.size(); checkParamsIdx++)
|
for (int checkParamsIdx = 0; checkParamsIdx < (int)checkTypeDef->mGenericParamDefs.size(); checkParamsIdx++)
|
||||||
{
|
{
|
||||||
if (checkTypeDef->mGenericParamDefs[checkParamsIdx]->mName == name)
|
if (checkTypeDef->mGenericParamDefs[checkParamsIdx]->mName == name)
|
||||||
|
@ -228,30 +228,53 @@ void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsD
|
||||||
if (genericConstraints == NULL)
|
if (genericConstraints == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (BfGenericConstraint* genericConstraint : genericConstraints->mGenericConstraints)
|
for (BfAstNode* genericConstraintNode : genericConstraints->mGenericConstraints)
|
||||||
{
|
{
|
||||||
if (genericConstraint->mGenericParamName == NULL)
|
auto genericConstraint = BfNodeDynCast<BfGenericConstraint>(genericConstraintNode);
|
||||||
|
if (genericConstraint == NULL)
|
||||||
|
continue;
|
||||||
|
if (genericConstraint->mTypeRef == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String findName = genericConstraint->mGenericParamName->ToString();
|
BfIdentifierNode* nameNode = NULL;
|
||||||
BfGenericParamDef* genericParamDef = NULL;
|
BfGenericParamDef* genericParamDef = NULL;
|
||||||
for (int genericParamIdx = outerGenericSize; genericParamIdx < (int) genericParams.size(); genericParamIdx++)
|
if (auto namedTypeRef = BfNodeDynCast<BfNamedTypeReference>(genericConstraint->mTypeRef))
|
||||||
{
|
{
|
||||||
auto checkGenericParam = genericParams[genericParamIdx];
|
nameNode = namedTypeRef->mNameNode;
|
||||||
if (checkGenericParam->mName == findName)
|
String findName = nameNode->ToString();
|
||||||
genericParamDef = checkGenericParam;
|
for (int genericParamIdx = outerGenericSize; genericParamIdx < (int)genericParams.size(); genericParamIdx++)
|
||||||
|
{
|
||||||
|
auto checkGenericParam = genericParams[genericParamIdx];
|
||||||
|
if (checkGenericParam->mName == findName)
|
||||||
|
genericParamDef = checkGenericParam;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfConstraintDef* constraintDef = genericParamDef;
|
||||||
|
|
||||||
if (genericParamDef == NULL)
|
if (genericParamDef == NULL)
|
||||||
{
|
{
|
||||||
mPassInstance->Fail("Cannot find generic parameter in constraint", genericConstraint->mGenericParamName);
|
if (externConstraintDefs == NULL)
|
||||||
|
{
|
||||||
|
mPassInstance->Fail("Cannot find generic parameter in constraint", genericConstraint->mTypeRef);
|
||||||
|
|
||||||
if (genericParams.IsEmpty())
|
if (genericParams.IsEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
genericParamDef = genericParams[0];
|
genericParamDef = genericParams[0];
|
||||||
|
constraintDef = genericParamDef;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
externConstraintDefs->Add(BfExternalConstraintDef());
|
||||||
|
BfExternalConstraintDef* externConstraintDef = &externConstraintDefs->back();
|
||||||
|
externConstraintDef->mTypeRef = genericConstraint->mTypeRef;
|
||||||
|
constraintDef = externConstraintDef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
genericParamDef->mNameNodes.Add(genericConstraint->mGenericParamName);
|
if (genericParamDef != NULL)
|
||||||
|
genericParamDef->mNameNodes.Add(nameNode);
|
||||||
|
|
||||||
for (BfAstNode* constraintNode : genericConstraint->mConstraintTypes)
|
for (BfAstNode* constraintNode : genericConstraint->mConstraintTypes)
|
||||||
{
|
{
|
||||||
|
@ -266,11 +289,13 @@ void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsD
|
||||||
name = tokenPairNode->mLeft->ToString() + tokenPairNode->mRight->ToString();
|
name = tokenPairNode->mLeft->ToString() + tokenPairNode->mRight->ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasEquals = (genericConstraint->mColonToken != NULL) && (genericConstraint->mColonToken->mToken == BfToken_AssignEquals);
|
||||||
|
|
||||||
if (!name.empty())
|
if (!name.empty())
|
||||||
{
|
{
|
||||||
if ((name == "class") || (name == "struct") || (name == "struct*") || (name == "const") || (name == "var"))
|
if ((name == "class") || (name == "struct") || (name == "struct*") || (name == "const") || (name == "var"))
|
||||||
{
|
{
|
||||||
int prevFlags = genericParamDef->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr);
|
int prevFlags = constraintDef->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr);
|
||||||
if (prevFlags != 0)
|
if (prevFlags != 0)
|
||||||
{
|
{
|
||||||
String prevFlagName;
|
String prevFlagName;
|
||||||
|
@ -289,38 +314,57 @@ void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsD
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == "class")
|
if (name == "class")
|
||||||
genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Class);
|
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Class);
|
||||||
else if (name == "struct")
|
else if (name == "struct")
|
||||||
genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Struct);
|
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Struct);
|
||||||
else if (name == "struct*")
|
else if (name == "struct*")
|
||||||
genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_StructPtr);
|
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_StructPtr);
|
||||||
else if (name == "const")
|
else if (name == "const")
|
||||||
genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Const);
|
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Const);
|
||||||
else //if (name == "var")
|
else //if (name == "var")
|
||||||
genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Var);
|
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Var);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (name == "new")
|
else if (name == "new")
|
||||||
{
|
{
|
||||||
genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_New);
|
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_New);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (name == "delete")
|
else if (name == "delete")
|
||||||
{
|
{
|
||||||
genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Delete);
|
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Delete);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto constraintType = BfNodeDynCast<BfTypeReference>(constraintNode);
|
if (auto genericOpConstraint = BfNodeDynCast<BfGenericOperatorConstraint>(constraintNode))
|
||||||
if (constraintType == NULL)
|
|
||||||
{
|
{
|
||||||
mPassInstance->Fail("Invalid constraint", constraintNode);
|
// Ok
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto constraintType = BfNodeDynCast<BfTypeReference>(constraintNode);
|
||||||
|
if (constraintType == NULL)
|
||||||
|
{
|
||||||
|
mPassInstance->Fail("Invalid constraint", constraintNode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasEquals)
|
||||||
|
{
|
||||||
|
if (constraintDef->mConstraints.IsEmpty())
|
||||||
|
{
|
||||||
|
constraintDef->mGenericParamFlags = (BfGenericParamFlags)(constraintDef->mGenericParamFlags | BfGenericParamFlag_Equals);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mPassInstance->Fail("Type assignment must be the first constraint", genericConstraint->mColonToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
genericParamDef->mInterfaceConstraints.push_back(constraintType);
|
constraintDef->mConstraints.Add(constraintNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -538,7 +582,7 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
|
||||||
int outerGenericSize = 0;
|
int outerGenericSize = 0;
|
||||||
if (outerMethodDef != NULL)
|
if (outerMethodDef != NULL)
|
||||||
outerGenericSize = (int)outerMethodDef->mGenericParams.size();
|
outerGenericSize = (int)outerMethodDef->mGenericParams.size();
|
||||||
ParseGenericParams(methodDeclaration->mGenericParams, methodDeclaration->mGenericConstraintsDeclaration, methodDef->mGenericParams, outerGenericSize);
|
ParseGenericParams(methodDeclaration->mGenericParams, methodDeclaration->mGenericConstraintsDeclaration, methodDef->mGenericParams, &methodDef->mExternalConstraints, outerGenericSize);
|
||||||
|
|
||||||
bool didDefaultsError = false;
|
bool didDefaultsError = false;
|
||||||
bool hadParams = false;
|
bool hadParams = false;
|
||||||
|
@ -623,13 +667,25 @@ void BfDefBuilder::Visit(BfMethodDeclaration* methodDeclaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto methodDef = CreateMethodDef(methodDeclaration);
|
auto methodDef = CreateMethodDef(methodDeclaration);
|
||||||
if (methodDef->mMethodType == BfMethodType_Operator)
|
methodDef->mWantsBody = wantsBody;
|
||||||
{
|
if (methodDef->mMethodType == BfMethodType_Operator)
|
||||||
mCurTypeDef->mOperators.push_back((BfOperatorDef*)methodDef);
|
mCurTypeDef->mOperators.push_back((BfOperatorDef*)methodDef);
|
||||||
}
|
|
||||||
mCurTypeDef->mMethods.push_back(methodDef);
|
mCurTypeDef->mMethods.push_back(methodDef);
|
||||||
|
|
||||||
methodDef->mWantsBody = wantsBody;
|
if (methodDef->mCommutableKind == BfCommutableKind_Forward)
|
||||||
|
{
|
||||||
|
auto revMethodDef = CreateMethodDef(methodDeclaration);
|
||||||
|
revMethodDef->mWantsBody = wantsBody;
|
||||||
|
if (revMethodDef->mMethodType == BfMethodType_Operator)
|
||||||
|
mCurTypeDef->mOperators.push_back((BfOperatorDef*)revMethodDef);
|
||||||
|
|
||||||
|
if (revMethodDef->mParams.size() >= 2)
|
||||||
|
{
|
||||||
|
BF_SWAP(revMethodDef->mParams[0], revMethodDef->mParams[1]);
|
||||||
|
}
|
||||||
|
revMethodDef->mCommutableKind = BfCommutableKind_Reverse;
|
||||||
|
mCurTypeDef->mMethods.push_back(revMethodDef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef* methodDef)
|
void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef* methodDef)
|
||||||
|
@ -647,7 +703,7 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef
|
||||||
else if (typeRefName == "CVarArgs")
|
else if (typeRefName == "CVarArgs")
|
||||||
methodDef->mCallingConvention = BfCallingConvention_CVarArgs;
|
methodDef->mCallingConvention = BfCallingConvention_CVarArgs;
|
||||||
else if (typeRefName == "Inline")
|
else if (typeRefName == "Inline")
|
||||||
methodDef->mAlwaysInline = true;
|
methodDef->mAlwaysInline = true;
|
||||||
else if (typeRefName == "AllowAppend")
|
else if (typeRefName == "AllowAppend")
|
||||||
methodDef->mHasAppend = true;
|
methodDef->mHasAppend = true;
|
||||||
else if (typeRefName == "Checked")
|
else if (typeRefName == "Checked")
|
||||||
|
@ -655,12 +711,12 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef
|
||||||
else if (typeRefName == "Unchecked")
|
else if (typeRefName == "Unchecked")
|
||||||
methodDef->mCheckedKind = BfCheckedKind_Unchecked;
|
methodDef->mCheckedKind = BfCheckedKind_Unchecked;
|
||||||
else if (typeRefName == "Export")
|
else if (typeRefName == "Export")
|
||||||
{
|
{
|
||||||
mCurTypeDef->mIsAlwaysInclude = true;
|
mCurTypeDef->mIsAlwaysInclude = true;
|
||||||
methodDef->mImportKind = BfImportKind_Export;
|
methodDef->mImportKind = BfImportKind_Export;
|
||||||
}
|
}
|
||||||
else if (typeRefName == "Import")
|
else if (typeRefName == "Import")
|
||||||
{
|
{
|
||||||
methodDef->mImportKind = BfImportKind_Static;
|
methodDef->mImportKind = BfImportKind_Static;
|
||||||
if (!attributes->mArguments.IsEmpty())
|
if (!attributes->mArguments.IsEmpty())
|
||||||
{
|
{
|
||||||
|
@ -677,7 +733,7 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (typeRefName == "NoReturn")
|
else if (typeRefName == "NoReturn")
|
||||||
methodDef->mNoReturn = true;
|
methodDef->mNoReturn = true;
|
||||||
|
@ -687,6 +743,17 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef
|
||||||
methodDef->mIsNoShow = true;
|
methodDef->mIsNoShow = true;
|
||||||
else if (typeRefName == "NoDiscard")
|
else if (typeRefName == "NoDiscard")
|
||||||
methodDef->mIsNoDiscard = true;
|
methodDef->mIsNoDiscard = true;
|
||||||
|
else if (typeRefName == "Commutable")
|
||||||
|
{
|
||||||
|
if (methodDef->mParams.size() != 2)
|
||||||
|
{
|
||||||
|
mPassInstance->Fail("Commutable attributes can only be applied to methods with two arguments", attributes->mAttributeTypeRef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
methodDef->mCommutableKind = BfCommutableKind_Forward;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes = attributes->mNextAttribute;
|
attributes = attributes->mNextAttribute;
|
||||||
|
@ -1304,7 +1371,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
|
||||||
BfGenericParamDef* copiedGenericParamDef = new BfGenericParamDef();
|
BfGenericParamDef* copiedGenericParamDef = new BfGenericParamDef();
|
||||||
*copiedGenericParamDef = *outerGenericParamDef;
|
*copiedGenericParamDef = *outerGenericParamDef;
|
||||||
mCurTypeDef->mGenericParamDefs.Add(copiedGenericParamDef);
|
mCurTypeDef->mGenericParamDefs.Add(copiedGenericParamDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypeDef* parentType = outerTypeDef;
|
BfTypeDef* parentType = outerTypeDef;
|
||||||
while (parentType != NULL)
|
while (parentType != NULL)
|
||||||
|
@ -1521,7 +1588,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
|
||||||
int outerGenericSize = 0;
|
int outerGenericSize = 0;
|
||||||
if (mCurTypeDef->mOuterType != NULL)
|
if (mCurTypeDef->mOuterType != NULL)
|
||||||
outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size();
|
outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size();
|
||||||
ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, outerGenericSize);
|
ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, NULL, outerGenericSize);
|
||||||
|
|
||||||
BF_ASSERT(mCurTypeDef->mNameEx == NULL);
|
BF_ASSERT(mCurTypeDef->mNameEx == NULL);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
HashContext* mSignatureHashCtx;
|
HashContext* mSignatureHashCtx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void ParseGenericParams(BfGenericParamsDeclaration* genericParamsDecl, BfGenericConstraintsDeclaration* genericConstraints, Array<BfGenericParamDef*>& genericParams, int outerGenericSize);
|
void ParseGenericParams(BfGenericParamsDeclaration* genericParamsDecl, BfGenericConstraintsDeclaration* genericConstraints, Array<BfGenericParamDef*>& genericParams, Array<BfExternalConstraintDef>* externConstraintDefs, int outerGenericSize);
|
||||||
BfProtection GetProtection(BfTokenNode* protectionToken);
|
BfProtection GetProtection(BfTokenNode* protectionToken);
|
||||||
bool WantsNode(BfAstNode* wholeNode, BfAstNode* startNode = NULL, int addLen = 0);
|
bool WantsNode(BfAstNode* wholeNode, BfAstNode* startNode = NULL, int addLen = 0);
|
||||||
//static BfNamedTypeReference* AllocTypeReference(BfSource* bfSource, const StringImpl& typeName);
|
//static BfNamedTypeReference* AllocTypeReference(BfSource* bfSource, const StringImpl& typeName);
|
||||||
|
|
|
@ -69,19 +69,29 @@ void BfElementVisitor::Visit(BfGenericParamsDeclaration* genericParams)
|
||||||
VisitChild(genericParams->mCloseChevron);
|
VisitChild(genericParams->mCloseChevron);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfElementVisitor::Visit(BfGenericOperatorConstraint* genericConstraints)
|
||||||
|
{
|
||||||
|
Visit(genericConstraints->ToBase());
|
||||||
|
|
||||||
|
VisitChild(genericConstraints->mOperatorToken);
|
||||||
|
VisitChild(genericConstraints->mLeftType);
|
||||||
|
VisitChild(genericConstraints->mOpToken);
|
||||||
|
VisitChild(genericConstraints->mRightType);
|
||||||
|
}
|
||||||
|
|
||||||
void BfElementVisitor::Visit(BfGenericConstraintsDeclaration* genericConstraints)
|
void BfElementVisitor::Visit(BfGenericConstraintsDeclaration* genericConstraints)
|
||||||
{
|
{
|
||||||
Visit(genericConstraints->ToBase());
|
Visit(genericConstraints->ToBase());
|
||||||
|
|
||||||
for (auto genericConstraint : genericConstraints->mGenericConstraints)
|
for (auto genericConstraint : genericConstraints->mGenericConstraints)
|
||||||
{
|
{
|
||||||
VisitChild(genericConstraint->mWhereToken);
|
VisitChild(genericConstraint->mWhereToken);
|
||||||
VisitChild(genericConstraint->mGenericParamName);
|
VisitChild(genericConstraint->mTypeRef);
|
||||||
VisitChild(genericConstraint->mColonToken);
|
VisitChild(genericConstraint->mColonToken);
|
||||||
for (auto val : genericConstraint->mConstraintTypes)
|
for (auto val : genericConstraint->mConstraintTypes)
|
||||||
VisitChild(val);
|
VisitChild(val);
|
||||||
for (auto val : genericConstraint->mCommas)
|
for (auto val : genericConstraint->mCommas)
|
||||||
VisitChild(val);
|
VisitChild(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
|
|
||||||
virtual void Visit(BfAttributeDirective* attributeDirective);
|
virtual void Visit(BfAttributeDirective* attributeDirective);
|
||||||
virtual void Visit(BfGenericParamsDeclaration* genericParams);
|
virtual void Visit(BfGenericParamsDeclaration* genericParams);
|
||||||
|
virtual void Visit(BfGenericOperatorConstraint* genericConstraints);
|
||||||
virtual void Visit(BfGenericConstraintsDeclaration* genericConstraints);
|
virtual void Visit(BfGenericConstraintsDeclaration* genericConstraints);
|
||||||
virtual void Visit(BfGenericArgumentsNode* genericArgumentsNode);
|
virtual void Visit(BfGenericArgumentsNode* genericArgumentsNode);
|
||||||
|
|
||||||
|
|
|
@ -26,50 +26,6 @@
|
||||||
USING_NS_BF;
|
USING_NS_BF;
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
static BfBinaryOp GetOppositeBinaryOp(BfBinaryOp origOp)
|
|
||||||
{
|
|
||||||
switch (origOp)
|
|
||||||
{
|
|
||||||
case BfBinaryOp_Equality:
|
|
||||||
return BfBinaryOp_InEquality;
|
|
||||||
case BfBinaryOp_InEquality:
|
|
||||||
return BfBinaryOp_Equality;
|
|
||||||
case BfBinaryOp_LessThan:
|
|
||||||
return BfBinaryOp_GreaterThanOrEqual;
|
|
||||||
case BfBinaryOp_LessThanOrEqual:
|
|
||||||
return BfBinaryOp_GreaterThan;
|
|
||||||
case BfBinaryOp_GreaterThan:
|
|
||||||
return BfBinaryOp_LessThanOrEqual;
|
|
||||||
case BfBinaryOp_GreaterThanOrEqual:
|
|
||||||
return BfBinaryOp_LessThan;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BfBinaryOp_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BfBinaryOp GetFlippedBinaryOp(BfBinaryOp origOp)
|
|
||||||
{
|
|
||||||
switch (origOp)
|
|
||||||
{
|
|
||||||
case BfBinaryOp_Equality:
|
|
||||||
return BfBinaryOp_Equality;
|
|
||||||
case BfBinaryOp_InEquality:
|
|
||||||
return BfBinaryOp_InEquality;
|
|
||||||
case BfBinaryOp_LessThan:
|
|
||||||
return BfBinaryOp_GreaterThan;
|
|
||||||
case BfBinaryOp_LessThanOrEqual:
|
|
||||||
return BfBinaryOp_GreaterThanOrEqual;
|
|
||||||
case BfBinaryOp_GreaterThan:
|
|
||||||
return BfBinaryOp_LessThan;
|
|
||||||
case BfBinaryOp_GreaterThanOrEqual:
|
|
||||||
return BfBinaryOp_LessThanOrEqual;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BfBinaryOp_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DeferredTupleAssignData::~DeferredTupleAssignData()
|
DeferredTupleAssignData::~DeferredTupleAssignData()
|
||||||
|
@ -197,6 +153,7 @@ BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMetho
|
||||||
void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments)
|
void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments)
|
||||||
{
|
{
|
||||||
//mArguments = arguments;
|
//mArguments = arguments;
|
||||||
|
mActiveTypeDef = NULL;
|
||||||
mBestMethodDef = NULL;
|
mBestMethodDef = NULL;
|
||||||
mBackupMethodDef = NULL;
|
mBackupMethodDef = NULL;
|
||||||
mBestMethodTypeInstance = NULL;
|
mBestMethodTypeInstance = NULL;
|
||||||
|
@ -237,6 +194,22 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BfMethodMatcher::IsMemberAccessible(BfTypeInstance* typeInst, BfTypeDef* declaringType)
|
||||||
|
{
|
||||||
|
if (mActiveTypeDef == NULL)
|
||||||
|
mActiveTypeDef = mModule->GetActiveTypeDef();
|
||||||
|
if (!typeInst->IsTypeMemberIncluded(declaringType, mActiveTypeDef, mModule))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// This may not be completely correct - BUT if we don't have this then even Dictionary TKey's operator == won't be considered accessible
|
||||||
|
if (!mModule->IsInSpecializedSection())
|
||||||
|
{
|
||||||
|
if (!typeInst->IsTypeMemberAccessible(declaringType, mActiveTypeDef))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue)
|
bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue)
|
||||||
{
|
{
|
||||||
if (argType == NULL)
|
if (argType == NULL)
|
||||||
|
@ -828,7 +801,8 @@ 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_RESULTS;
|
RETURN_RESULTS;
|
||||||
}
|
}
|
||||||
|
@ -1030,6 +1004,11 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
|
||||||
mMethodCheckCount++;
|
mMethodCheckCount++;
|
||||||
|
|
||||||
BfMethodInstance* methodInstance = mModule->GetRawMethodInstance(typeInstance, checkMethod);
|
BfMethodInstance* methodInstance = mModule->GetRawMethodInstance(typeInstance, checkMethod);
|
||||||
|
if (methodInstance == NULL)
|
||||||
|
{
|
||||||
|
BF_FATAL("Failed to get raw method in BfMethodMatcher::CheckMethod");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ((mInterfaceMethodInstance != NULL) && (methodInstance->GetExplicitInterface() != NULL))
|
if ((mInterfaceMethodInstance != NULL) && (methodInstance->GetExplicitInterface() != NULL))
|
||||||
{
|
{
|
||||||
|
@ -1203,6 +1182,24 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
|
||||||
auto& genericArg = mCheckMethodGenericArguments[genericArgIdx];
|
auto& genericArg = mCheckMethodGenericArguments[genericArgIdx];
|
||||||
if (genericArg == NULL)
|
if (genericArg == NULL)
|
||||||
{
|
{
|
||||||
|
auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericArgIdx];
|
||||||
|
//mModule->CheckGenericConstraints(BfGenericParamSource(), NULL, NULL, genericParam, &mCheckMethodGenericArguments, NULL);
|
||||||
|
if (genericArg != NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if ((genericParam->mGenericParamFlags & BfGenericParamFlag_Equals) != 0)
|
||||||
|
// {
|
||||||
|
// if ((genericParam->mGenericParamFlags & BfGenericParamFlag_Equals_Op) != 0)
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// else if ((genericParam->mGenericParamFlags & BfGenericParamFlag_Equals_Type) != 0)
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (!allowEmptyGenericSet.Contains(genericArgIdx))
|
if (!allowEmptyGenericSet.Contains(genericArgIdx))
|
||||||
goto NoMatch;
|
goto NoMatch;
|
||||||
}
|
}
|
||||||
|
@ -1944,7 +1941,7 @@ void BfResolvedArgs::HandleFixits(BfModule* module)
|
||||||
BfExprEvaluator::BfExprEvaluator(BfModule* module)
|
BfExprEvaluator::BfExprEvaluator(BfModule* module)
|
||||||
{
|
{
|
||||||
mBfEvalExprFlags = BfEvalExprFlags_None;
|
mBfEvalExprFlags = BfEvalExprFlags_None;
|
||||||
mModule = module;
|
mModule = module;
|
||||||
mPropDef = NULL;
|
mPropDef = NULL;
|
||||||
mPropSrc = NULL;
|
mPropSrc = NULL;
|
||||||
mPropGetMethodFlags = BfGetMethodInstanceFlag_None;
|
mPropGetMethodFlags = BfGetMethodInstanceFlag_None;
|
||||||
|
@ -6009,22 +6006,39 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
else if (lookupType->IsGenericParam())
|
else if (lookupType->IsGenericParam())
|
||||||
{
|
{
|
||||||
auto genericParamTarget = (BfGenericParamType*)lookupType;
|
auto genericParamTarget = (BfGenericParamType*)lookupType;
|
||||||
auto genericParamInstance = mModule->GetGenericParamInstance(genericParamTarget);
|
|
||||||
|
|
||||||
if (genericParamInstance->mTypeConstraint != NULL)
|
auto _HandleGenericParamInstance = [&](BfGenericParamInstance* genericParamInstance)
|
||||||
lookupTypeInst = genericParamInstance->mTypeConstraint->ToTypeInstance();
|
|
||||||
else
|
|
||||||
lookupTypeInst = mModule->mContext->mBfObjectType;
|
|
||||||
|
|
||||||
for (BfType* ifaceInst : genericParamInstance->mInterfaceConstraints)
|
|
||||||
{
|
{
|
||||||
if (ifaceInst->IsUnspecializedType())
|
if (genericParamInstance->mTypeConstraint != NULL)
|
||||||
ifaceInst = mModule->ResolveType(ifaceInst);
|
lookupTypeInst = genericParamInstance->mTypeConstraint->ToTypeInstance();
|
||||||
|
else
|
||||||
|
lookupTypeInst = mModule->mContext->mBfObjectType;
|
||||||
|
|
||||||
BfTypeInstance* typeInst = ifaceInst->ToTypeInstance();
|
for (BfType* ifaceInst : genericParamInstance->mInterfaceConstraints)
|
||||||
BF_ASSERT(typeInst != NULL);
|
{
|
||||||
if (methodMatcher.CheckType(typeInst, target, false))
|
if (ifaceInst->IsUnspecializedType())
|
||||||
methodMatcher.mSelfType = lookupType;
|
ifaceInst = mModule->ResolveType(ifaceInst);
|
||||||
|
|
||||||
|
BfTypeInstance* typeInst = ifaceInst->ToTypeInstance();
|
||||||
|
BF_ASSERT(typeInst != NULL);
|
||||||
|
if (methodMatcher.CheckType(typeInst, target, false))
|
||||||
|
methodMatcher.mSelfType = lookupType;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto genericParamInstance = mModule->GetGenericParamInstance(genericParamTarget);
|
||||||
|
_HandleGenericParamInstance(genericParamInstance);
|
||||||
|
|
||||||
|
// Check method generic constraints
|
||||||
|
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 == lookupType)
|
||||||
|
_HandleGenericParamInstance(genericParam);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11736,11 +11750,11 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
|
||||||
auto genericArg = methodMatcher.mBestMethodGenericArguments[checkGenericIdx];
|
auto genericArg = methodMatcher.mBestMethodGenericArguments[checkGenericIdx];
|
||||||
if (genericArg->IsVar())
|
if (genericArg->IsVar())
|
||||||
continue;
|
continue;
|
||||||
if (genericArg->IsPrimitiveType())
|
/*if (genericArg->IsPrimitiveType())
|
||||||
{
|
{
|
||||||
auto primType = (BfPrimitiveType*)genericArg;
|
auto primType = (BfPrimitiveType*)genericArg;
|
||||||
genericArg = mModule->GetPrimitiveStructType(primType->mTypeDef->mTypeCode);
|
genericArg = mModule->GetPrimitiveStructType(primType->mTypeDef->mTypeCode);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
BfAstNode* paramSrc;
|
BfAstNode* paramSrc;
|
||||||
if (methodMatcher.mBestMethodGenericArgumentSrcs.size() == 0)
|
if (methodMatcher.mBestMethodGenericArgumentSrcs.size() == 0)
|
||||||
|
@ -15506,6 +15520,9 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
|
||||||
if ((!isFailurePass) && (!methodMatcher.WantsCheckMethod(protectionCheckFlags, startCheckTypeInst, curCheckType, checkMethod)))
|
if ((!isFailurePass) && (!methodMatcher.WantsCheckMethod(protectionCheckFlags, startCheckTypeInst, curCheckType, checkMethod)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!methodMatcher.IsMemberAccessible(curCheckType, checkMethod->mDeclaringType))
|
||||||
|
continue;
|
||||||
|
|
||||||
methodMatcher.mCheckedKind = checkedKind;
|
methodMatcher.mCheckedKind = checkedKind;
|
||||||
methodMatcher.CheckMethod(curCheckType, checkMethod, false);
|
methodMatcher.CheckMethod(curCheckType, checkMethod, false);
|
||||||
|
|
||||||
|
@ -15794,10 +15811,17 @@ void BfExprEvaluator::PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mExpectingType = NULL;
|
mExpectingType = NULL;
|
||||||
}
|
}
|
||||||
VisitChild(unaryOpExpr);
|
VisitChild(unaryOpExpr);
|
||||||
mExpectingType = prevExpedcting;
|
mExpectingType = prevExpedcting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BfExprEvaluator::PerformUnaryOperation_OnResult(unaryOpExpr, unaryOp, opToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken)
|
||||||
|
{
|
||||||
BfAstNode* propSrc = mPropSrc;
|
BfAstNode* propSrc = mPropSrc;
|
||||||
BfTypedValue propTarget = mPropTarget;
|
BfTypedValue propTarget = mPropTarget;
|
||||||
BfPropertyDef* propDef = mPropDef;
|
BfPropertyDef* propDef = mPropDef;
|
||||||
|
@ -15806,7 +15830,7 @@ void BfExprEvaluator::PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp
|
||||||
|
|
||||||
GetResult();
|
GetResult();
|
||||||
if (!mResult)
|
if (!mResult)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mResult.mType->IsRef())
|
if (mResult.mType->IsRef())
|
||||||
mResult.mType = mResult.mType->GetUnderlyingType();
|
mResult.mType = mResult.mType->GetUnderlyingType();
|
||||||
|
@ -15851,12 +15875,17 @@ void BfExprEvaluator::PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp
|
||||||
for (auto operatorDef : checkType->mTypeDef->mOperators)
|
for (auto operatorDef : checkType->mTypeDef->mOperators)
|
||||||
{
|
{
|
||||||
if (operatorDef->mOperatorDeclaration->mUnaryOp == findOp)
|
if (operatorDef->mOperatorDeclaration->mUnaryOp == findOp)
|
||||||
|
{
|
||||||
|
if (!methodMatcher.IsMemberAccessible(checkType, operatorDef->mDeclaringType))
|
||||||
|
continue;
|
||||||
if (methodMatcher.CheckMethod(checkType, operatorDef, false))
|
if (methodMatcher.CheckMethod(checkType, operatorDef, false))
|
||||||
methodMatcher.mSelfType = entry.mSrcType;
|
methodMatcher.mSelfType = entry.mSrcType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (methodMatcher.mBestMethodDef != NULL)
|
if (methodMatcher.mBestMethodDef != NULL)
|
||||||
{
|
{
|
||||||
if (!baseClassWalker.mMayBeFromInterface)
|
if (!baseClassWalker.mMayBeFromInterface)
|
||||||
mModule->SetElementType(opToken, BfSourceElementType_Method);
|
mModule->SetElementType(opToken, BfSourceElementType_Method);
|
||||||
|
|
||||||
|
@ -15883,6 +15912,47 @@ void BfExprEvaluator::PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp
|
||||||
mResult = args[0].mTypedValue;
|
mResult = args[0].mTypedValue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check method generic constraints
|
||||||
|
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
|
||||||
|
{
|
||||||
|
for (int genericParamIdx = 0; genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
||||||
|
{
|
||||||
|
auto genericParam = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
||||||
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
if (opConstraint.mUnaryOp == findOp)
|
||||||
|
{
|
||||||
|
if (mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mRightType))
|
||||||
|
{
|
||||||
|
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check type generic constraints
|
||||||
|
if ((mModule->mCurTypeInstance->IsGenericTypeInstance()) && (mModule->mCurTypeInstance->IsUnspecializedType()))
|
||||||
|
{
|
||||||
|
auto genericTypeInst = (BfGenericTypeInstance*)mModule->mCurTypeInstance;
|
||||||
|
for (int genericParamIdx = 0; genericParamIdx < genericTypeInst->mGenericParams.size(); genericParamIdx++)
|
||||||
|
{
|
||||||
|
auto genericParam = mModule->GetGenericTypeParamInstance(genericParamIdx);
|
||||||
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
if (opConstraint.mUnaryOp == findOp)
|
||||||
|
{
|
||||||
|
if (mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mRightType))
|
||||||
|
{
|
||||||
|
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool numericFail = false;
|
bool numericFail = false;
|
||||||
|
@ -16612,7 +16682,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
}
|
}
|
||||||
else if ((leftValue.mValue.IsConst()) && (!rightValue.mValue.IsConst()))
|
else if ((leftValue.mValue.IsConst()) && (!rightValue.mValue.IsConst()))
|
||||||
{
|
{
|
||||||
if (CheckConstCompare(GetOppositeBinaryOp(binaryOp), opToken, rightValue, leftValue))
|
if (CheckConstCompare(BfGetOppositeBinaryOp(binaryOp), opToken, rightValue, leftValue))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16914,7 +16984,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
|
|
||||||
bool invertResult = false;
|
bool invertResult = false;
|
||||||
|
|
||||||
BfBinaryOp oppositeBinaryOp = GetOppositeBinaryOp(findBinaryOp);
|
BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -16935,6 +17005,10 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
if (allowOp)
|
if (allowOp)
|
||||||
{
|
{
|
||||||
foundOp = true;
|
foundOp = true;
|
||||||
|
|
||||||
|
if (!methodMatcher.IsMemberAccessible(checkType, operatorDef->mDeclaringType))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (methodMatcher.CheckMethod(checkType, operatorDef, false))
|
if (methodMatcher.CheckMethod(checkType, operatorDef, false))
|
||||||
{
|
{
|
||||||
methodMatcher.mSelfType = entry.mSrcType;
|
methodMatcher.mSelfType = entry.mSrcType;
|
||||||
|
@ -17006,7 +17080,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
|
|
||||||
auto useBinaryOp = binaryOp;
|
auto useBinaryOp = binaryOp;
|
||||||
if (pass == 1)
|
if (pass == 1)
|
||||||
useBinaryOp = GetFlippedBinaryOp(useBinaryOp);
|
useBinaryOp = BfGetFlippedBinaryOp(useBinaryOp);
|
||||||
|
|
||||||
auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
|
auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
|
||||||
switch (useBinaryOp)
|
switch (useBinaryOp)
|
||||||
|
@ -17036,19 +17110,57 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check method generic constraints
|
||||||
|
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
|
||||||
|
{
|
||||||
|
for (int genericParamIdx = 0; genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
||||||
|
{
|
||||||
|
auto genericParam = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
||||||
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
if (opConstraint.mBinaryOp == findBinaryOp)
|
||||||
|
{
|
||||||
|
if ((mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
|
||||||
|
(mModule->CanImplicitlyCast(args[1].mTypedValue, opConstraint.mRightType)))
|
||||||
|
{
|
||||||
|
BF_ASSERT(genericParam->mExternType != NULL);
|
||||||
|
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check type generic constraints
|
||||||
|
if ((mModule->mCurTypeInstance->IsGenericTypeInstance()) && (mModule->mCurTypeInstance->IsUnspecializedType()))
|
||||||
|
{
|
||||||
|
auto genericTypeInst = (BfGenericTypeInstance*)mModule->mCurTypeInstance;
|
||||||
|
for (int genericParamIdx = 0; genericParamIdx < genericTypeInst->mGenericParams.size(); genericParamIdx++)
|
||||||
|
{
|
||||||
|
auto genericParam = mModule->GetGenericTypeParamInstance(genericParamIdx);
|
||||||
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
if (opConstraint.mBinaryOp == findBinaryOp)
|
||||||
|
{
|
||||||
|
if ((mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
|
||||||
|
(mModule->CanImplicitlyCast(args[1].mTypedValue, opConstraint.mRightType)))
|
||||||
|
{
|
||||||
|
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((!foundOp) || (pass == 1))
|
if ((!foundOp) || (pass == 1))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (findBinaryOp)
|
switch (findBinaryOp)
|
||||||
{
|
{
|
||||||
case BfBinaryOp_Add:
|
|
||||||
case BfBinaryOp_Multiply:
|
|
||||||
case BfBinaryOp_Equality:
|
case BfBinaryOp_Equality:
|
||||||
case BfBinaryOp_InEquality:
|
case BfBinaryOp_InEquality:
|
||||||
case BfBinaryOp_BitwiseAnd:
|
|
||||||
case BfBinaryOp_BitwiseOr:
|
|
||||||
case BfBinaryOp_ConditionalAnd:
|
|
||||||
case BfBinaryOp_ConditionalOr:
|
|
||||||
case BfBinaryOp_Compare:
|
case BfBinaryOp_Compare:
|
||||||
// Still works
|
// Still works
|
||||||
break;
|
break;
|
||||||
|
@ -17071,7 +17183,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
|
|
||||||
if (findBinaryOp == BfBinaryOp_None)
|
if (findBinaryOp == BfBinaryOp_None)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ public:
|
||||||
public:
|
public:
|
||||||
BfAstNode* mTargetSrc;
|
BfAstNode* mTargetSrc;
|
||||||
BfModule* mModule;
|
BfModule* mModule;
|
||||||
|
BfTypeDef* mActiveTypeDef;
|
||||||
String mMethodName;
|
String mMethodName;
|
||||||
BfMethodInstance* mInterfaceMethodInstance;
|
BfMethodInstance* mInterfaceMethodInstance;
|
||||||
SizedArrayImpl<BfResolvedArg>& mArguments;
|
SizedArrayImpl<BfResolvedArg>& mArguments;
|
||||||
|
@ -164,6 +165,7 @@ public:
|
||||||
BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const StringImpl& methodName, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments);
|
BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const StringImpl& methodName, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments);
|
||||||
BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL);
|
BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL);
|
||||||
void Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments);
|
void Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments);
|
||||||
|
bool IsMemberAccessible(BfTypeInstance* typeInst, BfTypeDef* declaringType);
|
||||||
bool CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass);
|
bool CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass);
|
||||||
void CheckOuterTypeStaticMethods(BfTypeInstance* typeInstance, bool isFailurePass);
|
void CheckOuterTypeStaticMethods(BfTypeInstance* typeInstance, bool isFailurePass);
|
||||||
bool WantsCheckMethod(BfProtectionCheckFlags& flags, BfTypeInstance* startTypeInstance, BfTypeInstance* checkTypeInstance, BfMethodDef* methodDef);
|
bool WantsCheckMethod(BfProtectionCheckFlags& flags, BfTypeInstance* startTypeInstance, BfTypeInstance* checkTypeInstance, BfMethodDef* methodDef);
|
||||||
|
@ -379,6 +381,7 @@ public:
|
||||||
void VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* fieldDtor);
|
void VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* fieldDtor);
|
||||||
void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic);
|
void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic);
|
||||||
void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken);
|
void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken);
|
||||||
|
void PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken);
|
||||||
void PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue = NULL);
|
void PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue = NULL);
|
||||||
void PopulateDeferrredTupleAssignData(BfTupleExpression* tupleExr, DeferredTupleAssignData& deferredTupleAssignData);
|
void PopulateDeferrredTupleAssignData(BfTupleExpression* tupleExr, DeferredTupleAssignData& deferredTupleAssignData);
|
||||||
void AssignDeferrredTupleAssignData(BfAssignmentExpression* assignExpr, DeferredTupleAssignData& deferredTupleAssignData, BfTypedValue rightValue);
|
void AssignDeferrredTupleAssignData(BfAssignmentExpression* assignExpr, DeferredTupleAssignData& deferredTupleAssignData, BfTypedValue rightValue);
|
||||||
|
|
|
@ -2471,7 +2471,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
||||||
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecializedVariation))
|
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecializedVariation))
|
||||||
return NULL; // Ignore errors on unspecialized variations, they are always dups
|
return NULL; // Ignore errors on unspecialized variations, they are always dups
|
||||||
|
|
||||||
if (!mHadBuildError)
|
if (!mHadBuildError)
|
||||||
mHadBuildError = true;
|
mHadBuildError = true;
|
||||||
if (mParentModule != NULL)
|
if (mParentModule != NULL)
|
||||||
mParentModule->mHadBuildError = true;
|
mParentModule->mHadBuildError = true;
|
||||||
|
@ -6150,17 +6150,19 @@ BfIRFunction BfModule::GetBuiltInFunc(BfBuiltInFuncType funcTypeId)
|
||||||
return mBuiltInFuncs[(int)funcTypeId];
|
return mBuiltInFuncs[(int)funcTypeId];
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, const Array<BfGenericParamDef*>& genericParamDefs, int genericParamIdx)
|
void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized)
|
||||||
{
|
{
|
||||||
BfGenericParamDef* genericParamDef = genericParamDefs[genericParamIdx];
|
BfGenericParamDef* genericParamDef = genericParamInstance->GetGenericParamDef();
|
||||||
|
BfExternalConstraintDef* externConstraintDef = genericParamInstance->GetExternConstraintDef();
|
||||||
|
BfConstraintDef* constraintDef = genericParamInstance->GetConstraintDef();
|
||||||
|
|
||||||
BfType* startingTypeConstraint = genericParamInstance->mTypeConstraint;
|
BfType* startingTypeConstraint = genericParamInstance->mTypeConstraint;
|
||||||
|
|
||||||
BfAutoComplete* bfAutocomplete = NULL;
|
BfAutoComplete* bfAutocomplete = NULL;
|
||||||
if (mCompiler->mResolvePassData != NULL)
|
if ((mCompiler->mResolvePassData != NULL) && (isUnspecialized))
|
||||||
bfAutocomplete = mCompiler->mResolvePassData->mAutoComplete;
|
bfAutocomplete = mCompiler->mResolvePassData->mAutoComplete;
|
||||||
|
|
||||||
if (bfAutocomplete != NULL)
|
if ((bfAutocomplete != NULL) && (genericParamDef != NULL))
|
||||||
{
|
{
|
||||||
for (int nameIdx = 0; nameIdx < (int)genericParamDef->mNameNodes.size(); nameIdx++)
|
for (int nameIdx = 0; nameIdx < (int)genericParamDef->mNameNodes.size(); nameIdx++)
|
||||||
{
|
{
|
||||||
|
@ -6172,16 +6174,87 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
|
||||||
bfAutocomplete->mInsertEndIdx = nameNode->GetSrcEnd();
|
bfAutocomplete->mInsertEndIdx = nameNode->GetSrcEnd();
|
||||||
|
|
||||||
if (nameIdx != 0)
|
if (nameIdx != 0)
|
||||||
{
|
{
|
||||||
for (auto checkGenericParam : genericParamDefs)
|
bfAutocomplete->AddEntry(AutoCompleteEntry("generic", nameNode->ToString().c_str()), filter);
|
||||||
bfAutocomplete->AddEntry(AutoCompleteEntry("generic", checkGenericParam->mName.c_str()), filter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto constraintTypeRef : genericParamDef->mInterfaceConstraints)
|
for (auto constraint : constraintDef->mConstraints)
|
||||||
{
|
{
|
||||||
|
if (auto opConstraint = BfNodeDynCast<BfGenericOperatorConstraint>(constraint))
|
||||||
|
{
|
||||||
|
BfGenericOperatorConstraintInstance opConstraintInstance;
|
||||||
|
|
||||||
|
if (opConstraint->mLeftType != NULL)
|
||||||
|
{
|
||||||
|
if (bfAutocomplete != NULL)
|
||||||
|
bfAutocomplete->CheckTypeRef(opConstraint->mLeftType, false);
|
||||||
|
opConstraintInstance.mLeftType = ResolveTypeRef(opConstraint->mLeftType);
|
||||||
|
if (opConstraintInstance.mLeftType == NULL)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opConstraint->mRightType == NULL)
|
||||||
|
{
|
||||||
|
// We had a failure in parsing
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opConstraint->mRightType != NULL)
|
||||||
|
{
|
||||||
|
if (bfAutocomplete != NULL)
|
||||||
|
bfAutocomplete->CheckTypeRef(opConstraint->mRightType, false);
|
||||||
|
opConstraintInstance.mRightType = ResolveTypeRef(opConstraint->mRightType);
|
||||||
|
if (opConstraintInstance.mRightType == NULL)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opConstraint->mOpToken == NULL)
|
||||||
|
{
|
||||||
|
FailAfter("Missing operator", (opConstraint->mLeftType != NULL) ? (BfAstNode*)opConstraint->mLeftType : (BfAstNode*)opConstraint->mOperatorToken);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opConstraint->mLeftType != NULL)
|
||||||
|
{
|
||||||
|
if (opConstraint->mRightType == NULL)
|
||||||
|
{
|
||||||
|
// Parse should have failed
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
opConstraintInstance.mBinaryOp = BfTokenToBinaryOp(opConstraint->mOpToken->mToken);
|
||||||
|
if (opConstraintInstance.mBinaryOp == BfBinaryOp_None)
|
||||||
|
{
|
||||||
|
Fail("Invalid binary operator", opConstraint->mOpToken);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((opConstraint->mOpToken->mToken == BfToken_Implicit) || (opConstraint->mOpToken->mToken == BfToken_Explicit))
|
||||||
|
{
|
||||||
|
opConstraintInstance.mCastToken = opConstraint->mOpToken->mToken;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opConstraintInstance.mUnaryOp = BfTokenToUnaryOp(opConstraint->mOpToken->mToken);
|
||||||
|
if (opConstraintInstance.mUnaryOp == BfBinaryOp_None)
|
||||||
|
{
|
||||||
|
Fail("Invalid unary operator", opConstraint->mOpToken);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((constraintDef->mGenericParamFlags & BfGenericParamFlag_Equals) != 0)
|
||||||
|
genericParamInstance->mGenericParamFlags = (BfGenericParamFlags)(genericParamInstance->mGenericParamFlags | BfGenericParamFlag_Equals_Op);
|
||||||
|
genericParamInstance->mOperatorConstraints.Add(opConstraintInstance);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto constraintTypeRef = BfNodeDynCast<BfTypeReference>(constraint);
|
||||||
|
|
||||||
if (bfAutocomplete != NULL)
|
if (bfAutocomplete != NULL)
|
||||||
bfAutocomplete->CheckTypeRef(constraintTypeRef, true);
|
bfAutocomplete->CheckTypeRef(constraintTypeRef, true);
|
||||||
//TODO: Constraints may refer to other generic params (of either type or method)
|
//TODO: Constraints may refer to other generic params (of either type or method)
|
||||||
|
@ -6189,7 +6262,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
|
||||||
auto constraintType = ResolveTypeRef(constraintTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericMethodParamConstValue);
|
auto constraintType = ResolveTypeRef(constraintTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericMethodParamConstValue);
|
||||||
if (constraintType != NULL)
|
if (constraintType != NULL)
|
||||||
{
|
{
|
||||||
if ((genericParamDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
|
if ((constraintDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
|
||||||
{
|
{
|
||||||
bool isValidTypeCode = false;
|
bool isValidTypeCode = false;
|
||||||
BfTypeCode typeCode = BfTypeCode_None;
|
BfTypeCode typeCode = BfTypeCode_None;
|
||||||
|
@ -6238,26 +6311,57 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bool checkEquality = false;
|
||||||
|
|
||||||
if (constraintType->IsPrimitiveType())
|
if (constraintType->IsPrimitiveType())
|
||||||
{
|
{
|
||||||
Fail("Primitive constraints are not allowed unless preceded with 'const'", constraintTypeRef);
|
if (isUnspecialized)
|
||||||
continue;
|
{
|
||||||
|
Fail("Primitive constraints are not allowed unless preceded with 'const'", constraintTypeRef);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
checkEquality = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (constraintType->IsArray())
|
if (constraintType->IsArray())
|
||||||
{
|
{
|
||||||
Fail("Array constraints are not allowed. If a constant-sized array was intended, an type parameterized by a const generic param can be used (ie: where T : int[T2] where T2 : const int)", constraintTypeRef);
|
if (isUnspecialized)
|
||||||
|
{
|
||||||
|
Fail("Array constraints are not allowed. If a constant-sized array was intended, an type parameterized by a const generic param can be used (ie: where T : int[T2] where T2 : const int)", constraintTypeRef);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
checkEquality = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constraintType->IsGenericParam())
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!constraintType->IsTypeInstance()) && (!constraintType->IsSizedArray()))
|
if ((!constraintType->IsTypeInstance()) && (!constraintType->IsSizedArray()))
|
||||||
{
|
{
|
||||||
Fail(StrFormat("Type '%s' is not allowed as a generic constraint", TypeToString(constraintType).c_str()), constraintTypeRef);
|
if (isUnspecialized)
|
||||||
continue;
|
{
|
||||||
|
Fail(StrFormat("Type '%s' is not allowed as a generic constraint", TypeToString(constraintType).c_str()), constraintTypeRef);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
checkEquality = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (constraintType->IsInterface())
|
if ((constraintDef->mGenericParamFlags & BfGenericParamFlag_Equals) != 0)
|
||||||
{
|
{
|
||||||
|
genericParamInstance->mGenericParamFlags = (BfGenericParamFlags)(genericParamInstance->mGenericParamFlags | BfGenericParamFlag_Equals_Type);
|
||||||
|
checkEquality = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkEquality)
|
||||||
|
{
|
||||||
|
genericParamInstance->mTypeConstraint = constraintType;
|
||||||
|
}
|
||||||
|
else if (constraintType->IsInterface())
|
||||||
|
{
|
||||||
|
if ((constraintDef->mGenericParamFlags & BfGenericParamFlag_Equals) != 0)
|
||||||
|
genericParamInstance->mGenericParamFlags = (BfGenericParamFlags)(genericParamInstance->mGenericParamFlags | BfGenericParamFlag_Equals_IFace);
|
||||||
genericParamInstance->mInterfaceConstraints.push_back(constraintType->ToTypeInstance());
|
genericParamInstance->mInterfaceConstraints.push_back(constraintType->ToTypeInstance());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -6292,7 +6396,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((genericParamDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0) &&
|
if (((constraintDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0) &&
|
||||||
(genericParamInstance->mTypeConstraint == NULL))
|
(genericParamInstance->mTypeConstraint == NULL))
|
||||||
genericParamInstance->mTypeConstraint = GetPrimitiveType(BfTypeCode_IntPtr);
|
genericParamInstance->mTypeConstraint = GetPrimitiveType(BfTypeCode_IntPtr);
|
||||||
}
|
}
|
||||||
|
@ -6342,7 +6446,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
{
|
{
|
||||||
argMayBeReferenceType = true;
|
argMayBeReferenceType = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkArgType->IsObjectOrInterface())
|
if (checkArgType->IsObjectOrInterface())
|
||||||
argMayBeReferenceType = true;
|
argMayBeReferenceType = true;
|
||||||
|
@ -6356,7 +6460,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("The type '%s' must be a value type in order to use it as parameter '%s' for '%s'",
|
*errorOut = Fail(StrFormat("The type '%s' must be a value type in order to use it as parameter '%s' for '%s'",
|
||||||
TypeToString(origCheckArgType).c_str(), genericParamInst->GetGenericParamDef()->mName.c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6365,7 +6469,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("The type '%s' must be a pointer type in order to use it as parameter '%s' for '%s'",
|
*errorOut = Fail(StrFormat("The type '%s' must be a pointer type in order to use it as parameter '%s' for '%s'",
|
||||||
TypeToString(origCheckArgType).c_str(), genericParamInst->GetGenericParamDef()->mName.c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6374,7 +6478,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("The type '%s' must be a reference type in order to use it as parameter '%s' for '%s'",
|
*errorOut = Fail(StrFormat("The type '%s' must be a reference type in order to use it as parameter '%s' for '%s'",
|
||||||
TypeToString(origCheckArgType).c_str(), genericParamInst->GetGenericParamDef()->mName.c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6384,7 +6488,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("The type '%s' must be a const value in order to use it as parameter '%s' for '%s'",
|
*errorOut = Fail(StrFormat("The type '%s' must be a const value in order to use it as parameter '%s' for '%s'",
|
||||||
TypeToString(origCheckArgType).c_str(), genericParamInst->GetGenericParamDef()->mName.c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6394,12 +6498,12 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("The value '%s' cannot be used for generic type parameter '%s' for '%s'",
|
*errorOut = Fail(StrFormat("The value '%s' cannot be used for generic type parameter '%s' for '%s'",
|
||||||
TypeToString(origCheckArgType).c_str(), genericParamInst->GetGenericParamDef()->mName.c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((genericParamInst->mInterfaceConstraints.size() == 0) && (genericParamInst->mTypeConstraint == NULL))
|
if ((genericParamInst->mInterfaceConstraints.IsEmpty()) && (genericParamInst->mOperatorConstraints.IsEmpty()) && (genericParamInst->mTypeConstraint == NULL))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (checkArgType->IsPointer())
|
if (checkArgType->IsPointer())
|
||||||
|
@ -6435,7 +6539,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue.mInt64))
|
if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue.mInt64))
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with const '%lld', does not fit into const constraint '%s' for '%s'", genericParamInst->GetGenericParamDef()->mName.c_str(),
|
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with const '%lld', does not fit into const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
|
||||||
constExprValueType->mValue.mInt64, TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
constExprValueType->mValue.mInt64, TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -6443,7 +6547,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with integer const '%lld', is not compatible with const constraint '%s' for '%s'", genericParamInst->GetGenericParamDef()->mName.c_str(),
|
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with integer const '%lld', is not compatible with const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
|
||||||
constExprValueType->mValue.mInt64, TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
constExprValueType->mValue.mInt64, TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -6455,7 +6559,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
char valStr[64];
|
char valStr[64];
|
||||||
ExactMinimalDoubleToStr(constExprValueType->mValue.mDouble, valStr);
|
ExactMinimalDoubleToStr(constExprValueType->mValue.mDouble, valStr);
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with floating point const '%s', is not compatible with const constraint '%s' for '%s'", genericParamInst->GetGenericParamDef()->mName.c_str(),
|
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with floating point const '%s', is not compatible with const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
|
||||||
valStr, TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
valStr, TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -6514,7 +6618,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
if (!constraintMatched)
|
if (!constraintMatched)
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must derive from '%s'", genericParamInst->GetGenericParamDef()->mName.c_str(),
|
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must derive from '%s'", genericParamInst->GetName().c_str(),
|
||||||
TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(), TypeToString(convCheckConstraint).c_str(),
|
TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(), TypeToString(convCheckConstraint).c_str(),
|
||||||
TypeToString(genericParamInst->mTypeConstraint).c_str()), checkArgTypeRef);
|
TypeToString(genericParamInst->mTypeConstraint).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
|
@ -6529,7 +6633,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
if (checkTypeInst->mTypeDef->mIsConcrete)
|
if (checkTypeInst->mTypeDef->mIsConcrete)
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be concrete interface '%s' for '%s', must be a concrete type", genericParamInst->GetGenericParamDef()->mName.c_str(),
|
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be concrete interface '%s' for '%s', must be a concrete type", genericParamInst->GetName().c_str(),
|
||||||
TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -6570,11 +6674,100 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
if (!implementsInterface)
|
if (!implementsInterface)
|
||||||
{
|
{
|
||||||
if (!ignoreErrors)
|
if (!ignoreErrors)
|
||||||
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must implement '%s'", genericParamInst->GetGenericParamDef()->mName.c_str(),
|
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must implement '%s'", genericParamInst->GetName().c_str(),
|
||||||
TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(), TypeToString(checkConstraint).c_str()), checkArgTypeRef);
|
TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(), TypeToString(checkConstraint).c_str()), checkArgTypeRef);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& checkOpConstraint : genericParamInst->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
auto leftType = checkOpConstraint.mLeftType;
|
||||||
|
if ((leftType != NULL) && (leftType->IsUnspecializedType()))
|
||||||
|
leftType = ResolveGenericType(leftType, *methodGenericArgs);
|
||||||
|
if (leftType != NULL)
|
||||||
|
leftType = FixIntUnknown(leftType);
|
||||||
|
|
||||||
|
auto rightType = checkOpConstraint.mRightType;
|
||||||
|
if ((rightType != NULL) && (rightType->IsUnspecializedType()))
|
||||||
|
rightType = ResolveGenericType(rightType, *methodGenericArgs);
|
||||||
|
if (rightType != NULL)
|
||||||
|
rightType = FixIntUnknown(rightType);
|
||||||
|
|
||||||
|
if (checkOpConstraint.mBinaryOp != BfBinaryOp_None)
|
||||||
|
{
|
||||||
|
BfExprEvaluator exprEvaluator(this);
|
||||||
|
|
||||||
|
BfTypedValue leftValue(mBfIRBuilder->GetFakeVal(), leftType);
|
||||||
|
BfTypedValue rightValue(mBfIRBuilder->GetFakeVal(), rightType);
|
||||||
|
|
||||||
|
//
|
||||||
|
{
|
||||||
|
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
|
||||||
|
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
|
||||||
|
exprEvaluator.PerformBinaryOperation(NULL, NULL, checkOpConstraint.mBinaryOp, NULL, BfBinOpFlag_NoClassify, leftValue, rightValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((exprEvaluator.mResult == NULL) ||
|
||||||
|
(!CanImplicitlyCast(exprEvaluator.mResult, origCheckArgType)))
|
||||||
|
{
|
||||||
|
if (!ignoreErrors)
|
||||||
|
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from binary operation '%s %s %s'", genericParamInst->GetName().c_str(),
|
||||||
|
TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(),
|
||||||
|
TypeToString(leftType).c_str(), BfGetOpName(checkOpConstraint.mBinaryOp), TypeToString(rightType).c_str()
|
||||||
|
), checkArgTypeRef);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BfTypedValue rightValue(mBfIRBuilder->GetFakeVal(), rightType);
|
||||||
|
|
||||||
|
StringT<128> failedOpName;
|
||||||
|
|
||||||
|
if (checkOpConstraint.mCastToken == BfToken_Implicit)
|
||||||
|
{
|
||||||
|
if (!CanImplicitlyCast(rightValue, origCheckArgType, BfCastFlags_SilentFail))
|
||||||
|
failedOpName = "implicit conversion from '";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
|
||||||
|
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
|
||||||
|
|
||||||
|
if (checkOpConstraint.mCastToken == BfToken_Explicit)
|
||||||
|
{
|
||||||
|
if (!CastToValue(NULL, rightValue, origCheckArgType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail)))
|
||||||
|
failedOpName = "explicit conversion from '";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BfExprEvaluator exprEvaluator(this);
|
||||||
|
exprEvaluator.mResult = rightValue;
|
||||||
|
exprEvaluator.PerformUnaryOperation(NULL, checkOpConstraint.mUnaryOp, NULL);
|
||||||
|
|
||||||
|
if ((exprEvaluator.mResult == NULL) ||
|
||||||
|
(!CanImplicitlyCast(exprEvaluator.mResult, origCheckArgType)))
|
||||||
|
{
|
||||||
|
failedOpName += "unary operation '";
|
||||||
|
failedOpName += BfGetOpName(checkOpConstraint.mUnaryOp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!failedOpName.IsEmpty())
|
||||||
|
{
|
||||||
|
if (!ignoreErrors)
|
||||||
|
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from %s%s'", genericParamInst->GetName().c_str(),
|
||||||
|
TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(),
|
||||||
|
failedOpName.c_str(), TypeToString(rightType).c_str()
|
||||||
|
), checkArgTypeRef);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10389,6 +10582,9 @@ bool BfModule::CheckModifyValue(BfTypedValue& typedValue, BfAstNode* refNode, co
|
||||||
|
|
||||||
bool BfModule::CompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB)
|
bool BfModule::CompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB)
|
||||||
{
|
{
|
||||||
|
// If one is an interface and the other is an impl, B is the impl
|
||||||
|
auto implOwner = methodB->GetOwner();
|
||||||
|
|
||||||
if (methodA->mMethodDef->mIsLocalMethod)
|
if (methodA->mMethodDef->mIsLocalMethod)
|
||||||
{
|
{
|
||||||
int sepPosA = (int)BF_MIN(methodA->mMethodDef->mName.IndexOf('@'), methodA->mMethodDef->mName.length());
|
int sepPosA = (int)BF_MIN(methodA->mMethodDef->mName.IndexOf('@'), methodA->mMethodDef->mName.length());
|
||||||
|
@ -10421,7 +10617,7 @@ bool BfModule::CompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstan
|
||||||
return false;
|
return false;
|
||||||
if (operatorA->mOperatorDeclaration->mIsConvOperator)
|
if (operatorA->mOperatorDeclaration->mIsConvOperator)
|
||||||
{
|
{
|
||||||
if (methodA->mReturnType != methodB->mReturnType)
|
if (!BfTypeUtils::TypeEquals(methodA->mReturnType, methodB->mReturnType, implOwner))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10437,13 +10633,11 @@ bool BfModule::CompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstan
|
||||||
|
|
||||||
for (int paramIdx = 0; paramIdx < (int)methodA->GetParamCount() - implicitParamCountA; paramIdx++)
|
for (int paramIdx = 0; paramIdx < (int)methodA->GetParamCount() - implicitParamCountA; paramIdx++)
|
||||||
{
|
{
|
||||||
if ((methodA->GetParamType(paramIdx + implicitParamCountA) != methodB->GetParamType(paramIdx + implicitParamCountB)) ||
|
if ((!BfTypeUtils::TypeEquals(methodA->GetParamType(paramIdx + implicitParamCountA), methodB->GetParamType(paramIdx + implicitParamCountB), implOwner)) ||
|
||||||
(methodA->GetParamKind(paramIdx + implicitParamCountA) != methodB->GetParamKind(paramIdx + implicitParamCountB)))
|
(methodA->GetParamKind(paramIdx + implicitParamCountA) != methodB->GetParamKind(paramIdx + implicitParamCountB)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Compare generic params. Generic params are part of the method signature here
|
// Compare generic params. Generic params are part of the method signature here
|
||||||
if (methodA->GetNumGenericParams() != methodB->GetNumGenericParams())
|
if (methodA->GetNumGenericParams() != methodB->GetNumGenericParams())
|
||||||
return false;
|
return false;
|
||||||
|
@ -11403,6 +11597,12 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
|
||||||
auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx);
|
auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx);
|
||||||
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
|
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int externConstraintIdx = 0; externConstraintIdx < (int)methodDef->mExternalConstraints.size(); externConstraintIdx++)
|
||||||
|
{
|
||||||
|
auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, externConstraintIdx + (int)methodDef->mGenericParams.size());
|
||||||
|
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
|
||||||
|
}
|
||||||
|
|
||||||
bool addToWorkList = !processNow;
|
bool addToWorkList = !processNow;
|
||||||
if (mCompiler->GetAutoComplete() != NULL)
|
if (mCompiler->GetAutoComplete() != NULL)
|
||||||
|
@ -18578,23 +18778,48 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
BfAutoComplete* bfAutocomplete = NULL;
|
BfAutoComplete* bfAutocomplete = NULL;
|
||||||
if (mCompiler->mResolvePassData != NULL)
|
if (mCompiler->mResolvePassData != NULL)
|
||||||
bfAutocomplete = mCompiler->mResolvePassData->mAutoComplete;
|
bfAutocomplete = mCompiler->mResolvePassData->mAutoComplete;
|
||||||
|
|
||||||
for (int genericParamIdx = 0; genericParamIdx < (int)methodInstance->GetNumGenericArguments(); genericParamIdx++)
|
|
||||||
{
|
|
||||||
auto genericParamDef = methodDef->mGenericParams[genericParamIdx];
|
|
||||||
ResolveGenericParamConstraints(methodInstance->mMethodInfoEx->mGenericParams[genericParamIdx], methodDef->mGenericParams, genericParamIdx);
|
|
||||||
|
|
||||||
if (bfAutocomplete != NULL)
|
|
||||||
{
|
|
||||||
for (auto nameNode : genericParamDef->mNameNodes)
|
|
||||||
{
|
|
||||||
HandleMethodGenericParamRef(nameNode, typeDef, methodDef, genericParamIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (methodInstance->mMethodInfoEx != NULL)
|
if (methodInstance->mMethodInfoEx != NULL)
|
||||||
{
|
{
|
||||||
|
for (int genericParamIdx = 0; genericParamIdx < (int)methodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
||||||
|
{
|
||||||
|
auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
||||||
|
if (genericParamIdx < (int)methodDef->mGenericParams.size())
|
||||||
|
{
|
||||||
|
genericParam->mExternType = GetGenericParamType(BfGenericParamKind_Method, genericParamIdx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto externConstraintDef = genericParam->GetExternConstraintDef();
|
||||||
|
genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
|
||||||
|
|
||||||
|
auto autoComplete = mCompiler->GetAutoComplete();
|
||||||
|
if (autoComplete != NULL)
|
||||||
|
autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false);
|
||||||
|
|
||||||
|
if (genericParam->mExternType != NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
else
|
||||||
|
genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolveGenericParamConstraints(genericParam, methodInstance->mIsUnspecialized);
|
||||||
|
|
||||||
|
if (genericParamIdx < (int)methodDef->mGenericParams.size())
|
||||||
|
{
|
||||||
|
auto genericParamDef = methodDef->mGenericParams[genericParamIdx];
|
||||||
|
if (bfAutocomplete != NULL)
|
||||||
|
{
|
||||||
|
for (auto nameNode : genericParamDef->mNameNodes)
|
||||||
|
{
|
||||||
|
HandleMethodGenericParamRef(nameNode, typeDef, methodDef, genericParamIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto genericParam : methodInstance->mMethodInfoEx->mGenericParams)
|
for (auto genericParam : methodInstance->mMethodInfoEx->mGenericParams)
|
||||||
{
|
{
|
||||||
for (auto constraintTypeInst : genericParam->mInterfaceConstraints)
|
for (auto constraintTypeInst : genericParam->mInterfaceConstraints)
|
||||||
|
@ -19412,7 +19637,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
{
|
{
|
||||||
if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType))
|
if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool silentlyAllow = false;
|
bool silentlyAllow = false;
|
||||||
if (checkMethod->mDeclaringType != methodDef->mDeclaringType)
|
if (checkMethod->mDeclaringType != methodDef->mDeclaringType)
|
||||||
{
|
{
|
||||||
|
@ -19424,10 +19649,13 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
else
|
else
|
||||||
silentlyAllow = true;
|
silentlyAllow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse))
|
||||||
|
silentlyAllow = true;
|
||||||
|
|
||||||
if (!silentlyAllow)
|
if (!silentlyAllow)
|
||||||
{
|
{
|
||||||
if (!methodDef->mName.IsEmpty())
|
if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator))
|
||||||
{
|
{
|
||||||
auto refNode = methodDef->GetRefNode();
|
auto refNode = methodDef->GetRefNode();
|
||||||
auto bfError = Fail("Method already declared with the same parameter types", refNode, true);
|
auto bfError = Fail("Method already declared with the same parameter types", refNode, true);
|
||||||
|
|
|
@ -1537,6 +1537,7 @@ public:
|
||||||
bool ValidateGenericConstraints(BfTypeReference* typeRef, BfGenericTypeInstance* genericTypeInstance, bool ignoreErrors);
|
bool ValidateGenericConstraints(BfTypeReference* typeRef, BfGenericTypeInstance* genericTypeInstance, bool ignoreErrors);
|
||||||
bool AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGenericParamInstance* checkOuter);
|
bool AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGenericParamInstance* checkOuter);
|
||||||
bool ShouldAllowMultipleDefinitions(BfTypeInstance* typeInst, BfTypeDef* firstDeclaringTypeDef, BfTypeDef* secondDeclaringTypeDef);
|
bool ShouldAllowMultipleDefinitions(BfTypeInstance* typeInst, BfTypeDef* firstDeclaringTypeDef, BfTypeDef* secondDeclaringTypeDef);
|
||||||
|
void CheckInjectNewRevision(BfTypeInstance* typeInstance);
|
||||||
bool InitType(BfType* resolvedTypeRef, BfPopulateType populateType);
|
bool InitType(BfType* resolvedTypeRef, BfPopulateType populateType);
|
||||||
bool CheckAccessMemberProtection(BfProtection protection, BfType* memberType);
|
bool CheckAccessMemberProtection(BfProtection protection, BfType* memberType);
|
||||||
bool CheckDefineMemberProtection(BfProtection protection, BfType* memberType);
|
bool CheckDefineMemberProtection(BfProtection protection, BfType* memberType);
|
||||||
|
@ -1589,7 +1590,7 @@ public:
|
||||||
void FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs);
|
void FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs);
|
||||||
BfTypeDef* ResolveGenericInstanceDef(BfGenericInstanceTypeRef* genericTypeRef);
|
BfTypeDef* ResolveGenericInstanceDef(BfGenericInstanceTypeRef* genericTypeRef);
|
||||||
BfType* ResolveType(BfType* lookupType, BfPopulateType populateType = BfPopulateType_Data);
|
BfType* ResolveType(BfType* lookupType, BfPopulateType populateType = BfPopulateType_Data);
|
||||||
void ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, const Array<BfGenericParamDef*>& genericParamDefs, int genericParamIdx);
|
void ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized);
|
||||||
String GenericParamSourceToString(const BfGenericParamSource& genericParamSource);
|
String GenericParamSourceToString(const BfGenericParamSource& genericParamSource);
|
||||||
bool CheckGenericConstraints(const BfGenericParamSource& genericParamSource, BfType* checkArgType, BfAstNode* checkArgTypeRef, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs = NULL, BfError** errorOut = NULL);
|
bool CheckGenericConstraints(const BfGenericParamSource& genericParamSource, BfType* checkArgType, BfAstNode* checkArgTypeRef, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs = NULL, BfError** errorOut = NULL);
|
||||||
BfIRValue AllocLocalVariable(BfType* type, const StringImpl& name, bool doLifetimeEnd = true);
|
BfIRValue AllocLocalVariable(BfType* type, const StringImpl& name, bool doLifetimeEnd = true);
|
||||||
|
@ -1619,6 +1620,7 @@ public:
|
||||||
BfGenericParamType* GetGenericParamType(BfGenericParamKind paramKind, int paramIdx);
|
BfGenericParamType* GetGenericParamType(BfGenericParamKind paramKind, int paramIdx);
|
||||||
BfType* ResolveGenericType(BfType* unspecializedType, const BfTypeVector& methodGenericArguments, bool allowFail = false);
|
BfType* ResolveGenericType(BfType* unspecializedType, const BfTypeVector& methodGenericArguments, bool allowFail = false);
|
||||||
bool IsUnboundGeneric(BfType* type);
|
bool IsUnboundGeneric(BfType* type);
|
||||||
|
BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx);
|
||||||
BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type);
|
BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type);
|
||||||
BfTypeInstance* GetBaseType(BfTypeInstance* typeInst);
|
BfTypeInstance* GetBaseType(BfTypeInstance* typeInst);
|
||||||
void HandleTypeGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, int typeGenericParamIdx);
|
void HandleTypeGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, int typeGenericParamIdx);
|
||||||
|
|
|
@ -57,6 +57,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfGenericTypeInstan
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypeState typeState;
|
BfTypeState typeState;
|
||||||
|
typeState.mTypeInstance = genericTypeInst;
|
||||||
typeState.mCurTypeDef = partialTypeDef;
|
typeState.mCurTypeDef = partialTypeDef;
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
|
@ -71,6 +72,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfGenericTypeInstan
|
||||||
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mTypeGenericArguments.size(); paramIdx++)
|
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mTypeGenericArguments.size(); paramIdx++)
|
||||||
{
|
{
|
||||||
auto genericParamInstance = new BfGenericTypeParamInstance(partialTypeDef, paramIdx);
|
auto genericParamInstance = new BfGenericTypeParamInstance(partialTypeDef, paramIdx);
|
||||||
|
genericParamInstance->mExternType = GetGenericParamType(BfGenericParamKind_Type, paramIdx);
|
||||||
genericExEntry->mGenericParams.push_back(genericParamInstance);
|
genericExEntry->mGenericParams.push_back(genericParamInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfGenericTypeInstan
|
||||||
genericParamInstance->mInterfaceConstraints = rootGenericParamInstance->mInterfaceConstraints;
|
genericParamInstance->mInterfaceConstraints = rootGenericParamInstance->mInterfaceConstraints;
|
||||||
genericParamInstance->mGenericParamFlags |= rootGenericParamInstance->mGenericParamFlags;
|
genericParamInstance->mGenericParamFlags |= rootGenericParamInstance->mGenericParamFlags;
|
||||||
|
|
||||||
ResolveGenericParamConstraints(genericParamInstance, partialTypeDef->mGenericParamDefs, paramIdx);
|
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto genericParam : genericExEntry->mGenericParams)
|
for (auto genericParam : genericExEntry->mGenericParams)
|
||||||
|
@ -116,8 +118,9 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
||||||
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mTypeGenericArguments.size(); paramIdx++)
|
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mTypeGenericArguments.size(); paramIdx++)
|
||||||
{
|
{
|
||||||
auto genericParamInstance = new BfGenericTypeParamInstance(typeDef, paramIdx);
|
auto genericParamInstance = new BfGenericTypeParamInstance(typeDef, paramIdx);
|
||||||
|
genericParamInstance->mExternType = GetGenericParamType(BfGenericParamKind_Type, paramIdx);
|
||||||
genericTypeInst->mGenericParams.push_back(genericParamInstance);
|
genericTypeInst->mGenericParams.push_back(genericParamInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!typeDef->mPartials.empty())
|
if (!typeDef->mPartials.empty())
|
||||||
{
|
{
|
||||||
|
@ -130,7 +133,7 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
||||||
{
|
{
|
||||||
auto genericParamDef = typeDef->mGenericParamDefs[paramIdx];
|
auto genericParamDef = typeDef->mGenericParamDefs[paramIdx];
|
||||||
auto genericParamInstance = genericTypeInst->mGenericParams[paramIdx];
|
auto genericParamInstance = genericTypeInst->mGenericParams[paramIdx];
|
||||||
ResolveGenericParamConstraints(genericParamInstance, typeDef->mGenericParamDefs, paramIdx);
|
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
|
||||||
|
|
||||||
for (auto nameNode : genericParamDef->mNameNodes)
|
for (auto nameNode : genericParamDef->mNameNodes)
|
||||||
{
|
{
|
||||||
|
@ -164,15 +167,17 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mTypeGenericArguments.size(); paramIdx++)
|
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericParams.size(); paramIdx++)
|
||||||
{
|
{
|
||||||
auto genericParamInstance = genericTypeInst->mGenericParams[paramIdx];
|
auto genericParamInstance = genericTypeInst->mGenericParams[paramIdx];
|
||||||
ResolveGenericParamConstraints(genericParamInstance, typeDef->mGenericParamDefs, paramIdx);
|
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
|
||||||
auto genericParamDef = typeDef->mGenericParamDefs[paramIdx];
|
auto genericParamDef = genericParamInstance->GetGenericParamDef();
|
||||||
|
if (genericParamDef != NULL)
|
||||||
for (auto nameNode : genericParamDef->mNameNodes)
|
|
||||||
{
|
{
|
||||||
HandleTypeGenericParamRef(nameNode, typeDef, paramIdx);
|
for (auto nameNode : genericParamDef->mNameNodes)
|
||||||
|
{
|
||||||
|
HandleTypeGenericParamRef(nameNode, typeDef, paramIdx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,6 +266,12 @@ bool BfModule::AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGeneri
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& innerOp : checkInner->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
if (!checkOuter->mOperatorConstraints.Contains(innerOp))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,6 +316,37 @@ bool BfModule::ShouldAllowMultipleDefinitions(BfTypeInstance* typeInst, BfTypeDe
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfModule::CheckInjectNewRevision(BfTypeInstance* typeInstance)
|
||||||
|
{
|
||||||
|
if ((typeInstance != NULL) && (typeInstance->mTypeDef != NULL))
|
||||||
|
{
|
||||||
|
if (typeInstance->mTypeDef->mNextRevision != NULL)
|
||||||
|
{
|
||||||
|
// It's possible that our main compiler thread is generating a new typedef while we're autocompleting. This handles that case...
|
||||||
|
if (typeInstance->mDefineState == BfTypeDefineState_Undefined)
|
||||||
|
{
|
||||||
|
if (typeInstance->IsBoxed())
|
||||||
|
{
|
||||||
|
BfBoxedType* boxedType = (BfBoxedType*)typeInstance;
|
||||||
|
BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance();
|
||||||
|
PopulateType(innerType, BfPopulateType_Data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mContext->HandleChangedTypeDef(typeInstance->mTypeDef);
|
||||||
|
mSystem->InjectNewRevision(typeInstance->mTypeDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BF_ASSERT(mCompiler->IsAutocomplete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((!typeInstance->IsDeleting()) && (!mCompiler->IsAutocomplete()))
|
||||||
|
BF_ASSERT((typeInstance->mTypeDef->mDefState == BfTypeDef::DefState_Defined) || (typeInstance->mTypeDef->mDefState == BfTypeDef::DefState_New));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
bool BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
||||||
{
|
{
|
||||||
BP_ZONE("BfModule::InitType");
|
BP_ZONE("BfModule::InitType");
|
||||||
|
@ -318,6 +360,8 @@ bool BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
||||||
auto typeInst = resolvedTypeRef->ToTypeInstance();
|
auto typeInst = resolvedTypeRef->ToTypeInstance();
|
||||||
if (typeInst != NULL)
|
if (typeInst != NULL)
|
||||||
{
|
{
|
||||||
|
CheckInjectNewRevision(typeInst);
|
||||||
|
|
||||||
if (typeInst->mBaseType != NULL)
|
if (typeInst->mBaseType != NULL)
|
||||||
BF_ASSERT((typeInst->mBaseType->mRebuildFlags & BfTypeRebuildFlag_Deleted) == 0);
|
BF_ASSERT((typeInst->mBaseType->mRebuildFlags & BfTypeRebuildFlag_Deleted) == 0);
|
||||||
|
|
||||||
|
@ -606,22 +650,6 @@ bool BfModule::CheckCircularDataError()
|
||||||
{
|
{
|
||||||
bool hadError = false;
|
bool hadError = false;
|
||||||
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
auto checkTypeState = mContext->mCurTypeState;
|
|
||||||
while (checkTypeState != NULL)
|
|
||||||
{
|
|
||||||
checkTypeState = checkTypeState->mPrevState;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > 20)
|
|
||||||
{
|
|
||||||
NOP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int checkIdx = 0;
|
int checkIdx = 0;
|
||||||
auto checkTypeState = mContext->mCurTypeState;
|
auto checkTypeState = mContext->mCurTypeState;
|
||||||
bool isPreBaseCheck = checkTypeState->mPopulateType == BfPopulateType_Declaration;
|
bool isPreBaseCheck = checkTypeState->mPopulateType == BfPopulateType_Declaration;
|
||||||
|
@ -748,33 +776,7 @@ bool BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto typeInstance = resolvedTypeRef->ToTypeInstance();
|
auto typeInstance = resolvedTypeRef->ToTypeInstance();
|
||||||
if ((typeInstance != NULL) && (typeInstance->mTypeDef != NULL))
|
CheckInjectNewRevision(typeInstance);
|
||||||
{
|
|
||||||
if (typeInstance->mTypeDef->mNextRevision != NULL)
|
|
||||||
{
|
|
||||||
// It's possible that our main compiler thread is generating a new typedef while we're autocompleting. This handles that case...
|
|
||||||
if (typeInstance->mDefineState == BfTypeDefineState_Undefined)
|
|
||||||
{
|
|
||||||
if (typeInstance->IsBoxed())
|
|
||||||
{
|
|
||||||
BfBoxedType* boxedType = (BfBoxedType*)typeInstance;
|
|
||||||
BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance();
|
|
||||||
PopulateType(innerType, BfPopulateType_Data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mContext->HandleChangedTypeDef(typeInstance->mTypeDef);
|
|
||||||
mSystem->InjectNewRevision(typeInstance->mTypeDef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BF_ASSERT(mCompiler->IsAutocomplete());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((!typeInstance->IsDeleting()) && (!mCompiler->IsAutocomplete()))
|
|
||||||
BF_ASSERT(typeInstance->mTypeDef->mDefState == BfTypeDef::DefState_Defined);
|
|
||||||
}
|
|
||||||
|
|
||||||
BF_ASSERT((resolvedTypeRef->mRebuildFlags & (BfTypeRebuildFlag_Deleted | BfTypeRebuildFlag_DeleteQueued)) == 0);
|
BF_ASSERT((resolvedTypeRef->mRebuildFlags & (BfTypeRebuildFlag_Deleted | BfTypeRebuildFlag_DeleteQueued)) == 0);
|
||||||
|
|
||||||
|
@ -2167,6 +2169,10 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
|
|
||||||
if (propDef->mFieldDeclaration != NULL)
|
if (propDef->mFieldDeclaration != NULL)
|
||||||
{
|
{
|
||||||
|
BfTypeState typeState;
|
||||||
|
typeState.mCurTypeDef = propDef->mDeclaringType;
|
||||||
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
if (propDef->mFieldDeclaration->mAttributes != NULL)
|
if (propDef->mFieldDeclaration->mAttributes != NULL)
|
||||||
{
|
{
|
||||||
auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property);
|
auto customAttrs = GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property);
|
||||||
|
@ -2181,11 +2187,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
|
|
||||||
auto propDecl = (BfPropertyDeclaration*)propDef->mFieldDeclaration;
|
auto propDecl = (BfPropertyDeclaration*)propDef->mFieldDeclaration;
|
||||||
if (propDecl->mExplicitInterface != NULL)
|
if (propDecl->mExplicitInterface != NULL)
|
||||||
{
|
{
|
||||||
BfTypeState typeState;
|
|
||||||
typeState.mCurTypeDef = propDef->mDeclaringType;
|
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
|
||||||
|
|
||||||
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
|
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
|
||||||
mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(propDecl->mExplicitInterface, false);
|
mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(propDecl->mExplicitInterface, false);
|
||||||
auto explicitInterface = ResolveTypeRef(propDecl->mExplicitInterface, BfPopulateType_Declaration);
|
auto explicitInterface = ResolveTypeRef(propDecl->mExplicitInterface, BfPopulateType_Declaration);
|
||||||
|
@ -4841,9 +4843,15 @@ BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType
|
||||||
return resolvedtypeDefType;
|
return resolvedtypeDefType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get BaseClass even when we haven't populated the type yet
|
// Get BaseClass even when we haven't populated the type yet2
|
||||||
BfTypeInstance* BfModule::GetBaseType(BfTypeInstance* typeInst)
|
BfTypeInstance* BfModule::GetBaseType(BfTypeInstance* typeInst)
|
||||||
{
|
{
|
||||||
|
if ((mContext->mCurTypeState != NULL) && (mContext->mCurTypeState->mTypeInstance == typeInst))
|
||||||
|
{
|
||||||
|
if (typeInst->mBaseType == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if ((typeInst->mBaseType == NULL) && (typeInst != mContext->mBfObjectType))
|
if ((typeInst->mBaseType == NULL) && (typeInst != mContext->mBfObjectType))
|
||||||
PopulateType(typeInst, BfPopulateType_BaseType);
|
PopulateType(typeInst, BfPopulateType_BaseType);
|
||||||
return typeInst->mBaseType;
|
return typeInst->mBaseType;
|
||||||
|
@ -5093,6 +5101,7 @@ bool BfModule::IsInnerType(BfType* checkInnerType, BfType* checkOuterType)
|
||||||
|
|
||||||
bool BfModule::IsInnerType(BfTypeDef* checkInnerType, BfTypeDef* checkOuterType)
|
bool BfModule::IsInnerType(BfTypeDef* checkInnerType, BfTypeDef* checkOuterType)
|
||||||
{
|
{
|
||||||
|
BF_ASSERT(!checkOuterType->mIsPartial);
|
||||||
if (checkInnerType->mNestDepth <= checkOuterType->mNestDepth)
|
if (checkInnerType->mNestDepth <= checkOuterType->mNestDepth)
|
||||||
return false;
|
return false;
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -5100,6 +5109,8 @@ bool BfModule::IsInnerType(BfTypeDef* checkInnerType, BfTypeDef* checkOuterType)
|
||||||
BfTypeDef* outerType = checkInnerType->mOuterType;
|
BfTypeDef* outerType = checkInnerType->mOuterType;
|
||||||
if (outerType == NULL)
|
if (outerType == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
if (outerType->mIsPartial)
|
||||||
|
outerType = mSystem->GetCombinedPartial(outerType);
|
||||||
if (outerType == checkOuterType)
|
if (outerType == checkOuterType)
|
||||||
return true;
|
return true;
|
||||||
checkInnerType = checkInnerType->mOuterType;
|
checkInnerType = checkInnerType->mOuterType;
|
||||||
|
@ -5482,11 +5493,8 @@ bool BfModule::IsUnboundGeneric(BfType* type)
|
||||||
return (genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0;
|
return (genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* type)
|
BfGenericParamInstance* BfModule::GetGenericTypeParamInstance(int genericParamIdx)
|
||||||
{
|
{
|
||||||
if (type->mGenericParamKind == BfGenericParamKind_Method)
|
|
||||||
return mCurMethodInstance->mMethodInfoEx->mGenericParams[type->mGenericParamIdx];
|
|
||||||
|
|
||||||
// When we're evaluating a method, make sure the params refer back to that method context
|
// When we're evaluating a method, make sure the params refer back to that method context
|
||||||
auto curTypeInstance = mCurTypeInstance;
|
auto curTypeInstance = mCurTypeInstance;
|
||||||
if (mCurMethodInstance != NULL)
|
if (mCurMethodInstance != NULL)
|
||||||
|
@ -5505,23 +5513,35 @@ BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* ty
|
||||||
auto activeTypeDef = GetActiveTypeDef(NULL, true);
|
auto activeTypeDef = GetActiveTypeDef(NULL, true);
|
||||||
if ((activeTypeDef->mTypeDeclaration != genericTypeInst->mTypeDef->mTypeDeclaration) && (activeTypeDef->IsExtension()))
|
if ((activeTypeDef->mTypeDeclaration != genericTypeInst->mTypeDef->mTypeDeclaration) && (activeTypeDef->IsExtension()))
|
||||||
{
|
{
|
||||||
|
BfTypeDef* lookupTypeDef = activeTypeDef;
|
||||||
|
while (lookupTypeDef->mNestDepth > genericTypeInst->mTypeDef->mNestDepth)
|
||||||
|
lookupTypeDef = lookupTypeDef->mOuterType;
|
||||||
|
|
||||||
BfGenericExtensionEntry* genericExEntry;
|
BfGenericExtensionEntry* genericExEntry;
|
||||||
if (genericTypeInst->mGenericExtensionInfo->mExtensionMap.TryGetValue(activeTypeDef, &genericExEntry))
|
if (genericTypeInst->mGenericExtensionInfo->mExtensionMap.TryGetValue(lookupTypeDef, &genericExEntry))
|
||||||
{
|
{
|
||||||
return genericExEntry->mGenericParams[type->mGenericParamIdx];
|
return genericExEntry->mGenericParams[genericParamIdx];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((mCompiler->mResolvePassData == NULL) || (mCompiler->mResolvePassData->mAutoComplete == NULL))
|
if ((mCompiler->mResolvePassData == NULL) || (mCompiler->mResolvePassData->mAutoComplete == NULL))
|
||||||
{
|
{
|
||||||
BF_FATAL("Invalid GetGenericParamInstance with extention");
|
BF_FATAL("Invalid GetGenericParamInstance with extension");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_ASSERT(genericTypeInst != NULL);
|
BF_ASSERT(genericTypeInst != NULL);
|
||||||
return genericTypeInst->mGenericParams[type->mGenericParamIdx];
|
return genericTypeInst->mGenericParams[genericParamIdx];
|
||||||
|
}
|
||||||
|
|
||||||
|
BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* type)
|
||||||
|
{
|
||||||
|
if (type->mGenericParamKind == BfGenericParamKind_Method)
|
||||||
|
return mCurMethodInstance->mMethodInfoEx->mGenericParams[type->mGenericParamIdx];
|
||||||
|
|
||||||
|
return GetGenericTypeParamInstance(type->mGenericParamIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTypeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
|
BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTypeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
|
||||||
|
@ -5717,7 +5737,7 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
|
||||||
bool hadError = false;
|
bool hadError = false;
|
||||||
hadError = !PopulateType(resolvedTypeRef, populateType);
|
hadError = !PopulateType(resolvedTypeRef, populateType);
|
||||||
|
|
||||||
if ((genericTypeInstance != NULL) && (populateType > BfPopulateType_Identity))
|
if ((genericTypeInstance != NULL) && (genericTypeInstance != mCurTypeInstance) && (populateType > BfPopulateType_Identity))
|
||||||
{
|
{
|
||||||
if (((genericTypeInstance->mHadValidateErrors) || (!genericTypeInstance->mValidatedGenericConstraints) || (genericTypeInstance->mIsUnspecializedVariation)) &&
|
if (((genericTypeInstance->mHadValidateErrors) || (!genericTypeInstance->mValidatedGenericConstraints) || (genericTypeInstance->mIsUnspecializedVariation)) &&
|
||||||
((mCurMethodInstance == NULL) || (!mCurMethodInstance->mIsUnspecializedVariation)) &&
|
((mCurMethodInstance == NULL) || (!mCurMethodInstance->mIsUnspecializedVariation)) &&
|
||||||
|
@ -5852,6 +5872,12 @@ BfTypeDef* BfModule::FindTypeDefRaw(const BfAtomComposite& findName, int numGene
|
||||||
}
|
}
|
||||||
if (checkTypeInst == skipCheckBaseType)
|
if (checkTypeInst == skipCheckBaseType)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (checkTypeInst->mTypeDef == mCompiler->mNullableTypeDef)
|
||||||
|
{
|
||||||
|
NOP;
|
||||||
|
}
|
||||||
|
|
||||||
checkTypeInst = GetBaseType(checkTypeInst);
|
checkTypeInst = GetBaseType(checkTypeInst);
|
||||||
allowPrivate = false;
|
allowPrivate = false;
|
||||||
}
|
}
|
||||||
|
@ -5868,6 +5894,7 @@ BfTypeDef* BfModule::FindTypeDefRaw(const BfAtomComposite& findName, int numGene
|
||||||
}
|
}
|
||||||
if (checkTypeInst == skipCheckBaseType)
|
if (checkTypeInst == skipCheckBaseType)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
checkTypeInst = GetBaseType(checkTypeInst);
|
checkTypeInst = GetBaseType(checkTypeInst);
|
||||||
allowPrivate = false;
|
allowPrivate = false;
|
||||||
}
|
}
|
||||||
|
@ -6931,8 +6958,8 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
||||||
if ((mCurTypeInstance != NULL) && (typeDef->mGenericParamDefs.size() != 0))
|
if ((mCurTypeInstance != NULL) && (typeDef->mGenericParamDefs.size() != 0))
|
||||||
{
|
{
|
||||||
// Try to inherit generic params from current parent
|
// Try to inherit generic params from current parent
|
||||||
|
|
||||||
auto outerType = typeDef->mOuterType;
|
BfTypeDef* outerType = mSystem->GetCombinedPartial(typeDef->mOuterType);
|
||||||
BF_ASSERT(!outerType->mIsPartial);
|
BF_ASSERT(!outerType->mIsPartial);
|
||||||
if (TypeHasParent(mCurTypeInstance->mTypeDef, outerType))
|
if (TypeHasParent(mCurTypeInstance->mTypeDef, outerType))
|
||||||
{
|
{
|
||||||
|
@ -8699,62 +8726,87 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
if ((typedVal.mType->IsGenericParam()) && (!toType->IsGenericParam()))
|
if ((typedVal.mType->IsGenericParam()) && (!toType->IsGenericParam()))
|
||||||
{
|
{
|
||||||
if (toType == mContext->mBfObjectType)
|
if (toType == mContext->mBfObjectType)
|
||||||
{
|
{
|
||||||
/*auto resolvedType = ResolveGenericType(typedVal.mType);
|
// Always allow casting from generic to object
|
||||||
if (!resolvedType->IsGenericParam())
|
|
||||||
return CastToValue(srcNode, BfTypedValue(typedVal.mValue, resolvedType), toType, castFlags, silentFail);
|
|
||||||
return typedVal.mValue;*/
|
|
||||||
// Always allow casting to generic
|
|
||||||
return typedVal.mValue;
|
return typedVal.mValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto _CheckGenericParamInstance = [&](BfGenericParamInstance* genericParamInst)
|
||||||
|
{
|
||||||
|
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
|
||||||
|
{
|
||||||
|
return typedVal.mValue;
|
||||||
|
}
|
||||||
|
if (toType->IsInterface())
|
||||||
|
{
|
||||||
|
for (auto iface : genericParamInst->mInterfaceConstraints)
|
||||||
|
if (TypeIsSubTypeOf(iface, toType->ToTypeInstance()))
|
||||||
|
return GetDefaultValue(toType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genericParamInst->mTypeConstraint != NULL)
|
||||||
|
{
|
||||||
|
auto constraintTypeInst = genericParamInst->mTypeConstraint->ToTypeInstance();
|
||||||
|
if ((constraintTypeInst != NULL) && (constraintTypeInst->mTypeDef == mCompiler->mEnumTypeDef))
|
||||||
|
{
|
||||||
|
// Enum->int
|
||||||
|
if (toType->IsInteger())
|
||||||
|
return GetDefaultValue(toType);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto defaultFromValue = GetDefaultTypedValue(genericParamInst->mTypeConstraint);
|
||||||
|
auto result = CastToValue(srcNode, defaultFromValue, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail));
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if ((genericParamInst->mTypeConstraint->IsDelegate()) && (toType->IsDelegate()))
|
||||||
|
{
|
||||||
|
// Don't allow cast when we are constrained by a delegate type, because BfMethodRefs can match and we require an actual alloc
|
||||||
|
Fail(StrFormat("Unable to cast '%s' to '%s' because delegate constraints allow valueless direct method references", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
||||||
|
return BfIRValue();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic constrained with class or pointer type -> void*
|
||||||
|
if (toType->IsVoidPtr())
|
||||||
|
{
|
||||||
|
if ((genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_StructPtr)) ||
|
||||||
|
((genericParamInst->mTypeConstraint != NULL) &&
|
||||||
|
((genericParamInst->mTypeConstraint->IsPointer()) || (genericParamInst->mTypeConstraint->IsObjectOrInterface()))))
|
||||||
|
{
|
||||||
|
return GetDefaultValue(toType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BfIRValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
BfIRValue retVal;
|
||||||
|
|
||||||
// For these casts, it's just important we get *A* value to work with here,
|
// For these casts, it's just important we get *A* value to work with here,
|
||||||
// as this is just use for unspecialized parsing. We don't use the generated code
|
// as this is just use for unspecialized parsing. We don't use the generated code
|
||||||
auto genericParamInst = GetGenericParamInstance((BfGenericParamType*)typedVal.mType);
|
|
||||||
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
|
|
||||||
{
|
{
|
||||||
return typedVal.mValue;
|
auto genericParamInst = GetGenericParamInstance((BfGenericParamType*)typedVal.mType);
|
||||||
}
|
retVal = _CheckGenericParamInstance(genericParamInst);
|
||||||
if (toType->IsInterface())
|
if (retVal)
|
||||||
{
|
return retVal;
|
||||||
for (auto iface : genericParamInst->mInterfaceConstraints)
|
|
||||||
if (TypeIsSubTypeOf(iface, toType->ToTypeInstance()))
|
|
||||||
return GetDefaultValue(toType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (genericParamInst->mTypeConstraint != NULL)
|
// Check method generic constraints
|
||||||
|
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mMethodInfoEx != NULL))
|
||||||
{
|
{
|
||||||
auto constraintTypeInst = genericParamInst->mTypeConstraint->ToTypeInstance();
|
for (int genericParamIdx = (int)mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
|
||||||
if ((constraintTypeInst != NULL) && (constraintTypeInst->mTypeDef == mCompiler->mEnumTypeDef))
|
genericParamIdx < mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
||||||
{
|
{
|
||||||
// Enum->int
|
auto genericParamInst = mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
||||||
if (toType->IsInteger())
|
if (genericParamInst->mExternType == typedVal.mType)
|
||||||
return GetDefaultValue(toType);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto defaultFromValue = GetDefaultTypedValue(genericParamInst->mTypeConstraint);
|
|
||||||
auto result = CastToValue(srcNode, defaultFromValue, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail));
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
if ((genericParamInst->mTypeConstraint->IsDelegate()) && (toType->IsDelegate()))
|
|
||||||
{
|
{
|
||||||
// Don't allow cast when we are constrained by a delegate type, because BfMethodRefs can match and we require an actual alloc
|
retVal = _CheckGenericParamInstance(genericParamInst);
|
||||||
Fail(StrFormat("Unable to cast '%s' to '%s' because delegate constraints allow valueless direct method references", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
if (retVal)
|
||||||
return BfIRValue();
|
return retVal;
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic constrained with class or pointer type -> void*
|
|
||||||
if (toType->IsVoidPtr())
|
|
||||||
{
|
|
||||||
if ((genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_StructPtr)) ||
|
|
||||||
((genericParamInst->mTypeConstraint != NULL) &&
|
|
||||||
((genericParamInst->mTypeConstraint->IsPointer()) || (genericParamInst->mTypeConstraint->IsObjectOrInterface()))))
|
|
||||||
{
|
|
||||||
return GetDefaultValue(toType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9612,7 +9664,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
}
|
}
|
||||||
|
|
||||||
return CastToValue(srcNode, operatorOut, toType, castFlags, resultFlags);
|
return CastToValue(srcNode, operatorOut, toType, castFlags, resultFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestFromType == NULL)
|
if (bestFromType == NULL)
|
||||||
|
@ -9628,6 +9680,55 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
Fail(StrFormat(errStr, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
Fail(StrFormat(errStr, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
||||||
return BfIRValue();
|
return BfIRValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check method generic constraints
|
||||||
|
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mMethodInfoEx != NULL))
|
||||||
|
{
|
||||||
|
for (int genericParamIdx = 0; genericParamIdx < mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
||||||
|
{
|
||||||
|
auto genericParam = mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
||||||
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
if ((opConstraint.mCastToken == BfToken_Implicit) ||
|
||||||
|
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
|
||||||
|
{
|
||||||
|
// If we can convert OUR fromVal to the constraint's fromVal then we may match
|
||||||
|
if (CanImplicitlyCast(typedVal, opConstraint.mRightType))
|
||||||
|
{
|
||||||
|
// .. and we can convert the constraint's toType to OUR toType then we're good
|
||||||
|
auto opToVal = genericParam->mExternType;
|
||||||
|
if (CanImplicitlyCast(opToVal, toType))
|
||||||
|
return mBfIRBuilder->GetFakeVal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check type generic constraints
|
||||||
|
if ((mCurTypeInstance->IsGenericTypeInstance()) && (mCurTypeInstance->IsUnspecializedType()))
|
||||||
|
{
|
||||||
|
auto genericTypeInst = (BfGenericTypeInstance*)mCurTypeInstance;
|
||||||
|
for (int genericParamIdx = 0; genericParamIdx < genericTypeInst->mGenericParams.size(); genericParamIdx++)
|
||||||
|
{
|
||||||
|
auto genericParam = GetGenericTypeParamInstance(genericParamIdx);
|
||||||
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
if ((opConstraint.mCastToken == BfToken_Implicit) ||
|
||||||
|
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
|
||||||
|
{
|
||||||
|
// If we can convert OUR fromVal to the constraint's fromVal then we may match
|
||||||
|
if (CanImplicitlyCast(typedVal, opConstraint.mRightType))
|
||||||
|
{
|
||||||
|
// .. and we can convert the constraint's toType to OUR toType then we're good
|
||||||
|
auto opToVal = genericParam->mExternType;
|
||||||
|
if (CanImplicitlyCast(opToVal, toType))
|
||||||
|
return mBfIRBuilder->GetFakeVal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default typed primitive 'underlying casts' happen after checking cast operators
|
// Default typed primitive 'underlying casts' happen after checking cast operators
|
||||||
|
@ -10047,8 +10148,16 @@ BfTypeDef* BfModule::FindCommonOuterType(BfTypeDef* type, BfTypeDef* type2)
|
||||||
|
|
||||||
while (curNestDepth >= 0)
|
while (curNestDepth >= 0)
|
||||||
{
|
{
|
||||||
if (type == type2)
|
if ((!type->mIsPartial) && (!type2->mIsPartial))
|
||||||
return type;
|
{
|
||||||
|
if (type == type2)
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (type->mFullNameEx == type2->mFullNameEx)
|
||||||
|
return type;
|
||||||
|
}
|
||||||
type = type->mOuterType;
|
type = type->mOuterType;
|
||||||
type2 = type2->mOuterType;
|
type2 = type2->mOuterType;
|
||||||
curNestDepth--;
|
curNestDepth--;
|
||||||
|
@ -10627,7 +10736,11 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
|
||||||
}
|
}
|
||||||
|
|
||||||
auto genericParamInstance = GetGenericParamInstance(genericParam);
|
auto genericParamInstance = GetGenericParamInstance(genericParam);
|
||||||
str += genericParamInstance->GetGenericParamDef()->mName;
|
auto genericParamDef = genericParamInstance->GetGenericParamDef();
|
||||||
|
if (genericParamDef != NULL)
|
||||||
|
str += genericParamInstance->GetGenericParamDef()->mName;
|
||||||
|
else
|
||||||
|
str += "external generic " + TypeToString(genericParamInstance->mExternType, typeNameFlags, genericMethodNameOverrides);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (resolvedType->IsRef())
|
else if (resolvedType->IsRef())
|
||||||
|
|
|
@ -53,6 +53,7 @@ static bool IsWhitespaceOrPunctuation(char c)
|
||||||
case '!':
|
case '!':
|
||||||
case '%':
|
case '%':
|
||||||
case '&':
|
case '&':
|
||||||
|
case '|':
|
||||||
case '#':
|
case '#':
|
||||||
case '@':
|
case '@':
|
||||||
case '`':
|
case '`':
|
||||||
|
|
|
@ -746,12 +746,14 @@ void BfPrinter::Visit(BfGenericConstraintsDeclaration* genericConstraints)
|
||||||
{
|
{
|
||||||
Visit(genericConstraints->ToBase());
|
Visit(genericConstraints->ToBase());
|
||||||
|
|
||||||
for (auto genericConstraint : genericConstraints->mGenericConstraints)
|
for (auto genericConstraintNode : genericConstraints->mGenericConstraints)
|
||||||
{
|
{
|
||||||
|
auto genericConstraint = BfNodeDynCast<BfGenericConstraint>(genericConstraintNode);
|
||||||
|
|
||||||
ExpectSpace();
|
ExpectSpace();
|
||||||
VisitChild(genericConstraint->mWhereToken);
|
VisitChild(genericConstraint->mWhereToken);
|
||||||
ExpectSpace();
|
ExpectSpace();
|
||||||
VisitChild(genericConstraint->mGenericParamName);
|
VisitChild(genericConstraint->mTypeRef);
|
||||||
ExpectSpace();
|
ExpectSpace();
|
||||||
VisitChild(genericConstraint->mColonToken);
|
VisitChild(genericConstraint->mColonToken);
|
||||||
ExpectSpace();
|
ExpectSpace();
|
||||||
|
|
|
@ -26,120 +26,6 @@ USING_NS_BF;
|
||||||
dest->member = src; \
|
dest->member = src; \
|
||||||
MoveNode(src, dest); }
|
MoveNode(src, dest); }
|
||||||
|
|
||||||
static BfBinaryOp TokenToBinaryOp(BfToken token)
|
|
||||||
{
|
|
||||||
switch (token)
|
|
||||||
{
|
|
||||||
case BfToken_Plus:
|
|
||||||
return BfBinaryOp_Add;
|
|
||||||
case BfToken_Minus:
|
|
||||||
return BfBinaryOp_Subtract;
|
|
||||||
case BfToken_Star:
|
|
||||||
return BfBinaryOp_Multiply;
|
|
||||||
case BfToken_ForwardSlash:
|
|
||||||
return BfBinaryOp_Divide;
|
|
||||||
case BfToken_Modulus:
|
|
||||||
return BfBinaryOp_Modulus;
|
|
||||||
case BfToken_Ampersand:
|
|
||||||
return BfBinaryOp_BitwiseAnd;
|
|
||||||
case BfToken_Bar:
|
|
||||||
return BfBinaryOp_BitwiseOr;
|
|
||||||
case BfToken_Carat:
|
|
||||||
return BfBinaryOp_ExclusiveOr;
|
|
||||||
case BfToken_LDblChevron:
|
|
||||||
return BfBinaryOp_LeftShift;
|
|
||||||
case BfToken_RDblChevron:
|
|
||||||
return BfBinaryOp_RightShift;
|
|
||||||
case BfToken_CompareEquals:
|
|
||||||
return BfBinaryOp_Equality;
|
|
||||||
case BfToken_CompareNotEquals:
|
|
||||||
return BfBinaryOp_InEquality;
|
|
||||||
case BfToken_RChevron:
|
|
||||||
return BfBinaryOp_GreaterThan;
|
|
||||||
case BfToken_LChevron:
|
|
||||||
return BfBinaryOp_LessThan;
|
|
||||||
case BfToken_GreaterEquals:
|
|
||||||
return BfBinaryOp_GreaterThanOrEqual;
|
|
||||||
case BfToken_LessEquals:
|
|
||||||
return BfBinaryOp_LessThanOrEqual;
|
|
||||||
case BfToken_Spaceship:
|
|
||||||
return BfBinaryOp_Compare;
|
|
||||||
case BfToken_DblAmpersand:
|
|
||||||
return BfBinaryOp_ConditionalAnd;
|
|
||||||
case BfToken_DblBar:
|
|
||||||
return BfBinaryOp_ConditionalOr;
|
|
||||||
case BfToken_DblQuestion:
|
|
||||||
return BfBinaryOp_NullCoalesce;
|
|
||||||
default:
|
|
||||||
return BfBinaryOp_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static BfUnaryOp TokenToUnaryOp(BfToken token)
|
|
||||||
{
|
|
||||||
switch (token)
|
|
||||||
{
|
|
||||||
case BfToken_Star:
|
|
||||||
return BfUnaryOp_Dereference;
|
|
||||||
case BfToken_Ampersand:
|
|
||||||
return BfUnaryOp_AddressOf;
|
|
||||||
case BfToken_Minus:
|
|
||||||
return BfUnaryOp_Negate;
|
|
||||||
case BfToken_Bang:
|
|
||||||
return BfUnaryOp_Not;
|
|
||||||
case BfToken_Plus:
|
|
||||||
return BfUnaryOp_Positive;
|
|
||||||
case BfToken_Tilde:
|
|
||||||
return BfUnaryOp_InvertBits;
|
|
||||||
case BfToken_DblPlus:
|
|
||||||
return BfUnaryOp_Increment;
|
|
||||||
case BfToken_DblMinus:
|
|
||||||
return BfUnaryOp_Decrement;
|
|
||||||
case BfToken_Ref:
|
|
||||||
return BfUnaryOp_Ref;
|
|
||||||
case BfToken_Mut:
|
|
||||||
return BfUnaryOp_Mut;
|
|
||||||
case BfToken_Out:
|
|
||||||
return BfUnaryOp_Out;
|
|
||||||
case BfToken_Params:
|
|
||||||
return BfUnaryOp_Params;
|
|
||||||
default:
|
|
||||||
return BfUnaryOp_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static BfAssignmentOp TokenToAssignmentOp(BfToken token)
|
|
||||||
{
|
|
||||||
switch (token)
|
|
||||||
{
|
|
||||||
case BfToken_AssignEquals:
|
|
||||||
return BfAssignmentOp_Assign;
|
|
||||||
case BfToken_PlusEquals:
|
|
||||||
return BfAssignmentOp_Add;
|
|
||||||
case BfToken_MinusEquals:
|
|
||||||
return BfAssignmentOp_Subtract;
|
|
||||||
case BfToken_MultiplyEquals:
|
|
||||||
return BfAssignmentOp_Multiply;
|
|
||||||
case BfToken_DivideEquals:
|
|
||||||
return BfAssignmentOp_Divide;
|
|
||||||
case BfToken_ModulusEquals:
|
|
||||||
return BfAssignmentOp_Modulus;
|
|
||||||
case BfToken_ShiftLeftEquals:
|
|
||||||
return BfAssignmentOp_ShiftLeft;
|
|
||||||
case BfToken_ShiftRightEquals:
|
|
||||||
return BfAssignmentOp_ShiftRight;
|
|
||||||
case BfToken_AndEquals:
|
|
||||||
return BfAssignmentOp_BitwiseAnd;
|
|
||||||
case BfToken_OrEquals:
|
|
||||||
return BfAssignmentOp_BitwiseOr;
|
|
||||||
case BfToken_XorEquals:
|
|
||||||
return BfAssignmentOp_ExclusiveOr;
|
|
||||||
default:
|
|
||||||
return BfAssignmentOp_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BfReducer::BfReducer()
|
BfReducer::BfReducer()
|
||||||
{
|
{
|
||||||
mCurTypeDecl = NULL;
|
mCurTypeDecl = NULL;
|
||||||
|
@ -2122,7 +2008,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
{
|
{
|
||||||
BfToken nextToken = nextTokenNode->GetToken();
|
BfToken nextToken = nextTokenNode->GetToken();
|
||||||
//TODO: Hm. What other tokens make it into a cast expr?
|
//TODO: Hm. What other tokens make it into a cast expr?
|
||||||
auto binaryOp = TokenToBinaryOp(nextToken);
|
auto binaryOp = BfTokenToBinaryOp(nextToken);
|
||||||
// When we have a binary operator token following, it COULD either be a "(double)-val" or it COULD be a "(val2)-val"
|
// When we have a binary operator token following, it COULD either be a "(double)-val" or it COULD be a "(val2)-val"
|
||||||
// But we can't tell until we determine whether the thing inside the paren is a type name or a value name, so we
|
// But we can't tell until we determine whether the thing inside the paren is a type name or a value name, so we
|
||||||
// have special code in BfExprEvaluator that can fix those cases at evaluation time
|
// have special code in BfExprEvaluator that can fix those cases at evaluation time
|
||||||
|
@ -2232,7 +2118,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
|
|
||||||
if (exprLeft == NULL)
|
if (exprLeft == NULL)
|
||||||
{
|
{
|
||||||
BfUnaryOp unaryOp = TokenToUnaryOp(tokenNode->GetToken());
|
BfUnaryOp unaryOp = BfTokenToUnaryOp(tokenNode->GetToken());
|
||||||
|
|
||||||
if (unaryOp != BfUnaryOp_None)
|
if (unaryOp != BfUnaryOp_None)
|
||||||
{
|
{
|
||||||
|
@ -2624,7 +2510,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BfBinaryOp binOp = TokenToBinaryOp(tokenNode->GetToken());
|
BfBinaryOp binOp = BfTokenToBinaryOp(tokenNode->GetToken());
|
||||||
if (binOp != BfBinaryOp_None)
|
if (binOp != BfBinaryOp_None)
|
||||||
{
|
{
|
||||||
auto binOpExpression = mAlloc->Alloc<BfBinaryOperatorExpression>();
|
auto binOpExpression = mAlloc->Alloc<BfBinaryOperatorExpression>();
|
||||||
|
@ -2648,7 +2534,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
return CheckBinaryOperatorPrecedence(binOpExpression);
|
return CheckBinaryOperatorPrecedence(binOpExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto assignmentOp = TokenToAssignmentOp(tokenNode->GetToken());
|
auto assignmentOp = BfTokenToAssignmentOp(tokenNode->GetToken());
|
||||||
if (assignmentOp != BfAssignmentOp_None)
|
if (assignmentOp != BfAssignmentOp_None)
|
||||||
{
|
{
|
||||||
if ((createExprFlags & CreateExprFlags_NoAssignment) != 0)
|
if ((createExprFlags & CreateExprFlags_NoAssignment) != 0)
|
||||||
|
@ -3870,21 +3756,7 @@ BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createS
|
||||||
auto nameNode = ExpectIdentifierAfter(methodDecl);
|
auto nameNode = ExpectIdentifierAfter(methodDecl);
|
||||||
if (nameNode != NULL)
|
if (nameNode != NULL)
|
||||||
{
|
{
|
||||||
MEMBER_SET(methodDecl, mNameNode, nameNode);
|
MEMBER_SET(methodDecl, mNameNode, nameNode);
|
||||||
|
|
||||||
auto nextNode = mVisitorPos.GetNext();
|
|
||||||
if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
|
|
||||||
{
|
|
||||||
if (tokenNode->GetToken() == BfToken_LChevron)
|
|
||||||
{
|
|
||||||
auto genericParams = CreateGenericParamsDeclaration(tokenNode);
|
|
||||||
if (genericParams != NULL)
|
|
||||||
{
|
|
||||||
MEMBER_SET(methodDecl, mGenericParams, genericParams);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseMethod(methodDecl, ¶ms, &commas, true);
|
ParseMethod(methodDecl, ¶ms, &commas, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6493,7 +6365,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth)
|
||||||
auto nextNode = mVisitorPos.GetNext();
|
auto nextNode = mVisitorPos.GetNext();
|
||||||
if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
|
if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
|
||||||
{
|
{
|
||||||
operatorDecl->mBinOp = TokenToBinaryOp(nextToken->GetToken());
|
operatorDecl->mBinOp = BfTokenToBinaryOp(nextToken->GetToken());
|
||||||
if (operatorDecl->mBinOp != BfBinaryOp_None)
|
if (operatorDecl->mBinOp != BfBinaryOp_None)
|
||||||
{
|
{
|
||||||
MEMBER_SET(operatorDecl, mOpTypeToken, nextToken);
|
MEMBER_SET(operatorDecl, mOpTypeToken, nextToken);
|
||||||
|
@ -6501,7 +6373,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
operatorDecl->mUnaryOp = TokenToUnaryOp(nextToken->GetToken());
|
operatorDecl->mUnaryOp = BfTokenToUnaryOp(nextToken->GetToken());
|
||||||
if (operatorDecl->mUnaryOp != BfUnaryOp_None)
|
if (operatorDecl->mUnaryOp != BfUnaryOp_None)
|
||||||
{
|
{
|
||||||
MEMBER_SET(operatorDecl, mOpTypeToken, nextToken);
|
MEMBER_SET(operatorDecl, mOpTypeToken, nextToken);
|
||||||
|
@ -6509,7 +6381,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
operatorDecl->mAssignOp = TokenToAssignmentOp(nextToken->GetToken());
|
operatorDecl->mAssignOp = BfTokenToAssignmentOp(nextToken->GetToken());
|
||||||
if (operatorDecl->mAssignOp == BfAssignmentOp_Assign)
|
if (operatorDecl->mAssignOp == BfAssignmentOp_Assign)
|
||||||
{
|
{
|
||||||
Fail("The assignment operator '=' cannot be overridden", nextToken);
|
Fail("The assignment operator '=' cannot be overridden", nextToken);
|
||||||
|
@ -8768,7 +8640,24 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
|
||||||
|
|
||||||
bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayImpl<BfParameterDeclaration*>* params, SizedArrayImpl<BfTokenNode*>* commas, bool alwaysIncludeBlock)
|
bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayImpl<BfParameterDeclaration*>* params, SizedArrayImpl<BfTokenNode*>* commas, bool alwaysIncludeBlock)
|
||||||
{
|
{
|
||||||
auto tokenNode = ExpectTokenAfter(methodDeclaration, BfToken_LParen, BfToken_Bang);
|
BfTokenNode* tokenNode;
|
||||||
|
auto nextNode = mVisitorPos.GetNext();
|
||||||
|
if (methodDeclaration->mGenericParams == NULL)
|
||||||
|
{
|
||||||
|
if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
|
||||||
|
{
|
||||||
|
if (tokenNode->GetToken() == BfToken_LChevron)
|
||||||
|
{
|
||||||
|
auto genericParams = CreateGenericParamsDeclaration(tokenNode);
|
||||||
|
if (genericParams != NULL)
|
||||||
|
{
|
||||||
|
MEMBER_SET(methodDeclaration, mGenericParams, genericParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenNode = ExpectTokenAfter(methodDeclaration, BfToken_LParen, BfToken_Bang);
|
||||||
if (tokenNode == NULL)
|
if (tokenNode == NULL)
|
||||||
return false;
|
return false;
|
||||||
if (tokenNode->GetToken() == BfToken_Bang)
|
if (tokenNode->GetToken() == BfToken_Bang)
|
||||||
|
@ -8811,7 +8700,7 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm
|
||||||
mVisitorPos.MoveNext();
|
mVisitorPos.MoveNext();
|
||||||
|
|
||||||
auto typeDecl = mCurTypeDecl;
|
auto typeDecl = mCurTypeDecl;
|
||||||
auto nextNode = mVisitorPos.GetNext();
|
nextNode = mVisitorPos.GetNext();
|
||||||
if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
|
if ((tokenNode = BfNodeDynCast<BfTokenNode>(nextNode)))
|
||||||
{
|
{
|
||||||
if (tokenNode->GetToken() == BfToken_Mut)
|
if (tokenNode->GetToken() == BfToken_Mut)
|
||||||
|
@ -9038,7 +8927,7 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
|
||||||
|
|
||||||
bool isDone = false;
|
bool isDone = false;
|
||||||
for (int constraintIdx = 0; !isDone; constraintIdx++)
|
for (int constraintIdx = 0; !isDone; constraintIdx++)
|
||||||
{
|
{
|
||||||
BfGenericConstraint* genericConstraint = mAlloc->Alloc<BfGenericConstraint>();
|
BfGenericConstraint* genericConstraint = mAlloc->Alloc<BfGenericConstraint>();
|
||||||
BfDeferredAstSizedArray<BfAstNode*> constraintTypes(genericConstraint->mConstraintTypes, mAlloc);
|
BfDeferredAstSizedArray<BfAstNode*> constraintTypes(genericConstraint->mConstraintTypes, mAlloc);
|
||||||
BfDeferredAstSizedArray<BfTokenNode*> commas(genericConstraint->mCommas, mAlloc);
|
BfDeferredAstSizedArray<BfTokenNode*> commas(genericConstraint->mCommas, mAlloc);
|
||||||
|
@ -9047,11 +8936,12 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
|
||||||
genericConstraint->mWhereToken = tokenNode;
|
genericConstraint->mWhereToken = tokenNode;
|
||||||
|
|
||||||
genericConstraintsArr.push_back(genericConstraint);
|
genericConstraintsArr.push_back(genericConstraint);
|
||||||
auto genericParamName = ExpectIdentifierAfter(genericConstraint, "generic parameter name");
|
|
||||||
|
auto genericParamName = CreateTypeRefAfter(genericConstraint);
|
||||||
if (genericParamName != NULL)
|
if (genericParamName != NULL)
|
||||||
{
|
{
|
||||||
MEMBER_SET(genericConstraint, mGenericParamName, genericParamName);
|
MEMBER_SET(genericConstraint, mTypeRef, genericParamName);
|
||||||
tokenNode = ExpectTokenAfter(genericConstraint, BfToken_Colon);
|
tokenNode = ExpectTokenAfter(genericConstraint, BfToken_Colon, BfToken_AssignEquals);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
isDone = true;
|
isDone = true;
|
||||||
|
@ -9076,7 +8966,6 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenNode = ExpectTokenAfter(genericConstraint, BfToken_Comma, BfToken_LBrace, BfToken_Where, BfToken_Semicolon);
|
tokenNode = ExpectTokenAfter(genericConstraint, BfToken_Comma, BfToken_LBrace, BfToken_Where, BfToken_Semicolon);
|
||||||
|
|
||||||
if (tokenNode == NULL)
|
if (tokenNode == NULL)
|
||||||
{
|
{
|
||||||
isDone = true;
|
isDone = true;
|
||||||
|
@ -9098,6 +8987,8 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
|
||||||
auto nextNode = mVisitorPos.GetNext();
|
auto nextNode = mVisitorPos.GetNext();
|
||||||
if (auto constraintToken = BfNodeDynCast<BfTokenNode>(nextNode))
|
if (auto constraintToken = BfNodeDynCast<BfTokenNode>(nextNode))
|
||||||
{
|
{
|
||||||
|
BfAstNode* constraintNode = NULL;
|
||||||
|
|
||||||
bool addToConstraint = false;
|
bool addToConstraint = false;
|
||||||
switch (constraintToken->GetToken())
|
switch (constraintToken->GetToken())
|
||||||
{
|
{
|
||||||
|
@ -9107,13 +8998,43 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
|
||||||
case BfToken_Var:
|
case BfToken_Var:
|
||||||
addToConstraint = true;
|
addToConstraint = true;
|
||||||
break;
|
break;
|
||||||
|
case BfToken_Operator:
|
||||||
|
{
|
||||||
|
BfGenericOperatorConstraint* opConstraint = mAlloc->Alloc<BfGenericOperatorConstraint>();
|
||||||
|
constraintNode = opConstraint;
|
||||||
|
|
||||||
|
ReplaceNode(constraintToken, opConstraint);
|
||||||
|
|
||||||
|
MEMBER_SET(opConstraint, mOperatorToken, constraintToken);
|
||||||
|
mVisitorPos.MoveNext();
|
||||||
|
|
||||||
|
auto opToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
|
||||||
|
if (opToken == NULL)
|
||||||
|
{
|
||||||
|
auto typeRef = CreateTypeRefAfter(opConstraint);
|
||||||
|
if (typeRef == NULL)
|
||||||
|
break;
|
||||||
|
MEMBER_SET(opConstraint, mLeftType, typeRef);
|
||||||
|
opToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opToken == NULL)
|
||||||
|
break;
|
||||||
|
MEMBER_SET(opConstraint, mOpToken, opToken);
|
||||||
|
mVisitorPos.MoveNext();
|
||||||
|
|
||||||
|
auto typeRef = CreateTypeRefAfter(opConstraint);
|
||||||
|
if (typeRef == NULL)
|
||||||
|
break;
|
||||||
|
MEMBER_SET(opConstraint, mRightType, typeRef);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addToConstraint)
|
if (addToConstraint)
|
||||||
{
|
{
|
||||||
BfAstNode* constraintNode = constraintToken;
|
constraintNode = constraintToken;
|
||||||
MoveNode(constraintToken, genericConstraint);
|
|
||||||
bool addToConstraint = false;
|
bool addToConstraint = false;
|
||||||
|
|
||||||
mVisitorPos.MoveNext();
|
mVisitorPos.MoveNext();
|
||||||
|
@ -9152,8 +9073,12 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
|
||||||
constraintTypes.push_back(typeRef);
|
constraintTypes.push_back(typeRef);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constraintNode != NULL)
|
||||||
|
{
|
||||||
|
MoveNode(constraintNode, genericConstraint);
|
||||||
constraintTypes.push_back(constraintNode);
|
constraintTypes.push_back(constraintNode);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3754,6 +3754,15 @@ String BfTypeUtils::TypeToString(BfTypeReference* typeRef)
|
||||||
return "???";
|
return "???";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BfTypeUtils::TypeEquals(BfType* typeA, BfType* typeB, BfType* selfType)
|
||||||
|
{
|
||||||
|
if (typeA->IsSelf())
|
||||||
|
typeA = selfType;
|
||||||
|
if (typeB->IsSelf())
|
||||||
|
typeB = selfType;
|
||||||
|
return typeA == typeB;
|
||||||
|
}
|
||||||
|
|
||||||
String BfTypeUtils::TypeToString(BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags)
|
String BfTypeUtils::TypeToString(BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags)
|
||||||
{
|
{
|
||||||
String str;
|
String str;
|
||||||
|
|
|
@ -930,16 +930,49 @@ public:
|
||||||
virtual BfType* GetUnderlyingType() override { return mElementType; }
|
virtual BfType* GetUnderlyingType() override { return mElementType; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BfGenericOperatorConstraintInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BfType* mLeftType;
|
||||||
|
BfBinaryOp mBinaryOp;
|
||||||
|
BfUnaryOp mUnaryOp;
|
||||||
|
BfToken mCastToken;
|
||||||
|
BfType* mRightType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BfGenericOperatorConstraintInstance()
|
||||||
|
{
|
||||||
|
mLeftType = NULL;
|
||||||
|
mBinaryOp = BfBinaryOp_None;
|
||||||
|
mUnaryOp = BfUnaryOp_None;
|
||||||
|
mCastToken = BfToken_None;
|
||||||
|
mRightType = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const BfGenericOperatorConstraintInstance& other) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(mLeftType == other.mLeftType) &&
|
||||||
|
(mBinaryOp == other.mBinaryOp) &&
|
||||||
|
(mUnaryOp == other.mUnaryOp) &&
|
||||||
|
(mCastToken == other.mCastToken) &&
|
||||||
|
(mRightType == other.mRightType);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class BfGenericParamInstance
|
class BfGenericParamInstance
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int mGenericParamFlags;
|
int mGenericParamFlags;
|
||||||
|
BfType* mExternType;
|
||||||
Array<BfTypeInstance*> mInterfaceConstraints;
|
Array<BfTypeInstance*> mInterfaceConstraints;
|
||||||
|
Array<BfGenericOperatorConstraintInstance> mOperatorConstraints;
|
||||||
BfType* mTypeConstraint;
|
BfType* mTypeConstraint;
|
||||||
int mRefCount;
|
int mRefCount;
|
||||||
|
|
||||||
BfGenericParamInstance()
|
BfGenericParamInstance()
|
||||||
{
|
{
|
||||||
|
mExternType = NULL;
|
||||||
mGenericParamFlags = 0;
|
mGenericParamFlags = 0;
|
||||||
mTypeConstraint = NULL;
|
mTypeConstraint = NULL;
|
||||||
mRefCount = 1;
|
mRefCount = 1;
|
||||||
|
@ -954,7 +987,10 @@ public:
|
||||||
virtual ~BfGenericParamInstance()
|
virtual ~BfGenericParamInstance()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
virtual BfConstraintDef* GetConstraintDef() = 0;
|
||||||
virtual BfGenericParamDef* GetGenericParamDef() = 0;
|
virtual BfGenericParamDef* GetGenericParamDef() = 0;
|
||||||
|
virtual BfExternalConstraintDef* GetExternConstraintDef() = 0;
|
||||||
|
virtual String GetName() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BfGenericTypeParamInstance : public BfGenericParamInstance
|
class BfGenericTypeParamInstance : public BfGenericParamInstance
|
||||||
|
@ -962,12 +998,13 @@ class BfGenericTypeParamInstance : public BfGenericParamInstance
|
||||||
public:
|
public:
|
||||||
BfTypeDef* mTypeDef;
|
BfTypeDef* mTypeDef;
|
||||||
int mGenericIdx;
|
int mGenericIdx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfGenericTypeParamInstance(BfTypeDef* typeDef, int genericIdx)
|
BfGenericTypeParamInstance(BfTypeDef* typeDef, int genericIdx)
|
||||||
{
|
{
|
||||||
mTypeDef = typeDef;
|
mTypeDef = typeDef;
|
||||||
mGenericIdx = genericIdx;
|
mGenericIdx = genericIdx;
|
||||||
mGenericParamFlags = GetGenericParamDef()->mGenericParamFlags;
|
mGenericParamFlags = GetConstraintDef()->mGenericParamFlags;
|
||||||
mTypeConstraint = NULL;
|
mTypeConstraint = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,9 +1014,32 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual BfConstraintDef* GetConstraintDef() override
|
||||||
|
{
|
||||||
|
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
|
||||||
|
return mTypeDef->mGenericParamDefs[mGenericIdx];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
virtual BfGenericParamDef* GetGenericParamDef() override
|
virtual BfGenericParamDef* GetGenericParamDef() override
|
||||||
{
|
{
|
||||||
return mTypeDef->mGenericParamDefs[mGenericIdx];
|
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
|
||||||
|
return mTypeDef->mGenericParamDefs[mGenericIdx];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BfExternalConstraintDef* GetExternConstraintDef() override
|
||||||
|
{
|
||||||
|
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
|
||||||
|
return NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual String GetName() override
|
||||||
|
{
|
||||||
|
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
|
||||||
|
return mTypeDef->mGenericParamDefs[mGenericIdx]->mName;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -988,12 +1048,13 @@ class BfGenericMethodParamInstance : public BfGenericParamInstance
|
||||||
public:
|
public:
|
||||||
BfMethodDef* mMethodDef;
|
BfMethodDef* mMethodDef;
|
||||||
int mGenericIdx;
|
int mGenericIdx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfGenericMethodParamInstance(BfMethodDef* methodDef, int genericIdx)
|
BfGenericMethodParamInstance(BfMethodDef* methodDef, int genericIdx)
|
||||||
{
|
{
|
||||||
mMethodDef = methodDef;
|
mMethodDef = methodDef;
|
||||||
mGenericIdx = genericIdx;
|
mGenericIdx = genericIdx;
|
||||||
mGenericParamFlags = GetGenericParamDef()->mGenericParamFlags;
|
mGenericParamFlags = GetConstraintDef()->mGenericParamFlags;
|
||||||
mTypeConstraint = NULL;
|
mTypeConstraint = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1003,9 +1064,32 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual BfConstraintDef* GetConstraintDef() override
|
||||||
|
{
|
||||||
|
if (mGenericIdx < (int)mMethodDef->mGenericParams.size())
|
||||||
|
return mMethodDef->mGenericParams[mGenericIdx];
|
||||||
|
return &mMethodDef->mExternalConstraints[mGenericIdx - (int)mMethodDef->mGenericParams.size()];
|
||||||
|
}
|
||||||
|
|
||||||
virtual BfGenericParamDef* GetGenericParamDef() override
|
virtual BfGenericParamDef* GetGenericParamDef() override
|
||||||
{
|
{
|
||||||
return mMethodDef->mGenericParams[mGenericIdx];
|
if (mGenericIdx < (int)mMethodDef->mGenericParams.size())
|
||||||
|
return mMethodDef->mGenericParams[mGenericIdx];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual BfExternalConstraintDef* GetExternConstraintDef() override
|
||||||
|
{
|
||||||
|
if (mGenericIdx < (int)mMethodDef->mGenericParams.size())
|
||||||
|
return NULL;
|
||||||
|
return &mMethodDef->mExternalConstraints[mGenericIdx - (int)mMethodDef->mGenericParams.size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual String GetName() override
|
||||||
|
{
|
||||||
|
if (mGenericIdx < (int)mMethodDef->mGenericParams.size())
|
||||||
|
return mMethodDef->mGenericParams[mGenericIdx]->mName;
|
||||||
|
return mMethodDef->mExternalConstraints[mGenericIdx - (int)mMethodDef->mGenericParams.size()].mTypeRef->ToString();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2246,6 +2330,7 @@ public:
|
||||||
static String TypeToString(BfTypeReference* typeRef);
|
static String TypeToString(BfTypeReference* typeRef);
|
||||||
static String TypeToString(BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None);
|
static String TypeToString(BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None);
|
||||||
static bool TypeToString(StringImpl& str, BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None);
|
static bool TypeToString(StringImpl& str, BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None);
|
||||||
|
static bool TypeEquals(BfType* typeA, BfType* typeB, BfType* selfType);
|
||||||
|
|
||||||
static void GetProjectList(BfType* checkType, Array<BfProject*>* projectVector, int immutableLength);
|
static void GetProjectList(BfType* checkType, Array<BfProject*>* projectVector, int immutableLength);
|
||||||
|
|
||||||
|
|
|
@ -468,11 +468,8 @@ void BfSourceClassifier::Visit(BfMethodDeclaration* methodDeclaration)
|
||||||
SetAndRestoreValue<BfAstNode*> prevMember(mCurMember, methodDeclaration);
|
SetAndRestoreValue<BfAstNode*> prevMember(mCurMember, methodDeclaration);
|
||||||
|
|
||||||
BfElementVisitor::Visit(methodDeclaration);
|
BfElementVisitor::Visit(methodDeclaration);
|
||||||
|
|
||||||
BfIdentifierNode* identifier = methodDeclaration->mNameNode;
|
SetElementType(methodDeclaration->mNameNode, BfSourceElementType_Method);
|
||||||
if (identifier == NULL)
|
|
||||||
return;
|
|
||||||
SetElementType(identifier, BfSourceElementType_Method);
|
|
||||||
|
|
||||||
if (methodDeclaration->mGenericParams != NULL)
|
if (methodDeclaration->mGenericParams != NULL)
|
||||||
{
|
{
|
||||||
|
@ -485,11 +482,14 @@ void BfSourceClassifier::Visit(BfMethodDeclaration* methodDeclaration)
|
||||||
|
|
||||||
if (methodDeclaration->mGenericConstraintsDeclaration != NULL)
|
if (methodDeclaration->mGenericConstraintsDeclaration != NULL)
|
||||||
{
|
{
|
||||||
for (auto constraint : methodDeclaration->mGenericConstraintsDeclaration->mGenericConstraints)
|
for (auto constraintNode : methodDeclaration->mGenericConstraintsDeclaration->mGenericConstraints)
|
||||||
{
|
{
|
||||||
BfIdentifierNode* typeRef = constraint->mGenericParamName;
|
if (auto genericConstraint = BfNodeDynCast<BfGenericConstraint>(constraintNode))
|
||||||
if (typeRef != NULL)
|
{
|
||||||
SetElementType(typeRef, BfSourceElementType_TypeRef);
|
BfTypeReference* typeRef = genericConstraint->mTypeRef;
|
||||||
|
if (typeRef != NULL)
|
||||||
|
SetElementType(typeRef, BfSourceElementType_TypeRef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -563,9 +563,11 @@ void BfSourceClassifier::Handle(BfTypeDeclaration* typeDeclaration)
|
||||||
|
|
||||||
if (typeDeclaration->mGenericConstraintsDeclaration != NULL)
|
if (typeDeclaration->mGenericConstraintsDeclaration != NULL)
|
||||||
{
|
{
|
||||||
for (auto constraint : typeDeclaration->mGenericConstraintsDeclaration->mGenericConstraints)
|
for (auto constraintNode : typeDeclaration->mGenericConstraintsDeclaration->mGenericConstraints)
|
||||||
{
|
{
|
||||||
BfIdentifierNode* typeRef = constraint->mGenericParamName;
|
auto genericConstraint = BfNodeDynCast<BfGenericConstraint>(constraintNode);
|
||||||
|
|
||||||
|
BfTypeReference* typeRef = genericConstraint->mTypeRef;
|
||||||
if (typeRef != NULL)
|
if (typeRef != NULL)
|
||||||
SetElementType(typeRef, BfSourceElementType_TypeRef);
|
SetElementType(typeRef, BfSourceElementType_TypeRef);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2379,11 +2379,12 @@ BfTypeDef* BfSystem::FindTypeDefEx(const StringImpl& fullTypeName)
|
||||||
|
|
||||||
int numGenericArgs = 0;
|
int numGenericArgs = 0;
|
||||||
String typeName = fullTypeName.Substring(colonPos + 1);
|
String typeName = fullTypeName.Substring(colonPos + 1);
|
||||||
int tildePos = (int)typeName.IndexOf('`');
|
int tildePos = (int)typeName.LastIndexOf('`');
|
||||||
if (tildePos != -1)
|
if (tildePos != -1)
|
||||||
{
|
{
|
||||||
|
BF_ASSERT(tildePos > (int)typeName.LastIndexOf('.'));
|
||||||
numGenericArgs = atoi(typeName.c_str() + tildePos + 1);
|
numGenericArgs = atoi(typeName.c_str() + tildePos + 1);
|
||||||
typeName.RemoveToEnd(tildePos);
|
typeName.RemoveToEnd(tildePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FindTypeDef(typeName, numGenericArgs, project);
|
return FindTypeDef(typeName, numGenericArgs, project);
|
||||||
|
@ -2587,13 +2588,13 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef)
|
||||||
typeDef->mGenericParamDefs.Clear();
|
typeDef->mGenericParamDefs.Clear();
|
||||||
|
|
||||||
typeDef->mGenericParamDefs = nextTypeDef->mGenericParamDefs;
|
typeDef->mGenericParamDefs = nextTypeDef->mGenericParamDefs;
|
||||||
nextTypeDef->mGenericParamDefs.Clear();
|
nextTypeDef->mGenericParamDefs.Clear();
|
||||||
|
|
||||||
typeDef->mBaseTypes = nextTypeDef->mBaseTypes;
|
typeDef->mBaseTypes = nextTypeDef->mBaseTypes;
|
||||||
typeDef->mNestedTypes = nextTypeDef->mNestedTypes;
|
typeDef->mNestedTypes = nextTypeDef->mNestedTypes;
|
||||||
|
|
||||||
// If we are a partial then the mOuterType gets set to the combined partial so don't do that here
|
// If we are a partial then the mOuterType gets set to the combined partial so don't do that here
|
||||||
if (!typeDef->mIsPartial)
|
if (!typeDef->mIsCombinedPartial)
|
||||||
{
|
{
|
||||||
for (auto nestedType : typeDef->mNestedTypes)
|
for (auto nestedType : typeDef->mNestedTypes)
|
||||||
{
|
{
|
||||||
|
@ -2658,7 +2659,7 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
|
||||||
BfGenericParamDef* newGeneric = new BfGenericParamDef();
|
BfGenericParamDef* newGeneric = new BfGenericParamDef();
|
||||||
*newGeneric = *generic;
|
*newGeneric = *generic;
|
||||||
typeDef->mGenericParamDefs.push_back(newGeneric);
|
typeDef->mGenericParamDefs.push_back(newGeneric);
|
||||||
}
|
}
|
||||||
|
|
||||||
typeDef->mBaseTypes = partialTypeDef->mBaseTypes;
|
typeDef->mBaseTypes = partialTypeDef->mBaseTypes;
|
||||||
|
|
||||||
|
@ -2675,7 +2676,7 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
|
||||||
{
|
{
|
||||||
typeDef->mTypeCode = partialTypeDef->mTypeCode;
|
typeDef->mTypeCode = partialTypeDef->mTypeCode;
|
||||||
typeDef->mTypeDeclaration = partialTypeDef->mTypeDeclaration;
|
typeDef->mTypeDeclaration = partialTypeDef->mTypeDeclaration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge attributes together
|
// Merge attributes together
|
||||||
|
|
|
@ -574,34 +574,52 @@ public:
|
||||||
BfAstNode* GetRefNode();
|
BfAstNode* GetRefNode();
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BfGenericParamFlags : uint8
|
enum BfGenericParamFlags : uint16
|
||||||
{
|
{
|
||||||
BfGenericParamFlag_None = 0,
|
BfGenericParamFlag_None = 0,
|
||||||
BfGenericParamFlag_Class = 1,
|
BfGenericParamFlag_Class = 1,
|
||||||
BfGenericParamFlag_Struct = 2,
|
BfGenericParamFlag_Struct = 2,
|
||||||
BfGenericParamFlag_StructPtr = 4,
|
BfGenericParamFlag_StructPtr = 4,
|
||||||
BfGenericParamFlag_New = 8,
|
BfGenericParamFlag_New = 8,
|
||||||
BfGenericParamFlag_Delete = 16,
|
BfGenericParamFlag_Delete = 0x10,
|
||||||
BfGenericParamFlag_Var = 32,
|
BfGenericParamFlag_Var = 0x20,
|
||||||
BfGenericParamFlag_Const = 64
|
BfGenericParamFlag_Const = 0x40,
|
||||||
|
BfGenericParamFlag_Equals = 0x80,
|
||||||
|
BfGenericParamFlag_Equals_Op = 0x100,
|
||||||
|
BfGenericParamFlag_Equals_Type = 0x200,
|
||||||
|
BfGenericParamFlag_Equals_IFace = 0x400
|
||||||
};
|
};
|
||||||
|
|
||||||
class BfGenericParamDef
|
class BfConstraintDef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//BfTypeDef* mOwner;
|
BfGenericParamFlags mGenericParamFlags;
|
||||||
|
Array<BfAstNode*> mConstraints;
|
||||||
|
|
||||||
|
BfConstraintDef()
|
||||||
|
{
|
||||||
|
mGenericParamFlags = BfGenericParamFlag_None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BfGenericParamDef : public BfConstraintDef
|
||||||
|
{
|
||||||
|
public:
|
||||||
String mName;
|
String mName;
|
||||||
Array<BfIdentifierNode*> mNameNodes; // 0 is always the def name
|
Array<BfIdentifierNode*> mNameNodes; // 0 is always the def name
|
||||||
BfGenericParamFlags mGenericParamFlags;
|
};
|
||||||
Array<BfTypeReference*> mInterfaceConstraints;
|
|
||||||
|
class BfExternalConstraintDef : public BfConstraintDef
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BfTypeReference* mTypeRef;
|
||||||
};
|
};
|
||||||
|
|
||||||
// CTOR is split into two for Objects - Ctor clears and sets up VData, Ctor_Body executes ctor body code
|
// CTOR is split into two for Objects - Ctor clears and sets up VData, Ctor_Body executes ctor body code
|
||||||
enum BfMethodType : uint8
|
enum BfMethodType : uint8
|
||||||
{
|
{
|
||||||
BfMethodType_Ignore,
|
BfMethodType_Ignore,
|
||||||
BfMethodType_Normal,
|
BfMethodType_Normal,
|
||||||
//BfMethodType_Lambda,
|
|
||||||
BfMethodType_PropertyGetter,
|
BfMethodType_PropertyGetter,
|
||||||
BfMethodType_PropertySetter,
|
BfMethodType_PropertySetter,
|
||||||
BfMethodType_CtorCalcAppend,
|
BfMethodType_CtorCalcAppend,
|
||||||
|
@ -658,6 +676,13 @@ enum BfCheckedKind : int8
|
||||||
BfCheckedKind_Unchecked
|
BfCheckedKind_Unchecked
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BfCommutableKind : int8
|
||||||
|
{
|
||||||
|
BfCommutableKind_None,
|
||||||
|
BfCommutableKind_Forward,
|
||||||
|
BfCommutableKind_Reverse,
|
||||||
|
};
|
||||||
|
|
||||||
class BfMethodDef : public BfMemberDef
|
class BfMethodDef : public BfMemberDef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -668,6 +693,7 @@ public:
|
||||||
BfTypeReference* mReturnTypeRef;
|
BfTypeReference* mReturnTypeRef;
|
||||||
Array<BfParameterDef*> mParams;
|
Array<BfParameterDef*> mParams;
|
||||||
Array<BfGenericParamDef*> mGenericParams;
|
Array<BfGenericParamDef*> mGenericParams;
|
||||||
|
Array<BfExternalConstraintDef> mExternalConstraints;
|
||||||
BfMethodDef* mNextWithSameName;
|
BfMethodDef* mNextWithSameName;
|
||||||
Val128 mFullHash;
|
Val128 mFullHash;
|
||||||
|
|
||||||
|
@ -694,6 +720,7 @@ public:
|
||||||
bool mIsOperator;
|
bool mIsOperator;
|
||||||
bool mIsExtern;
|
bool mIsExtern;
|
||||||
bool mIsNoDiscard;
|
bool mIsNoDiscard;
|
||||||
|
BfCommutableKind mCommutableKind;
|
||||||
BfCheckedKind mCheckedKind;
|
BfCheckedKind mCheckedKind;
|
||||||
BfImportKind mImportKind;
|
BfImportKind mImportKind;
|
||||||
BfCallingConvention mCallingConvention;
|
BfCallingConvention mCallingConvention;
|
||||||
|
@ -726,6 +753,7 @@ public:
|
||||||
mMethodDeclaration = NULL;
|
mMethodDeclaration = NULL;
|
||||||
mCodeChanged = false;
|
mCodeChanged = false;
|
||||||
mWantsBody = true;
|
mWantsBody = true;
|
||||||
|
mCommutableKind = BfCommutableKind_None;
|
||||||
mCheckedKind = BfCheckedKind_NotSet;
|
mCheckedKind = BfCheckedKind_NotSet;
|
||||||
mImportKind = BfImportKind_None;
|
mImportKind = BfImportKind_None;
|
||||||
mMethodType = BfMethodType_Normal;
|
mMethodType = BfMethodType_Normal;
|
||||||
|
|
45
IDEHelper/Tests/src/Generics.bf
Normal file
45
IDEHelper/Tests/src/Generics.bf
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Tests
|
||||||
|
{
|
||||||
|
class Generics
|
||||||
|
{
|
||||||
|
class ClassA : IDisposable
|
||||||
|
{
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoDispose<T>(mut T val) where T : IDisposable
|
||||||
|
{
|
||||||
|
val.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Disposer<T>
|
||||||
|
{
|
||||||
|
static void UseDispose(IDisposable disp)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoDisposeA(mut T val) where T : IDisposable
|
||||||
|
{
|
||||||
|
val.Dispose();
|
||||||
|
UseDispose(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DoDisposeB(mut T val) where T : IDisposable
|
||||||
|
{
|
||||||
|
val.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public static void TestBasics()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma warning disable 168
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Tests
|
namespace Tests
|
||||||
|
@ -23,6 +25,151 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StructB
|
||||||
|
{
|
||||||
|
public int mB;
|
||||||
|
|
||||||
|
public static StructA operator+(StructA sa, StructB sb)
|
||||||
|
{
|
||||||
|
StructA result;
|
||||||
|
result.mA = sa.mA + sb.mB + 1000;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StructOp<T, T2> where T : operator T + T2
|
||||||
|
{
|
||||||
|
public T DoIt(T val, T2 val2)
|
||||||
|
{
|
||||||
|
return val + val2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StructOp2<T>
|
||||||
|
{
|
||||||
|
public T mVal;
|
||||||
|
|
||||||
|
public static T operator+<T2>(StructOp2<T> lhs, T2 rhs) where T : operator T + T2
|
||||||
|
{
|
||||||
|
return lhs.mVal + rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T operator|<T2>(StructOp2<T> lhs, T2 rhs) where T : operator implicit T2
|
||||||
|
{
|
||||||
|
T temp = rhs;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetNeg<T2>(T2 val) where T : operator -T2
|
||||||
|
{
|
||||||
|
return -val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetInt() where T : Int
|
||||||
|
{
|
||||||
|
return mVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*struct OuterOp<T>
|
||||||
|
{
|
||||||
|
public struct InnerOp<T2>
|
||||||
|
where T : operator T + T2
|
||||||
|
where T : operator -T
|
||||||
|
where T : operator implicit T2
|
||||||
|
{
|
||||||
|
public static T Op(T val, T2 val2)
|
||||||
|
{
|
||||||
|
return val + val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Neg(T val)
|
||||||
|
{
|
||||||
|
return -val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Cast(T2 val)
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InnerOp2
|
||||||
|
{
|
||||||
|
public static T Op(T val, T2 val2)
|
||||||
|
{
|
||||||
|
return val + val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Neg(T val)
|
||||||
|
{
|
||||||
|
return -val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Cast(T2 val)
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InnerOp3<T3>
|
||||||
|
{
|
||||||
|
public static T Op(T val, T2 val2)
|
||||||
|
{
|
||||||
|
return val + val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Neg(T val)
|
||||||
|
{
|
||||||
|
return -val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Cast(T2 val)
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OuterOp2<T>
|
||||||
|
{
|
||||||
|
public struct InnerOp<T2>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension InnerOp<T2>
|
||||||
|
where T : operator T + T2
|
||||||
|
where T : operator -T
|
||||||
|
{
|
||||||
|
public static T Op(T val, T2 val2)
|
||||||
|
{
|
||||||
|
return val + val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Neg(T val)
|
||||||
|
{
|
||||||
|
return -val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public static T Op<T, T2>(T val, T2 val2) where T : operator T + T2
|
||||||
|
{
|
||||||
|
return val + val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Complex<T, T2>(T val, T2 val2)
|
||||||
|
where T : operator T + T2
|
||||||
|
where T : operator -T
|
||||||
|
where T : operator implicit T2
|
||||||
|
{
|
||||||
|
T conv = val2;
|
||||||
|
T result = val + val2;
|
||||||
|
result = -result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestBasics()
|
public static void TestBasics()
|
||||||
{
|
{
|
||||||
|
@ -33,6 +180,40 @@ namespace Tests
|
||||||
|
|
||||||
StructA sa2 = sa0 + sa1;
|
StructA sa2 = sa0 + sa1;
|
||||||
Test.Assert(sa2.mA == 3);
|
Test.Assert(sa2.mA == 3);
|
||||||
|
|
||||||
|
StructB sb0;
|
||||||
|
sb0.mB = 11;
|
||||||
|
StructB sb1;
|
||||||
|
sb1.mB = 12;
|
||||||
|
|
||||||
|
StructA sa3 = sa0 + sb0;
|
||||||
|
Test.Assert(sa3.mA == 1012);
|
||||||
|
|
||||||
|
StructA sa4 = Op(sa0, sb0);
|
||||||
|
Test.Assert(sa4.mA == 1012);
|
||||||
|
|
||||||
|
float val = Op((int32)100, (int16)23);
|
||||||
|
Test.Assert(val == 123);
|
||||||
|
|
||||||
|
int32 i32res = Complex((int32)100, (int16)23);
|
||||||
|
Test.Assert(i32res == -123);
|
||||||
|
|
||||||
|
StructOp<StructA, StructB> sOp;
|
||||||
|
let sa5 = sOp.DoIt(sa1, sb1);
|
||||||
|
Test.Assert(sa5.mA == 1014);
|
||||||
|
|
||||||
|
StructOp2<int32> sOp2;
|
||||||
|
sOp2.mVal = 100;
|
||||||
|
int32 res6 = sOp2 + (int16)40;
|
||||||
|
Test.Assert(res6 == 140);
|
||||||
|
int32 res7 = sOp2.GetInt();
|
||||||
|
Test.Assert(res7 == 100);
|
||||||
|
|
||||||
|
/*let oai = OuterOp<float>.InnerOp<int>.Op(1.0f, 100);
|
||||||
|
Test.Assert(oai == 101.0f);
|
||||||
|
|
||||||
|
let oai2 = OuterOp2<float>.InnerOp<int>.Op(2.0f, 200);
|
||||||
|
Test.Assert(oai2 == 202.0f);*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue