diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index ef2ccdbf..dca7e006 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -671,7 +671,7 @@ public: bool IsStatic() const { - return !mValue; + return (!mValue) && (mKind != BfTypedValueKind_GenericConstValue); } bool IsAddr() const @@ -2948,7 +2948,7 @@ public: BF_AST_TYPE(BfGenericArgumentsNode, BfAstNode); ASTREF(BfTokenNode*) mOpenChevron; - BfSizedArray mGenericArgs; + BfSizedArray mGenericArgs; BfSizedArray mCommas; ASTREF(BfTokenNode*) mCloseChevron; }; BF_AST_DECL(BfGenericArgumentsNode, BfAstNode); diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 4fa92343..be87a627 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -2075,8 +2075,7 @@ void BfAutoComplete::CheckTypeRef(BfTypeReference* typeRef, bool mayBeIdentifier { CheckTypeRef(genericTypeRef->mElementType, mayBeIdentifier, isInExpression, onlyAttribute); for (auto genericArg : genericTypeRef->mGenericArguments) - CheckNode(genericArg); - //CheckTypeRef(genericArg, false, isInExpression, false); + CheckNode(genericArg, false, isInExpression); 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)) return; @@ -2267,7 +2266,7 @@ void BfAutoComplete::CheckNode(BfAstNode* node) if (auto identifer = BfNodeDynCast(node)) CheckIdentifier(identifer); if (auto typeRef = BfNodeDynCast(node)) - CheckTypeRef(typeRef, true); + CheckTypeRef(typeRef, mayBeIdentifier, isInExpression); if (auto memberRef = BfNodeDynCast(node)) { if (memberRef->mTarget != NULL) diff --git a/IDEHelper/Compiler/BfAutoComplete.h b/IDEHelper/Compiler/BfAutoComplete.h index 3bae6874..428f99a1 100644 --- a/IDEHelper/Compiler/BfAutoComplete.h +++ b/IDEHelper/Compiler/BfAutoComplete.h @@ -256,7 +256,7 @@ public: void CheckTypeRef(BfTypeReference* typeRef, bool mayBeIdentifier, bool isInExpression = false, bool onlyAttribute = false); void CheckAttributeTypeRef(BfTypeReference* typeRef); void CheckInvocation(BfAstNode* invocationNode, BfTokenNode* openParen, BfTokenNode* closeParen, const BfSizedArray& commas); - void CheckNode(BfAstNode* node); + void CheckNode(BfAstNode* node, bool mayBeIdentifier, bool isInExpression = false); void CheckMethod(BfMethodDeclaration* methodDeclaration, bool isLocalMethod); void CheckProperty(BfPropertyDeclaration* propertyDeclaration); void CheckVarResolution(BfAstNode* varTypeRef, BfType* resolvedTypeRef); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index e8351fd3..8cf9a7fc 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -137,7 +137,7 @@ BfBaseClassWalker::Entry BfBaseClassWalker::Next() ////////////////////////////////////////////////////////////////////////// -BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const StringImpl& methodName, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments) : +BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const StringImpl& methodName, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments) : mArguments(arguments) { mTargetSrc = targetSrc; @@ -146,7 +146,7 @@ BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const S Init(/*arguments, */methodGenericArguments); } -BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments) : +BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments) : mArguments(arguments) { mTargetSrc = targetSrc; @@ -156,7 +156,7 @@ BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMetho mMethodName = mInterfaceMethodInstance->mMethodDef->mName; } -void BfMethodMatcher::Init(/*SizedArrayImpl& arguments, */BfSizedArray* methodGenericArguments) +void BfMethodMatcher::Init(/*SizedArrayImpl& arguments, */BfSizedArray* methodGenericArguments) { //mArguments = arguments; mActiveTypeDef = NULL; @@ -204,9 +204,9 @@ void BfMethodMatcher::Init(/*SizedArrayImpl& arguments, */BfSized 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())) { auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)genericArgType); @@ -4251,7 +4251,10 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI } if ((!result) && (identifierNode != NULL)) + { result = mModule->TryLookupGenericConstVaue(identifierNode, mExpectingType); + mModule->FixValueActualization(result); + } return result; } @@ -6382,7 +6385,6 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl& ir if (argVal.mType->IsValuelessType()) return; - bool wantSplat = false; 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, - BfResolvedArgs& argValues, BfSizedArray* methodGenericArguments, BfCheckedKind checkedKind) + BfResolvedArgs& argValues, BfSizedArray* methodGenericArguments, BfCheckedKind checkedKind) { BP_ZONE("MatchMethod"); @@ -8650,9 +8652,6 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp for (BfType* ifaceInst : genericParamInstance->mInterfaceConstraints) { - if (ifaceInst->IsUnspecializedType()) - ifaceInst = mModule->ResolveType(ifaceInst); - BfTypeInstance* typeInst = ifaceInst->ToTypeInstance(); BF_ASSERT(typeInst != NULL); if (methodMatcher.CheckType(typeInst, target, false)) @@ -11599,7 +11598,7 @@ bool BfExprEvaluator::CanBindDelegate(BfDelegateBindExpression* delegateBindExpr args[i] = typedValueExpr; } - BfSizedArray* methodGenericArguments = NULL; + BfSizedArray* methodGenericArguments = NULL; if (delegateBindExpr->mGenericArgs != NULL) methodGenericArguments = &delegateBindExpr->mGenericArgs->mGenericArgs; @@ -12003,7 +12002,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr) args[i] = typedValueExpr; } - BfSizedArray* methodGenericArguments = NULL; + BfSizedArray* methodGenericArguments = NULL; if (delegateBindExpr->mGenericArgs != NULL) methodGenericArguments = &delegateBindExpr->mGenericArgs->mGenericArgs; @@ -12017,7 +12016,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr) if (autoComplete != NULL) { SetAndRestoreValue prevForceAllowNonStatic(autoComplete->mForceAllowNonStatic, methodInstance->mMethodDef->mHasExplicitThis); - GetAutoComplete()->CheckNode(delegateBindExpr->mTarget); + GetAutoComplete()->CheckNode(delegateBindExpr->mTarget, true); } if ((!delegateBindExpr->mTarget->IsA()) && @@ -14056,11 +14055,13 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs unresolvedTypeRef = unresolvedTypeRef->GetUnderlyingType(); isArrayAlloc = true; } - } + } else if (mExpectingType->IsPointer()) { - unresolvedTypeRef = mExpectingType->GetUnderlyingType(); + unresolvedTypeRef = mExpectingType->GetUnderlyingType(); } + else if (mExpectingType->IsVar()) + unresolvedTypeRef = mExpectingType; } if (unresolvedTypeRef == NULL) @@ -14166,7 +14167,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs } if (unresolvedTypeRef == NULL) - { + { unresolvedTypeRef = ResolveTypeRef(objCreateExpr->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_NoResolveGenericParam); } } @@ -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& arguments, BfSizedArray* methodGenericArgs) +void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, bool allowImplicitThis, const StringImpl& name, const BfSizedArray& arguments, BfSizedArray* methodGenericArgs) { if (mModule->mCurMethodState == NULL) return; @@ -16511,7 +16512,7 @@ void BfExprEvaluator::SetMethodElementType(BfAstNode* target) mModule->SetElementType(target, BfSourceElementType_Method); } -void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray& args, BfSizedArray* methodGenericArguments, BfTypedValue* outCascadeValue) +void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray& args, BfSizedArray* methodGenericArguments, BfTypedValue* outCascadeValue) { // Just a check mModule->mBfIRBuilder->GetInsertBlock(); @@ -16520,8 +16521,10 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m auto autoComplete = GetAutoComplete(); if ((autoComplete != NULL) && (methodGenericArguments != NULL)) { - for (BfTypeReference* methodGenericArg : *methodGenericArguments) - autoComplete->CheckTypeRef(methodGenericArg, false, true); + for (BfAstNode* methodGenericArg : *methodGenericArguments) + { + autoComplete->CheckNode(methodGenericArg, false, true); + } } if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo)) @@ -17250,7 +17253,7 @@ void BfExprEvaluator::Visit(BfInvocationExpression* invocationExpr) autoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas); mModule->UpdateExprSrcPos(invocationExpr); - BfSizedArray* methodGenericArguments = NULL; + BfSizedArray* methodGenericArguments = NULL; if (invocationExpr->mGenericArgs != NULL) methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs; SizedArray copiedArgs; @@ -20694,13 +20697,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, auto derefTarget = mModule->LoadValue(mResult); BfPointerType* pointerType = (BfPointerType*)derefTarget.mType; - auto resolvedType = mModule->ResolveType(pointerType->mElementType); - if (resolvedType == NULL) - { - mResult = BfTypedValue(); - return; - } - + auto resolvedType = pointerType->mElementType; mModule->PopulateType(resolvedType); if (resolvedType->IsValuelessType()) mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), resolvedType, true); diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index 50a8dbce..dc66e38f 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -236,9 +236,9 @@ public: int GetMostSpecificType(BfType* lhs, BfType* rhs); // 0, 1, or -1 public: - BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const StringImpl& methodName, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments); - BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments = NULL); - void Init(/*SizedArrayImpl& arguments, */BfSizedArray* methodGenericArguments); + BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, const StringImpl& methodName, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments); + BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments = NULL); + void Init(/*SizedArrayImpl& arguments, */BfSizedArray* methodGenericArguments); bool IsMemberAccessible(BfTypeInstance* typeInst, BfTypeDef* declaringType); bool CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass, bool forceOuterCheck = false); void CheckOuterTypeStaticMethods(BfTypeInstance* typeInstance, bool isFailurePass); @@ -462,16 +462,16 @@ public: BfResolvedArgs& argValues, bool callCtorBodyOnly, bool allowAppendAlloc, BfTypedValue* appendIndexValue = NULL); 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, - BfResolvedArgs& argValue, BfSizedArray* methodGenericArguments, BfCheckedKind checkedKind = BfCheckedKind_NotSet); + BfResolvedArgs& argValue, BfSizedArray* methodGenericArguments, BfCheckedKind checkedKind = BfCheckedKind_NotSet); BfTypedValue MakeCallableTarget(BfAstNode* targetSrc, BfTypedValue target); BfModuleMethodInstance GetSelectedMethod(BfAstNode* targetSrc, BfTypeInstance* curTypeInst, BfMethodDef* methodDef, BfMethodMatcher& methodMatcher, BfType** overrideReturnType = NULL); BfModuleMethodInstance GetSelectedMethod(BfMethodMatcher& methodMatcher); bool CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail); bool HasVariableDeclaration(BfAstNode* checkNode); - void DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray& args, BfSizedArray* methodGenericArgs, BfTypedValue* outCascadeValue = NULL); + void DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray& args, BfSizedArray* methodGenericArgs, BfTypedValue* outCascadeValue = NULL); int GetMixinVariable(); 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& arguments, BfSizedArray* methodGenericArgs); + void InjectMixin(BfAstNode* targetSrc, BfTypedValue target, bool allowImplicitThis, const StringImpl& name, const BfSizedArray& arguments, BfSizedArray* methodGenericArgs); void SetMethodElementType(BfAstNode* target); 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()); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index c71d1040..4b28ab3f 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -8091,7 +8091,10 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode)) { char valStr[64]; - ExactMinimalDoubleToStr(constExprValueType->mValue.mDouble, valStr); + if (constExprValueType->mValue.mTypeCode == BfTypeCode_Double) + ExactMinimalDoubleToStr(constExprValueType->mValue.mDouble, valStr); + else + ExactMinimalFloatToStr(constExprValueType->mValue.mSingle, valStr); 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(), 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 @@ -8521,13 +8531,15 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator, auto genericTypeConstraint = genericParamDef->mTypeConstraint; if (genericTypeConstraint != NULL) { - auto primType = genericTypeConstraint->ToPrimitiveType(); - if (primType != NULL) + auto underlyingConstraint = genericTypeConstraint; + if ((underlyingConstraint != NULL) && (underlyingConstraint->IsBoxed())) + underlyingConstraint = underlyingConstraint->GetUnderlyingType(); + if (underlyingConstraint != NULL) { BfTypedValue result; result.mKind = BfTypedValueKind_Value; result.mType = genericTypeConstraint; - result.mValue = mBfIRBuilder->GetUndefConstValue(mBfIRBuilder->MapType(primType)); + result.mValue = mBfIRBuilder->GetUndefConstValue(mBfIRBuilder->MapType(underlyingConstraint)); typedVal = result; handled = true; } @@ -9844,6 +9856,9 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal) if (typedVal.mValue.IsConst()) { + int stringIdx = GetStringPoolIdx(typedVal.mValue, mBfIRBuilder); + if (stringIdx != -1) + return; auto constant = mBfIRBuilder->GetConstant(typedVal.mValue); if (constant->mTypeCode == BfTypeCode_NullPtr) return; @@ -10893,11 +10908,11 @@ StringT<128> BfModule::MethodToString(BfMethodInstance* methodInst, BfMethodName { if (i > 0) 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 //if (!methodInst->mIsUnspecializedVariation && allowResolveGenericParamNames) if (allowResolveGenericParamNames) - typeNameFlags = BfTypeNameFlag_ResolveGenericParamNames; + typeNameFlags = (BfTypeNameFlags)(typeNameFlags | BfTypeNameFlag_ResolveGenericParamNames); BfType* type = methodInst->mMethodInfoEx->mMethodGenericArguments[i]; if ((methodGenericArgs != NULL) && (type->IsUnspecializedType())) { @@ -11529,7 +11544,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri { inPropSet = true; if (autoComplete != NULL) - autoComplete->CheckNode(assignExpr->mLeft); + autoComplete->CheckNode(assignExpr->mLeft, true); String findName = assignExpr->mLeft->ToString(); BfPropertyDef* bestProp = NULL; diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 63798597..5ac11f19 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1792,6 +1792,7 @@ public: BfPointerType* CreatePointerType(BfType* resolvedType); BfPointerType* CreatePointerType(BfTypeReference* typeRef); 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); BfTypeInstance* CreateTupleType(const BfTypeVector& fieldTypes, const Array& fieldNames, bool allowVar = false); BfTypeInstance* SantizeTupleType(BfTypeInstance* tupleType); @@ -1869,7 +1870,8 @@ public: void GetDelegateTypeRefAttributes(BfDelegateTypeRef* delegateTypeRef, BfCallingConvention& callingConvention); 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* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0); + BfType* ResolveTypeRef_Type(BfAstNode* astNode, const BfSizedArray* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0); + BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray* 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, 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); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index d4abfb2a..58e2bae5 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -6560,6 +6560,29 @@ BfConstExprValueType* BfModule::CreateConstExprValueType(const BfTypedValue& typ 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) { if (type->IsPointer()) @@ -10617,11 +10640,14 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula 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())) { 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); } @@ -11371,15 +11397,12 @@ BfTypeInstance* BfModule::GetUnspecializedTypeInstance(BfTypeInstance* typeInst) return result->ToTypeInstance(); } -BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags) +BfType* BfModule::ResolveTypeRef_Type(BfAstNode* astNode, const BfSizedArray* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags) { - if (auto typeRef = BfNodeDynCast(astNode)) - return ResolveTypeRef(typeRef, populateType, resolveFlags); - if ((genericArgs == NULL) || (genericArgs->size() == 0)) { if (auto identifier = BfNodeDynCast(astNode)) - { + { BfNamedTypeReference typeRef; typeRef.mNameNode = identifier; typeRef.mSrcEnd = 0; @@ -11388,12 +11411,12 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArrayGetSourceData(); - std::function _ConvType = [&] (BfAstNode* astNode) -> BfTypeReference* - { + std::function _ConvType = [&](BfAstNode* astNode) -> BfTypeReference* + { if (auto typeRef = BfNodeDynCast(astNode)) return typeRef; @@ -11401,9 +11424,9 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray(astNode)) { auto* typeRef = alloc.Alloc(); - typeRef->mNameNode = identifier; + typeRef->mNameNode = identifier; result = typeRef; - } + } else if (auto memberRefExpr = BfNodeDynCast(astNode)) { auto qualifiedTypeRef = alloc.Alloc(); @@ -11440,7 +11463,7 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray arguments(genericInstanceTypeRef->mGenericArguments, &alloc); for (auto genericArg : *genericArgs) - { + { if (genericArg != NULL) { arguments.push_back(genericArg); @@ -11454,6 +11477,36 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags) +{ + if (auto typeRef = BfNodeDynCast(astNode)) + return ResolveTypeRef(typeRef, populateType, resolveFlags); + + if ((resolveFlags & BfResolveTypeRefFlag_AllowImplicitConstExpr) != 0) + { + if (auto expr = BfNodeDynCast(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 bool BfModule::CanCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags) { @@ -14148,7 +14201,7 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF if (i > prevGenericParamCount) 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 += '>'; } @@ -14339,11 +14392,14 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF } else if (resolvedType->IsConstExprValue()) { - auto constExprValueType = (BfConstExprValueType*)resolvedType; - str += "const "; - - DoTypeToString(str, constExprValueType->mType, typeNameFlags, genericMethodNameOverrides); - str += " "; + auto constExprValueType = (BfConstExprValueType*)resolvedType; + if ((typeNameFlags & BfTypeNameFlag_ShortConst) == 0) + { + str += "const "; + + DoTypeToString(str, constExprValueType->mType, typeNameFlags, genericMethodNameOverrides); + str += " "; + } VariantToString(str, constExprValueType->mValue); diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index ac1991ff..9226140a 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -928,12 +928,22 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int* { // Allow identifierExpected = false; - } + } else { - if (outEndNode != NULL) - *outEndNode = checkIdx; - return false; + bool mayBeExprPart = false; + if (chevronDepth > 0) + { + if (checkNode->IsExact()) + mayBeExprPart = true; + } + + if (!mayBeExprPart) + { + if (outEndNode != NULL) + *outEndNode = checkIdx; + return false; + } } lastToken = checkTokenNode; checkIdx++; @@ -5224,10 +5234,15 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF auto nextNode = mVisitorPos.GetNext(); auto genericIdentifier = BfNodeDynCast(nextNode); bool doAddType = genericIdentifier != NULL; - if (mCompatMode) + bool addAsExpr = false; + + //if (mCompatMode) { if (BfNodeDynCast(nextNode) != NULL) + { doAddType = true; + addAsExpr = true; + } } if (genericIdentifier == NULL) { @@ -5255,7 +5270,14 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF } if ((doAddType) && (!isUnboundName)) { - auto genericArgumentTypeRef = CreateTypeRefAfter(genericInstance); + BfAstNode* genericArgumentTypeRef = NULL; + + if (addAsExpr) + { + genericArgumentTypeRef = CreateExpressionAfter(genericInstance, CreateExprFlags_BreakOnRChevron); + } + else + genericArgumentTypeRef = CreateTypeRefAfter(genericInstance); if (genericArgumentTypeRef == NULL) return NULL; MoveNode(genericArgumentTypeRef, genericInstance); @@ -9707,14 +9729,23 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm BfGenericArgumentsNode* BfReducer::CreateGenericArguments(BfTokenNode* tokenNode) { auto genericArgs = mAlloc->Alloc(); - BfDeferredAstSizedArray genericArgsArray(genericArgs->mGenericArgs, mAlloc); + BfDeferredAstSizedArray genericArgsArray(genericArgs->mGenericArgs, mAlloc); BfDeferredAstSizedArray commas(genericArgs->mCommas, mAlloc); ReplaceNode(tokenNode, genericArgs); genericArgs->mOpenChevron = tokenNode; while (true) { - auto genericArg = CreateTypeRefAfter(genericArgs); + bool doAsExpr = false; + auto nextNode = mVisitorPos.GetNext(); + if (BfNodeIsA(nextNode)) + doAsExpr = true; + + BfAstNode* genericArg = NULL; + if (doAsExpr) + genericArg = CreateExpressionAfter(genericArgs, CreateExprFlags_BreakOnRChevron); + else + genericArg = CreateTypeRefAfter(genericArgs); if (genericArg == NULL) { genericArgsArray.push_back(NULL); // Leave empty for purposes of generic argument count @@ -9739,7 +9770,7 @@ BfGenericArgumentsNode* BfReducer::CreateGenericArguments(BfTokenNode* tokenNode MoveNode(genericArg, genericArgs); genericArgsArray.push_back(genericArg); - auto nextNode = mVisitorPos.GetNext(); + nextNode = mVisitorPos.GetNext(); tokenNode = BfNodeDynCast(nextNode); if (tokenNode == NULL) { diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 17b48327..8b6f91ce 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -3752,12 +3752,17 @@ int BfResolvedTypeSet::Hash(BfAstNode* typeRefNode, LookupContext* ctx, BfHashFl if (auto typeRef = BfNodeDynCast(typeRefNode)) 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) { if (lhs->IsBoxed()) @@ -3768,7 +3773,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx) BfBoxedType* rhsBoxedType = (BfBoxedType*)rhs; if (lhsBoxedType->mBoxedFlags != rhsBoxedType->mBoxedFlags) return false; - return Equals(lhsBoxedType->mElementType, rhsBoxedType->mElementType, ctx); + return lhsBoxedType->mElementType == rhsBoxedType->mElementType; } else if (lhs->IsArray()) { @@ -3778,7 +3783,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx) BfArrayType* rhsArrayType = (BfArrayType*) rhs; if (lhsArrayType->mDimensions != rhsArrayType->mDimensions) 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()) { @@ -3880,7 +3885,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx) return false; 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; } } @@ -3901,7 +3906,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx) return false; BfPointerType* lhsPtrType = (BfPointerType*)lhs; BfPointerType* rhsPtrType = (BfPointerType*)rhs; - return Equals(lhsPtrType->mElementType, rhsPtrType->mElementType, ctx); + return lhsPtrType->mElementType == rhsPtrType->mElementType; } else if (lhs->IsGenericParam()) { @@ -4177,7 +4182,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* ctx->mFailed = true; return false; } - return Equals(lhs, rhsResolvedType, ctx); + return lhs == rhsResolvedType; } } @@ -4571,7 +4576,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* if (constExprTypeRef->mConstExpr != NULL) { BfType* resultType = NULL; - result = EvaluateToVariant(ctx, constExprTypeRef->mConstExpr, resultType); + result = EvaluateToVariant(ctx, constExprTypeRef->mConstExpr, resultType); if (resultType != lhsConstExprType->mType) return false; } @@ -4592,7 +4597,11 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfAstNode* rhs, LookupContext* ctx) if (auto rhsTypeRef = BfNodeDynCast(rhs)) 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; } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 2a008587..18485956 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -37,6 +37,7 @@ enum BfResolveTypeRefFlags BfResolveTypeRefFlag_AllowGlobalContainer = 0x4000, BfResolveTypeRefFlag_AllowInferredSizedArray = 0x8000, BfResolveTypeRefFlag_AllowGlobalsSelf = 0x10000, + BfResolveTypeRefFlag_AllowImplicitConstExpr = 0x20000 }; enum BfTypeNameFlags : uint16 @@ -52,7 +53,8 @@ enum BfTypeNameFlags : uint16 BfTypeNameFlag_AddGlobalContainerName = 0x80, BfTypeNameFlag_InternalName = 0x100, // Use special delimiters to remove ambiguities (ie: '+' for inner types) BfTypeNameFlag_HideGlobalName = 0x200, - BfTypeNameFlag_ExtendedInfo = 0x400 + BfTypeNameFlag_ExtendedInfo = 0x400, + BfTypeNameFlag_ShortConst = 0x800 }; enum BfMethodNameFlags : uint8 @@ -1982,7 +1984,7 @@ public: virtual BfModule* GetModule() override { return mModule; } virtual BfTypeInstance* ToTypeInstance() override { return this; } 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(); } int GetEndingInstanceAlignment() { if (mInstSize % mInstAlign == 0) return mInstAlign; return mInstSize % mInstAlign; } @@ -2525,6 +2527,12 @@ public: BfHashFlag_AllowDotDotDot = 4, }; + struct BfExprResult + { + BfVariant mValue; + BfType* mResultType; + }; + class LookupContext { public: @@ -2533,7 +2541,7 @@ public: BfTypeDef* mRootTypeDef; BfTypeInstance* mRootOuterTypeInstance; BfType* mRootResolvedType; - Dictionary mResolvedTypeMap; + Dictionary mResolvedTypeMap; BfResolveTypeRefFlags mResolveFlags; BfCallingConvention mCallingConvention; bool mHadVar; @@ -2572,7 +2580,8 @@ public: 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(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, BfAstNode* rhs, LookupContext* ctx); static bool Equals(BfType* lhs, BfTypeReference* rhs, BfTypeDef* rhsTypeDef, LookupContext* ctx); diff --git a/IDEHelper/DbgExprEvaluator.cpp b/IDEHelper/DbgExprEvaluator.cpp index 7acdefe8..94694dae 100644 --- a/IDEHelper/DbgExprEvaluator.cpp +++ b/IDEHelper/DbgExprEvaluator.cpp @@ -19,7 +19,7 @@ using namespace llvm; ////////////////////////////////////////////////////////////////////////// -DwMethodMatcher::DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEvaluator, const StringImpl& methodName, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments) : +DwMethodMatcher::DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEvaluator, const StringImpl& methodName, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments) : mArguments(arguments) { 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, - const BfSizedArray& arguments, BfSizedArray* methodGenericArguments) + const BfSizedArray& arguments, BfSizedArray* methodGenericArguments) { SetAndRestoreValue prevReferenceId(mReferenceId, NULL); @@ -7904,7 +7904,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue return CreateCall(targetSrc, callTarget, methodDef, bypassVirtual, arguments, argValues); } -void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray& args, BfSizedArray* methodGenericArguments) +void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray& args, BfSizedArray* methodGenericArguments) { bool allowImplicitThis = false; BfAstNode* methodNodeSrc = target; @@ -8107,7 +8107,7 @@ void DbgExprEvaluator::Visit(BfInvocationExpression* invocationExpr) /*if (mAutoComplete != NULL) mAutoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas);*/ - BfSizedArray* methodGenericArguments = NULL; + BfSizedArray* methodGenericArguments = NULL; if (invocationExpr->mGenericArgs != NULL) methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs; DoInvocation(invocationExpr->mTarget, invocationExpr->mArguments, methodGenericArguments); diff --git a/IDEHelper/DbgExprEvaluator.h b/IDEHelper/DbgExprEvaluator.h index e49c65e8..f35aba8f 100644 --- a/IDEHelper/DbgExprEvaluator.h +++ b/IDEHelper/DbgExprEvaluator.h @@ -224,7 +224,7 @@ public: bool* outNewIsBetter, bool* outNewIsWorse, bool allowSpecializeFail); public: - DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEvaluator, const StringImpl& methodName, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments); + DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEvaluator, const StringImpl& methodName, SizedArrayImpl& arguments, BfSizedArray* methodGenericArguments); bool CheckType(DbgType* typeInstance, bool isFailurePass); bool CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMethod); }; @@ -323,13 +323,13 @@ public: DbgTypedValue ReadTypedValue(BfAstNode* targetSrc, DbgType* type, uint64 valAddr, DbgAddrType addrType); bool CheckTupleCreation(addr_target receiveAddr, BfAstNode* targetSrc, DbgType* tupleType, const BfSizedArray& argValues, BfSizedArray* names); DbgTypedValue CheckEnumCreation(BfAstNode* targetSrc, DbgType* enumType, const StringImpl& caseName, const BfSizedArray& argValues); - void DoInvocation(BfAstNode* target, BfSizedArray& args, BfSizedArray* methodGenericArguments); + void DoInvocation(BfAstNode* target, BfSizedArray& args, BfSizedArray* methodGenericArguments); bool ResolveArgValues(const BfSizedArray& arguments, SizedArrayImpl& outArgValues); DbgTypedValue CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers); DbgTypedValue CreateCall(DbgSubprogram* method, SizedArrayImpl& argPushQueue, bool bypassVirtual); DbgTypedValue CreateCall(BfAstNode* targetSrc, DbgTypedValue target, DbgSubprogram* methodDef, bool bypassVirtual, const BfSizedArray& arguments, SizedArrayImpl& argValues); DbgTypedValue MatchMethod(BfAstNode* targetSrc, DbgTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName, - const BfSizedArray& arguments, BfSizedArray* methodGenericArguments); + const BfSizedArray& arguments, BfSizedArray* methodGenericArguments); DbgType* ResolveSubTypeRef(DbgType* checkType, const StringImpl& name); 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); diff --git a/IDEHelper/Tests/src/Comptime.bf b/IDEHelper/Tests/src/Comptime.bf index 6e64362c..358674f7 100644 --- a/IDEHelper/Tests/src/Comptime.bf +++ b/IDEHelper/Tests/src/Comptime.bf @@ -451,6 +451,15 @@ namespace Tests Compiler.Mixin(GetMathString(expr)); } + class GenClass where TDesc : const String + { + [OnCompile(.TypeInit), Comptime] + static void Init() + { + Compiler.EmitTypeBody(typeof(Self), TDesc); + } + } + [Test] public static void TestBasics() { @@ -527,8 +536,14 @@ namespace Tests float math = ComputeMath(2.3f, 2, "*"); Test.Assert(math == 4.6f); - float math2 = ComputeMath(2.3f, 1, "+"); + float math2 = ComputeMath(2.3f, 1, "+"); Test.Assert(math2 == 3.3f); + + GenClass< + """ + public int mA = 123; + """> genClass = scope .(); + Test.Assert(genClass.mA == 123); } } } diff --git a/IDEHelper/Tests/src/Generics.bf b/IDEHelper/Tests/src/Generics.bf index a5999428..3717754f 100644 --- a/IDEHelper/Tests/src/Generics.bf +++ b/IDEHelper/Tests/src/Generics.bf @@ -409,6 +409,12 @@ namespace Tests return total; } + static int CheckString(T str) where T : const String + { + const bool eq = str == "Abc"; + return T.Length; + } + [Test] public static void TestBasics() { @@ -441,6 +447,11 @@ namespace Tests Test.Assert(l2.Front[0] == "2"); Test.Assert(l2.Front[1] == "4"); + + int len = CheckString("Abc"); + Test.Assert(len == 3); + len = CheckString<"Abcd">("Abcd"); + Test.Assert(len == 4); } } }