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:
parent
7093476126
commit
0ebd306d93
5 changed files with 108 additions and 18 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,6 +2,17 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace System
|
||||
{
|
||||
extension Event<T>
|
||||
{
|
||||
public implicit void operator+=(T dlg) mut
|
||||
{
|
||||
Add(dlg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
class Delegates
|
||||
|
@ -146,6 +157,9 @@ namespace Tests
|
|||
|
||||
ClassB<int8>.DelegateB dlg2 = scope (val) => val + 123;
|
||||
Test.Assert(dlg2(3) == 126);
|
||||
|
||||
Event<EventHandler> e = .();
|
||||
e += scope (sender, e) => {};
|
||||
}
|
||||
|
||||
public static void Modify(ref int a, ref Splattable b)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue