1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +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
{
return !mValue;
return (!mValue) && (mKind != BfTypedValueKind_GenericConstValue);
}
bool IsAddr() const
@ -2948,7 +2948,7 @@ public:
BF_AST_TYPE(BfGenericArgumentsNode, BfAstNode);
ASTREF(BfTokenNode*) mOpenChevron;
BfSizedArray<ASTREF(BfTypeReference*)> mGenericArgs;
BfSizedArray<ASTREF(BfAstNode*)> mGenericArgs;
BfSizedArray<ASTREF(BfAstNode*)> mCommas;
ASTREF(BfTokenNode*) mCloseChevron;
}; BF_AST_DECL(BfGenericArgumentsNode, BfAstNode);

View file

@ -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<BfIdentifierNode>(node))
CheckIdentifier(identifer);
if (auto typeRef = BfNodeDynCast<BfTypeReference>(node))
CheckTypeRef(typeRef, true);
CheckTypeRef(typeRef, mayBeIdentifier, isInExpression);
if (auto memberRef = BfNodeDynCast<BfMemberReferenceExpression>(node))
{
if (memberRef->mTarget != NULL)

View file

@ -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<BfTokenNode*>& 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);

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)
{
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<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments) :
BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments) :
mArguments(arguments)
{
mTargetSrc = targetSrc;
@ -156,7 +156,7 @@ BfMethodMatcher::BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMetho
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;
mActiveTypeDef = NULL;
@ -204,9 +204,9 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& 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<BfIRValue>& 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<ASTREF(BfTypeReference*)>* methodGenericArguments, BfCheckedKind checkedKind)
BfResolvedArgs& argValues, BfSizedArray<ASTREF(BfAstNode*)>* 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<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL;
BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
if (delegateBindExpr->mGenericArgs != NULL)
methodGenericArguments = &delegateBindExpr->mGenericArgs->mGenericArgs;
@ -12003,7 +12002,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
args[i] = typedValueExpr;
}
BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL;
BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
if (delegateBindExpr->mGenericArgs != NULL)
methodGenericArguments = &delegateBindExpr->mGenericArgs->mGenericArgs;
@ -12017,7 +12016,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
if (autoComplete != NULL)
{
SetAndRestoreValue<bool> prevForceAllowNonStatic(autoComplete->mForceAllowNonStatic, methodInstance->mMethodDef->mHasExplicitThis);
GetAutoComplete()->CheckNode(delegateBindExpr->mTarget);
GetAutoComplete()->CheckNode(delegateBindExpr->mTarget, true);
}
if ((!delegateBindExpr->mTarget->IsA<BfIdentifierNode>()) &&
@ -14061,6 +14060,8 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
unresolvedTypeRef = mExpectingType->GetUnderlyingType();
}
else if (mExpectingType->IsVar())
unresolvedTypeRef = mExpectingType;
}
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)
return;
@ -16511,7 +16512,7 @@ void BfExprEvaluator::SetMethodElementType(BfAstNode* target)
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
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<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL;
BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
if (invocationExpr->mGenericArgs != NULL)
methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs;
SizedArray<BfExpression*, 8> 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);

View file

@ -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<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments);
BfMethodMatcher(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* interfaceMethodInstance, SizedArrayImpl<BfResolvedArg>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL);
void Init(/*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(BfAstNode*)>* methodGenericArguments = NULL);
void Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSizedArray<ASTREF(BfAstNode*)>* 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<ASTREF(BfTypeReference*)>* methodGenericArguments, BfCheckedKind checkedKind = BfCheckedKind_NotSet);
BfResolvedArgs& argValue, BfSizedArray<ASTREF(BfAstNode*)>* 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<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();
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);
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());

View file

@ -8091,7 +8091,10 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode))
{
char valStr[64];
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;

View file

@ -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<String>& 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<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, 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);

View file

@ -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,11 +11397,8 @@ BfTypeInstance* BfModule::GetUnspecializedTypeInstance(BfTypeInstance* typeInst)
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 (auto identifier = BfNodeDynCast<BfIdentifierNode>(astNode))
@ -11454,6 +11477,36 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeRe
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
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 += '>';
}
@ -14340,10 +14393,13 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
else if (resolvedType->IsConstExprValue())
{
auto constExprValueType = (BfConstExprValueType*)resolvedType;
if ((typeNameFlags & BfTypeNameFlag_ShortConst) == 0)
{
str += "const ";
DoTypeToString(str, constExprValueType->mType, typeNameFlags, genericMethodNameOverrides);
str += " ";
}
VariantToString(str, constExprValueType->mValue);

View file

@ -930,11 +930,21 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int*
identifierExpected = false;
}
else
{
bool mayBeExprPart = false;
if (chevronDepth > 0)
{
if (checkNode->IsExact<BfLiteralExpression>())
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<BfIdentifierNode>(nextNode);
bool doAddType = genericIdentifier != NULL;
if (mCompatMode)
bool addAsExpr = false;
//if (mCompatMode)
{
if (BfNodeDynCast<BfLiteralExpression>(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<BfGenericArgumentsNode>();
BfDeferredAstSizedArray<BfTypeReference*> genericArgsArray(genericArgs->mGenericArgs, mAlloc);
BfDeferredAstSizedArray<BfAstNode*> genericArgsArray(genericArgs->mGenericArgs, mAlloc);
BfDeferredAstSizedArray<BfAstNode*> 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<BfLiteralExpression>(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<BfTokenNode>(nextNode);
if (tokenNode == NULL)
{

View file

@ -3752,12 +3752,17 @@ int BfResolvedTypeSet::Hash(BfAstNode* typeRefNode, LookupContext* ctx, BfHashFl
if (auto typeRef = BfNodeDynCast<BfTypeReference>(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;
}
// These types can be from different contexts ("foreign" types) so we can't just compare ptrs
ctx->mResolvedTypeMap[typeRefNode] = result;
return Hash(result, ctx, false, hashSeed);
}
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;
}
}
@ -4592,7 +4597,11 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfAstNode* rhs, LookupContext* ctx)
if (auto rhsTypeRef = BfNodeDynCast<BfTypeReference>(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;
}

View file

@ -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<BfTypeReference*, BfType*> mResolvedTypeMap;
Dictionary<BfAstNode*, BfType*> mResolvedTypeMap;
BfResolveTypeRefFlags mResolveFlags;
BfCallingConvention mCallingConvention;
bool mHadVar;
@ -2572,6 +2580,7 @@ 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, BfTypeReference* 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)
{
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<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments)
const BfSizedArray<ASTREF(BfExpression*)>& arguments, BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments)
{
SetAndRestoreValue<String*> 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<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments)
void DbgExprEvaluator::DoInvocation(BfAstNode* target, BfSizedArray<ASTREF(BfExpression*)>& args, BfSizedArray<ASTREF(BfAstNode*)>* 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<ASTREF(BfTypeReference*)>* methodGenericArguments = NULL;
BfSizedArray<ASTREF(BfAstNode*)>* methodGenericArguments = NULL;
if (invocationExpr->mGenericArgs != NULL)
methodGenericArguments = &invocationExpr->mGenericArgs->mGenericArgs;
DoInvocation(invocationExpr->mTarget, invocationExpr->mArguments, methodGenericArguments);

View file

@ -224,7 +224,7 @@ public:
bool* outNewIsBetter, bool* outNewIsWorse, bool allowSpecializeFail);
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 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<BfExpression*>& argValues, BfSizedArray<BfTupleNameNode*>* names);
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);
DbgTypedValue CreateCall(DbgSubprogram* method, DbgTypedValue thisVal, DbgTypedValue structRetVal, bool bypassVirtual, CPURegisters* registers);
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 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);
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);

View file

@ -451,6 +451,15 @@ namespace Tests
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]
public static void TestBasics()
{
@ -527,8 +536,14 @@ namespace Tests
float math = ComputeMath(2.3f, 2, "*");
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);
GenClass<
"""
public int mA = 123;
"""> genClass = scope .();
Test.Assert(genClass.mA == 123);
}
}
}

View file

@ -409,6 +409,12 @@ namespace Tests
return total;
}
static int CheckString<T>(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);
}
}
}