From d5073e810ceaa1eddb1022d097d6cd58b7c11c29 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 1 May 2020 16:29:12 -0700 Subject: [PATCH] Reworked ref enumerators to support non-pointer refs --- BeefLibs/corlib/src/Collections/Dictionary.bf | 22 +++++++++++++-- .../corlib/src/Collections/IEnumerator.bf | 9 ++++-- BeefLibs/corlib/src/Collections/List.bf | 2 +- BeefLibs/corlib/src/Collections/Queue.bf | 2 +- BeefLibs/corlib/src/Span.bf | 2 +- BeefLibs/corlib/src/String.bf | 2 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 2 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 14 +++++++--- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 23 ++++++++++++++- IDEHelper/Compiler/BfStmtEvaluator.cpp | 28 +++++++++++++------ 10 files changed, 82 insertions(+), 24 deletions(-) diff --git a/BeefLibs/corlib/src/Collections/Dictionary.bf b/BeefLibs/corlib/src/Collections/Dictionary.bf index 69dc57fd..168a1cc9 100644 --- a/BeefLibs/corlib/src/Collections/Dictionary.bf +++ b/BeefLibs/corlib/src/Collections/Dictionary.bf @@ -13,9 +13,13 @@ namespace System.Collections using System.Diagnostics; using System.Diagnostics.Contracts; - public class Dictionary : ICollection<(TKey key, TValue value)>, IEnumerable<(TKey key, TValue value)> where TKey : IHashable + public class Dictionary : + ICollection<(TKey key, TValue value)>, + IEnumerable<(TKey key, TValue value)>, + IRefEnumerable<(TKey key, TValue* valueRef)> where TKey : IHashable { typealias KeyValuePair=(TKey key, TValue value); + typealias KeyRefValuePair=(TKey key, TValue* valueRef); private struct Entry { @@ -606,7 +610,7 @@ namespace System.Collections return (key is TKey); } - public struct Enumerator : IEnumerator//, IDictionaryEnumerator + public struct Enumerator : IEnumerator, IRefEnumerator { private Dictionary mDictionary; #if VERSION_DICTIONARY @@ -687,6 +691,11 @@ namespace System.Collections get { return (mDictionary.mEntries[mCurrentIndex].mKey, mDictionary.mEntries[mCurrentIndex].mValue); } } + public KeyRefValuePair CurrentRef + { + get { return (mDictionary.mEntries[mCurrentIndex].mKey, &mDictionary.mEntries[mCurrentIndex].mValue); } + } + public void Dispose() { @@ -753,9 +762,16 @@ namespace System.Collections return .Err; return Current; } + + public Result GetNextRef() mut + { + if (!MoveNext()) + return .Err; + return CurrentRef; + } } - public struct ValueEnumerator : IRefEnumerator, IResettable + public struct ValueEnumerator : IRefEnumerator, IEnumerator, IResettable { private Dictionary mDictionary; #if VERSION_DICTIONARY diff --git a/BeefLibs/corlib/src/Collections/IEnumerator.bf b/BeefLibs/corlib/src/Collections/IEnumerator.bf index e1950341..61f02f8d 100644 --- a/BeefLibs/corlib/src/Collections/IEnumerator.bf +++ b/BeefLibs/corlib/src/Collections/IEnumerator.bf @@ -12,13 +12,18 @@ namespace System.Collections void Reset() mut; } - interface IRefEnumerator : IEnumerator + interface IRefEnumerator { - Result GetNextRef() mut; + Result GetNextRef() mut; } concrete interface IEnumerable { concrete IEnumerator GetEnumerator(); } + + concrete interface IRefEnumerable + { + concrete IRefEnumerator GetEnumerator(); + } } diff --git a/BeefLibs/corlib/src/Collections/List.bf b/BeefLibs/corlib/src/Collections/List.bf index 3bcc165c..e69c9036 100644 --- a/BeefLibs/corlib/src/Collections/List.bf +++ b/BeefLibs/corlib/src/Collections/List.bf @@ -623,7 +623,7 @@ namespace System.Collections } } - public struct Enumerator : IRefEnumerator, IResettable + public struct Enumerator : IRefEnumerator, IEnumerator, IResettable { private List mList; private int mIndex; diff --git a/BeefLibs/corlib/src/Collections/Queue.bf b/BeefLibs/corlib/src/Collections/Queue.bf index 005ae687..4d8b8d81 100644 --- a/BeefLibs/corlib/src/Collections/Queue.bf +++ b/BeefLibs/corlib/src/Collections/Queue.bf @@ -351,7 +351,7 @@ namespace System.Collections /// Implements an enumerator for a Queue. The enumerator uses the /// internal version number of the list to ensure that no modifications are /// made to the list while an enumeration is in progress. - public struct Enumerator : IRefEnumerator + public struct Enumerator : IRefEnumerator, IEnumerator { private Queue mQueue; private int32 mIndex; // -1 = not started, -2 = ended/disposed diff --git a/BeefLibs/corlib/src/Span.bf b/BeefLibs/corlib/src/Span.bf index 9ab08f41..8fea2ec3 100644 --- a/BeefLibs/corlib/src/Span.bf +++ b/BeefLibs/corlib/src/Span.bf @@ -184,7 +184,7 @@ namespace System return Enumerator(this); } - public struct Enumerator : IEnumerator, IRefEnumerator + public struct Enumerator : IEnumerator, IRefEnumerator { private Span mList; private int mIndex; diff --git a/BeefLibs/corlib/src/String.bf b/BeefLibs/corlib/src/String.bf index c3cc8c26..413930dd 100644 --- a/BeefLibs/corlib/src/String.bf +++ b/BeefLibs/corlib/src/String.bf @@ -2360,7 +2360,7 @@ namespace System } } - public struct RawEnumerator : IRefEnumerator + public struct RawEnumerator : IRefEnumerator, IEnumerator { char8* mPtr; int_strsize mIdx; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 58cd19c2..b74bb737 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -12150,7 +12150,7 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc, if ((invocationExpr != NULL) && (invocationExpr->mGenericArgs != NULL)) { errorNode = invocationExpr->mGenericArgs->mGenericArgs[(int)methodDef->mGenericParams.size()]; - if (errorNode == NULL) + if ((errorNode == NULL) && (!invocationExpr->mGenericArgs->mCommas.IsEmpty())) errorNode = invocationExpr->mGenericArgs->mCommas[(int)methodDef->mGenericParams.size() - 1]; } mModule->Fail(StrFormat("Too many generic arguments, expected %d fewer", genericArgCountDiff), errorNode); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 6fbf2f11..0b8b55ed 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -906,9 +906,7 @@ bool BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType if (typeAliasDecl->mAliasToType != NULL) aliasToType = ResolveTypeRef(typeAliasDecl->mAliasToType, BfPopulateType_IdentityNoRemapAlias); } - //typeAlias->mModule = mContext->mScratchModule; - typeAlias->mTypeIncomplete = false; - typeAlias->mDefineState = BfTypeDefineState_DefinedAndMethodsSlotted; + if (aliasToType != NULL) { AddDependency(aliasToType, typeAlias, BfDependencyMap::DependencyFlag_DerivedFrom); @@ -951,7 +949,7 @@ bool BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType resolvedTypeRef->mRebuildFlags = BfTypeRebuildFlag_None; typeAlias->mCustomAttributes = GetCustomAttributes(typeDef->mTypeDeclaration->mAttributes, BfAttributeTargets_Alias); - return true; + // Fall through so generic params are populated in DoPopulateType } if (resolvedTypeRef->IsSizedArray()) @@ -1159,6 +1157,7 @@ bool BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType case BfTypeCode_Struct: case BfTypeCode_Interface: case BfTypeCode_Enum: + case BfTypeCode_TypeAlias: // Implemented below break; case BfTypeCode_Extension: @@ -1518,6 +1517,13 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy BuildGenericParams(resolvedTypeRef); } + if (resolvedTypeRef->IsTypeAlias()) + { + typeInstance->mTypeIncomplete = false; + resolvedTypeRef->mDefineState = BfTypeDefineState_DefinedAndMethodsSlotted; + return true; + } + if (_CheckTypeDone()) return true; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 7ca5f766..050ccb11 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -3768,7 +3768,28 @@ String BfTypeUtils::TypeToString(BfTypeReference* typeRef) } if (auto directStrTypeName = BfNodeDynCast(typeRef)) return directStrTypeName->mTypeName; - BF_FATAL("Not implemented"); + + if (auto tupleTypeRef = BfNodeDynCast(typeRef)) + { + String name = "("; + + for (int i = 0; i < tupleTypeRef->mFieldTypes.size(); i++) + { + if (i > 0) + name += ", "; + name += TypeToString(tupleTypeRef->mFieldTypes[i]); + if ((i < tupleTypeRef->mFieldNames.size()) && (tupleTypeRef->mFieldNames[i] != NULL)) + { + name += " "; + name += tupleTypeRef->mFieldNames[i]->ToString(); + } + } + + name += ")"; + return name; + } + + BF_DBG_FATAL("Not implemented"); return "???"; } diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 52175eb5..561dd67f 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -3696,6 +3696,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) if (checkType->IsPointer()) { auto innerType = checkType->GetUnderlyingType(); + PopulateType(innerType); if (innerType->IsValuelessType()) mayBeSentinel = true; } @@ -5383,7 +5384,7 @@ void BfModule::Visit(BfForStatement* forStmt) } void BfModule::DoForLess(BfForEachStatement* forEachStmt) -{ +{ UpdateSrcPos(forEachStmt); BfScopeData scopeData; @@ -5714,8 +5715,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) { if (genericItrInterface != NULL) { - Fail(StrFormat("Type '%s' implements multiple %s interfaces", TypeToString(itr.mType).c_str(), isRefExpression ? "IRefEnumerator" : "IEnumerator"), forEachStmt->mCollectionExpression); - return; + Fail(StrFormat("Type '%s' implements multiple %s interfaces", TypeToString(itr.mType).c_str(), isRefExpression ? "IRefEnumerator" : "IEnumerator"), forEachStmt->mCollectionExpression); } itrInterface = interface; @@ -5724,7 +5724,11 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) { varType = genericItrInterface->mTypeGenericArguments[0]; if (isRefExpression) - varType = CreateRefType(varType); + { + if (varType->IsPointer()) + varType = CreateRefType(varType->GetUnderlyingType()); + } + } } } @@ -5737,7 +5741,10 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) { varType = genericItrInterface->mTypeGenericArguments[0]; if (isRefExpression) - varType = CreateRefType(varType); + { + if (varType->IsPointer()) + varType = CreateRefType(varType); + } } } } @@ -5761,9 +5768,9 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) refItrInterface = itrInterface; PopulateType(refItrInterface); // Must IRefEnumeratorf must include only IEnumerator - BF_ASSERT(refItrInterface->mInterfaces.size() == 1); - if (refItrInterface->mInterfaces.size() == 1) - itrInterface = refItrInterface->mInterfaces[0].mInterfaceType; +// BF_ASSERT(refItrInterface->mInterfaces.size() == 1); +// if (refItrInterface->mInterfaces.size() == 1) +// itrInterface = refItrInterface->mInterfaces[0].mInterfaceType; } itr = MakeAddressable(itr); itr = RemoveReadOnly(itr); @@ -6220,7 +6227,10 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) { auto nextVal = BfTypedValue(mBfIRBuilder->CreateBitCast(nextResult.mValue, mBfIRBuilder->MapType(CreatePointerType(nextEmbeddedType))), nextEmbeddedType, true); if (isRefExpression) - nextVal = BfTypedValue(nextVal.mValue, CreateRefType(nextVal.mType->GetUnderlyingType()), true); + { + if (nextVal.mType->IsPointer()) + nextVal = BfTypedValue(nextVal.mValue, CreateRefType(nextVal.mType->GetUnderlyingType()), true); + } nextVal = Cast(forEachStmt->mCollectionExpression, nextVal, varType, BfCastFlags_Explicit); nextVal = LoadValue(nextVal); if (nextVal)