소스 검색

Added 'in' parameter support

Brian Fiete 4 년 전
부모
커밋
4d1672fbcf

+ 1 - 1
BeefLibs/corlib/src/SizedArray.bf

@@ -20,7 +20,7 @@ namespace System
 			return val.mVal;
 		}
 
-		public implicit static operator Span<T> (ref Self val)
+		public implicit static operator Span<T> (in Self val)
 		{
 #unwarn
 			return .(&val.mVal, CSize);

+ 5 - 4
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)

+ 16 - 0
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))
 		{

+ 8 - 0
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 ";

+ 10 - 8
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<BfTokenNode>(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<BfRefTypeRef>())
 	{
@@ -8880,7 +8880,7 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
 	BfAttributeDirective* attributes = NULL;
 	for (int paramIdx = 0; true; paramIdx++)
 	{
-		auto nextNode = ReplaceTokenStarter(mVisitorPos.GetNext(), mVisitorPos.mReadPos + 1);
+		auto nextNode = ReplaceTokenStarter(mVisitorPos.GetNext(), mVisitorPos.mReadPos + 1, true);
 
 		auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
 		if (tokenNode != NULL)
@@ -8910,7 +8910,7 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
 				return tokenNode;
 
 			if ((paramIdx == 0) && (
-				(token == BfToken_Out) || (token == BfToken_Ref) || (token == BfToken_Mut) ||
+				(token == BfToken_In) || (token == BfToken_Out) || (token == BfToken_Ref) || (token == BfToken_Mut) ||
 				(token == BfToken_Delegate) || (token == BfToken_Function) ||
 				(token == BfToken_Params) || (token == BfToken_LParen) ||
 				(token == BfToken_Var) || (token == BfToken_LBracket) ||
@@ -8942,9 +8942,11 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
 			}
 		}
 
+		bool nextNextIsIdentifier = BfNodeIsA<BfIdentifierNode>(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<BfTokenNode>(nextNode);
 		BfTypeReference* typeRef = NULL;
 		if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_LBracket))
@@ -8973,7 +8975,7 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
 			}
 			else
 			{
-				if ((token != BfToken_Out) && (token != BfToken_Ref) && (token != BfToken_Mut) && (token != BfToken_Params) && (token != BfToken_ReadOnly))
+				if ((token != BfToken_In) && (token != BfToken_Out) && (token != BfToken_Ref) && (token != BfToken_Mut) && (token != BfToken_Params) && (token != BfToken_ReadOnly))
 				{
 					Fail("Invalid token", tokenNode);
 					return NULL;
@@ -9009,7 +9011,7 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
 		if (modTokenNode != NULL)
 			modToken = modTokenNode->GetToken();
 
-		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;

+ 1 - 1
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);

+ 8 - 2
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<BfRefTypeRef>(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<BfDirectStrTypeReference>(typeRef))
 		return directStrTypeName->mTypeName;

+ 3 - 0
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; }