mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Added overflow operators &+, &-, &*
This commit is contained in:
parent
8d2b222c1a
commit
d475d3641f
7 changed files with 151 additions and 25 deletions
|
@ -1500,6 +1500,12 @@ const char* Beefy::BfTokenToString(BfToken token)
|
|||
return ">>=";
|
||||
case BfToken_AndEquals:
|
||||
return "&=";
|
||||
case BfToken_AndMinus:
|
||||
return "&-";
|
||||
case BfToken_AndPlus:
|
||||
return "&+";
|
||||
case BfToken_AndStar:
|
||||
return "&*";
|
||||
case BfToken_OrEquals:
|
||||
return "|=";
|
||||
case BfToken_XorEquals:
|
||||
|
@ -1630,11 +1636,14 @@ int Beefy::BfGetBinaryOpPrecendence(BfBinaryOp binOp)
|
|||
switch (binOp)
|
||||
{
|
||||
case BfBinaryOp_Multiply:
|
||||
case BfBinaryOp_OverflowMultiply:
|
||||
case BfBinaryOp_Divide:
|
||||
case BfBinaryOp_Modulus:
|
||||
case BfBinaryOp_Modulus:
|
||||
return 13;
|
||||
case BfBinaryOp_Add:
|
||||
case BfBinaryOp_Subtract:
|
||||
case BfBinaryOp_Subtract:
|
||||
case BfBinaryOp_OverflowAdd:
|
||||
case BfBinaryOp_OverflowSubtract:
|
||||
return 12;
|
||||
case BfBinaryOp_LeftShift:
|
||||
case BfBinaryOp_RightShift:
|
||||
|
@ -1682,6 +1691,9 @@ const char* Beefy::BfGetOpName(BfBinaryOp binOp)
|
|||
case BfBinaryOp_Add: return "+";
|
||||
case BfBinaryOp_Subtract: return "-";
|
||||
case BfBinaryOp_Multiply: return "*";
|
||||
case BfBinaryOp_OverflowAdd: return "&+";
|
||||
case BfBinaryOp_OverflowSubtract: return "&-";
|
||||
case BfBinaryOp_OverflowMultiply: return "&*";
|
||||
case BfBinaryOp_Divide: return "/";
|
||||
case BfBinaryOp_Modulus: return "%";
|
||||
case BfBinaryOp_BitwiseAnd: return "&";
|
||||
|
@ -1742,6 +1754,12 @@ BfBinaryOp Beefy::BfTokenToBinaryOp(BfToken token)
|
|||
return BfBinaryOp_Subtract;
|
||||
case BfToken_Star:
|
||||
return BfBinaryOp_Multiply;
|
||||
case BfToken_AndPlus:
|
||||
return BfBinaryOp_OverflowAdd;
|
||||
case BfToken_AndMinus:
|
||||
return BfBinaryOp_OverflowSubtract;
|
||||
case BfToken_AndStar:
|
||||
return BfBinaryOp_OverflowMultiply;
|
||||
case BfToken_ForwardSlash:
|
||||
return BfBinaryOp_Divide;
|
||||
case BfToken_Modulus:
|
||||
|
|
|
@ -210,6 +210,9 @@ enum BfToken : uint8
|
|||
BfToken_ShiftLeftEquals,
|
||||
BfToken_ShiftRightEquals,
|
||||
BfToken_AndEquals,
|
||||
BfToken_AndMinus,
|
||||
BfToken_AndPlus,
|
||||
BfToken_AndStar,
|
||||
BfToken_OrEquals,
|
||||
BfToken_XorEquals,
|
||||
BfToken_NullCoalsceEquals,
|
||||
|
@ -1795,6 +1798,9 @@ enum BfBinaryOp
|
|||
BfBinaryOp_Add,
|
||||
BfBinaryOp_Subtract,
|
||||
BfBinaryOp_Multiply,
|
||||
BfBinaryOp_OverflowAdd,
|
||||
BfBinaryOp_OverflowSubtract,
|
||||
BfBinaryOp_OverflowMultiply,
|
||||
BfBinaryOp_Divide,
|
||||
BfBinaryOp_Modulus,
|
||||
BfBinaryOp_BitwiseAnd,
|
||||
|
|
|
@ -21177,11 +21177,20 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
BfBinaryOp findBinaryOp = binaryOp;
|
||||
|
||||
bool isComparison = (binaryOp >= BfBinaryOp_Equality) && (binaryOp <= BfBinaryOp_LessThanOrEqual);
|
||||
|
||||
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp);
|
||||
bool foundOp = false;
|
||||
BfBinaryOp overflowBinaryOp = BfBinaryOp_None;
|
||||
|
||||
if (findBinaryOp == BfBinaryOp_OverflowAdd)
|
||||
overflowBinaryOp = BfBinaryOp_Add;
|
||||
else if (findBinaryOp == BfBinaryOp_OverflowSubtract)
|
||||
overflowBinaryOp = BfBinaryOp_Subtract;
|
||||
else if (findBinaryOp == BfBinaryOp_OverflowMultiply)
|
||||
overflowBinaryOp = BfBinaryOp_Multiply;
|
||||
|
||||
bool foundOp = false;
|
||||
|
||||
BfResolvedArg leftArg;
|
||||
leftArg.mExpression = leftExpression;
|
||||
|
@ -21225,7 +21234,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
bool invertResult = false;
|
||||
BfType* operatorConstraintReturnType = NULL;
|
||||
|
||||
bool wasTransformedUsage = pass == 1;
|
||||
bool wasTransformedUsage = (pass == 1);
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
@ -21288,7 +21297,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp)
|
||||
else if ((operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp) || (operatorDef->mOperatorDeclaration->mBinOp == overflowBinaryOp))
|
||||
oppositeOperatorDefs.Add(operatorDef);
|
||||
}
|
||||
|
||||
|
@ -21309,7 +21318,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
methodMatcher.mBestMethodDef = oppositeOperatorDef;
|
||||
methodMatcher.mBestMethodTypeInstance = checkType;
|
||||
methodMatcher.mSelfType = entry.mSrcType;
|
||||
wasTransformedUsage = true;
|
||||
if (oppositeBinaryOp != BfBinaryOp_None)
|
||||
wasTransformedUsage = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -21322,7 +21332,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
{
|
||||
operatorConstraintReturnType = returnType;
|
||||
methodMatcher.mSelfType = entry.mSrcType;
|
||||
wasTransformedUsage = true;
|
||||
if (oppositeBinaryOp != BfBinaryOp_None)
|
||||
wasTransformedUsage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21332,7 +21343,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
if (methodMatcher.CheckMethod(NULL, checkType, oppositeOperatorDef, false))
|
||||
{
|
||||
methodMatcher.mSelfType = entry.mSrcType;
|
||||
wasTransformedUsage = true;
|
||||
if (oppositeBinaryOp != BfBinaryOp_None)
|
||||
wasTransformedUsage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21526,12 +21538,12 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
|
||||
if (pass == 1)
|
||||
break;
|
||||
|
||||
auto flippedBinaryOp = BfGetFlippedBinaryOp(findBinaryOp);
|
||||
|
||||
auto flippedBinaryOp = BfGetFlippedBinaryOp(findBinaryOp);
|
||||
if (flippedBinaryOp != BfBinaryOp_None)
|
||||
findBinaryOp = flippedBinaryOp;
|
||||
findBinaryOp = flippedBinaryOp;
|
||||
}
|
||||
|
||||
|
||||
auto prevResultType = resultType;
|
||||
if ((leftValue.mType->IsPrimitiveType()) && (!rightValue.mType->IsTypedPrimitive()))
|
||||
resultType = leftValue.mType;
|
||||
|
@ -21567,7 +21579,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
}
|
||||
|
||||
//TODO: Allow all pointer comparisons, but only allow SUBTRACTION between equal pointer types
|
||||
if (binaryOp == BfBinaryOp_Subtract)
|
||||
if ((binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowSubtract))
|
||||
{
|
||||
if (!mModule->CanCast(*otherTypedValue, resultType))
|
||||
{
|
||||
|
@ -21622,7 +21634,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
|
||||
// One pointer
|
||||
if ((!otherType->IsIntegral()) ||
|
||||
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract)))
|
||||
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract) && (binaryOp != BfBinaryOp_OverflowAdd) && (binaryOp != BfBinaryOp_OverflowSubtract)))
|
||||
{
|
||||
_OpFail();
|
||||
return;
|
||||
|
@ -21632,7 +21644,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
BfIRValue addValue = otherTypedValue->mValue;
|
||||
if ((!otherTypedValue->mType->IsSigned()) && (otherTypedValue->mType->mSize < mModule->mSystem->mPtrSize))
|
||||
addValue = mModule->mBfIRBuilder->CreateNumericCast(addValue, false, BfTypeCode_UIntPtr);
|
||||
if (binaryOp == BfBinaryOp_Subtract)
|
||||
if ((binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowSubtract))
|
||||
{
|
||||
if (resultTypeSrc == rightExpression)
|
||||
mModule->Fail("Cannot subtract a pointer from an integer", resultTypeSrc);
|
||||
|
@ -21731,7 +21743,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
}
|
||||
|
||||
// Allow integer offsetting
|
||||
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract))
|
||||
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract))
|
||||
{
|
||||
if (otherType->IsIntegral())
|
||||
needsOtherCast = false;
|
||||
|
@ -21954,7 +21966,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
if (rightValue.mType->IsIntegral())
|
||||
explicitCast = true;
|
||||
}
|
||||
else if (((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract)) && (resultType->IsChar()) && (otherType->IsInteger()))
|
||||
else if (((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract)) && (resultType->IsChar()) && (otherType->IsInteger()))
|
||||
{
|
||||
// charVal += intVal;
|
||||
explicitCast = true;
|
||||
|
@ -21980,14 +21992,15 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((binaryOp == BfBinaryOp_Subtract) && (resultType->IsChar()) && (otherType->IsChar()))
|
||||
if (((binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowSubtract)) &&
|
||||
(resultType->IsChar()) && (otherType->IsChar()))
|
||||
{
|
||||
// "wchar - char" subtraction will always fit into int32, because of unicode range
|
||||
resultType = mModule->GetPrimitiveType(BfTypeCode_Int32);
|
||||
explicitCast = true;
|
||||
}
|
||||
else if ((otherType->IsChar()) &&
|
||||
((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract)))
|
||||
((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract)))
|
||||
{
|
||||
mModule->Fail(StrFormat("Cannot perform operation between types '%s' and '%s'",
|
||||
mModule->TypeToString(leftValue.mType).c_str(),
|
||||
|
@ -22142,6 +22155,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
|
|||
|
||||
if ((resultType->IsChar()) &&
|
||||
((binaryOp == BfBinaryOp_Multiply) ||
|
||||
(binaryOp == BfBinaryOp_OverflowMultiply) ||
|
||||
(binaryOp == BfBinaryOp_Divide) ||
|
||||
(binaryOp == BfBinaryOp_Modulus)))
|
||||
{
|
||||
|
@ -22151,15 +22165,18 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
|
|||
|
||||
switch (binaryOp)
|
||||
{
|
||||
case BfBinaryOp_Add:
|
||||
case BfBinaryOp_Add:
|
||||
case BfBinaryOp_OverflowAdd:
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateAdd(convLeftValue, convRightValue), resultType);
|
||||
mModule->CheckRangeError(resultType, opToken);
|
||||
break;
|
||||
case BfBinaryOp_Subtract:
|
||||
case BfBinaryOp_Subtract:
|
||||
case BfBinaryOp_OverflowSubtract:
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateSub(convLeftValue, convRightValue), resultType);
|
||||
mModule->CheckRangeError(resultType, opToken);
|
||||
break;
|
||||
case BfBinaryOp_Multiply:
|
||||
case BfBinaryOp_Multiply:
|
||||
case BfBinaryOp_OverflowMultiply:
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateMul(convLeftValue, convRightValue), resultType);
|
||||
mModule->CheckRangeError(resultType, opToken);
|
||||
break;
|
||||
|
|
|
@ -754,6 +754,15 @@ String BfGNUMangler::Mangle(BfMethodInstance* methodInst)
|
|||
case BfBinaryOp_Multiply:
|
||||
methodName = "ml";
|
||||
break;
|
||||
case BfBinaryOp_OverflowAdd:
|
||||
methodName = "opl";
|
||||
break;
|
||||
case BfBinaryOp_OverflowSubtract:
|
||||
methodName = "omi";
|
||||
break;
|
||||
case BfBinaryOp_OverflowMultiply:
|
||||
methodName = "oml";
|
||||
break;
|
||||
case BfBinaryOp_Divide:
|
||||
methodName = "dv";
|
||||
break;
|
||||
|
@ -1872,6 +1881,15 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho
|
|||
case BfBinaryOp_Multiply:
|
||||
name += "?D";
|
||||
break;
|
||||
case BfBinaryOp_OverflowAdd:
|
||||
name += "?OH";
|
||||
break;
|
||||
case BfBinaryOp_OverflowSubtract:
|
||||
name += "?OG";
|
||||
break;
|
||||
case BfBinaryOp_OverflowMultiply:
|
||||
name += "?OD";
|
||||
break;
|
||||
case BfBinaryOp_Divide:
|
||||
name += "?K";
|
||||
break;
|
||||
|
|
|
@ -1549,6 +1549,21 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
mToken = BfToken_AndEquals;
|
||||
mTokenEnd = ++mSrcIdx;
|
||||
}
|
||||
else if (mSrc[mSrcIdx] == '+')
|
||||
{
|
||||
mToken = BfToken_AndPlus;
|
||||
mTokenEnd = ++mSrcIdx;
|
||||
}
|
||||
else if (mSrc[mSrcIdx] == '-')
|
||||
{
|
||||
mToken = BfToken_AndMinus;
|
||||
mTokenEnd = ++mSrcIdx;
|
||||
}
|
||||
else if (mSrc[mSrcIdx] == '*')
|
||||
{
|
||||
mToken = BfToken_AndStar;
|
||||
mTokenEnd = ++mSrcIdx;
|
||||
}
|
||||
else
|
||||
mToken = BfToken_Ampersand;
|
||||
mSyntaxToken = BfSyntaxToken_Token;
|
||||
|
|
|
@ -5975,13 +5975,13 @@ void DbgExprEvaluator::PerformBinaryOperation(ASTREF(BfExpression*)& leftExpress
|
|||
|
||||
// One pointer
|
||||
if ((!otherType->IsInteger()) ||
|
||||
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract) && (!isCompare)))
|
||||
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract) && (binaryOp != BfBinaryOp_OverflowAdd) && (binaryOp != BfBinaryOp_OverflowSubtract) && (!isCompare)))
|
||||
{
|
||||
Fail("Can only add or subtract integer values from pointers", rightExpression);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract))
|
||||
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract))
|
||||
{
|
||||
auto underlyingType = otherType->GetUnderlyingType();
|
||||
mResult.mType = resultType;
|
||||
|
@ -6262,6 +6262,7 @@ void DbgExprEvaluator::PerformBinaryOperation(DbgType* resultType, DbgTypedValue
|
|||
switch (binaryOp)
|
||||
{
|
||||
case BfBinaryOp_Add:
|
||||
case BfBinaryOp_OverflowAdd:
|
||||
if (resultType->mTypeCode == DbgType_Single)
|
||||
mResult.mSingle = convLeftValue.mSingle + convRightValue.mSingle;
|
||||
else if (resultType->mTypeCode == DbgType_Double)
|
||||
|
@ -6270,6 +6271,7 @@ void DbgExprEvaluator::PerformBinaryOperation(DbgType* resultType, DbgTypedValue
|
|||
mResult.mInt64 = convLeftValue.GetInt64() + convRightValue.GetInt64();
|
||||
break;
|
||||
case BfBinaryOp_Subtract:
|
||||
case BfBinaryOp_OverflowSubtract:
|
||||
if (resultType->mTypeCode == DbgType_Single)
|
||||
mResult.mSingle = convLeftValue.mSingle - convRightValue.mSingle;
|
||||
else if (resultType->mTypeCode == DbgType_Double)
|
||||
|
@ -6278,6 +6280,7 @@ void DbgExprEvaluator::PerformBinaryOperation(DbgType* resultType, DbgTypedValue
|
|||
mResult.mInt64 = convLeftValue.GetInt64() - convRightValue.GetInt64();
|
||||
break;
|
||||
case BfBinaryOp_Multiply:
|
||||
case BfBinaryOp_OverflowMultiply:
|
||||
if (resultType->mTypeCode == DbgType_Single)
|
||||
mResult.mSingle = convLeftValue.mSingle * convRightValue.mSingle;
|
||||
else if (resultType->mTypeCode == DbgType_Double)
|
||||
|
|
|
@ -198,6 +198,41 @@ namespace Tests
|
|||
}
|
||||
}
|
||||
|
||||
struct StructH
|
||||
{
|
||||
public static int operator+(StructH lhs, int rhs)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int operator+(int lhs, StructH rhs)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
[Commutable]
|
||||
public static int operator+(StructH lhs, float rhs)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public static int operator&+(StructH lhs, int rhs)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
public static int operator&+(int lhs, StructH rhs)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
[Commutable]
|
||||
public static int operator&+(StructH lhs, float rhs)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
struct StructOp<T, T2> where T : operator T + T2
|
||||
{
|
||||
public T DoIt(T val, T2 val2)
|
||||
|
@ -428,6 +463,20 @@ namespace Tests
|
|||
Test.Assert(10 + sf == 2);
|
||||
Test.Assert(sf + 1.0f == 3);
|
||||
Test.Assert(2.0f + sf == 3);
|
||||
Test.Assert(sf &+ 10 == 1);
|
||||
Test.Assert(10 &+ sf == 2);
|
||||
Test.Assert(sf &+ 1.0f == 3);
|
||||
Test.Assert(2.0f &+ sf == 3);
|
||||
|
||||
StructH sh = default;
|
||||
Test.Assert(sh + 10 == 1);
|
||||
Test.Assert(10 + sh == 2);
|
||||
Test.Assert(sh + 1.0f == 3);
|
||||
Test.Assert(2.0f + sh == 3);
|
||||
Test.Assert(sh &+ 10 == 4);
|
||||
Test.Assert(10 &+ sh == 5);
|
||||
Test.Assert(sh &+ 1.0f == 6);
|
||||
Test.Assert(2.0f &+ sh == 6);
|
||||
|
||||
StructG sg = .(100);
|
||||
StructG sg2 = .(200);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue