diff --git a/BeefLibs/corlib/src/SizedArray.bf b/BeefLibs/corlib/src/SizedArray.bf index 605c95fb..0e0885d3 100644 --- a/BeefLibs/corlib/src/SizedArray.bf +++ b/BeefLibs/corlib/src/SizedArray.bf @@ -20,7 +20,7 @@ namespace System return val.mVal; } - public implicit static operator Span (ref Self val) + public implicit static operator Span (in Self val) { #unwarn return .(&val.mVal, CSize); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index e0c9abe1..305b57be 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -2069,7 +2069,8 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst } else { - if ((mAllowImplicitRef) && (wantType->IsRef()) && (!argTypedValue.mType->IsRef())) + if ((wantType->IsRef()) && (!argTypedValue.mType->IsRef()) && + ((mAllowImplicitRef) || (wantType->IsIn()))) wantType = wantType->GetUnderlyingType(); if (!mModule->CanCast(argTypedValue, wantType)) goto NoMatch; @@ -3662,7 +3663,7 @@ BfTypedValue BfExprEvaluator::LoadLocal(BfLocalVariable* varDecl, bool allowRef) } } - localResult = BfTypedValue(varDecl->mValue, innerType, BfTypedValueKind_Addr); + localResult = BfTypedValue(varDecl->mValue, innerType, varDecl->mIsReadOnly ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr); } else { @@ -7011,8 +7012,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu if (refNode == NULL) refNode = targetSrc; - if (((callFlags & BfCreateFallFlags_AllowImplicitRef) != 0) && - (wantType->IsRef()) && (!argValue.mType->IsRef())) + if ((wantType->IsRef()) && (!argValue.mType->IsRef()) && + (((callFlags & BfCreateFallFlags_AllowImplicitRef) != 0) || (wantType->IsIn()))) argValue = mModule->ToRef(argValue, (BfRefType*)wantType); if (mModule->mCurMethodState != NULL) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 063b0ea3..d223e2bf 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -11490,6 +11490,8 @@ BfTypedValue BfModule::RemoveRef(BfTypedValue typedValue) { if ((typedValue.mType != NULL) && (typedValue.mType->IsRef())) { + auto refType = (BfRefType*)typedValue.mType; + auto elementType = typedValue.mType->GetUnderlyingType(); if (typedValue.IsAddr()) { @@ -11508,6 +11510,12 @@ BfTypedValue BfModule::RemoveRef(BfTypedValue typedValue) { BF_ASSERT(typedValue.mValue.IsFake()); } + + if (refType->mRefKind == BfRefType::RefKind_In) + { + if (typedValue.mKind == BfTypedValueKind_Addr) + typedValue.mKind = BfTypedValueKind_ReadOnlyAddr; + } } return typedValue; } @@ -17275,6 +17283,10 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp { auto refType = (BfRefType*)resolvedType; paramVar->mAssignedKind = (refType->mRefKind != BfRefType::RefKind_Out) ? BfLocalVarAssignKind_Unconditional : BfLocalVarAssignKind_None; + if (refType->mRefKind == BfRefType::RefKind_In) + { + paramVar->mIsReadOnly = true; + } } else { @@ -21736,7 +21748,11 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool if ((paramDef != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (paramDef->mParamKind != BfParamKind_AppendIdx)) + { mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(paramDef->mTypeRef, false); + if (mCompiler->mResolvePassData->mAutoComplete->IsAutocompleteNode(paramDef->mTypeRef)) + mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("token", "in"), paramDef->mTypeRef->ToString()); + } if ((paramDef != NULL) && (paramDef->mParamDeclaration != NULL) && (paramDef->mParamDeclaration->mAttributes != NULL)) { diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index b9ad2be8..c983b0fb 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -9961,6 +9961,8 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula refType->mRefKind = BfRefType::RefKind_Ref; if (refTypeRef->mRefToken == NULL) refType->mRefKind = BfRefType::RefKind_Ref; + else if (refTypeRef->mRefToken->GetToken() == BfToken_In) + refType->mRefKind = BfRefType::RefKind_In; else if (refTypeRef->mRefToken->GetToken() == BfToken_Out) refType->mRefKind = BfRefType::RefKind_Out; else if (refTypeRef->mRefToken->GetToken() == BfToken_Mut) @@ -13214,6 +13216,12 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF DoTypeToString(str, refType->mElementType, typeNameFlags, genericMethodNameOverrides); return; } + else if (refType->mRefKind == BfRefType::RefKind_In) + { + str += "in "; + DoTypeToString(str, refType->mElementType, typeNameFlags, genericMethodNameOverrides); + return; + } else if (refType->mRefKind == BfRefType::RefKind_Out) { str += "out "; diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index b8492981..c010e0ae 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -1303,12 +1303,12 @@ BfExpression* BfReducer::CheckBinaryOperatorPrecedence(BfBinaryOperatorExpressio return resultExpr; } -BfAstNode* BfReducer::ReplaceTokenStarter(BfAstNode* astNode, int idx) +BfAstNode* BfReducer::ReplaceTokenStarter(BfAstNode* astNode, int idx, bool allowIn) { if (auto tokenNode = BfNodeDynCast(astNode)) { if ((tokenNode->GetToken() == BfToken_As) || - (tokenNode->GetToken() == BfToken_In)) + ((tokenNode->GetToken() == BfToken_In) && (!allowIn))) { if (idx == -1) idx = mVisitorPos.mReadPos; @@ -5206,7 +5206,7 @@ BfTypeReference* BfReducer::CreateTypeRefAfter(BfAstNode* astNode, CreateTypeRef BfTypeReference* BfReducer::CreateRefTypeRef(BfTypeReference* elementType, BfTokenNode* refTokenNode) { BfToken refToken = refTokenNode->GetToken(); - BF_ASSERT((refToken == BfToken_Ref) || (refToken == BfToken_Mut) || (refToken == BfToken_Out)); + BF_ASSERT((refToken == BfToken_Ref) || (refToken == BfToken_Mut) || (refToken == BfToken_In) || (refToken == BfToken_Out)); if (elementType->IsA()) { @@ -8880,7 +8880,7 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl(nextNode); if (tokenNode != NULL) @@ -8910,7 +8910,7 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl(mVisitorPos.Get(mVisitorPos.mReadPos + 2)); + attributes = NULL; BfTokenNode* modTokenNode = NULL; - nextNode = ReplaceTokenStarter(mVisitorPos.GetNext(), mVisitorPos.mReadPos + 1); + nextNode = ReplaceTokenStarter(mVisitorPos.GetNext(), mVisitorPos.mReadPos + 1, nextNextIsIdentifier); tokenNode = BfNodeDynCast(nextNode); BfTypeReference* typeRef = NULL; if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_LBracket)) @@ -8973,7 +8975,7 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImplGetToken(); - if ((modTokenNode != NULL) && ((modToken == BfToken_Ref) || (modToken == BfToken_Mut) || (modToken == BfToken_Out))) + if ((modTokenNode != NULL) && ((modToken == BfToken_Ref) || (modToken == BfToken_Mut) || (modToken == BfToken_In) || (modToken == BfToken_Out))) { typeRef = CreateRefTypeRef(typeRef, modTokenNode); modTokenNode = NULL; diff --git a/IDEHelper/Compiler/BfReducer.h b/IDEHelper/Compiler/BfReducer.h index e882a168..d233fedb 100644 --- a/IDEHelper/Compiler/BfReducer.h +++ b/IDEHelper/Compiler/BfReducer.h @@ -178,7 +178,7 @@ public: bool SetProtection(BfAstNode* parentNode, BfAstNode*& protectionNodeRef, BfTokenNode* tokenNode); BfAstNode* CreateAllocNode(BfTokenNode* newNode); - BfAstNode* ReplaceTokenStarter(BfAstNode* astNode, int idx = -1); + BfAstNode* ReplaceTokenStarter(BfAstNode* astNode, int idx = -1, bool allowIn = false); BfEnumCaseBindExpression* CreateEnumCaseBindExpression(BfTokenNode* bindToken); BfExpression* CheckBinaryOperatorPrecedence(BfBinaryOperatorExpression* binOpExpression); BfExpression* ApplyToFirstExpression(BfUnaryOperatorExpression* unaryOp, BfExpression* target); diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 5ccb3a99..8d47d964 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -3297,6 +3297,8 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash auto refKind = BfRefType::RefKind_Ref; if (refType->mRefToken == NULL) refKind = BfRefType::RefKind_Ref; + else if (refType->mRefToken->GetToken() == BfToken_In) + refKind = BfRefType::RefKind_In; else if (refType->mRefToken->GetToken() == BfToken_Out) refKind = BfRefType::RefKind_Out; else if (refType->mRefToken->GetToken() == BfToken_Mut) @@ -4176,6 +4178,8 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* auto refKind = BfRefType::RefKind_Ref; if (rhsRefTypeRef->mRefToken == NULL) refKind = BfRefType::RefKind_Ref; + else if (rhsRefTypeRef->mRefToken->GetToken() == BfToken_In) + refKind = BfRefType::RefKind_In; else if (rhsRefTypeRef->mRefToken->GetToken() == BfToken_Out) refKind = BfRefType::RefKind_Out; else if (rhsRefTypeRef->mRefToken->GetToken() == BfToken_Mut) @@ -4612,8 +4616,10 @@ String BfTypeUtils::TypeToString(BfAstNode* typeRefNode) } if (auto refTypeRef = BfNodeDynCast(typeRef)) { - return ((refTypeRef->mRefToken->GetToken() == BfToken_Out) ? "out " : "ref ") + - TypeToString(refTypeRef->mElementType); + String str = BfTokenToString(refTypeRef->mRefToken->GetToken()); + str += " "; + str += TypeToString(refTypeRef->mElementType); + return str; } if (auto directStrTypeName = BfNodeDynCast(typeRef)) return directStrTypeName->mTypeName; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index afd8c3bc..e41f8a18 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -569,6 +569,7 @@ public: virtual bool IsIntPtrable() { return false; } virtual bool IsRef() { return false; } virtual bool IsMut() { return false; } + virtual bool IsIn() { return false; } virtual bool IsOut() { return false; } virtual bool IsGenericParam() { return false; } virtual bool IsClosure() { return false; } @@ -2263,6 +2264,7 @@ public: enum RefKind { RefKind_Ref, + RefKind_In, RefKind_Out, RefKind_Mut }; @@ -2283,6 +2285,7 @@ public: virtual bool IsRef() override { return true; } virtual bool IsMut() override { return mRefKind == RefKind_Mut; } + virtual bool IsIn() override { return mRefKind == RefKind_In; } virtual bool IsOut() override { return mRefKind == RefKind_Out; } virtual bool IsDependentOnUnderlyingType() override { return true; } virtual BfType* GetUnderlyingType() override { return mElementType; }