1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00

Deferred evaluation support for binary operators

This commit is contained in:
Brian Fiete 2021-01-22 11:37:39 -08:00
parent 7093476126
commit 0ebd306d93
5 changed files with 108 additions and 18 deletions

View file

@ -5,6 +5,8 @@ USING_NS_BF;
BfDeferEvalChecker::BfDeferEvalChecker()
{
mNeedsDeferEval = false;
mDeferLiterals = true;
mDeferLambdaBind = true;
}
void BfDeferEvalChecker::Visit(BfAstNode* attribExpr)
@ -31,7 +33,8 @@ void BfDeferEvalChecker::Visit(BfLiteralExpression* literalExpr)
case BfTypeCode_UIntPtr:
case BfTypeCode_IntUnknown:
case BfTypeCode_UIntUnknown:
mNeedsDeferEval = true;
if (mDeferLiterals)
mNeedsDeferEval = true;
break;
default:
mNeedsDeferEval = false;
@ -82,6 +85,12 @@ void BfDeferEvalChecker::Visit(BfInvocationExpression* invocationExpr)
VisitChild(invocationExpr->mTarget);
}
void BfDeferEvalChecker::Visit(BfLambdaBindExpression* lambdaBindExpr)
{
if (mDeferLambdaBind)
mNeedsDeferEval = true;
}
void BfDeferEvalChecker::Visit(BfConditionalExpression* condExpr)
{
VisitChild(condExpr->mConditionExpression);

View file

@ -9,6 +9,8 @@ class BfDeferEvalChecker : public BfStructuralVisitor
{
public:
bool mNeedsDeferEval;
bool mDeferLambdaBind;
bool mDeferLiterals;
public:
BfDeferEvalChecker();
@ -21,6 +23,7 @@ public:
virtual void Visit(BfTupleExpression* tupleExpr) override;
virtual void Visit(BfMemberReferenceExpression* memberRefExpr) override;
virtual void Visit(BfInvocationExpression* invocationExpr) override;
virtual void Visit(BfLambdaBindExpression* lambdaBindExpr) override;
virtual void Visit(BfConditionalExpression* condExpr) override;
virtual void Visit(BfUnaryOperatorExpression* unaryOpExpr) override;
virtual void Visit(BfObjectCreateExpression* objCreateExpr) override;

View file

@ -5008,6 +5008,7 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
if (argExpr != NULL)
{
BfDeferEvalChecker deferEvalChecker;
deferEvalChecker.mDeferLambdaBind = false;
argExpr->Accept(&deferEvalChecker);
deferParamEval = deferEvalChecker.mNeedsDeferEval;
}
@ -17762,18 +17763,29 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
CheckResultForReading(ptr);
BfTypedValue leftValue = ptr;
auto expectedType = ptr.mType;
if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift))
expectedType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
bool deferBinop = false;
BfDeferEvalChecker deferEvalChecker;
deferEvalChecker.mDeferLiterals = false;
assignExpr->mRight->Accept(&deferEvalChecker);
if (deferEvalChecker.mNeedsDeferEval)
deferBinop = true;
if ((!rightValue) && (assignExpr->mRight != NULL))
if (!deferBinop)
{
rightValue = mModule->CreateValueFromExpression(assignExpr->mRight, expectedType, (BfEvalExprFlags)(BfEvalExprFlags_AllowSplat | BfEvalExprFlags_NoCast));
auto expectedType = ptr.mType;
if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift))
expectedType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
if ((!rightValue) && (assignExpr->mRight != NULL))
{
rightValue = mModule->CreateValueFromExpression(assignExpr->mRight, expectedType, (BfEvalExprFlags)(BfEvalExprFlags_AllowSplat | BfEvalExprFlags_NoCast));
}
}
bool handled = false;
BfResolvedArgs argValues;
if (rightValue)
if ((rightValue) || (deferBinop))
{
auto checkTypeInst = leftValue.mType->ToTypeInstance();
while (checkTypeInst != NULL)
@ -17788,8 +17800,26 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
continue;
auto paramType = methodInst->GetParamType(0);
if (!mModule->CanCast(rightValue, paramType))
continue;
if (deferBinop)
{
if (argValues.mArguments == NULL)
{
SizedArray<BfExpression*, 2> argExprs;
argExprs.push_back(assignExpr->mRight);
BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
argValues.Init(&sizedArgExprs);
ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
}
rightValue = ResolveArgValue(argValues.mResolvedArgs[0], paramType);
if (!rightValue)
continue;
}
else
{
if (!mModule->CanCast(rightValue, paramType))
continue;
}
mModule->SetElementType(assignExpr->mOpToken, BfSourceElementType_Method);
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(assignExpr->mOpToken)))
@ -17817,8 +17847,12 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
if (!handled)
{
auto flags = BfBinOpFlag_ForceLeftType;
if (deferBinop)
flags = (BfBinOpFlags)(flags | BfBinOpFlag_DeferRight);
leftValue = mModule->LoadValue(leftValue);
PerformBinaryOperation(assignExpr->mLeft, assignExpr->mRight, binaryOp, assignExpr->mOpToken, BfBinOpFlag_ForceLeftType, leftValue, rightValue);
PerformBinaryOperation(assignExpr->mLeft, assignExpr->mRight, binaryOp, assignExpr->mOpToken, flags, leftValue, rightValue);
}
}
@ -20417,6 +20451,12 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{
bool noClassify = (flags & BfBinOpFlag_NoClassify) != 0;
bool forceLeftType = (flags & BfBinOpFlag_ForceLeftType) != 0;
bool deferRight = (flags & BfBinOpFlag_DeferRight) != 0;
if (deferRight)
{
rightValue = mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Var));
}
if ((rightValue.mValue.IsConst()) && (!leftValue.mValue.IsConst()))
{
@ -20646,7 +20686,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
BfIRValue convLeftValue;
BfIRValue convRightValue;
if ((resultType->IsVar()) || (otherType->IsVar()))
if (((resultType->IsVar()) || (otherType->IsVar())) && (!deferRight))
{
bool isComparison = (binaryOp >= BfBinaryOp_Equality) && (binaryOp <= BfBinaryOp_LessThanOrEqual);
if (isComparison)
@ -20794,7 +20834,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
}
if (!skipOpOverload)
{
{
BfBinaryOp findBinaryOp = binaryOp;
bool isComparison = (binaryOp >= BfBinaryOp_Equality) && (binaryOp <= BfBinaryOp_LessThanOrEqual);
@ -20802,16 +20842,28 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
for (int pass = 0; pass < 2; pass++)
{
BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp);
bool foundOp = false;
bool foundOp = false;
SizedArray<BfResolvedArg, 2> args;
BfResolvedArg leftArg;
leftArg.mExpression = leftExpression;
leftArg.mTypedValue = leftValue;
leftArg.mTypedValue = leftValue;
BfResolvedArg rightArg;
rightArg.mExpression = rightExpression;
rightArg.mTypedValue = rightValue;
if (deferRight)
{
BfResolvedArgs argValues;
SizedArray<BfExpression*, 2> argExprs;
argExprs.push_back(BfNodeDynCast<BfExpression>(rightExpression));
BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
argValues.Init(&sizedArgExprs);
ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
rightArg = argValues.mResolvedArgs[0];
}
SizedArray<BfResolvedArg, 2> args;
if (pass == 0)
{
args.push_back(leftArg);
@ -20820,8 +20872,9 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
else
{
args.push_back(rightArg);
args.push_back(leftArg);
args.push_back(leftArg);
}
BfMethodMatcher methodMatcher(opToken, mModule, "", args, NULL);
methodMatcher.mBfEvalExprFlags = BfEvalExprFlags_NoAutoComplete;
BfBaseClassWalker baseClassWalker(leftValue.mType, rightValue.mType, mModule);
@ -21135,7 +21188,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if (flippedBinaryOp != BfBinaryOp_None)
findBinaryOp = flippedBinaryOp;
}
auto prevResultType = resultType;
if ((leftValue.mType->IsPrimitiveType()) && (!rightValue.mType->IsTypedPrimitive()))
resultType = leftValue.mType;
@ -21144,6 +21197,16 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
}
}
if (deferRight)
{
auto expectedType = resultType;
if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift))
expectedType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
rightValue = mModule->CreateValueFromExpression(BfNodeDynCast<BfExpression>(rightExpression), expectedType, (BfEvalExprFlags)(BfEvalExprFlags_AllowSplat | BfEvalExprFlags_NoCast));
PerformBinaryOperation(leftExpression, rightExpression, binaryOp, opToken, (BfBinOpFlags)(flags & ~BfBinOpFlag_DeferRight), leftValue, rightValue);
return;
}
if (mModule->IsUnboundGeneric(resultType))
{
mResult = mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Var));

View file

@ -347,7 +347,8 @@ enum BfBinOpFlags
BfBinOpFlag_NoClassify = 1,
BfBinOpFlag_ForceLeftType = 2,
BfBinOpFlag_IgnoreOperatorWithWrongResult = 4,
BfBinOpFlag_IsConstraintCheck = 8
BfBinOpFlag_IsConstraintCheck = 8,
BfBinOpFlag_DeferRight = 0x10
};
class BfExprEvaluator : public BfStructuralVisitor