Ver código fonte

Additional `if` variable restrictions

Brian Fiete 5 anos atrás
pai
commit
980fc63b74
2 arquivos alterados com 31 adições e 31 exclusões
  1. 5 0
      IDEHelper/Compiler/BfAst.h
  2. 26 31
      IDEHelper/Compiler/BfExprEvaluator.cpp

+ 5 - 0
IDEHelper/Compiler/BfAst.h

@@ -1409,6 +1409,11 @@ public:
 	{
 	{
 		return (srcPos >= mSrcStart + startAdd) && (srcPos < mSrcEnd + lenAdd);
 		return (srcPos >= mSrcStart + startAdd) && (srcPos < mSrcEnd + lenAdd);
 	}
 	}
+
+	bool Contains(BfAstNode* node)
+	{
+		return (node->mSrcStart >= mSrcStart) && (node->mSrcEnd <= mSrcEnd);
+	}
 #endif
 #endif
 
 
 
 

+ 26 - 31
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -2702,6 +2702,7 @@ void BfExprEvaluator::Visit(BfBlock* blockExpr)
 bool BfExprEvaluator::CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail)
 bool BfExprEvaluator::CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail)
 {
 {
 	BfAstNode* checkChild = checkNode;
 	BfAstNode* checkChild = checkNode;
+	bool childWasAndRHS = false;
 	bool foundIf = false;
 	bool foundIf = false;
 
 
 	auto parentNodeEntry = mModule->mParentNodeEntry;
 	auto parentNodeEntry = mModule->mParentNodeEntry;
@@ -2712,7 +2713,20 @@ bool BfExprEvaluator::CheckVariableDeclaration(BfAstNode* checkNode, bool requir
 			checkChild = parentNodeEntry->mNode;
 			checkChild = parentNodeEntry->mNode;
 			parentNodeEntry = parentNodeEntry->mPrev;
 			parentNodeEntry = parentNodeEntry->mPrev;
 		}
 		}
-	}
+	}	
+
+	auto _Fail = [&](const StringImpl& errorStr, BfAstNode* node)
+	{
+		if (!silentFail)
+		{
+			auto error = mModule->Fail(errorStr, node);
+			if ((error != NULL) && (node != checkNode))
+			{
+				mModule->mCompiler->mPassInstance->MoreInfo("See variable declaration", checkNode);
+			}
+		}
+		return false;
+	};
 
 
 	while (parentNodeEntry != NULL)
 	while (parentNodeEntry != NULL)
 	{		
 	{		
@@ -2723,41 +2737,20 @@ bool BfExprEvaluator::CheckVariableDeclaration(BfAstNode* checkNode, bool requir
 			if (binOpExpr->mOp == BfBinaryOp_ConditionalAnd)
 			if (binOpExpr->mOp == BfBinaryOp_ConditionalAnd)
 			{
 			{
 				// This is always okay
 				// This is always okay
+				childWasAndRHS = (binOpExpr->mRight != NULL) && (binOpExpr->mRight->Contains(checkChild));
 			}
 			}
 			else if ((binOpExpr->mOp == BfBinaryOp_ConditionalOr) && (!exprMustBeTrue))
 			else if ((binOpExpr->mOp == BfBinaryOp_ConditionalOr) && (!exprMustBeTrue))
 			{
 			{
-				bool matches = false;
-				auto checkRight = binOpExpr->mRight;
-				while (checkRight != NULL)
+				if ((binOpExpr->mRight != NULL) & (binOpExpr->mRight->Contains(checkChild)))				
 				{
 				{
-					if (checkRight == checkChild)
-					{
-						matches = true;
-						break;
-					}
-
-					if (auto parenExpr = BfNodeDynCast<BfParenthesizedExpression>(checkRight))
-						checkRight = parenExpr->mExpression;
-					else
-					{
-						break;
-					}
-				}
-
-				if (matches)
-				{
-					if (!silentFail)
-						mModule->Fail("Conditional short-circuiting may skip variable initialization", binOpExpr->mOpToken);
-					return false;
+					return _Fail("Conditional short-circuiting may skip variable initialization", binOpExpr->mOpToken);					
 				}
 				}
 			}
 			}
 			else
 			else
 			{
 			{
 				if (exprMustBeTrue)
 				if (exprMustBeTrue)
 				{
 				{
-					if (!silentFail)
-						mModule->Fail("Operator cannot be used with variable initialization", binOpExpr->mOpToken);
-					return false;
+					return _Fail("Operator cannot be used with variable initialization", binOpExpr->mOpToken);					
 				}
 				}
 			}
 			}
 		}
 		}
@@ -2769,10 +2762,14 @@ bool BfExprEvaluator::CheckVariableDeclaration(BfAstNode* checkNode, bool requir
 		{			
 		{			
 			if (exprMustBeTrue)
 			if (exprMustBeTrue)
 			{
 			{
-				if (!silentFail)
-					mModule->Fail("Operator cannot be used with variable initialization", unaryOp->mOpToken);
+				return _Fail("Operator cannot be used with variable initialization", unaryOp->mOpToken);
 				return false;
 				return false;
 			}
 			}
+
+			if (childWasAndRHS)
+			{		
+				return _Fail("Operator may allow conditional short-circuiting to skip variable initialization", unaryOp->mOpToken);				
+			}
 		}
 		}
 		else if (auto ifStmt = BfNodeDynCast<BfIfStatement>(checkParent))
 		else if (auto ifStmt = BfNodeDynCast<BfIfStatement>(checkParent))
 		{
 		{
@@ -2784,9 +2781,7 @@ bool BfExprEvaluator::CheckVariableDeclaration(BfAstNode* checkNode, bool requir
 		{
 		{
 			if (requireSimpleIfExpr)
 			if (requireSimpleIfExpr)
 			{
 			{
-				if (!silentFail)
-					mModule->Fail("Variable declaration expression can only be contained in simple 'if' expressions", checkNode);
-				return false;
+				return _Fail("Variable declaration expression can only be contained in simple 'if' expressions", checkNode);				
 			}
 			}
 			break;
 			break;
 		}
 		}