mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 03:52:19 +02:00
Added nameof
This commit is contained in:
parent
dd0d67cca1
commit
7dd2324fcf
13 changed files with 307 additions and 13 deletions
|
@ -361,6 +361,11 @@ void BfStructuralVisitor::Visit(BfOffsetOfExpression* offsetOfExpr)
|
|||
Visit(offsetOfExpr->ToBase());
|
||||
}
|
||||
|
||||
void BfStructuralVisitor::Visit(BfNameOfExpression* nameOfExpr)
|
||||
{
|
||||
Visit(nameOfExpr->ToBase());
|
||||
}
|
||||
|
||||
void BfStructuralVisitor::Visit(BfIsConstExpression* isConstExpr)
|
||||
{
|
||||
Visit(isConstExpr->ToBase());
|
||||
|
|
|
@ -381,6 +381,7 @@ class BfTypeAttrExpression;
|
|||
class BfSizeOfExpression;
|
||||
class BfAlignOfExpression;
|
||||
class BfOffsetOfExpression;
|
||||
class BfNameOfExpression;
|
||||
class BfStrideOfExpression;
|
||||
class BfIsConstExpression;
|
||||
class BfDefaultExpression;
|
||||
|
@ -508,6 +509,7 @@ public:
|
|||
virtual void Visit(BfAlignOfExpression* alignOfExpr);
|
||||
virtual void Visit(BfStrideOfExpression* strideOfExpr);
|
||||
virtual void Visit(BfOffsetOfExpression* offsetOfExpr);
|
||||
virtual void Visit(BfNameOfExpression* nameOfExpr);
|
||||
virtual void Visit(BfIsConstExpression* isConstExpr);
|
||||
virtual void Visit(BfDefaultExpression* defaultExpr);
|
||||
virtual void Visit(BfUninitializedExpression* uninitializedExpr);
|
||||
|
@ -2728,6 +2730,16 @@ public:
|
|||
BfIdentifierNode* mMemberName;
|
||||
}; BF_AST_DECL(BfOffsetOfExpression, BfTypeAttrExpression);
|
||||
|
||||
class BfNameOfExpression : public BfExpression
|
||||
{
|
||||
public:
|
||||
BF_AST_TYPE(BfNameOfExpression, BfExpression);
|
||||
BfTokenNode* mToken;
|
||||
BfTokenNode* mOpenParen;
|
||||
BfAstNode* mTarget;
|
||||
BfTokenNode* mCloseParen;
|
||||
}; BF_AST_DECL(BfNameOfExpression, BfExpression);
|
||||
|
||||
class BfIsConstExpression : public BfExpression
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -690,6 +690,12 @@ void BfAutoComplete::AddTypeDef(BfTypeDef* typeDef, const StringImpl& filter, bo
|
|||
|
||||
bool BfAutoComplete::CheckProtection(BfProtection protection, BfTypeDef* typeDef, bool allowProtected, bool allowPrivate)
|
||||
{
|
||||
if (mResolveType == BfResolveType_GetSymbolInfo)
|
||||
{
|
||||
// This is needed for nameof on private inner types
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((protection == BfProtection_Internal) && (typeDef != NULL))
|
||||
{
|
||||
return mModule->CheckProtection(protection, typeDef, allowProtected, allowPrivate);
|
||||
|
|
|
@ -519,6 +519,8 @@ void BfElementVisitor::Visit(BfTypeAttrExpression* typeAttrExpr)
|
|||
|
||||
void BfElementVisitor::Visit(BfOffsetOfExpression* offsetOfExpr)
|
||||
{
|
||||
Visit(offsetOfExpr->ToBase());
|
||||
|
||||
VisitChild(offsetOfExpr->mToken);
|
||||
VisitChild(offsetOfExpr->mOpenParen);
|
||||
VisitChild(offsetOfExpr->mTypeRef);
|
||||
|
@ -527,6 +529,16 @@ void BfElementVisitor::Visit(BfOffsetOfExpression* offsetOfExpr)
|
|||
VisitChild(offsetOfExpr->mCloseParen);
|
||||
}
|
||||
|
||||
void BfElementVisitor::Visit(BfNameOfExpression* nameOfExpr)
|
||||
{
|
||||
Visit(nameOfExpr->ToBase());
|
||||
|
||||
VisitChild(nameOfExpr->mToken);
|
||||
VisitChild(nameOfExpr->mOpenParen);
|
||||
VisitChild(nameOfExpr->mTarget);
|
||||
VisitChild(nameOfExpr->mCloseParen);
|
||||
}
|
||||
|
||||
void BfElementVisitor::Visit(BfDefaultExpression* defaultExpr)
|
||||
{
|
||||
Visit(defaultExpr->ToBase());
|
||||
|
|
|
@ -72,6 +72,7 @@ public:
|
|||
virtual void Visit(BfParameterDeclaration* paramDecl);
|
||||
virtual void Visit(BfTypeAttrExpression* typeAttrExpr);
|
||||
virtual void Visit(BfOffsetOfExpression* offsetOfExpr);
|
||||
virtual void Visit(BfNameOfExpression* nameOfExpr);
|
||||
virtual void Visit(BfDefaultExpression* defaultExpr);
|
||||
virtual void Visit(BfIsConstExpression* isConstExpr);
|
||||
virtual void Visit(BfUninitializedExpression* uninitializedExpr);
|
||||
|
|
|
@ -3762,6 +3762,49 @@ static bool IsCharType(BfTypeCode typeCode)
|
|||
}
|
||||
}
|
||||
|
||||
bool BfExprEvaluator::CheckForMethodName(BfAstNode* refNode, BfTypeInstance* typeInst, const StringImpl& findName)
|
||||
{
|
||||
BF_ASSERT((mBfEvalExprFlags & BfEvalExprFlags_NameOf) != 0);
|
||||
|
||||
auto autoComplete = GetAutoComplete();
|
||||
|
||||
while (typeInst != NULL)
|
||||
{
|
||||
auto typeDef = typeInst->mTypeDef;
|
||||
typeDef->PopulateMemberSets();
|
||||
|
||||
BfMemberSetEntry* memberSetEntry;
|
||||
if (typeDef->mMethodSet.TryGetWith(findName, &memberSetEntry))
|
||||
{
|
||||
if (mModule->mCompiler->mResolvePassData != NULL)
|
||||
mModule->mCompiler->mResolvePassData->HandleMethodReference(refNode, typeDef, (BfMethodDef*)memberSetEntry->mMemberDef);
|
||||
|
||||
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(refNode)))
|
||||
{
|
||||
autoComplete->SetDefinitionLocation(((BfMethodDef*)memberSetEntry->mMemberDef)->GetRefNode());
|
||||
if ((autoComplete->mResolveType == BfResolveType_GetSymbolInfo) && (autoComplete->mDefType == NULL))
|
||||
{
|
||||
autoComplete->mDefType = typeDef;
|
||||
autoComplete->mDefMethod = (BfMethodDef*)memberSetEntry->mMemberDef;
|
||||
}
|
||||
}
|
||||
|
||||
if (mModule->mCompiler->mResolvePassData != NULL)
|
||||
{
|
||||
if (auto sourceClassifier = mModule->mCompiler->mResolvePassData->GetSourceClassifier(refNode))
|
||||
sourceClassifier->SetElementType(refNode, BfSourceElementType_Method);
|
||||
}
|
||||
|
||||
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_NameOfSuccess);
|
||||
return true;
|
||||
}
|
||||
|
||||
typeInst = typeInst->mBaseType;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BfExprEvaluator::IsVar(BfType* type, bool forceIgnoreWrites)
|
||||
{
|
||||
if (type->IsVar())
|
||||
|
@ -4591,6 +4634,9 @@ void BfExprEvaluator::Visit(BfIdentifierNode* identifierNode)
|
|||
}
|
||||
}
|
||||
|
||||
if (((mBfEvalExprFlags & BfEvalExprFlags_NameOf) != 0) && (mModule->mCurTypeInstance != NULL) && (CheckForMethodName(identifierNode, mModule->mCurTypeInstance, identifierNode->ToString())))
|
||||
return;
|
||||
|
||||
if ((mBfEvalExprFlags & BfEvalExprFlags_NoLookupError) == 0)
|
||||
mModule->Fail("Identifier not found", identifierNode);
|
||||
}
|
||||
|
@ -5063,7 +5109,7 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
|
|||
}
|
||||
else if (!target)
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
if (((mBfEvalExprFlags & BfEvalExprFlags_NameOf) == 0) && (mModule->PreFail()))
|
||||
{
|
||||
if ((flags & BfLookupFieldFlag_CheckingOuter) != 0)
|
||||
mModule->Fail(StrFormat("An instance reference is required to reference non-static outer field '%s.%s'", mModule->TypeToString(typeInstance).c_str(), fieldDef->mName.c_str()),
|
||||
|
@ -5530,7 +5576,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
auto prop = nextProp;
|
||||
nextProp = nextProp->mNextWithSameName;
|
||||
|
||||
if ((!isFailurePass) && (!mModule->CheckProtection(protectionCheckFlags, curCheckType, prop->mDeclaringType->mProject, prop->mProtection, startCheckType)))
|
||||
if ((!isFailurePass) && ((mBfEvalExprFlags & BfEvalExprFlags_NameOf) == 0) && (!mModule->CheckProtection(protectionCheckFlags, curCheckType, prop->mDeclaringType->mProject, prop->mProtection, startCheckType)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -5543,7 +5589,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((!target.IsStatic()) || (prop->mIsStatic))
|
||||
if ((!target.IsStatic()) || (prop->mIsStatic) || ((mBfEvalExprFlags & BfEvalExprFlags_NameOf) != 0))
|
||||
{
|
||||
if (!mModule->IsInSpecializedSection())
|
||||
{
|
||||
|
@ -10864,6 +10910,10 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode*
|
|||
{
|
||||
FixitAddMember(typeInst, mExpectingType, nameRight->ToString(), false);
|
||||
}
|
||||
|
||||
if (((mBfEvalExprFlags & BfEvalExprFlags_NameOf) != 0) && (typeInst != NULL) && (CheckForMethodName(nameRight, typeInst, fieldName)))
|
||||
return;
|
||||
|
||||
mModule->Fail(StrFormat("Unable to find member '%s' in '%s'", fieldName.c_str(), mModule->TypeToString(lookupType).c_str()), nameRight);
|
||||
}
|
||||
|
||||
|
@ -11013,6 +11063,13 @@ void BfExprEvaluator::LookupQualifiedStaticField(BfAstNode* nameNode, BfIdentifi
|
|||
}
|
||||
}
|
||||
|
||||
if ((mBfEvalExprFlags & BfEvalExprFlags_NameOf) != 0)
|
||||
{
|
||||
auto typeInst = lookupType.mType->ToTypeInstance();
|
||||
if ((typeInst != NULL) && (CheckForMethodName(nameRight, typeInst, findName)))
|
||||
return;
|
||||
}
|
||||
|
||||
if ((mBfEvalExprFlags & BfEvalExprFlags_NoLookupError) == 0)
|
||||
mModule->Fail("Field not found", nameRight);
|
||||
return;
|
||||
|
@ -11885,6 +11942,135 @@ void BfExprEvaluator::Visit(BfOffsetOfExpression* offsetOfExpr)
|
|||
DoTypeIntAttr(offsetOfExpr->mTypeRef, offsetOfExpr->mCommaToken, offsetOfExpr->mMemberName, BfToken_OffsetOf);
|
||||
}
|
||||
|
||||
void BfExprEvaluator::Visit(BfNameOfExpression* nameOfExpr)
|
||||
{
|
||||
String name;
|
||||
|
||||
if (mModule->IsInSpecializedGeneric())
|
||||
{
|
||||
if (auto identifierNode = BfNodeDynCastExact<BfIdentifierNode>(nameOfExpr->mTarget))
|
||||
{
|
||||
// This is necessary so we don't resolve 'T' to the actual generic argument type
|
||||
name = identifierNode->ToString();
|
||||
}
|
||||
}
|
||||
|
||||
if (name.IsEmpty())
|
||||
{
|
||||
auto type = mModule->ResolveTypeRef(nameOfExpr->mTarget, {}, BfPopulateType_IdentityNoRemapAlias,
|
||||
(BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowUnboundGeneric | BfResolveTypeRefFlag_IgnoreLookupError | BfResolveTypeRefFlag_IgnoreProtection));
|
||||
if (type != NULL)
|
||||
{
|
||||
auto typeInst = type->ToTypeInstance();
|
||||
if (typeInst != NULL)
|
||||
name = typeInst->mTypeDef->mName->ToString();
|
||||
else
|
||||
name = mModule->TypeToString(type);
|
||||
|
||||
mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_NameReference);
|
||||
|
||||
// Just do this for autocomplete
|
||||
SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, true);
|
||||
VisitChild(nameOfExpr->mTarget);
|
||||
}
|
||||
}
|
||||
|
||||
if (name.IsEmpty())
|
||||
{
|
||||
if (auto identifer = BfNodeDynCast<BfIdentifierNode>(nameOfExpr->mTarget))
|
||||
{
|
||||
String targetStr = nameOfExpr->mTarget->ToString();
|
||||
BfAtomComposite targetComposite;
|
||||
bool isValid = mModule->mSystem->ParseAtomComposite(targetStr, targetComposite);
|
||||
bool namespaceExists = false;
|
||||
|
||||
BfProject* bfProject = NULL;
|
||||
auto activeTypeDef = mModule->GetActiveTypeDef();
|
||||
if (activeTypeDef != NULL)
|
||||
bfProject = activeTypeDef->mProject;
|
||||
auto _CheckProject = [&](BfProject* project)
|
||||
{
|
||||
if ((isValid) && (project->mNamespaces.ContainsKey(targetComposite)))
|
||||
namespaceExists = true;
|
||||
};
|
||||
|
||||
if (bfProject != NULL)
|
||||
{
|
||||
for (int depIdx = -1; depIdx < (int)bfProject->mDependencies.size(); depIdx++)
|
||||
{
|
||||
BfProject* depProject = (depIdx == -1) ? bfProject : bfProject->mDependencies[depIdx];
|
||||
_CheckProject(depProject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto project : mModule->mSystem->mProjects)
|
||||
_CheckProject(project);
|
||||
}
|
||||
|
||||
if (namespaceExists)
|
||||
{
|
||||
if (mModule->mCompiler->mResolvePassData != NULL)
|
||||
{
|
||||
if (auto sourceClassifier = mModule->mCompiler->mResolvePassData->GetSourceClassifier(nameOfExpr->mTarget))
|
||||
{
|
||||
BfAstNode* checkIdentifier = identifer;
|
||||
while (true)
|
||||
{
|
||||
auto qualifiedIdentifier = BfNodeDynCast<BfQualifiedNameNode>(checkIdentifier);
|
||||
if (qualifiedIdentifier == NULL)
|
||||
break;
|
||||
sourceClassifier->SetElementType(qualifiedIdentifier->mRight, BfSourceElementType_Namespace);
|
||||
checkIdentifier = qualifiedIdentifier->mLeft;
|
||||
}
|
||||
|
||||
sourceClassifier->SetElementType(checkIdentifier, BfSourceElementType_Namespace);
|
||||
}
|
||||
}
|
||||
|
||||
name = targetComposite.mParts[targetComposite.mSize - 1]->ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (name.IsEmpty())
|
||||
{
|
||||
SetAndRestoreValue<BfEvalExprFlags> prevFlags(mBfEvalExprFlags, (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_NameOf));
|
||||
VisitChild(nameOfExpr->mTarget);
|
||||
|
||||
if ((mBfEvalExprFlags & BfEvalExprFlags_NameOfSuccess) != 0)
|
||||
{
|
||||
BfAstNode* nameNode = nameOfExpr->mTarget;
|
||||
if (auto attributedIdentifierNode = BfNodeDynCast<BfAttributedIdentifierNode>(nameNode))
|
||||
nameNode = attributedIdentifierNode->mIdentifier;
|
||||
if (auto memberReferenceExpr = BfNodeDynCast<BfMemberReferenceExpression>(nameNode))
|
||||
nameNode = memberReferenceExpr->mMemberName;
|
||||
if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(nameNode))
|
||||
nameNode = qualifiedNameNode->mRight;
|
||||
name = nameNode->ToString();
|
||||
}
|
||||
else if (mResultFieldInstance != NULL)
|
||||
{
|
||||
auto fieldDef = mResultFieldInstance->GetFieldDef();
|
||||
if (fieldDef != NULL)
|
||||
name = fieldDef->mName;
|
||||
}
|
||||
else if (mResultLocalVar != NULL)
|
||||
{
|
||||
name = mResultLocalVar->mName;
|
||||
}
|
||||
else if (mPropDef != NULL)
|
||||
{
|
||||
name = mPropDef->mName;
|
||||
}
|
||||
}
|
||||
|
||||
if ((name.IsEmpty()) && (nameOfExpr->mTarget != NULL))
|
||||
mModule->Fail("Expression does not have a name", nameOfExpr->mTarget);
|
||||
|
||||
mResult = BfTypedValue(mModule->GetStringObjectValue(name), mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef));
|
||||
}
|
||||
|
||||
void BfExprEvaluator::Visit(BfIsConstExpression* isConstExpr)
|
||||
{
|
||||
if (isConstExpr->mExpression == NULL)
|
||||
|
@ -21142,6 +21328,13 @@ void BfExprEvaluator::DoMemberReference(BfMemberReferenceExpression* memberRefEx
|
|||
{
|
||||
if (auto targetIdentifier = BfNodeDynCast<BfIdentifierNode>(memberRefExpr->mMemberName))
|
||||
{
|
||||
if ((mBfEvalExprFlags & BfEvalExprFlags_NameOf) != 0)
|
||||
{
|
||||
auto typeInst = thisValue.mType->ToTypeInstance();
|
||||
if ((typeInst != NULL) && (CheckForMethodName(nameRight, typeInst, findName)))
|
||||
return;
|
||||
}
|
||||
|
||||
mResult.mType = mModule->ResolveInnerType(thisValue.mType, targetIdentifier, BfPopulateType_Declaration);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -273,8 +273,6 @@ public:
|
|||
bool IsVarCall(BfType*& outReturnType);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class BfBaseClassWalker
|
||||
{
|
||||
public:
|
||||
|
@ -432,6 +430,7 @@ public:
|
|||
BfExprEvaluator(BfModule* module);
|
||||
~BfExprEvaluator();
|
||||
|
||||
bool CheckForMethodName(BfAstNode* refNode, BfTypeInstance* typeInst, const StringImpl& findName);
|
||||
bool IsVar(BfType* type, bool forceIgnoreWrites = false);
|
||||
void GetLiteral(BfAstNode* refNode, const BfVariant& variant);
|
||||
void FinishExpressionResult();
|
||||
|
@ -559,6 +558,7 @@ public:
|
|||
virtual void Visit(BfAlignOfExpression* alignOfExpr) override;
|
||||
virtual void Visit(BfStrideOfExpression* strideOfExpr) override;
|
||||
virtual void Visit(BfOffsetOfExpression* offsetOfExpr) override;
|
||||
virtual void Visit(BfNameOfExpression* nameOfExpr) override;
|
||||
virtual void Visit(BfIsConstExpression* isConstExpr) override;
|
||||
virtual void Visit(BfDefaultExpression* defaultExpr) override;
|
||||
virtual void Visit(BfUninitializedExpression* uninitialziedExpr) override;
|
||||
|
|
|
@ -54,7 +54,7 @@ enum BfPopulateType
|
|||
BfPopulateType_Full_Force
|
||||
};
|
||||
|
||||
enum BfEvalExprFlags
|
||||
enum BfEvalExprFlags : int64
|
||||
{
|
||||
BfEvalExprFlags_None = 0,
|
||||
BfEvalExprFlags_ExplicitCast = 1,
|
||||
|
@ -89,6 +89,8 @@ enum BfEvalExprFlags
|
|||
BfEvalExprFlags_AllowGenericConstValue = 0x20000000,
|
||||
BfEvalExprFlags_IsExpressionBody = 0x40000000,
|
||||
BfEvalExprFlags_AppendFieldInitializer = 0x80000000,
|
||||
BfEvalExprFlags_NameOf = 0x100000000LL,
|
||||
BfEvalExprFlags_NameOfSuccess = 0x200000000LL,
|
||||
|
||||
BfEvalExprFlags_InheritFlags = BfEvalExprFlags_NoAutoComplete | BfEvalExprFlags_Comptime | BfEvalExprFlags_DeclType
|
||||
};
|
||||
|
@ -1947,7 +1949,7 @@ public:
|
|||
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);
|
||||
BfType* ResolveInnerType(BfType* outerType, BfAstNode* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool ignoreErrors = false, int numGenericArgs = 0, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);
|
||||
BfTypeDef* GetCombinedPartialTypeDef(BfTypeDef* type);
|
||||
BfTypeInstance* GetOuterType(BfType* type);
|
||||
bool IsInnerType(BfType* checkInnerType, BfType* checkOuterType);
|
||||
|
|
|
@ -8029,7 +8029,7 @@ void BfModule::HandleMethodGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDe
|
|||
mCompiler->mResolvePassData->HandleMethodGenericParam(refNode, typeDef, methodDef, methodGenericParamIdx);
|
||||
}
|
||||
|
||||
BfType* BfModule::ResolveInnerType(BfType* outerType, BfAstNode* typeRef, BfPopulateType populateType, bool ignoreErrors, int numGenericArgs)
|
||||
BfType* BfModule::ResolveInnerType(BfType* outerType, BfAstNode* typeRef, BfPopulateType populateType, bool ignoreErrors, int numGenericArgs, BfResolveTypeRefFlags resolveFlags)
|
||||
{
|
||||
BfTypeDef* nestedTypeDef = NULL;
|
||||
|
||||
|
@ -8092,7 +8092,8 @@ BfType* BfModule::ResolveInnerType(BfType* outerType, BfAstNode* typeRef, BfPopu
|
|||
{
|
||||
auto latestCheckType = checkType->GetLatest();
|
||||
|
||||
if ((!isFailurePass) && (!CheckProtection(latestCheckType->mProtection, latestCheckType, allowProtected, allowPrivate)))
|
||||
if ((!isFailurePass) && ((resolveFlags & BfResolveTypeRefFlag_IgnoreProtection) == 0) &&
|
||||
(!CheckProtection(latestCheckType->mProtection, latestCheckType, allowProtected, allowPrivate)))
|
||||
continue;
|
||||
|
||||
if (checkType->mProject != checkOuterType->mTypeDef->mProject)
|
||||
|
@ -8135,7 +8136,7 @@ BfType* BfModule::ResolveInnerType(BfType* outerType, BfAstNode* typeRef, BfPopu
|
|||
|
||||
if (nestedTypeDef == NULL)
|
||||
{
|
||||
if (!mIgnoreErrors && !ignoreErrors)
|
||||
if ((!mIgnoreErrors) && (!ignoreErrors) && ((resolveFlags & BfResolveTypeRefFlag_IgnoreLookupError) == 0))
|
||||
{
|
||||
StringT<64> name;
|
||||
name.Append(findName);
|
||||
|
@ -11020,7 +11021,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
}
|
||||
}
|
||||
|
||||
auto resolvedType = ResolveInnerType(leftType, qualifiedTypeRef->mRight, populateType, false, numGenericArgs);
|
||||
auto resolvedType = ResolveInnerType(leftType, qualifiedTypeRef->mRight, populateType, false, numGenericArgs, resolveFlags);
|
||||
if ((resolvedType != NULL) && (mCurTypeInstance != NULL))
|
||||
AddDependency(leftType, mCurTypeInstance, BfDependencyMap::DependencyFlag_NameReference);
|
||||
return ResolveTypeResult(typeRef, resolvedType, populateType, resolveFlags);
|
||||
|
|
|
@ -3174,6 +3174,8 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
|
|||
case TOKEN_HASH('n', 'a', 'm', 'e'):
|
||||
if (SrcPtrHasToken("namespace"))
|
||||
mToken = BfToken_Namespace;
|
||||
else if (SrcPtrHasToken("nameof"))
|
||||
mToken = BfToken_NameOf;
|
||||
break;
|
||||
case TOKEN_HASH('n', 'e', 'w', 0):
|
||||
if (SrcPtrHasToken("new"))
|
||||
|
|
|
@ -2352,6 +2352,41 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
|||
exprLeft = CreateMemberReferenceExpression(typeRef);
|
||||
}
|
||||
}
|
||||
else if (tokenNode->GetToken() == BfToken_NameOf)
|
||||
{
|
||||
BfNameOfExpression* nameOfExpr = mAlloc->Alloc<BfNameOfExpression>();
|
||||
ReplaceNode(tokenNode, nameOfExpr);
|
||||
nameOfExpr->mToken = tokenNode;
|
||||
tokenNode = ExpectTokenAfter(nameOfExpr, BfToken_LParen);
|
||||
MEMBER_SET_CHECKED(nameOfExpr, mOpenParen, tokenNode);
|
||||
|
||||
mVisitorPos.MoveNext();
|
||||
int outEndNode = -1;
|
||||
bool isTypeRef = IsTypeReference(mVisitorPos.GetCurrent(), BfToken_RParen, -1, &outEndNode);
|
||||
mVisitorPos.mReadPos--;
|
||||
|
||||
if ((isTypeRef) && (outEndNode > 0))
|
||||
{
|
||||
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(outEndNode - 1)))
|
||||
{
|
||||
if ((tokenNode->mToken == BfToken_RChevron) || (tokenNode->mToken == BfToken_RDblChevron))
|
||||
{
|
||||
// Can ONLY be a type reference
|
||||
auto typeRef = CreateTypeRefAfter(nameOfExpr);
|
||||
MEMBER_SET_CHECKED(nameOfExpr, mTarget, typeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nameOfExpr->mTarget == NULL)
|
||||
{
|
||||
auto expr = CreateExpressionAfter(nameOfExpr);
|
||||
MEMBER_SET_CHECKED(nameOfExpr, mTarget, expr);
|
||||
}
|
||||
tokenNode = ExpectTokenAfter(nameOfExpr, BfToken_RParen);
|
||||
MEMBER_SET_CHECKED(nameOfExpr, mCloseParen, tokenNode);
|
||||
exprLeft = nameOfExpr;
|
||||
}
|
||||
|
||||
if (exprLeft == NULL)
|
||||
{
|
||||
|
|
|
@ -40,7 +40,8 @@ enum BfResolveTypeRefFlags
|
|||
BfResolveTypeRefFlag_AllowGlobalsSelf = 0x10000,
|
||||
BfResolveTypeRefFlag_AllowImplicitConstExpr = 0x20000,
|
||||
BfResolveTypeRefFlag_AllowUnboundGeneric = 0x40000,
|
||||
BfResolveTypeRefFlag_ForceUnboundGeneric = 0x80000
|
||||
BfResolveTypeRefFlag_ForceUnboundGeneric = 0x80000,
|
||||
BfResolveTypeRefFlag_IgnoreProtection = 0x100000
|
||||
};
|
||||
|
||||
enum BfTypeNameFlags : uint16
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma warning disable 168
|
||||
|
||||
using System;
|
||||
using System.Interop;
|
||||
using System.Collections;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
|
@ -24,5 +26,27 @@ namespace Tests
|
|||
inStr.Length > 1 || 2 == 3
|
||||
};
|
||||
}
|
||||
|
||||
static void GetName<T>(String str)
|
||||
{
|
||||
str.Append(nameof(T));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestNameof()
|
||||
{
|
||||
var point = (x: 3, y: 4);
|
||||
|
||||
Test.Assert(nameof(System) == "System");
|
||||
Test.Assert(nameof(System.Collections) == "Collections");
|
||||
Test.Assert(nameof(point) == "point");
|
||||
Test.Assert(nameof(point.x) == "x");
|
||||
Test.Assert(nameof(Tests.Expressions) == "Expressions");
|
||||
Test.Assert(nameof(c_int) == "c_int");
|
||||
Test.Assert(nameof(List<int>) == "List");
|
||||
Test.Assert(nameof(List<int>.Add) == "Add");
|
||||
Test.Assert(nameof(TestBasics) == "TestBasics");
|
||||
Test.Assert(GetName<String>(.. scope .()) == "T");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue