1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 20:12:21 +02:00

Improvements to const string generic arg, literal generic args

This commit is contained in:
Brian Fiete 2022-02-05 09:23:44 -05:00
parent cd1e65231e
commit cf5c969d1f
15 changed files with 243 additions and 99 deletions

View file

@ -671,7 +671,7 @@ public:
bool IsStatic() const bool IsStatic() const
{ {
return !mValue; return (!mValue) && (mKind != BfTypedValueKind_GenericConstValue);
} }
bool IsAddr() const bool IsAddr() const
@ -2948,7 +2948,7 @@ public:
BF_AST_TYPE(BfGenericArgumentsNode, BfAstNode); BF_AST_TYPE(BfGenericArgumentsNode, BfAstNode);
ASTREF(BfTokenNode*) mOpenChevron; ASTREF(BfTokenNode*) mOpenChevron;
BfSizedArray<ASTREF(BfTypeReference*)> mGenericArgs; BfSizedArray<ASTREF(BfAstNode*)> mGenericArgs;
BfSizedArray<ASTREF(BfAstNode*)> mCommas; BfSizedArray<ASTREF(BfAstNode*)> mCommas;
ASTREF(BfTokenNode*) mCloseChevron; ASTREF(BfTokenNode*) mCloseChevron;
}; BF_AST_DECL(BfGenericArgumentsNode, BfAstNode); }; BF_AST_DECL(BfGenericArgumentsNode, BfAstNode);

View file

@ -2075,8 +2075,7 @@ void BfAutoComplete::CheckTypeRef(BfTypeReference* typeRef, bool mayBeIdentifier
{ {
CheckTypeRef(genericTypeRef->mElementType, mayBeIdentifier, isInExpression, onlyAttribute); CheckTypeRef(genericTypeRef->mElementType, mayBeIdentifier, isInExpression, onlyAttribute);
for (auto genericArg : genericTypeRef->mGenericArguments) for (auto genericArg : genericTypeRef->mGenericArguments)
CheckNode(genericArg); CheckNode(genericArg, false, isInExpression);
//CheckTypeRef(genericArg, false, isInExpression, false);
return; return;
} }
@ -2259,7 +2258,7 @@ void BfAutoComplete::CheckInvocation(BfAstNode* invocationNode, BfTokenNode* ope
} }
} }
void BfAutoComplete::CheckNode(BfAstNode* node) void BfAutoComplete::CheckNode(BfAstNode* node, bool mayBeIdentifier, bool isInExpression)
{ {
if (!IsAutocompleteNode(node)) if (!IsAutocompleteNode(node))
return; return;
@ -2267,7 +2266,7 @@ void BfAutoComplete::CheckNode(BfAstNode* node)
if (auto identifer = BfNodeDynCast<BfIdentifierNode>(node)) if (auto identifer = BfNodeDynCast<BfIdentifierNode>(node))
CheckIdentifier(identifer); CheckIdentifier(identifer);
if (auto typeRef = BfNodeDynCast<BfTypeReference>(node)) if (auto typeRef = BfNodeDynCast<BfTypeReference>(node))
CheckTypeRef(typeRef, true); CheckTypeRef(typeRef, mayBeIdentifier, isInExpression);
if (auto memberRef = BfNodeDynCast<BfMemberReferenceExpression>(node)) if (auto memberRef = BfNodeDynCast<BfMemberReferenceExpression>(node))
{ {
if (memberRef->mTarget != NULL) if (memberRef->mTarget != NULL)

View file

@ -256,7 +256,7 @@ public:
void CheckTypeRef(BfTypeReference* typeRef, bool mayBeIdentifier, bool isInExpression = false, bool onlyAttribute = false); void CheckTypeRef(BfTypeReference* typeRef, bool mayBeIdentifier, bool isInExpression = false, bool onlyAttribute = false);
void CheckAttributeTypeRef(BfTypeReference* typeRef); void CheckAttributeTypeRef(BfTypeReference* typeRef);
void CheckInvocation(BfAstNode* invocationNode, BfTokenNode* openParen, BfTokenNode* closeParen, const BfSizedArray<BfTokenNode*>& commas); void CheckInvocation(BfAstNode* invocationNode, BfTokenNode* openParen, BfTokenNode* closeParen, const BfSizedArray<BfTokenNode*>& commas);
void CheckNode(BfAstNode* node); void CheckNode(BfAstNode* node, bool mayBeIdentifier, bool isInExpression = false);
void CheckMethod(BfMethodDeclaration* methodDeclaration, bool isLocalMethod); void CheckMethod(BfMethodDeclaration* methodDeclaration, bool isLocalMethod);
void CheckProperty(BfPropertyDeclaration* propertyDeclaration); void CheckProperty(BfPropertyDeclaration* propertyDeclaration);
void CheckVarResolution(BfAstNode* varTypeRef, BfType* resolvedTypeRef); void CheckVarResolution(BfAstNode* varTypeRef, BfType* resolvedTypeRef);

View file

@ -137,7 +137,7 @@ BfBaseClassWalker::Entry BfBaseClassWalker::Next()
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const StringImpl& methodName, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments) : BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const StringImpl& methodName, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments) :
mArguments(arguments) mArguments(arguments)
{ {
mTargetSrc = targetSrc; mTargetSrc = targetSrc;
@ -146,7 +146,7 @@ BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const S
Init(/*arguments, */methodGenericArguments); Init(/*arguments, */methodGenericArguments);
} }
BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments) : BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments) :
mArguments(arguments) mArguments(arguments)
{ {
mTargetSrc = targetSrc; mTargetSrc = targetSrc;
@ -156,7 +156,7 @@ BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMetho
mMethodName = mInterfaceMethodInstance->mMethodDef->mName; mMethodName = mInterfaceMethodInstance->mMethodDef->mName;
} }
void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments) void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments)
{ {
//mArguments = arguments; //mArguments = arguments;
mActiveTypeDef = NULL; mActiveTypeDef = NULL;
@ -204,9 +204,9 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSized
if (methodGenericArguments != NULL) if (methodGenericArguments != NULL)
{ {
for (BfTypeReference* genericArg : *methodGenericArguments) for (BfAstNode* genericArg : *methodGenericArguments)
{ {
auto genericArgType = mModule->ResolveTypeRef(genericArg); auto genericArgType = mModule->ResolveTypeRef(genericArg, NULL, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowImplicitConstExpr);
if ((genericArgType != NULL) && (genericArgType->IsGenericParam())) if ((genericArgType != NULL) && (genericArgType->IsGenericParam()))
{ {
auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)genericArgType); auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)genericArgType);
@ -4251,7 +4251,10 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
} }
if ((!result) && (identifierNode != NULL)) if ((!result) && (identifierNode != NULL))
{
result = mModule->TryLookupGenericConstVaue(identifierNode, mExpectingType); result = mModule->TryLookupGenericConstVaue(identifierNode, mExpectingType);
mModule->FixValueActualization(result);
}
return result; return result;
} }
@ -6382,7 +6385,6 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
if (argVal.mType->IsValuelessType()) if (argVal.mType->IsValuelessType())
return; return;
bool wantSplat = false; bool wantSplat = false;
if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsComptime())) if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsComptime()))
{ {
@ -8249,7 +8251,7 @@ bool BfExprEvaluator::CheckGenericCtor(BfGenericParamType* genericParamType, BfR
} }
BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName, BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
BfResolvedArgs& argValues, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments, BfCheckedKind checkedKind) BfResolvedArgs& argValues, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments, BfCheckedKind checkedKind)
{ {
BP_ZONE("MatchMethod"); BP_ZONE("MatchMethod");
@ -8650,9 +8652,6 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
for (BfType* ifaceInst : genericParamInstance->mInterfaceConstraints) for (BfType* ifaceInst : genericParamInstance->mInterfaceConstraints)
{ {
if (ifaceInst->IsUnspecializedType())
ifaceInst = mModule->ResolveType(ifaceInst);
BfTypeInstance* typeInst = ifaceInst->ToTypeInstance(); BfTypeInstance* typeInst = ifaceInst->ToTypeInstance();
BF_ASSERT(typeInst != NULL); BF_ASSERT(typeInst != NULL);
if (methodMatcher.CheckType(typeInst, target, false)) if (methodMatcher.CheckType(typeInst, target, false))
@ -11599,7 +11598,7 @@ bool BfExprEvaluator::CanBindDelegate(BfDelegateBindExpression* delegateBindExpr
args[i] = typedValueExpr; args[i] = typedValueExpr;
} }
BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL; BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
if (delegateBindExpr->mGenericArgs != NULL) if (delegateBindExpr->mGenericArgs != NULL)
methodGenericArguments = &delegateBindExpr->mGenericArgs->mGenericArgs; methodGenericArguments = &delegateBindExpr->mGenericArgs->mGenericArgs;
@ -12003,7 +12002,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
args[i] = typedValueExpr; args[i] = typedValueExpr;
} }
BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL; BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
if (delegateBindExpr->mGenericArgs != NULL) if (delegateBindExpr->mGenericArgs != NULL)
methodGenericArguments = &delegateBindExpr->mGenericArgs->mGenericArgs; methodGenericArguments = &delegateBindExpr->mGenericArgs->mGenericArgs;
@ -12017,7 +12016,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
if (autoComplete != NULL) if (autoComplete != NULL)
{ {
SetAndRestoreValue<bool> prevForceAllowNonStatic(autoComplete->mForceAllowNonStatic, methodInstance->mMethodDef->mHasExplicitThis); SetAndRestoreValue<bool> prevForceAllowNonStatic(autoComplete->mForceAllowNonStatic, methodInstance->mMethodDef->mHasExplicitThis);
GetAutoComplete()->CheckNode(delegateBindExpr->mTarget); GetAutoComplete()->CheckNode(delegateBindExpr->mTarget, true);
} }
if ((!delegateBindExpr->mTarget->IsA<BfIdentifierNode>()) && if ((!delegateBindExpr->mTarget->IsA<BfIdentifierNode>()) &&
@ -14061,6 +14060,8 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{ {
unresolvedTypeRef = mExpectingType->GetUnderlyingType(); unresolvedTypeRef = mExpectingType->GetUnderlyingType();
} }
else if (mExpectingType->IsVar())
unresolvedTypeRef = mExpectingType;
} }
if (unresolvedTypeRef == NULL) if (unresolvedTypeRef == NULL)
@ -15645,7 +15646,7 @@ void BfExprEvaluator::CheckLocalMethods(BfAstNode* targetSrc, BfTypeInstance* ty
} }
} }
void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, bool allowImplicitThis, const StringImpl& name, const BfSizedArray<BfExpression*>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArgs) void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, bool allowImplicitThis, const StringImpl& name, const BfSizedArray<BfExpression*>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArgs)
{ {
if (mModule->mCurMethodState == NULL) if (mModule->mCurMethodState == NULL)
return; return;
@ -16511,7 +16512,7 @@ void BfExprEvaluator::SetMethodElementType(BfAstNode* target)
mModule->SetElementType(target, BfSourceElementType_Method); mModule->SetElementType(target, BfSourceElementType_Method);
} }
void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray<BfExpression*>& args, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments, BfTypedValue* outCascadeValue) void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray<BfExpression*>& args, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments, BfTypedValue* outCascadeValue)
{ {
// Just a check // Just a check
mModule->mBfIRBuilder->GetInsertBlock(); mModule->mBfIRBuilder->GetInsertBlock();
@ -16520,8 +16521,10 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
auto autoComplete = GetAutoComplete(); auto autoComplete = GetAutoComplete();
if ((autoComplete != NULL) && (methodGenericArguments != NULL)) if ((autoComplete != NULL) && (methodGenericArguments != NULL))
{ {
for (BfTypeReference* methodGenericArg : *methodGenericArguments) for (BfAstNode* methodGenericArg : *methodGenericArguments)
autoComplete->CheckTypeRef(methodGenericArg, false, true); {
autoComplete->CheckNode(methodGenericArg, false, true);
}
} }
if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo)) if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
@ -17250,7 +17253,7 @@ void BfExprEvaluator::Visit(BfInvocationExpression* invocationExpr)
autoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas); autoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas);
mModule->UpdateExprSrcPos(invocationExpr); mModule->UpdateExprSrcPos(invocationExpr);
BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL; BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
if (invocationExpr->mGenericArgs != NULL) if (invocationExpr->mGenericArgs != NULL)
methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs; methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs;
SizedArray<BfExpression*, 8> copiedArgs; SizedArray<BfExpression*, 8> copiedArgs;
@ -20694,13 +20697,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
auto derefTarget = mModule->LoadValue(mResult); auto derefTarget = mModule->LoadValue(mResult);
BfPointerType* pointerType = (BfPointerType*)derefTarget.mType; BfPointerType* pointerType = (BfPointerType*)derefTarget.mType;
auto resolvedType = mModule->ResolveType(pointerType->mElementType); auto resolvedType = pointerType->mElementType;
if (resolvedType == NULL)
{
mResult = BfTypedValue();
return;
}
mModule->PopulateType(resolvedType); mModule->PopulateType(resolvedType);
if (resolvedType->IsValuelessType()) if (resolvedType->IsValuelessType())
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), resolvedType, true); mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), resolvedType, true);

View file

@ -236,9 +236,9 @@ public:
int GetMostSpecificType(BfType* lhs, BfType* rhs); // 0, 1, or -1 int GetMostSpecificType(BfType* lhs, BfType* rhs); // 0, 1, or -1
public: 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(BfAstNode*)>* 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(BfAstNode*)>* methodGenericArguments = NULL);
void Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments); void Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments);
bool IsMemberAccessible(BfTypeInstance* typeInst, BfTypeDef* declaringType); bool IsMemberAccessible(BfTypeInstance* typeInst, BfTypeDef* declaringType);
bool CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass, bool forceOuterCheck = false); bool CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass, bool forceOuterCheck = false);
void CheckOuterTypeStaticMethods(BfTypeInstance* typeInstance, bool isFailurePass); void CheckOuterTypeStaticMethods(BfTypeInstance* typeInstance, bool isFailurePass);
@ -462,16 +462,16 @@ public:
BfResolvedArgs& argValues, bool callCtorBodyOnly, bool allowAppendAlloc, BfTypedValue* appendIndexValue = NULL); BfResolvedArgs& argValues, bool callCtorBodyOnly, bool allowAppendAlloc, BfTypedValue* appendIndexValue = NULL);
BfTypedValue CheckEnumCreation(BfAstNode* targetSrc, BfTypeInstance* enumType, const StringImpl& caseName, BfResolvedArgs& argValues); BfTypedValue CheckEnumCreation(BfAstNode* targetSrc, BfTypeInstance* enumType, const StringImpl& caseName, BfResolvedArgs& argValues);
BfTypedValue MatchMethod(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& name, BfTypedValue MatchMethod(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& name,
BfResolvedArgs& argValue, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments, BfCheckedKind checkedKind = BfCheckedKind_NotSet); BfResolvedArgs& argValue, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments, BfCheckedKind checkedKind = BfCheckedKind_NotSet);
BfTypedValue MakeCallableTarget(BfAstNode* targetSrc, BfTypedValue target); BfTypedValue MakeCallableTarget(BfAstNode* targetSrc, BfTypedValue target);
BfModuleMethodInstance GetSelectedMethod(BfAstNode* targetSrc, BfTypeInstance* curTypeInst, BfMethodDef* methodDef, BfMethodMatcher& methodMatcher, BfType** overrideReturnType = NULL); BfModuleMethodInstance GetSelectedMethod(BfAstNode* targetSrc, BfTypeInstance* curTypeInst, BfMethodDef* methodDef, BfMethodMatcher& methodMatcher, BfType** overrideReturnType = NULL);
BfModuleMethodInstance GetSelectedMethod(BfMethodMatcher& methodMatcher); BfModuleMethodInstance GetSelectedMethod(BfMethodMatcher& methodMatcher);
bool CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail); bool CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail);
bool HasVariableDeclaration(BfAstNode* checkNode); bool HasVariableDeclaration(BfAstNode* checkNode);
void DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray<BfExpression*>& args, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArgs, BfTypedValue* outCascadeValue = NULL); void DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray<BfExpression*>& args, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArgs, BfTypedValue* outCascadeValue = NULL);
int GetMixinVariable(); int GetMixinVariable();
void CheckLocalMethods(BfAstNode* targetSrc, BfTypeInstance* typeInstance, const StringImpl& methodName, BfMethodMatcher& methodMatcher, BfMethodType methodType); void CheckLocalMethods(BfAstNode* targetSrc, BfTypeInstance* typeInstance, const StringImpl& methodName, BfMethodMatcher& methodMatcher, BfMethodType methodType);
void InjectMixin(BfAstNode* targetSrc, BfTypedValue target, bool allowImplicitThis, const StringImpl& name, const BfSizedArray<BfExpression*>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArgs); void InjectMixin(BfAstNode* targetSrc, BfTypedValue target, bool allowImplicitThis, const StringImpl& name, const BfSizedArray<BfExpression*>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArgs);
void SetMethodElementType(BfAstNode* target); void SetMethodElementType(BfAstNode* target);
BfTypedValue DoImplicitArgCapture(BfAstNode* refNode, BfIdentifierNode* identifierNode, int shadowIdx); BfTypedValue DoImplicitArgCapture(BfAstNode* refNode, BfIdentifierNode* identifierNode, int shadowIdx);
BfTypedValue DoImplicitArgCapture(BfAstNode* refNode, BfMethodInstance* methodInstance, int paramIdx, bool& failed, BfImplicitParamKind paramKind = BfImplicitParamKind_General, const BfTypedValue& methodRefTarget = BfTypedValue()); BfTypedValue DoImplicitArgCapture(BfAstNode* refNode, BfMethodInstance* methodInstance, int paramIdx, bool& failed, BfImplicitParamKind paramKind = BfImplicitParamKind_General, const BfTypedValue& methodRefTarget = BfTypedValue());

View file

@ -8091,7 +8091,10 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode)) if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode))
{ {
char valStr[64]; char valStr[64];
if (constExprValueType->mValue.mTypeCode == BfTypeCode_Double)
ExactMinimalDoubleToStr(constExprValueType->mValue.mDouble, valStr); ExactMinimalDoubleToStr(constExprValueType->mValue.mDouble, valStr);
else
ExactMinimalFloatToStr(constExprValueType->mValue.mSingle, valStr);
if ((!ignoreErrors) && (PreFail())) if ((!ignoreErrors) && (PreFail()))
*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(), *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);
@ -8100,6 +8103,13 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
} }
} }
} }
else if (genericParamInst->mTypeConstraint != constExprValueType->mType)
{
if ((!ignoreErrors) && (PreFail()))
*errorOut = Fail(StrFormat("Const generic argument '%s', declared as '%s', is not compatible with const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
_TypeToString(constExprValueType).c_str(), _TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
return false;
}
} }
} }
else else
@ -8521,13 +8531,15 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator,
auto genericTypeConstraint = genericParamDef->mTypeConstraint; auto genericTypeConstraint = genericParamDef->mTypeConstraint;
if (genericTypeConstraint != NULL) if (genericTypeConstraint != NULL)
{ {
auto primType = genericTypeConstraint->ToPrimitiveType(); auto underlyingConstraint = genericTypeConstraint;
if (primType != NULL) if ((underlyingConstraint != NULL) && (underlyingConstraint->IsBoxed()))
underlyingConstraint = underlyingConstraint->GetUnderlyingType();
if (underlyingConstraint != NULL)
{ {
BfTypedValue result; BfTypedValue result;
result.mKind = BfTypedValueKind_Value; result.mKind = BfTypedValueKind_Value;
result.mType = genericTypeConstraint; result.mType = genericTypeConstraint;
result.mValue = mBfIRBuilder->GetUndefConstValue(mBfIRBuilder->MapType(primType)); result.mValue = mBfIRBuilder->GetUndefConstValue(mBfIRBuilder->MapType(underlyingConstraint));
typedVal = result; typedVal = result;
handled = true; handled = true;
} }
@ -9844,6 +9856,9 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
if (typedVal.mValue.IsConst()) if (typedVal.mValue.IsConst())
{ {
int stringIdx = GetStringPoolIdx(typedVal.mValue, mBfIRBuilder);
if (stringIdx != -1)
return;
auto constant = mBfIRBuilder->GetConstant(typedVal.mValue); auto constant = mBfIRBuilder->GetConstant(typedVal.mValue);
if (constant->mTypeCode == BfTypeCode_NullPtr) if (constant->mTypeCode == BfTypeCode_NullPtr)
return; return;
@ -10893,11 +10908,11 @@ StringT<128> BfModule::MethodToString(BfMethodInstance* methodInst, BfMethodName
{ {
if (i > 0) if (i > 0)
methodName += ", "; methodName += ", ";
BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None; BfTypeNameFlags typeNameFlags = BfTypeNameFlag_ShortConst;
//Why did we have this methodInst->mIsUnspecializedVariation check? Sometimes we do need to show errors calling methods that refer back to our types //Why did we have this methodInst->mIsUnspecializedVariation check? Sometimes we do need to show errors calling methods that refer back to our types
//if (!methodInst->mIsUnspecializedVariation && allowResolveGenericParamNames) //if (!methodInst->mIsUnspecializedVariation && allowResolveGenericParamNames)
if (allowResolveGenericParamNames) if (allowResolveGenericParamNames)
typeNameFlags = BfTypeNameFlag_ResolveGenericParamNames; typeNameFlags = (BfTypeNameFlags)(typeNameFlags | BfTypeNameFlag_ResolveGenericParamNames);
BfType* type = methodInst->mMethodInfoEx->mMethodGenericArguments[i]; BfType* type = methodInst->mMethodInfoEx->mMethodGenericArguments[i];
if ((methodGenericArgs != NULL) && (type->IsUnspecializedType())) if ((methodGenericArgs != NULL) && (type->IsUnspecializedType()))
{ {
@ -11529,7 +11544,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
{ {
inPropSet = true; inPropSet = true;
if (autoComplete != NULL) if (autoComplete != NULL)
autoComplete->CheckNode(assignExpr->mLeft); autoComplete->CheckNode(assignExpr->mLeft, true);
String findName = assignExpr->mLeft->ToString(); String findName = assignExpr->mLeft->ToString();
BfPropertyDef* bestProp = NULL; BfPropertyDef* bestProp = NULL;

View file

@ -1792,6 +1792,7 @@ public:
BfPointerType* CreatePointerType(BfType* resolvedType); BfPointerType* CreatePointerType(BfType* resolvedType);
BfPointerType* CreatePointerType(BfTypeReference* typeRef); BfPointerType* CreatePointerType(BfTypeReference* typeRef);
BfConstExprValueType* CreateConstExprValueType(const BfTypedValue& typedValue, bool allowCreate = true); BfConstExprValueType* CreateConstExprValueType(const BfTypedValue& typedValue, bool allowCreate = true);
BfConstExprValueType* CreateConstExprValueType(const BfVariant& variant, BfType* type, bool allowCreate = true);
BfBoxedType* CreateBoxedType(BfType* resolvedTypeRef, bool allowCreate = true); BfBoxedType* CreateBoxedType(BfType* resolvedTypeRef, bool allowCreate = true);
BfTypeInstance* CreateTupleType(const BfTypeVector& fieldTypes, const Array<String>& fieldNames, bool allowVar = false); BfTypeInstance* CreateTupleType(const BfTypeVector& fieldTypes, const Array<String>& fieldNames, bool allowVar = false);
BfTypeInstance* SantizeTupleType(BfTypeInstance* tupleType); BfTypeInstance* SantizeTupleType(BfTypeInstance* tupleType);
@ -1869,7 +1870,8 @@ public:
void GetDelegateTypeRefAttributes(BfDelegateTypeRef* delegateTypeRef, BfCallingConvention& callingConvention); void GetDelegateTypeRefAttributes(BfDelegateTypeRef* delegateTypeRef, BfCallingConvention& callingConvention);
BfType* ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, int numGenericArgs = 0); BfType* ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, int numGenericArgs = 0);
BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool resolveGenericParam = true); BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool resolveGenericParam = true);
BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeReference*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0); BfType* ResolveTypeRef_Type(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);
BfType* ResolveTypeDef(BfTypeDef* typeDef, const BfTypeVector& genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); BfType* ResolveTypeDef(BfTypeDef* typeDef, const BfTypeVector& genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);
BfType* ResolveInnerType(BfType* outerType, BfAstNode* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool ignoreErrors = false, int numGenericArgs = 0); BfType* ResolveInnerType(BfType* outerType, BfAstNode* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool ignoreErrors = false, int numGenericArgs = 0);

View file

@ -6560,6 +6560,29 @@ BfConstExprValueType* BfModule::CreateConstExprValueType(const BfTypedValue& typ
return resolvedConstExprValueType; return resolvedConstExprValueType;
} }
BfConstExprValueType* BfModule::CreateConstExprValueType(const BfVariant& variant, BfType* type, bool allowCreate)
{
BfPopulateType populateType = allowCreate ? BfPopulateType_Data : BfPopulateType_Identity;
BfResolveTypeRefFlags resolveFlags = allowCreate ? BfResolveTypeRefFlag_None : BfResolveTypeRefFlag_NoCreate;
if (variant.mTypeCode == BfTypeCode_None)
return NULL;
auto constExprValueType = mContext->mConstExprValueTypePool.Get();
constExprValueType->mContext = mContext;
constExprValueType->mType = type;
constExprValueType->mValue = variant;
auto resolvedConstExprValueType = (BfConstExprValueType*)ResolveType(constExprValueType, populateType, resolveFlags);
if (resolvedConstExprValueType != constExprValueType)
mContext->mConstExprValueTypePool.GiveBack(constExprValueType);
if (resolvedConstExprValueType != NULL)
BF_ASSERT(resolvedConstExprValueType->mValue.mInt64 == constExprValueType->mValue.mInt64);
return resolvedConstExprValueType;
}
BfTypeInstance* BfModule::GetWrappedStructType(BfType* type, bool allowSpecialized) BfTypeInstance* BfModule::GetWrappedStructType(BfType* type, bool allowSpecialized)
{ {
if (type->IsPointer()) if (type->IsPointer())
@ -10617,11 +10640,14 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
for (auto genericArgRef : genericArguments) for (auto genericArgRef : genericArguments)
{ {
auto genericArg = ResolveTypeRef(genericArgRef, NULL, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGenericTypeParamConstValue | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue)); BfType* genericArg = NULL;
lookupCtx.mResolvedTypeMap.TryGetValue(genericArgRef, &genericArg);
if (genericArg == NULL)
genericArg = ResolveTypeRef(genericArgRef, NULL, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGenericTypeParamConstValue | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue));
if ((genericArg == NULL) || (genericArg->IsVar())) if ((genericArg == NULL) || (genericArg->IsVar()))
{ {
mContext->mResolvedTypes.RemoveEntry(resolvedEntry); mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
return ResolveTypeResult(typeRef, genericArg->IsVar() ? genericArg : NULL, populateType, resolveFlags); return ResolveTypeResult(typeRef, ((genericArg != NULL) && (genericArg->IsVar())) ? genericArg : NULL, populateType, resolveFlags);
} }
genericArgs.Add(genericArg); genericArgs.Add(genericArg);
} }
@ -11371,11 +11397,8 @@ BfTypeInstance* BfModule::GetUnspecializedTypeInstance(BfTypeInstance* typeInst)
return result->ToTypeInstance(); return result->ToTypeInstance();
} }
BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeReference*>* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags) BfType* BfModule::ResolveTypeRef_Type(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
{ {
if (auto typeRef = BfNodeDynCast<BfTypeReference>(astNode))
return ResolveTypeRef(typeRef, populateType, resolveFlags);
if ((genericArgs == NULL) || (genericArgs->size() == 0)) if ((genericArgs == NULL) || (genericArgs->size() == 0))
{ {
if (auto identifier = BfNodeDynCast<BfIdentifierNode>(astNode)) if (auto identifier = BfNodeDynCast<BfIdentifierNode>(astNode))
@ -11392,7 +11415,7 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeRe
BfAstAllocator alloc; BfAstAllocator alloc;
alloc.mSourceData = astNode->GetSourceData(); alloc.mSourceData = astNode->GetSourceData();
std::function<BfTypeReference*(BfAstNode*)> _ConvType = [&] (BfAstNode* astNode) -> BfTypeReference* std::function<BfTypeReference* (BfAstNode*)> _ConvType = [&](BfAstNode* astNode) -> BfTypeReference*
{ {
if (auto typeRef = BfNodeDynCast<BfTypeReference>(astNode)) if (auto typeRef = BfNodeDynCast<BfTypeReference>(astNode))
return typeRef; return typeRef;
@ -11454,6 +11477,36 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeRe
return ResolveTypeRef(typeRef, populateType, resolveFlags); return ResolveTypeRef(typeRef, populateType, resolveFlags);
} }
BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
{
if (auto typeRef = BfNodeDynCast<BfTypeReference>(astNode))
return ResolveTypeRef(typeRef, populateType, resolveFlags);
if ((resolveFlags & BfResolveTypeRefFlag_AllowImplicitConstExpr) != 0)
{
if (auto expr = BfNodeDynCast<BfExpression>(astNode))
{
auto checkType = ResolveTypeRef_Type(astNode, genericArgs, populateType, (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_IgnoreLookupError));
if (checkType != NULL)
return checkType;
BfResolvedTypeSet::LookupContext lookupCtx;
lookupCtx.mModule = this;
BfResolvedTypeSet::Entry* typeEntry = NULL;
BfType* resultType = NULL;
auto result = mContext->mResolvedTypes.EvaluateToVariant(&lookupCtx, expr, resultType);
if (resultType != NULL)
{
auto constExprValue = CreateConstExprValueType(result, resultType);
return constExprValue;
}
}
}
return ResolveTypeRef_Type(astNode, genericArgs, populateType, resolveFlags);
}
// This flow should mirror CastToValue // This flow should mirror CastToValue
bool BfModule::CanCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags) bool BfModule::CanCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags)
{ {
@ -14148,7 +14201,7 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
if (i > prevGenericParamCount) if (i > prevGenericParamCount)
str += ", "; str += ", ";
DoTypeToString(str, typeGenericArg, (BfTypeNameFlags)(typeNameFlags & ~(BfTypeNameFlag_OmitNamespace | BfTypeNameFlag_OmitOuterType | BfTypeNameFlag_ExtendedInfo)), genericMethodNameOverrides); DoTypeToString(str, typeGenericArg, (BfTypeNameFlags)((typeNameFlags | BfTypeNameFlag_ShortConst) & ~(BfTypeNameFlag_OmitNamespace | BfTypeNameFlag_OmitOuterType | BfTypeNameFlag_ExtendedInfo)), genericMethodNameOverrides);
} }
str += '>'; str += '>';
} }
@ -14340,10 +14393,13 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
else if (resolvedType->IsConstExprValue()) else if (resolvedType->IsConstExprValue())
{ {
auto constExprValueType = (BfConstExprValueType*)resolvedType; auto constExprValueType = (BfConstExprValueType*)resolvedType;
if ((typeNameFlags & BfTypeNameFlag_ShortConst) == 0)
{
str += "const "; str += "const ";
DoTypeToString(str, constExprValueType->mType, typeNameFlags, genericMethodNameOverrides); DoTypeToString(str, constExprValueType->mType, typeNameFlags, genericMethodNameOverrides);
str += " "; str += " ";
}
VariantToString(str, constExprValueType->mValue); VariantToString(str, constExprValueType->mValue);

View file

@ -930,11 +930,21 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int*
identifierExpected = false; identifierExpected = false;
} }
else else
{
bool mayBeExprPart = false;
if (chevronDepth > 0)
{
if (checkNode->IsExact<BfLiteralExpression>())
mayBeExprPart = true;
}
if (!mayBeExprPart)
{ {
if (outEndNode != NULL) if (outEndNode != NULL)
*outEndNode = checkIdx; *outEndNode = checkIdx;
return false; return false;
} }
}
lastToken = checkTokenNode; lastToken = checkTokenNode;
checkIdx++; checkIdx++;
} }
@ -5224,10 +5234,15 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
auto nextNode = mVisitorPos.GetNext(); auto nextNode = mVisitorPos.GetNext();
auto genericIdentifier = BfNodeDynCast<BfIdentifierNode>(nextNode); auto genericIdentifier = BfNodeDynCast<BfIdentifierNode>(nextNode);
bool doAddType = genericIdentifier != NULL; bool doAddType = genericIdentifier != NULL;
if (mCompatMode) bool addAsExpr = false;
//if (mCompatMode)
{ {
if (BfNodeDynCast<BfLiteralExpression>(nextNode) != NULL) if (BfNodeDynCast<BfLiteralExpression>(nextNode) != NULL)
{
doAddType = true; doAddType = true;
addAsExpr = true;
}
} }
if (genericIdentifier == NULL) if (genericIdentifier == NULL)
{ {
@ -5255,7 +5270,14 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
} }
if ((doAddType) && (!isUnboundName)) if ((doAddType) && (!isUnboundName))
{ {
auto genericArgumentTypeRef = CreateTypeRefAfter(genericInstance); BfAstNode* genericArgumentTypeRef = NULL;
if (addAsExpr)
{
genericArgumentTypeRef = CreateExpressionAfter(genericInstance, CreateExprFlags_BreakOnRChevron);
}
else
genericArgumentTypeRef = CreateTypeRefAfter(genericInstance);
if (genericArgumentTypeRef == NULL) if (genericArgumentTypeRef == NULL)
return NULL; return NULL;
MoveNode(genericArgumentTypeRef, genericInstance); MoveNode(genericArgumentTypeRef, genericInstance);
@ -9707,14 +9729,23 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm
BfGenericArgumentsNode* BfReducer::CreateGenericArguments(BfTokenNode* tokenNode) BfGenericArgumentsNode* BfReducer::CreateGenericArguments(BfTokenNode* tokenNode)
{ {
auto genericArgs = mAlloc->Alloc<BfGenericArgumentsNode>(); auto genericArgs = mAlloc->Alloc<BfGenericArgumentsNode>();
BfDeferredAstSizedArray<BfTypeReference*> genericArgsArray(genericArgs->mGenericArgs, mAlloc); BfDeferredAstSizedArray<BfAstNode*> genericArgsArray(genericArgs->mGenericArgs, mAlloc);
BfDeferredAstSizedArray<BfAstNode*> commas(genericArgs->mCommas, mAlloc); BfDeferredAstSizedArray<BfAstNode*> commas(genericArgs->mCommas, mAlloc);
ReplaceNode(tokenNode, genericArgs); ReplaceNode(tokenNode, genericArgs);
genericArgs->mOpenChevron = tokenNode; genericArgs->mOpenChevron = tokenNode;
while (true) while (true)
{ {
auto genericArg = CreateTypeRefAfter(genericArgs); bool doAsExpr = false;
auto nextNode = mVisitorPos.GetNext();
if (BfNodeIsA<BfLiteralExpression>(nextNode))
doAsExpr = true;
BfAstNode* genericArg = NULL;
if (doAsExpr)
genericArg = CreateExpressionAfter(genericArgs, CreateExprFlags_BreakOnRChevron);
else
genericArg = CreateTypeRefAfter(genericArgs);
if (genericArg == NULL) if (genericArg == NULL)
{ {
genericArgsArray.push_back(NULL); // Leave empty for purposes of generic argument count genericArgsArray.push_back(NULL); // Leave empty for purposes of generic argument count
@ -9739,7 +9770,7 @@ BfGenericArgumentsNode* BfReducer::CreateGenericArguments(BfTokenNode* tokenNode
MoveNode(genericArg, genericArgs); MoveNode(genericArg, genericArgs);
genericArgsArray.push_back(genericArg); genericArgsArray.push_back(genericArg);
auto nextNode = mVisitorPos.GetNext(); nextNode = mVisitorPos.GetNext();
tokenNode = BfNodeDynCast<BfTokenNode>(nextNode); tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
if (tokenNode == NULL) if (tokenNode == NULL)
{ {

View file

@ -3752,12 +3752,17 @@ int BfResolvedTypeSet::Hash(BfAstNode* typeRefNode, LookupContext* ctx, BfHashFl
if (auto typeRef = BfNodeDynCast<BfTypeReference>(typeRefNode)) if (auto typeRef = BfNodeDynCast<BfTypeReference>(typeRefNode))
return Hash(typeRef, ctx, flags, hashSeed); return Hash(typeRef, ctx, flags, hashSeed);
BF_FATAL("Not supported"); auto result = ctx->mModule->ResolveTypeRef(typeRefNode, NULL, BfPopulateType_Identity, (BfResolveTypeRefFlags)(ctx->mResolveFlags | BfResolveTypeRefFlag_AllowImplicitConstExpr));
if (result == NULL)
{
ctx->mFailed = true;
return 0; return 0;
}
ctx->mResolvedTypeMap[typeRefNode] = result;
return Hash(result, ctx, false, hashSeed);
} }
// These types can be from different contexts ("foreign" types) so we can't just compare ptrs
bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx) bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
{ {
if (lhs->IsBoxed()) if (lhs->IsBoxed())
@ -3768,7 +3773,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
BfBoxedType* rhsBoxedType = (BfBoxedType*)rhs; BfBoxedType* rhsBoxedType = (BfBoxedType*)rhs;
if (lhsBoxedType->mBoxedFlags != rhsBoxedType->mBoxedFlags) if (lhsBoxedType->mBoxedFlags != rhsBoxedType->mBoxedFlags)
return false; return false;
return Equals(lhsBoxedType->mElementType, rhsBoxedType->mElementType, ctx); return lhsBoxedType->mElementType == rhsBoxedType->mElementType;
} }
else if (lhs->IsArray()) else if (lhs->IsArray())
{ {
@ -3778,7 +3783,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
BfArrayType* rhsArrayType = (BfArrayType*) rhs; BfArrayType* rhsArrayType = (BfArrayType*) rhs;
if (lhsArrayType->mDimensions != rhsArrayType->mDimensions) if (lhsArrayType->mDimensions != rhsArrayType->mDimensions)
return false; return false;
return Equals(lhsArrayType->mGenericTypeInfo->mTypeGenericArguments[0], rhsArrayType->mGenericTypeInfo->mTypeGenericArguments[0], ctx); return lhsArrayType->mGenericTypeInfo->mTypeGenericArguments[0] == rhsArrayType->mGenericTypeInfo->mTypeGenericArguments[0];
} }
else if (lhs->IsTypeInstance()) else if (lhs->IsTypeInstance())
{ {
@ -3880,7 +3885,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
return false; return false;
for (int i = 0; i < (int)lhsGenericType->mGenericTypeInfo->mTypeGenericArguments.size(); i++) for (int i = 0; i < (int)lhsGenericType->mGenericTypeInfo->mTypeGenericArguments.size(); i++)
{ {
if (!Equals(lhsGenericType->mGenericTypeInfo->mTypeGenericArguments[i], rhsGenericType->mGenericTypeInfo->mTypeGenericArguments[i], ctx)) if (lhsGenericType->mGenericTypeInfo->mTypeGenericArguments[i] != rhsGenericType->mGenericTypeInfo->mTypeGenericArguments[i])
return false; return false;
} }
} }
@ -3901,7 +3906,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
return false; return false;
BfPointerType* lhsPtrType = (BfPointerType*)lhs; BfPointerType* lhsPtrType = (BfPointerType*)lhs;
BfPointerType* rhsPtrType = (BfPointerType*)rhs; BfPointerType* rhsPtrType = (BfPointerType*)rhs;
return Equals(lhsPtrType->mElementType, rhsPtrType->mElementType, ctx); return lhsPtrType->mElementType == rhsPtrType->mElementType;
} }
else if (lhs->IsGenericParam()) else if (lhs->IsGenericParam())
{ {
@ -4177,7 +4182,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext*
ctx->mFailed = true; ctx->mFailed = true;
return false; return false;
} }
return Equals(lhs, rhsResolvedType, ctx); return lhs == rhsResolvedType;
} }
} }
@ -4592,7 +4597,11 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfAstNode* rhs, LookupContext* ctx)
if (auto rhsTypeRef = BfNodeDynCast<BfTypeReference>(rhs)) if (auto rhsTypeRef = BfNodeDynCast<BfTypeReference>(rhs))
return Equals(lhs, rhsTypeRef, ctx); return Equals(lhs, rhsTypeRef, ctx);
BF_FATAL("Illegal"); BfType* rhsResultType;
if (ctx->mResolvedTypeMap.TryGetValue(rhs, &rhsResultType))
return lhs == rhsResultType;
BF_FATAL("Invalid value in BfResolvedTypeSet::Equals");
return false; return false;
} }

View file

@ -37,6 +37,7 @@ enum BfResolveTypeRefFlags
BfResolveTypeRefFlag_AllowGlobalContainer = 0x4000, BfResolveTypeRefFlag_AllowGlobalContainer = 0x4000,
BfResolveTypeRefFlag_AllowInferredSizedArray = 0x8000, BfResolveTypeRefFlag_AllowInferredSizedArray = 0x8000,
BfResolveTypeRefFlag_AllowGlobalsSelf = 0x10000, BfResolveTypeRefFlag_AllowGlobalsSelf = 0x10000,
BfResolveTypeRefFlag_AllowImplicitConstExpr = 0x20000
}; };
enum BfTypeNameFlags : uint16 enum BfTypeNameFlags : uint16
@ -52,7 +53,8 @@ enum BfTypeNameFlags : uint16
BfTypeNameFlag_AddGlobalContainerName = 0x80, BfTypeNameFlag_AddGlobalContainerName = 0x80,
BfTypeNameFlag_InternalName = 0x100, // Use special delimiters to remove ambiguities (ie: '+' for inner types) BfTypeNameFlag_InternalName = 0x100, // Use special delimiters to remove ambiguities (ie: '+' for inner types)
BfTypeNameFlag_HideGlobalName = 0x200, BfTypeNameFlag_HideGlobalName = 0x200,
BfTypeNameFlag_ExtendedInfo = 0x400 BfTypeNameFlag_ExtendedInfo = 0x400,
BfTypeNameFlag_ShortConst = 0x800
}; };
enum BfMethodNameFlags : uint8 enum BfMethodNameFlags : uint8
@ -1982,7 +1984,7 @@ public:
virtual BfModule* GetModule() override { return mModule; } virtual BfModule* GetModule() override { return mModule; }
virtual BfTypeInstance* ToTypeInstance() override { return this; } virtual BfTypeInstance* ToTypeInstance() override { return this; }
virtual bool IsDependentOnUnderlyingType() override { return true; } virtual bool IsDependentOnUnderlyingType() override { return true; }
virtual BfPrimitiveType* ToPrimitiveType() override { return GetUnderlyingType()->ToPrimitiveType(); } virtual BfPrimitiveType* ToPrimitiveType() override { return IsBoxed() ? GetUnderlyingType()->ToPrimitiveType() : NULL; }
virtual bool HasWrappedRepresentation() override { return IsTypedPrimitive(); } virtual bool HasWrappedRepresentation() override { return IsTypedPrimitive(); }
int GetEndingInstanceAlignment() { if (mInstSize % mInstAlign == 0) return mInstAlign; return mInstSize % mInstAlign; } int GetEndingInstanceAlignment() { if (mInstSize % mInstAlign == 0) return mInstAlign; return mInstSize % mInstAlign; }
@ -2525,6 +2527,12 @@ public:
BfHashFlag_AllowDotDotDot = 4, BfHashFlag_AllowDotDotDot = 4,
}; };
struct BfExprResult
{
BfVariant mValue;
BfType* mResultType;
};
class LookupContext class LookupContext
{ {
public: public:
@ -2533,7 +2541,7 @@ public:
BfTypeDef* mRootTypeDef; BfTypeDef* mRootTypeDef;
BfTypeInstance* mRootOuterTypeInstance; BfTypeInstance* mRootOuterTypeInstance;
BfType* mRootResolvedType; BfType* mRootResolvedType;
Dictionary<BfTypeReference*, BfType*> mResolvedTypeMap; Dictionary<BfAstNode*, BfType*> mResolvedTypeMap;
BfResolveTypeRefFlags mResolveFlags; BfResolveTypeRefFlags mResolveFlags;
BfCallingConvention mCallingConvention; BfCallingConvention mCallingConvention;
bool mHadVar; bool mHadVar;
@ -2572,6 +2580,7 @@ public:
static int DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int& hashSeed); static int DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int& hashSeed);
static int Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None, int hashSeed = 0); static int Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None, int hashSeed = 0);
static int Hash(BfAstNode* typeRefNode, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None, int hashSeed = 0); static int Hash(BfAstNode* typeRefNode, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None, int hashSeed = 0);
static bool Equals(BfType* lhs, BfType* rhs, LookupContext* ctx); static bool Equals(BfType* lhs, BfType* rhs, LookupContext* ctx);
static bool Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* ctx); static bool Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* ctx);
static bool Equals(BfType* lhs, BfAstNode* rhs, LookupContext* ctx); static bool Equals(BfType* lhs, BfAstNode* rhs, LookupContext* ctx);

View file

@ -19,7 +19,7 @@ using namespace llvm;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
DwMethodMatcher::DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEvaluator, const StringImpl& methodName, SizedArrayImpl<DbgTypedValue>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments) : DwMethodMatcher::DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEvaluator, const StringImpl& methodName, SizedArrayImpl<DbgTypedValue>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments) :
mArguments(arguments) mArguments(arguments)
{ {
mTargetSrc = targetSrc; mTargetSrc = targetSrc;
@ -7369,7 +7369,7 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, SizedArrayImpl
} }
DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName, DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
const BfSizedArray<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments) const BfSizedArray<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments)
{ {
SetAndRestoreValue<String*> prevReferenceId(mReferenceId, NULL); SetAndRestoreValue<String*> prevReferenceId(mReferenceId, NULL);
@ -7904,7 +7904,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
return CreateCall(targetSrc, callTarget, methodDef, bypassVirtual, arguments, argValues); return CreateCall(targetSrc, callTarget, methodDef, bypassVirtual, arguments, argValues);
} }
void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments) void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments)
{ {
bool allowImplicitThis = false; bool allowImplicitThis = false;
BfAstNode* methodNodeSrc = target; BfAstNode* methodNodeSrc = target;
@ -8107,7 +8107,7 @@ void DbgExprEvaluator::Visit(BfInvocationExpression* invocationExpr)
/*if (mAutoComplete != NULL) /*if (mAutoComplete != NULL)
mAutoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas);*/ mAutoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas);*/
BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL; BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
if (invocationExpr->mGenericArgs != NULL) if (invocationExpr->mGenericArgs != NULL)
methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs; methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs;
DoInvocation(invocationExpr->mTarget, invocationExpr->mArguments, methodGenericArguments); DoInvocation(invocationExpr->mTarget, invocationExpr->mArguments, methodGenericArguments);

View file

@ -224,7 +224,7 @@ public:
bool* outNewIsBetter, bool* outNewIsWorse, bool allowSpecializeFail); bool* outNewIsBetter, bool* outNewIsWorse, bool allowSpecializeFail);
public: public:
DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEvaluator, const StringImpl& methodName, SizedArrayImpl<DbgTypedValue>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments); DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEvaluator, const StringImpl& methodName, SizedArrayImpl<DbgTypedValue>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments);
bool CheckType(DbgType* typeInstance, bool isFailurePass); bool CheckType(DbgType* typeInstance, bool isFailurePass);
bool CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMethod); bool CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMethod);
}; };
@ -323,13 +323,13 @@ public:
DbgTypedValue ReadTypedValue(BfAstNode* targetSrc, DbgType* type, uint64 valAddr, DbgAddrType addrType); DbgTypedValue ReadTypedValue(BfAstNode* targetSrc, DbgType* type, uint64 valAddr, DbgAddrType addrType);
bool CheckTupleCreation(addr_target receiveAddr, BfAstNode* targetSrc, DbgType* tupleType, const BfSizedArray<BfExpression*>& argValues, BfSizedArray<BfTupleNameNode*>* names); bool CheckTupleCreation(addr_target receiveAddr, BfAstNode* targetSrc, DbgType* tupleType, const BfSizedArray<BfExpression*>& argValues, BfSizedArray<BfTupleNameNode*>* names);
DbgTypedValue CheckEnumCreation(BfAstNode* targetSrc, DbgType* enumType, const StringImpl& caseName, const BfSizedArray<BfExpression*>& argValues); DbgTypedValue CheckEnumCreation(BfAstNode* targetSrc, DbgType* enumType, const StringImpl& caseName, const BfSizedArray<BfExpression*>& argValues);
void DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments); void DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments);
bool ResolveArgValues(const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& outArgValues); bool ResolveArgValues(const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& outArgValues);
DbgTypedValue CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers); DbgTypedValue CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers);
DbgTypedValue CreateCall(DbgSubprogram* method, SizedArrayImpl<DbgMethodArgument>& argPushQueue, bool bypassVirtual); DbgTypedValue CreateCall(DbgSubprogram* method, SizedArrayImpl<DbgMethodArgument>& argPushQueue, bool bypassVirtual);
DbgTypedValue CreateCall(BfAstNode* targetSrc, DbgTypedValue target, DbgSubprogram* methodDef, bool bypassVirtual, const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& argValues); DbgTypedValue CreateCall(BfAstNode* targetSrc, DbgTypedValue target, DbgSubprogram* methodDef, bool bypassVirtual, const BfSizedArray<ASTREF(BfExpression*)>& arguments, SizedArrayImpl<DbgTypedValue>& argValues);
DbgTypedValue MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName, DbgTypedValue MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
const BfSizedArray<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments); const BfSizedArray<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments);
DbgType* ResolveSubTypeRef(DbgType* checkType, const StringImpl& name); DbgType* ResolveSubTypeRef(DbgType* checkType, const StringImpl& name);
void PerformBinaryOperation(ASTREF(BfExpression*)& leftExpression, ASTREF(BfExpression*)& rightExpression, BfBinaryOp binaryOp, BfTokenNode* opToken, bool forceLeftType); void PerformBinaryOperation(ASTREF(BfExpression*)& leftExpression, ASTREF(BfExpression*)& rightExpression, BfBinaryOp binaryOp, BfTokenNode* opToken, bool forceLeftType);
void PerformBinaryOperation(DbgType* resultType, DbgTypedValue convLeftValue, DbgTypedValue convRightValue, BfBinaryOp binaryOp, BfTokenNode* opToken); void PerformBinaryOperation(DbgType* resultType, DbgTypedValue convLeftValue, DbgTypedValue convRightValue, BfBinaryOp binaryOp, BfTokenNode* opToken);

View file

@ -451,6 +451,15 @@ namespace Tests
Compiler.Mixin(GetMathString<T, T2>(expr)); Compiler.Mixin(GetMathString<T, T2>(expr));
} }
class GenClass<TDesc> where TDesc : const String
{
[OnCompile(.TypeInit), Comptime]
static void Init()
{
Compiler.EmitTypeBody(typeof(Self), TDesc);
}
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -527,8 +536,14 @@ namespace Tests
float math = ComputeMath(2.3f, 2, "*"); float math = ComputeMath(2.3f, 2, "*");
Test.Assert(math == 4.6f); Test.Assert(math == 4.6f);
float math2 = ComputeMath<float, int, const "+">(2.3f, 1, "+"); float math2 = ComputeMath<float, int, "+">(2.3f, 1, "+");
Test.Assert(math2 == 3.3f); Test.Assert(math2 == 3.3f);
GenClass<
"""
public int mA = 123;
"""> genClass = scope .();
Test.Assert(genClass.mA == 123);
} }
} }
} }

View file

@ -409,6 +409,12 @@ namespace Tests
return total; return total;
} }
static int CheckString<T>(T str) where T : const String
{
const bool eq = str == "Abc";
return T.Length;
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -441,6 +447,11 @@ namespace Tests
Test.Assert(l2.Front[0] == "2"); Test.Assert(l2.Front[0] == "2");
Test.Assert(l2.Front[1] == "4"); Test.Assert(l2.Front[1] == "4");
int len = CheckString("Abc");
Test.Assert(len == 3);
len = CheckString<"Abcd">("Abcd");
Test.Assert(len == 4);
} }
} }
} }