Implementation for SyntaxKinds: AddExpression, MultiplyExpression, SubtractExpression, DivideExpression, ModuloExpression, RightShiftExpression, LeftShiftExpression, BitwiseNotExpression, LogicalAndExpression, LogicalOrExpression, ExclusiveOrExpression, BitwiseAndExpression, BitwiseOrExpression, LogicalNotExpression, EqualsExpression, NotEqualsExpression, GreaterThanExpression, LessThanExpression, GreaterThanOrEqualExpression, LessThanOrEqualExpression.
PVOID Ptr;
};
+ // Keep in sync with BasicTypes enum in Evaluation.cs
+ enum class BasicTypes : int32_t
+ {
+ TypeBoolean = 1,
+ TypeByte,
+ TypeSByte,
+ TypeChar,
+ TypeDouble,
+ TypeSingle,
+ TypeInt32,
+ TypeUInt32,
+ TypeInt64,
+ TypeUInt64,
+ TypeInt16,
+ TypeUInt16,
+ TypeString
+ };
+
+ // Keep in sync with OperationType enum in Evaluation.cs
+ enum class OperationType : int32_t
+ {
+ AddExpression = 1,
+ SubtractExpression,
+ MultiplyExpression,
+ DivideExpression,
+ ModuloExpression,
+ RightShiftExpression,
+ LeftShiftExpression,
+ BitwiseNotExpression,
+ LogicalAndExpression,
+ LogicalOrExpression,
+ ExclusiveOrExpression,
+ BitwiseAndExpression,
+ BitwiseOrExpression,
+ LogicalNotExpression,
+ EqualsExpression,
+ NotEqualsExpression,
+ LessThanExpression,
+ GreaterThanExpression,
+ LessThanOrEqualExpression,
+ GreaterThanOrEqualExpression,
+ UnaryPlusExpression,
+ UnaryMinusExpression
+ };
+
void ReplaceAllSubstring(std::string &str, const std::string &from, const std::string &to)
{
size_t start = 0;
return S_OK;
}
- template<typename T1, typename T2>
- HRESULT NumericPromotionWithValue(ICorDebugValue *pInputValue, ICorDebugValue **ppResultValue, EvalData &ed)
- {
- HRESULT Status;
- ToRelease<ICorDebugGenericValue> pGenericValue;
- IfFailRet(pInputValue->QueryInterface(IID_ICorDebugGenericValue, (LPVOID*) &pGenericValue));
-
- T1 oldTypeValue = 0;
- IfFailRet(pGenericValue->GetValue((LPVOID) &oldTypeValue));
- T2 newTypeValue = oldTypeValue;
-
- static_assert(std::is_same<T2, int32_t>::value || std::is_same<T2, int64_t>::value, "only int32_t or int64_t allowed");
- CorElementType elemType = std::is_same<T2, int32_t>::value ? ELEMENT_TYPE_I4 : ELEMENT_TYPE_I8;
-
- return CreatePrimitiveValue(ed.pThread, ppResultValue, elemType, &newTypeValue);
- }
-
- HRESULT UnaryNumericPromotion(ICorDebugValue *pInputValue, ICorDebugValue **ppResultValue, EvalData &ed)
- {
- HRESULT Status;
- CorElementType elemType;
- IfFailRet(pInputValue->GetType(&elemType));
-
- // From ECMA-334:
- // Unary numeric promotions
- // Unary numeric promotion occurs for the operands of the predefined +, -, and ~unary operators.
- // Unary numeric promotion simply consists of converting operands of type sbyte, byte, short, ushort, or char to type int.
- // Additionally, for the unary - operator, unary numeric promotion converts operands of type uint to type long.
-
- switch (elemType)
- {
- case ELEMENT_TYPE_CHAR:
- return NumericPromotionWithValue<uint16_t, int32_t>(pInputValue, ppResultValue, ed);
-
- case ELEMENT_TYPE_I1:
- return NumericPromotionWithValue<int8_t, int32_t>(pInputValue, ppResultValue, ed);
-
- case ELEMENT_TYPE_U1:
- return NumericPromotionWithValue<uint8_t, int32_t>(pInputValue, ppResultValue, ed);
-
- case ELEMENT_TYPE_I2:
- return NumericPromotionWithValue<int16_t, int32_t>(pInputValue, ppResultValue, ed);
-
- case ELEMENT_TYPE_U2:
- return NumericPromotionWithValue<uint16_t, int32_t>(pInputValue, ppResultValue, ed);
-
- case ELEMENT_TYPE_U4:
- return NumericPromotionWithValue<uint32_t, int64_t>(pInputValue, ppResultValue, ed);
-
- default:
- return E_INVALIDARG;
- }
- }
-
- template<typename T>
- HRESULT InvertNumberValue(ICorDebugValue *pInputValue)
- {
- HRESULT Status;
- ToRelease<ICorDebugGenericValue> pGenericValue;
- IfFailRet(pInputValue->QueryInterface(IID_ICorDebugGenericValue, (LPVOID*) &pGenericValue));
-
- T value = 0;
- IfFailRet(pGenericValue->GetValue(&value));
- value = -value;
- return pGenericValue->SetValue(&value);
- }
-
- HRESULT InvertNumber(ICorDebugValue *pValue)
- {
- HRESULT Status;
- CorElementType elemType;
- IfFailRet(pValue->GetType(&elemType));
-
- switch (elemType)
- {
- case ELEMENT_TYPE_I1:
- return InvertNumberValue<int8_t>(pValue);
-
- case ELEMENT_TYPE_I2:
- return InvertNumberValue<int16_t>(pValue);
-
- case ELEMENT_TYPE_I4:
- return InvertNumberValue<int32_t>(pValue);
-
- case ELEMENT_TYPE_I8:
- return InvertNumberValue<int64_t>(pValue);
-
- case ELEMENT_TYPE_R4:
- return InvertNumberValue<float>(pValue);
-
- case ELEMENT_TYPE_R8:
- return InvertNumberValue<double>(pValue);
-
- default:
- return E_INVALIDARG;
- }
- }
-
HRESULT GetArgData(ICorDebugValue *pTypeValue, std::string &typeName, CorElementType &elemType)
{
HRESULT Status;
return S_OK;
};
- HRESULT CallUnaryOperator(const std::string opName, ICorDebugValue *pValue, ICorDebugValue **pResultValue, EvalData &ed)
+ HRESULT CallUnaryOperator(const std::string &opName, ICorDebugValue *pValue, ICorDebugValue **pResultValue, EvalData &ed)
{
HRESULT Status;
std::string typeName;
return ed.pEvalHelpers->EvalFunction(ed.pThread, iCorFunc, nullptr, 0, &pValue, 1, pResultValue, ed.evalFlags);
}
- HRESULT CallCastOperator(const std::string opName, ICorDebugValue *pValue, ICorDebugValue *pType1Value, ICorDebugValue *pType2Value,
- ICorDebugValue **pResultValue, EvalData &ed)
+ HRESULT CallCastOperator(const std::string &opName, ICorDebugValue *pValue, CorElementType elemRetType, const std::string &typeRetName,
+ ICorDebugValue *pTypeValue, ICorDebugValue **pResultValue, EvalData &ed)
{
HRESULT Status;
- std::string typeName1;
- CorElementType elemType1;
- IfFailRet(GetArgData(pType1Value, typeName1, elemType1));
- std::string typeName2;
- CorElementType elemType2;
- IfFailRet(GetArgData(pType2Value, typeName2, elemType2));
+ std::string typeName;
+ CorElementType elemType;
+ IfFailRet(GetArgData(pTypeValue, typeName, elemType));
ToRelease<ICorDebugFunction> iCorFunc;
ed.pEvaluator->WalkMethods(pValue, [&](
Evaluator::GetFunctionCallback getFunction)
{
if (!is_static || methodArgs.size() != 1 || opName != methodName ||
- elemType1 != methodRet.corType || typeName1 != methodRet.typeName ||
- elemType2 != methodArgs[0].corType || typeName2 != methodArgs[0].typeName)
+ elemRetType != methodRet.corType || typeRetName != methodRet.typeName ||
+ elemType != methodArgs[0].corType || typeName != methodArgs[0].typeName)
return S_OK;
IfFailRet(getFunction(&iCorFunc));
if (!iCorFunc)
return E_FAIL;
- return ed.pEvalHelpers->EvalFunction(ed.pThread, iCorFunc, nullptr, 0, &pType2Value, 1, pResultValue, ed.evalFlags);
+ return ed.pEvalHelpers->EvalFunction(ed.pThread, iCorFunc, nullptr, 0, &pTypeValue, 1, pResultValue, ed.evalFlags);
+ }
+
+ HRESULT CallCastOperator(const std::string &opName, ICorDebugValue *pValue, ICorDebugValue *pTypeRetValue, ICorDebugValue *pTypeValue,
+ ICorDebugValue **pResultValue, EvalData &ed)
+ {
+ HRESULT Status;
+ std::string typeRetName;
+ CorElementType elemRetType;
+ IfFailRet(GetArgData(pTypeRetValue, typeRetName, elemRetType));
+
+ return CallCastOperator(opName, pValue, elemRetType, typeRetName, pTypeValue, pResultValue, ed);
}
template<typename T1, typename T2>
return implicitCastLiteralMap;
}
- HRESULT GetRealValueWithType(ICorDebugValue *pValue, ICorDebugValue **ppResultValue, CorElementType &elemType)
+ HRESULT GetRealValueWithType(ICorDebugValue *pValue, ICorDebugValue **ppResultValue, CorElementType *pElemType = nullptr)
{
HRESULT Status;
// Dereference and unbox value, since we need real value.
ToRelease<ICorDebugValue> iCorRealValue;
IfFailRet(DereferenceAndUnboxValue(pValue, &iCorRealValue));
+ CorElementType elemType;
IfFailRet(iCorRealValue->GetType(&elemType));
// Note, in case of class (string is class), we must use reference instead.
if (elemType == ELEMENT_TYPE_STRING ||
elemType == ELEMENT_TYPE_CLASS)
{
pValue->AddRef();
- (*ppResultValue) = pValue;
+ *ppResultValue = pValue;
+ if (pElemType)
+ *pElemType = elemType;
}
else
{
- (*ppResultValue) = iCorRealValue.Detach();
+ *ppResultValue = iCorRealValue.Detach();
+ if (pElemType)
+ *pElemType = elemType;
}
return S_OK;
ToRelease<ICorDebugValue> iCorRealValue1;
CorElementType elemType1;
- IfFailRet(GetRealValueWithType(pSrcValue, &iCorRealValue1, elemType1));
+ IfFailRet(GetRealValueWithType(pSrcValue, &iCorRealValue1, &elemType1));
ToRelease<ICorDebugValue> iCorRealValue2;
CorElementType elemType2;
- IfFailRet(GetRealValueWithType(pDstValue, &iCorRealValue2, elemType2));
+ IfFailRet(GetRealValueWithType(pDstValue, &iCorRealValue2, &elemType2));
bool haveSameType = true;
if (elemType1 == elemType2)
return Status;
iCorRealValue1.Free();
- IfFailRet(GetRealValueWithType(iCorResultValue, &iCorRealValue1, elemType1));
+ IfFailRet(GetRealValueWithType(iCorResultValue, &iCorRealValue1, &elemType1));
haveSameType = true;
}
return E_INVALIDARG;
}
+ HRESULT GetOperandDataTypeByValue(ICorDebugValue *pValue, CorElementType elemType, PVOID &resultData, int32_t &resultType)
+ {
+ HRESULT Status;
+
+ if (elemType == ELEMENT_TYPE_STRING)
+ {
+ resultType = (int32_t)BasicTypes::TypeString;
+ ToRelease<ICorDebugValue> iCorValue;
+ BOOL isNull = FALSE;
+ IfFailRet(DereferenceAndUnboxValue(pValue, &iCorValue, &isNull));
+ resultData = 0;
+ if (!isNull)
+ {
+ std::string String;
+ IfFailRet(PrintStringValue(iCorValue, String));
+ resultData = Interop::AllocString(String);
+ }
+ return S_OK;
+ }
+
+ static std::unordered_map<CorElementType, BasicTypes> basicTypesMap
+ {
+ {ELEMENT_TYPE_BOOLEAN, BasicTypes::TypeBoolean},
+ {ELEMENT_TYPE_U1, BasicTypes::TypeByte},
+ {ELEMENT_TYPE_I1, BasicTypes::TypeSByte},
+ {ELEMENT_TYPE_CHAR, BasicTypes::TypeChar},
+ {ELEMENT_TYPE_R8, BasicTypes::TypeDouble},
+ {ELEMENT_TYPE_R4, BasicTypes::TypeSingle},
+ {ELEMENT_TYPE_I4, BasicTypes::TypeInt32},
+ {ELEMENT_TYPE_U4, BasicTypes::TypeUInt32},
+ {ELEMENT_TYPE_I8, BasicTypes::TypeInt64},
+ {ELEMENT_TYPE_U8, BasicTypes::TypeUInt64},
+ {ELEMENT_TYPE_I2, BasicTypes::TypeInt16},
+ {ELEMENT_TYPE_U2, BasicTypes::TypeUInt16}
+ };
+
+ auto findType = basicTypesMap.find(elemType);
+ if (findType == basicTypesMap.end())
+ return E_FAIL;
+ resultType = (int32_t)findType->second;
+
+ ToRelease<ICorDebugGenericValue> iCorGenValue;
+ IfFailRet(pValue->QueryInterface(IID_ICorDebugGenericValue, (LPVOID *) &iCorGenValue));
+ return iCorGenValue->GetValue(resultData);
+ }
+
+ HRESULT GetValueByOperandDataType(PVOID valueData, BasicTypes valueType, ICorDebugValue **ppValue, EvalData &ed)
+ {
+ if (valueType == BasicTypes::TypeString)
+ {
+ std::string String = to_utf8((WCHAR*)valueData);
+ return ed.pEvalHelpers->CreateString(ed.pThread, String, ppValue);
+ }
+
+ static std::unordered_map<BasicTypes, CorElementType> basicTypesMap
+ {
+ {BasicTypes::TypeBoolean, ELEMENT_TYPE_BOOLEAN},
+ {BasicTypes::TypeByte, ELEMENT_TYPE_U1},
+ {BasicTypes::TypeSByte, ELEMENT_TYPE_I1},
+ {BasicTypes::TypeChar, ELEMENT_TYPE_CHAR},
+ {BasicTypes::TypeDouble, ELEMENT_TYPE_R8},
+ {BasicTypes::TypeSingle, ELEMENT_TYPE_R4},
+ {BasicTypes::TypeInt32, ELEMENT_TYPE_I4},
+ {BasicTypes::TypeUInt32, ELEMENT_TYPE_U4},
+ {BasicTypes::TypeInt64, ELEMENT_TYPE_I8},
+ {BasicTypes::TypeUInt64, ELEMENT_TYPE_U8},
+ {BasicTypes::TypeInt16, ELEMENT_TYPE_I2},
+ {BasicTypes::TypeUInt16, ELEMENT_TYPE_U2}
+ };
+
+ auto findType = basicTypesMap.find(valueType);
+ if (findType == basicTypesMap.end())
+ return E_FAIL;
+
+ return CreatePrimitiveValue(ed.pThread, ppValue, findType->second, valueData);
+ }
+
+ HRESULT CallBinaryOperator(const std::string &opName, ICorDebugValue *pValue, ICorDebugValue *pType1Value, ICorDebugValue *pType2Value,
+ ICorDebugValue **pResultValue, EvalData &ed)
+ {
+ HRESULT Status;
+ std::string typeName1;
+ CorElementType elemType1;
+ IfFailRet(GetArgData(pType1Value, typeName1, elemType1));
+ std::string typeName2;
+ CorElementType elemType2;
+ IfFailRet(GetArgData(pType2Value, typeName2, elemType2));
+ // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading
+ // A unary operator has one input parameter. A binary operator has two input parameters. In each case,
+ // at least one parameter must have type T or T? where T is the type that contains the operator declaration.
+ std::string typeName;
+ CorElementType elemType;
+ IfFailRet(GetArgData(pValue, typeName, elemType));
+ if ((elemType != elemType1 || typeName != typeName1) && (elemType != elemType2 || typeName != typeName2))
+ return E_INVALIDARG;
+
+ ToRelease<ICorDebugValue> iCorTypeValue;
+ auto CallOperator = [&](std::function<HRESULT(std::vector<Evaluator::ArgElementType>&)> cb)
+ {
+ ToRelease<ICorDebugFunction> iCorFunc;
+ ed.pEvaluator->WalkMethods(pValue, [&](
+ bool is_static,
+ const std::string &methodName,
+ Evaluator::ReturnElementType&,
+ std::vector<Evaluator::ArgElementType> &methodArgs,
+ Evaluator::GetFunctionCallback getFunction)
+ {
+ if (!is_static || methodArgs.size() != 2 || opName != methodName ||
+ FAILED(cb(methodArgs)))
+ return S_OK; // Return with success to continue walk.
+
+ IfFailRet(getFunction(&iCorFunc));
+
+ return E_ABORT; // Fast exit from cycle, since we already found iCorFunc.
+ });
+ if (!iCorFunc)
+ return E_INVALIDARG;
+
+ ICorDebugValue *ppArgsValue[] = {pType1Value, pType2Value};
+ return ed.pEvalHelpers->EvalFunction(ed.pThread, iCorFunc, nullptr, 0, ppArgsValue, 2, pResultValue, ed.evalFlags);
+ };
+
+ // Try execute operator for exact same type as provided values.
+ if (SUCCEEDED(CallOperator([&](std::vector<Evaluator::ArgElementType> &methodArgs)
+ {
+ return elemType1 != methodArgs[0].corType || typeName1 != methodArgs[0].typeName ||
+ elemType2 != methodArgs[1].corType || typeName2 != methodArgs[1].typeName
+ ? E_FAIL : S_OK;
+ })))
+ return S_OK;
+
+ // Try execute operator with implicit cast for second value.
+ // Make sure we don't cast "base" struct/class value for this case, since "... at least one parameter must have type T...".
+ if (elemType == elemType1 && typeName == typeName1 &&
+ SUCCEEDED(CallOperator([&](std::vector<Evaluator::ArgElementType> &methodArgs)
+ {
+ if (elemType1 != methodArgs[0].corType || typeName1 != methodArgs[0].typeName)
+ return E_FAIL;
+
+ ToRelease<ICorDebugValue> iCorResultValue;
+ if (FAILED(CallCastOperator("op_Implicit", pType1Value, methodArgs[1].corType, methodArgs[1].typeName, pType2Value, &iCorResultValue, ed)) &&
+ FAILED(CallCastOperator("op_Implicit", pType2Value, methodArgs[1].corType, methodArgs[1].typeName, pType2Value, &iCorResultValue, ed)))
+ return E_FAIL;
+
+ IfFailRet(GetRealValueWithType(iCorResultValue, &iCorTypeValue));
+ pType2Value = iCorTypeValue.GetPtr();
+
+ return S_OK;
+ })))
+ return S_OK;
+
+ // Try execute operator with implicit cast for first value.
+ return CallOperator([&](std::vector<Evaluator::ArgElementType> &methodArgs)
+ {
+ if (elemType2 != methodArgs[1].corType || typeName2 != methodArgs[1].typeName)
+ return E_FAIL;
+
+ ToRelease<ICorDebugValue> iCorResultValue;
+ if (FAILED(CallCastOperator("op_Implicit", pType1Value, methodArgs[0].corType, methodArgs[0].typeName, pType1Value, &iCorResultValue, ed)) &&
+ FAILED(CallCastOperator("op_Implicit", pType2Value, methodArgs[0].corType, methodArgs[0].typeName, pType1Value, &iCorResultValue, ed)))
+ return E_FAIL;
+
+ iCorTypeValue.Free();
+ IfFailRet(GetRealValueWithType(iCorResultValue, &iCorTypeValue));
+ pType1Value = iCorTypeValue.GetPtr();
+
+ return S_OK;
+ });
+ }
+
+ bool SupportedByCalculationDelegateType(CorElementType elemType)
+ {
+ static std::unordered_set<CorElementType> supportedElementTypes{
+ ELEMENT_TYPE_BOOLEAN,
+ ELEMENT_TYPE_U1,
+ ELEMENT_TYPE_I1,
+ ELEMENT_TYPE_CHAR,
+ ELEMENT_TYPE_R8,
+ ELEMENT_TYPE_R4,
+ ELEMENT_TYPE_I4,
+ ELEMENT_TYPE_U4,
+ ELEMENT_TYPE_I8,
+ ELEMENT_TYPE_U8,
+ ELEMENT_TYPE_I2,
+ ELEMENT_TYPE_U2,
+ ELEMENT_TYPE_STRING
+ };
+
+ return supportedElementTypes.find(elemType) != supportedElementTypes.end();
+ }
+
+ HRESULT CalculateTwoOparands(OperationType opType, std::list<EvalStackEntry> &evalStack, std::string &output, EvalData &ed)
+ {
+ HRESULT Status;
+ ToRelease<ICorDebugValue> iCorValue2;
+ IfFailRet(GetFrontStackEntryValue(&iCorValue2, evalStack, ed, output));
+ evalStack.pop_front();
+ ToRelease<ICorDebugValue> iCorRealValue2;
+ CorElementType elemType2;
+ IfFailRet(GetRealValueWithType(iCorValue2, &iCorRealValue2, &elemType2));
+
+ ToRelease<ICorDebugValue> iCorValue1;
+ IfFailRet(GetFrontStackEntryValue(&iCorValue1, evalStack, ed, output));
+ evalStack.front().ResetEntry();
+ ToRelease<ICorDebugValue> iCorRealValue1;
+ CorElementType elemType1;
+ IfFailRet(GetRealValueWithType(iCorValue1, &iCorRealValue1, &elemType1));
+
+ if (elemType1 == ELEMENT_TYPE_VALUETYPE || elemType2 == ELEMENT_TYPE_VALUETYPE ||
+ elemType1 == ELEMENT_TYPE_CLASS || elemType2 == ELEMENT_TYPE_CLASS)
+ {
+ static std::unordered_map<OperationType, std::pair<std::string,std::string>> opMap{
+ {OperationType::AddExpression, {"op_Addition", "+"}},
+ {OperationType::SubtractExpression, {"op_Subtraction", "-"}},
+ {OperationType::MultiplyExpression, {"op_Multiply", "*"}},
+ {OperationType::DivideExpression, {"op_Division", "/"}},
+ {OperationType::ModuloExpression, {"op_Modulus", "%"}},
+ {OperationType::RightShiftExpression, {"op_RightShift", ">>"}},
+ {OperationType::LeftShiftExpression, {"op_LeftShift", "<<"}},
+ {OperationType::LogicalAndExpression, {"op_LogicalAnd", "&&"}},
+ {OperationType::LogicalOrExpression, {"op_LogicalOr", "||"}},
+ {OperationType::ExclusiveOrExpression, {"op_ExclusiveOr", "^"}},
+ {OperationType::BitwiseAndExpression, {"op_BitwiseAnd", "&"}},
+ {OperationType::BitwiseOrExpression, {"op_BitwiseOr", "|"}},
+ {OperationType::EqualsExpression, {"op_Equality", "=="}},
+ {OperationType::NotEqualsExpression, {"op_Inequality", "!="}},
+ {OperationType::LessThanExpression, {"op_LessThan", "<"}},
+ {OperationType::GreaterThanExpression, {"op_GreaterThan", ">"}},
+ {OperationType::LessThanOrEqualExpression, {"op_LessThanOrEqual", "<="}},
+ {OperationType::GreaterThanOrEqualExpression, {"op_GreaterThanOrEqual", ">="}}
+ };
+
+ auto findOpName = opMap.find(opType);
+ if (findOpName == opMap.end())
+ return E_FAIL;
+
+ if (((elemType1 == ELEMENT_TYPE_VALUETYPE || elemType1 == ELEMENT_TYPE_CLASS) &&
+ SUCCEEDED(CallBinaryOperator(findOpName->second.first, iCorRealValue1, iCorRealValue1, iCorRealValue2, &evalStack.front().iCorValue, ed))) ||
+ ((elemType2 == ELEMENT_TYPE_VALUETYPE || elemType2 == ELEMENT_TYPE_CLASS) &&
+ SUCCEEDED(CallBinaryOperator(findOpName->second.first, iCorRealValue2, iCorRealValue1, iCorRealValue2, &evalStack.front().iCorValue, ed))))
+ return S_OK;
+
+ std::string typeRetName;
+ CorElementType elemRetType;
+ ToRelease<ICorDebugValue> iCorResultValue;
+ // Try to implicitly cast struct/class object into build-in type supported by CalculationDelegate().
+ if (SupportedByCalculationDelegateType(elemType2) && // First is ELEMENT_TYPE_VALUETYPE or ELEMENT_TYPE_CLASS
+ SUCCEEDED(GetArgData(iCorRealValue2, typeRetName, elemRetType)) &&
+ SUCCEEDED(CallCastOperator("op_Implicit", iCorRealValue1, elemRetType, typeRetName, iCorRealValue1, &iCorResultValue, ed)))
+ {
+ iCorRealValue1.Free();
+ IfFailRet(GetRealValueWithType(iCorResultValue, &iCorRealValue1, &elemType1));
+ // goto CalculationDelegate() related routine (see code below this 'if' statement scope)
+ }
+ else if (SupportedByCalculationDelegateType(elemType1) && // Second is ELEMENT_TYPE_VALUETYPE or ELEMENT_TYPE_CLASS
+ SUCCEEDED(GetArgData(iCorRealValue1, typeRetName, elemRetType)) &&
+ SUCCEEDED(CallCastOperator("op_Implicit", iCorRealValue2, elemRetType, typeRetName, iCorRealValue2, &iCorResultValue, ed)))
+ {
+ iCorRealValue2.Free();
+ IfFailRet(GetRealValueWithType(iCorResultValue, &iCorRealValue2, &elemType2));
+ // goto CalculationDelegate() related routine (see code below this 'if' statement scope)
+ }
+ else
+ {
+ std::string typeName1;
+ IfFailRet(TypePrinter::GetTypeOfValue(iCorRealValue1, typeName1));
+ std::string typeName2;
+ IfFailRet(TypePrinter::GetTypeOfValue(iCorRealValue2, typeName2));
+ output = "error CS0019: Operator '" + findOpName->second.second + "' cannot be applied to operands of type '" + typeName1 + "' and '" + typeName2 + "'";
+ return E_INVALIDARG;
+ }
+ }
+ else if (!SupportedByCalculationDelegateType(elemType1) || !SupportedByCalculationDelegateType(elemType2))
+ return E_INVALIDARG;
+
+ int64_t valueDataHolder1 = 0;
+ PVOID valueData1 = &valueDataHolder1;
+ int32_t valueType1 = 0;
+ int64_t valueDataHolder2 = 0;
+ PVOID valueData2 = &valueDataHolder2;
+ int32_t valueType2 = 0;
+ PVOID resultData = NULL;
+ int32_t resultType = 0;
+ if (SUCCEEDED(Status = GetOperandDataTypeByValue(iCorRealValue1, elemType1, valueData1, valueType1)) &&
+ SUCCEEDED(Status = GetOperandDataTypeByValue(iCorRealValue2, elemType2, valueData2, valueType2)) &&
+ SUCCEEDED(Status = Interop::CalculationDelegate(valueData1, valueType1, valueData2, valueType2, (int32_t)opType, resultType, &resultData, output)))
+ {
+ Status = GetValueByOperandDataType(resultData, (BasicTypes)resultType, &evalStack.front().iCorValue, ed);
+ if (resultType == (int32_t)BasicTypes::TypeString)
+ Interop::SysFreeString((BSTR)resultData);
+ else
+ Interop::CoTaskMemFree(resultData);
+ }
+
+ if (valueType1 == (int32_t)BasicTypes::TypeString && valueData1)
+ Interop::SysFreeString((BSTR)valueData1);
+
+ if (valueType2 == (int32_t)BasicTypes::TypeString && valueData2)
+ Interop::SysFreeString((BSTR)valueData2);
+
+ return Status;
+ }
+
+ HRESULT CalculateOneOparand(OperationType opType, std::list<EvalStackEntry> &evalStack, std::string &output, EvalData &ed)
+ {
+ HRESULT Status;
+ ToRelease<ICorDebugValue> iCorValue;
+ IfFailRet(GetFrontStackEntryValue(&iCorValue, evalStack, ed, output));
+ evalStack.front().ResetEntry(true); // Don't reset literal status.
+ ToRelease<ICorDebugValue> iCorRealValue;
+ CorElementType elemType;
+ IfFailRet(GetRealValueWithType(iCorValue, &iCorRealValue, &elemType));
+
+ if (elemType == ELEMENT_TYPE_VALUETYPE || elemType == ELEMENT_TYPE_CLASS)
+ {
+ static std::unordered_map<OperationType, std::pair<std::string,std::string>> opMap{
+ {OperationType::LogicalNotExpression, {"op_LogicalNot", "!"}},
+ {OperationType::BitwiseNotExpression, {"op_OnesComplement", "~"}},
+ {OperationType::UnaryPlusExpression, {"op_UnaryPlus", "+"}},
+ {OperationType::UnaryMinusExpression, {"op_UnaryNegation", "-"}}
+ };
+
+ auto findOpName = opMap.find(opType);
+ if (findOpName == opMap.end())
+ return E_FAIL;
+
+ if (SUCCEEDED(CallUnaryOperator(findOpName->second.first, iCorRealValue, &evalStack.front().iCorValue, ed)))
+ return S_OK;
+ else
+ {
+ std::string typeName;
+ IfFailRet(TypePrinter::GetTypeOfValue(iCorRealValue, typeName));
+ output = "error CS0023: Operator '" + findOpName->second.second + "' cannot be applied to operand of type '" + typeName + "'";
+ return E_INVALIDARG;
+ }
+ }
+ else if (!SupportedByCalculationDelegateType(elemType))
+ return E_INVALIDARG;
+
+ int64_t valueDataHolder1 = 0;
+ PVOID valueData1 = &valueDataHolder1;
+ int32_t valueType1 = 0;
+ // Note, we need fake second operand for delegate.
+ int64_t fakeValueData2 = 0;
+ PVOID resultData = NULL;
+ int32_t resultType = 0;
+ if (SUCCEEDED(Status = GetOperandDataTypeByValue(iCorRealValue, elemType, valueData1, valueType1)) &&
+ SUCCEEDED(Status = Interop::CalculationDelegate(valueData1, valueType1, &fakeValueData2, (int32_t)BasicTypes::TypeInt64, (int32_t)opType, resultType, &resultData, output)))
+ {
+ Status = GetValueByOperandDataType(resultData, (BasicTypes)resultType, &evalStack.front().iCorValue, ed);
+ if (resultType == (int32_t)BasicTypes::TypeString)
+ Interop::SysFreeString((BSTR)resultData);
+ else
+ Interop::CoTaskMemFree(resultData);
+ }
+
+ if (valueType1 == (int32_t)BasicTypes::TypeString && valueData1)
+ Interop::SysFreeString((BSTR)valueData1);
+
+ return Status;
+ }
+
HRESULT IdentifierName(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
HRESULT AddExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::AddExpression, evalStack, output, ed);
}
HRESULT MultiplyExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::MultiplyExpression, evalStack, output, ed);
}
HRESULT SubtractExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::SubtractExpression, evalStack, output, ed);
}
HRESULT DivideExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::DivideExpression, evalStack, output, ed);
}
HRESULT ModuloExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::ModuloExpression, evalStack, output, ed);
}
HRESULT LeftShiftExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::LeftShiftExpression, evalStack, output, ed);
}
HRESULT RightShiftExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::RightShiftExpression, evalStack, output, ed);
}
HRESULT BitwiseAndExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::BitwiseAndExpression, evalStack, output, ed);
}
HRESULT BitwiseOrExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::BitwiseOrExpression, evalStack, output, ed);
}
HRESULT ExclusiveOrExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::ExclusiveOrExpression, evalStack, output, ed);
}
HRESULT LogicalAndExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::LogicalAndExpression, evalStack, output, ed);
}
HRESULT LogicalOrExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::LogicalOrExpression, evalStack, output, ed);
}
HRESULT EqualsExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::EqualsExpression, evalStack, output, ed);
}
HRESULT NotEqualsExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::NotEqualsExpression, evalStack, output, ed);
}
HRESULT GreaterThanExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::GreaterThanExpression, evalStack, output, ed);
}
HRESULT LessThanExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::LessThanExpression, evalStack, output, ed);
}
HRESULT GreaterThanOrEqualExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::GreaterThanOrEqualExpression, evalStack, output, ed);
}
HRESULT LessThanOrEqualExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateTwoOparands(OperationType::LessThanOrEqualExpression, evalStack, output, ed);
}
HRESULT IsExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
HRESULT UnaryPlusExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- HRESULT Status;
- ToRelease<ICorDebugValue> iCorRefValue;
- IfFailRet(GetFrontStackEntryValue(&iCorRefValue, evalStack, ed, output));
- evalStack.front().ResetEntry(true);
-
- ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(DereferenceAndUnboxValue(iCorRefValue, &iCorValue, nullptr));
- CorElementType elemType;
- IfFailRet(iCorValue->GetType(&elemType));
-
- switch (elemType)
- {
- case ELEMENT_TYPE_CHAR:
- case ELEMENT_TYPE_I1:
- case ELEMENT_TYPE_U1:
- case ELEMENT_TYPE_I2:
- case ELEMENT_TYPE_U2:
- return UnaryNumericPromotion(iCorValue, &evalStack.front().iCorValue, ed);
-
- case ELEMENT_TYPE_I4:
- case ELEMENT_TYPE_U4:
- case ELEMENT_TYPE_I8:
- case ELEMENT_TYPE_U8:
- case ELEMENT_TYPE_R4:
- case ELEMENT_TYPE_R8:
- evalStack.front().iCorValue = iCorValue.Detach();
- return S_OK;
-
- case ELEMENT_TYPE_VALUETYPE:
- case ELEMENT_TYPE_CLASS:
- if (SUCCEEDED(CallUnaryOperator("op_UnaryPlus", iCorValue, &evalStack.front().iCorValue, ed)))
- return S_OK;
- else
- {
- std::string typeName;
- IfFailRet(TypePrinter::NameForTypeByValue(iCorValue, typeName));
- output = "error CS0023: Operator '+' cannot be applied to operand of type " + typeName;
- return E_INVALIDARG;
- }
-
- default:
- return E_INVALIDARG;
- }
+ return CalculateOneOparand(OperationType::UnaryPlusExpression, evalStack, output, ed);
}
HRESULT UnaryMinusExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- HRESULT Status;
- ToRelease<ICorDebugValue> iCorRefValue;
- IfFailRet(GetFrontStackEntryValue(&iCorRefValue, evalStack, ed, output));
- evalStack.front().ResetEntry(true);
-
- ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(DereferenceAndUnboxValue(iCorRefValue, &iCorValue, nullptr));
- CorElementType elemType;
- IfFailRet(iCorValue->GetType(&elemType));
-
- switch (elemType)
- {
- case ELEMENT_TYPE_U8:
- output = "error CS0023: Operator '-' cannot be applied to operand of type 'ulong'";
- return E_INVALIDARG;
-
- case ELEMENT_TYPE_CHAR:
- case ELEMENT_TYPE_I1:
- case ELEMENT_TYPE_U1:
- case ELEMENT_TYPE_I2:
- case ELEMENT_TYPE_U2:
- case ELEMENT_TYPE_U4:
- IfFailRet(UnaryNumericPromotion(iCorValue, &evalStack.front().iCorValue, ed));
- return InvertNumber(evalStack.front().iCorValue);
-
- case ELEMENT_TYPE_I4:
- case ELEMENT_TYPE_I8:
- case ELEMENT_TYPE_R4:
- case ELEMENT_TYPE_R8:
- evalStack.front().iCorValue = iCorValue.Detach();
- return InvertNumber(evalStack.front().iCorValue);
-
- case ELEMENT_TYPE_VALUETYPE:
- case ELEMENT_TYPE_CLASS:
- if (SUCCEEDED(CallUnaryOperator("op_UnaryNegation", iCorValue, &evalStack.front().iCorValue, ed)))
- return S_OK;
- else
- {
- std::string typeName;
- IfFailRet(TypePrinter::NameForTypeByValue(iCorValue, typeName));
- output = "error CS0023: Operator '-' cannot be applied to operand of type " + typeName;
- return E_INVALIDARG;
- }
-
- default:
- return E_INVALIDARG;
- }
+ return CalculateOneOparand(OperationType::UnaryMinusExpression, evalStack, output, ed);
}
HRESULT LogicalNotExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateOneOparand(OperationType::LogicalNotExpression, evalStack, output, ed);
}
HRESULT BitwiseNotExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatF*)pArguments)->Flags;
- return E_NOTIMPL;
+ return CalculateOneOparand(OperationType::BitwiseNotExpression, evalStack, output, ed);
}
HRESULT TrueLiteralExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
if (FAILED(Status = GetFrontStackEntryValue(&iCorValue, m_evalStack, m_evalData, output)))
break;
- Status = ImplicitCast(iCorValue, (*ppResultValue), m_evalStack.front().literal, m_evalData);
+ Status = ImplicitCast(iCorValue, *ppResultValue, m_evalStack.front().literal, m_evalData);
}
while (0);
return S_OK;
}
-static HRESULT PrintStringValue(ICorDebugValue * pValue, std::string &output)
+HRESULT PrintStringValue(ICorDebugValue * pValue, std::string &output)
{
HRESULT Status;
{
HRESULT PrintValue(ICorDebugValue *pInputValue, std::string &output, bool escape = true);
+HRESULT PrintStringValue(ICorDebugValue * pValue, std::string &output);
HRESULT DereferenceAndUnboxValue(ICorDebugValue * pValue, ICorDebugValue** ppOutputValue, BOOL * pIsNull = nullptr);
} // namespace netcoredbg
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
-using Microsoft.CodeAnalysis.CSharp.Scripting;
-using Microsoft.CodeAnalysis.Scripting;
-using Microsoft.CodeAnalysis;
-using System.Reflection;
-using System.Dynamic;
-using Microsoft.CodeAnalysis.CSharp;
-using System.Text;
namespace NetCoreDbg
{
//BasicTypes enum must be sync with enum from native part
internal enum BasicTypes
{
- TypeCorValue = -1,
- TypeObject = 0,
- TypeBoolean,
+ TypeBoolean = 1,
TypeByte,
TypeSByte,
TypeChar,
TypeUInt64,
TypeInt16,
TypeUInt16,
- TypeIntPtr,
- TypeUIntPtr,
- TypeDecimal,
TypeString,
};
//OperationType enum must be sync with enum from native part
internal enum OperationType
{
- Addition = 1,
- Subtraction,
- Multiplication,
- Division,
- Remainder,
- BitwiseRightShift,
- BitwiseLeftShift,
- BitwiseComplement,
- LogicalAnd,
- LogicalOR,
- LogicalXOR,
- ConditionalLogicalAnd,
- ConditionalLogicalOR,
- LogicalNegation,
- Equality,
- Inequality,
- LessThan,
- GreaterThan,
- LessThanOrEqual,
- GreaterThanOrEqual
+ AddExpression = 1,
+ SubtractExpression,
+ MultiplyExpression,
+ DivideExpression,
+ ModuloExpression,
+ RightShiftExpression,
+ LeftShiftExpression,
+ BitwiseNotExpression,
+ LogicalAndExpression,
+ LogicalOrExpression,
+ ExclusiveOrExpression,
+ BitwiseAndExpression,
+ BitwiseOrExpression,
+ LogicalNotExpression,
+ EqualsExpression,
+ NotEqualsExpression,
+ LessThanExpression,
+ GreaterThanExpression,
+ LessThanOrEqualExpression,
+ GreaterThanOrEqualExpression,
+ UnaryPlusExpression,
+ UnaryMinusExpression
};
internal static Dictionary<OperationType, Func<object, object, object>> operationTypesMap = new Dictionary<OperationType, Func<object, object, object>>
{
- { OperationType.Addition, (object firstOp, object secondOp) => { return Addition(firstOp, secondOp); }},
- { OperationType.Division, (object firstOp, object secondOp) => { return Division(firstOp, secondOp); }},
- { OperationType.Multiplication, (object firstOp, object secondOp) => { return Multiplication(firstOp, secondOp); }},
- { OperationType.Remainder, (object firstOp, object secondOp) => { return Remainder(firstOp, secondOp); }},
- { OperationType.Subtraction, (object firstOp, object secondOp) => { return Subtraction(firstOp, secondOp); }},
- { OperationType.BitwiseRightShift, (object firstOp, object secondOp) => { return BitwiseRightShift(firstOp, secondOp); }},
- { OperationType.BitwiseLeftShift, (object firstOp, object secondOp) => { return BitwiseLeftShift(firstOp, secondOp); }},
- { OperationType.BitwiseComplement, (object firstOp, object secondOp) => { return BitwiseComplement(firstOp); }},
- { OperationType.LogicalAnd, (object firstOp, object secondOp) => { return LogicalAnd(firstOp, secondOp); }},
- { OperationType.LogicalOR, (object firstOp, object secondOp) => { return LogicalOR(firstOp, secondOp); }},
- { OperationType.LogicalXOR, (object firstOp, object secondOp) => { return LogicalXOR(firstOp, secondOp); }},
- { OperationType.ConditionalLogicalAnd, (object firstOp, object secondOp) => { return ConditionalLogicalAnd(firstOp, secondOp); }},
- { OperationType.ConditionalLogicalOR, (object firstOp, object secondOp) => { return ConditionalLogicalOR(firstOp, secondOp); }},
- { OperationType.LogicalNegation, (object firstOp, object secondOp) => { return LogicalNegation(firstOp); }},
- { OperationType.Equality, (object firstOp, object secondOp) => { return Equality(firstOp, secondOp); }},
- { OperationType.Inequality, (object firstOp, object secondOp) => { return Inequality(firstOp, secondOp); }},
- { OperationType.LessThan, (object firstOp, object secondOp) => { return LessThan(firstOp, secondOp); }},
- { OperationType.GreaterThan, (object firstOp, object secondOp) => { return GreaterThan(firstOp, secondOp); }},
- { OperationType.LessThanOrEqual, (object firstOp, object secondOp) => { return LessThanOrEqual(firstOp, secondOp); }},
- { OperationType.GreaterThanOrEqual, (object firstOp, object secondOp) => { return GreaterThanOrEqual(firstOp, secondOp); }}
+ { OperationType.AddExpression, (object firstOp, object secondOp) => { return AddExpression(firstOp, secondOp); }},
+ { OperationType.DivideExpression, (object firstOp, object secondOp) => { return DivideExpression(firstOp, secondOp); }},
+ { OperationType.MultiplyExpression, (object firstOp, object secondOp) => { return MultiplyExpression(firstOp, secondOp); }},
+ { OperationType.ModuloExpression, (object firstOp, object secondOp) => { return ModuloExpression(firstOp, secondOp); }},
+ { OperationType.SubtractExpression, (object firstOp, object secondOp) => { return SubtractExpression(firstOp, secondOp); }},
+ { OperationType.RightShiftExpression, (object firstOp, object secondOp) => { return RightShiftExpression(firstOp, secondOp); }},
+ { OperationType.LeftShiftExpression, (object firstOp, object secondOp) => { return LeftShiftExpression(firstOp, secondOp); }},
+ { OperationType.BitwiseNotExpression, (object firstOp, object secondOp) => { return BitwiseNotExpression(firstOp); }},
+ { OperationType.LogicalAndExpression, (object firstOp, object secondOp) => { return LogicalAndExpression(firstOp, secondOp); }},
+ { OperationType.LogicalOrExpression, (object firstOp, object secondOp) => { return LogicalOrExpression(firstOp, secondOp); }},
+ { OperationType.ExclusiveOrExpression, (object firstOp, object secondOp) => { return ExclusiveOrExpression(firstOp, secondOp); }},
+ { OperationType.BitwiseAndExpression, (object firstOp, object secondOp) => { return BitwiseAndExpression(firstOp, secondOp); }},
+ { OperationType.BitwiseOrExpression, (object firstOp, object secondOp) => { return BitwiseOrExpression(firstOp, secondOp); }},
+ { OperationType.LogicalNotExpression, (object firstOp, object secondOp) => { return LogicalNotExpression(firstOp); }},
+ { OperationType.EqualsExpression, (object firstOp, object secondOp) => { return EqualsExpression(firstOp, secondOp); }},
+ { OperationType.NotEqualsExpression, (object firstOp, object secondOp) => { return NotEqualsExpression(firstOp, secondOp); }},
+ { OperationType.LessThanExpression, (object firstOp, object secondOp) => { return LessThanExpression(firstOp, secondOp); }},
+ { OperationType.GreaterThanExpression, (object firstOp, object secondOp) => { return GreaterThanExpression(firstOp, secondOp); }},
+ { OperationType.LessThanOrEqualExpression, (object firstOp, object secondOp) => { return LessThanOrEqualExpression(firstOp, secondOp); }},
+ { OperationType.GreaterThanOrEqualExpression, (object firstOp, object secondOp) => { return GreaterThanOrEqualExpression(firstOp, secondOp); }},
+ { OperationType.UnaryPlusExpression, (object firstOp, object secondOp) => { return UnaryPlusExpression(firstOp); }},
+ { OperationType.UnaryMinusExpression, (object firstOp, object secondOp) => { return UnaryMinusExpression(firstOp); }}
};
internal static Dictionary<BasicTypes, Func<byte[], object>> typesMap = new Dictionary<BasicTypes, Func<byte[], object>>
{ typeof(Single), BasicTypes.TypeSingle },
{ typeof(UInt16), BasicTypes.TypeUInt16 },
{ typeof(UInt32), BasicTypes.TypeUInt32 },
- { typeof(UInt64), BasicTypes.TypeUInt64 }
+ { typeof(UInt64), BasicTypes.TypeUInt64 },
+ { typeof(String), BasicTypes.TypeString }
};
- /// <summary>
- /// Convert Single(float) type to Int32
- /// </summary>
- /// <param name="value">float value</param>
- /// <returns></returns>
- private static unsafe int floatToInt32Bits(float value)
- {
- return *((int*)&value);
- }
-
/// <summary>
/// Converts value ​​to a IntPtr to IntPtr
/// </summary>
/// <returns></returns>
private static IntPtr valueToPtr(object value)
{
- IntPtr result = IntPtr.Zero;
- IntPtr ptr = IntPtr.Zero;
- Int64 newValue = 0;
if (value.GetType() == typeof(string))
+ return Marshal.StringToBSTR(value as string);
+
+ dynamic dynValue = value;
+ byte[] bytes = BitConverter.GetBytes(dynValue);
+ IntPtr ptr = Marshal.AllocCoTaskMem(bytes.Length);
+ for (int i = 0; i < bytes.Length; i++)
{
- result = Marshal.AllocHGlobal(Marshal.SizeOf(newValue));
- ptr = Marshal.StringToBSTR(value as string);
- }
- else
- {
- if (value.GetType() == typeof(float) || value.GetType() == typeof(double))
- newValue = value.GetType() == typeof(float) ? Convert.ToInt64(floatToInt32Bits(Convert.ToSingle(value))) : BitConverter.DoubleToInt64Bits(Convert.ToDouble(value));
- else
- newValue = Convert.ToInt64(value);
- var size = Marshal.SizeOf(newValue);
- result = Marshal.AllocHGlobal(Marshal.SizeOf(newValue));
- ptr = Marshal.AllocHGlobal(size);
- Marshal.WriteInt64(ptr, newValue);
+ Marshal.WriteByte(ptr, i, bytes[i]);
}
- Marshal.WriteIntPtr(result, ptr);
- return result;
+ return ptr;
}
private static object ptrToValue(IntPtr ptr, int type)
{
if ((BasicTypes)type == BasicTypes.TypeString)
- return Marshal.PtrToStringAuto(ptr);
+ {
+ if (ptr == IntPtr.Zero)
+ return String.Empty;
+ else
+ return Marshal.PtrToStringBSTR(ptr);
+ }
var intValue = Marshal.ReadInt64(ptr);
var bytesArray = BitConverter.GetBytes(intValue);
return typesMap[(BasicTypes)type](bytesArray);
}
- internal static RetCode CalculationDelegate(IntPtr firstOpPtr, int firstType, IntPtr secondOpPtr, int secondType, int operation, int resultType, out IntPtr result, out IntPtr errorText)
+ internal static RetCode CalculationDelegate(IntPtr firstOpPtr, int firstType, IntPtr secondOpPtr, int secondType, int operation, out int resultType, out IntPtr result, out IntPtr errorText)
{
+ resultType = 0;
result = IntPtr.Zero;
errorText = IntPtr.Zero;
resultType = (int)basicTypesMap[operationResult.GetType()];
result = valueToPtr(operationResult);
}
- catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
- {
- errorText = Marshal.StringToBSTR(ex.ToString());
- return RetCode.Exception;
- }
catch (System.Exception ex)
{
- errorText = Marshal.StringToBSTR(ex.ToString());
+ errorText = Marshal.StringToBSTR("error: " + ex.Message);
return RetCode.Exception;
}
return RetCode.OK;
}
- private static object Addition(dynamic first, dynamic second)
+ private static object AddExpression(dynamic first, dynamic second)
{
return first + second;
}
- private static object Subtraction(dynamic first, dynamic second)
+ private static object SubtractExpression(dynamic first, dynamic second)
{
return first - second;
}
- private static object Multiplication(dynamic first, dynamic second)
+ private static object MultiplyExpression(dynamic first, dynamic second)
{
return first * second;
}
- private static object Division(dynamic first, dynamic second)
+ private static object DivideExpression(dynamic first, dynamic second)
{
return first / second;
}
- private static object Remainder(dynamic first, dynamic second)
+ private static object ModuloExpression(dynamic first, dynamic second)
{
return first % second;
}
- private static object BitwiseRightShift(dynamic first, dynamic second)
+ private static object RightShiftExpression(dynamic first, dynamic second)
{
return first >> second;
}
- private static object BitwiseLeftShift(dynamic first, dynamic second)
+ private static object LeftShiftExpression(dynamic first, dynamic second)
{
return first << second;
}
- private static object BitwiseComplement(dynamic first)
+ private static object BitwiseNotExpression(dynamic first)
{
return ~first;
}
- private static object LogicalAnd(dynamic first, dynamic second)
+ private static object ExclusiveOrExpression(dynamic first, dynamic second)
{
- return first & second;
+ return first ^ second;
}
- private static object LogicalOR(dynamic first, dynamic second)
+ private static object BitwiseAndExpression(dynamic first, dynamic second)
{
- return first | second;
+ return first & second;
}
- private static object LogicalXOR(dynamic first, dynamic second)
+ private static object BitwiseOrExpression(dynamic first, dynamic second)
{
- return first ^ second;
+ return first | second;
}
- private static bool ConditionalLogicalAnd(dynamic first, dynamic second)
+ private static bool LogicalAndExpression(dynamic first, dynamic second)
{
return first && second;
}
- private static bool ConditionalLogicalOR(dynamic first, dynamic second)
+ private static bool LogicalOrExpression(dynamic first, dynamic second)
{
return first || second;
}
- private static object LogicalNegation(dynamic first)
+ private static object LogicalNotExpression(dynamic first)
{
return !first;
}
- private static bool Equality(dynamic first, dynamic second)
+ private static bool EqualsExpression(dynamic first, dynamic second)
{
return first == second;
}
- private static bool Inequality(dynamic first, dynamic second)
+ private static bool NotEqualsExpression(dynamic first, dynamic second)
{
return first != second;
}
- private static bool LessThan(dynamic first, dynamic second)
+ private static bool LessThanExpression(dynamic first, dynamic second)
{
return first < second;
}
- private static bool GreaterThan(dynamic first, dynamic second)
+ private static bool GreaterThanExpression(dynamic first, dynamic second)
{
return first > second;
}
- private static bool LessThanOrEqual(dynamic first, dynamic second)
+ private static bool LessThanOrEqualExpression(dynamic first, dynamic second)
{
return first <= second;
}
- private static bool GreaterThanOrEqual(dynamic first, dynamic second)
+ private static bool GreaterThanOrEqualExpression(dynamic first, dynamic second)
{
return first >= second;
}
+
+ private static object UnaryPlusExpression(dynamic first)
+ {
+ return +first;
+ }
+
+ private static object UnaryMinusExpression(dynamic first)
+ {
+ return -first;
+ }
}
}
case SyntaxKind.MemberBindingExpression:
case SyntaxKind.UnaryPlusExpression:
case SyntaxKind.UnaryMinusExpression:
-/* TODO
- case SyntaxKind.QualifiedName:
- case SyntaxKind.AliasQualifiedName:
- case SyntaxKind.ConditionalExpression:
- case SyntaxKind.PointerMemberAccessExpression:
- case SyntaxKind.CastExpression:
- case SyntaxKind.AsExpression:
case SyntaxKind.AddExpression:
case SyntaxKind.MultiplyExpression:
case SyntaxKind.SubtractExpression:
case SyntaxKind.DivideExpression:
case SyntaxKind.ModuloExpression:
- case SyntaxKind.LeftShiftExpression:
case SyntaxKind.RightShiftExpression:
- case SyntaxKind.BitwiseAndExpression:
- case SyntaxKind.BitwiseOrExpression:
- case SyntaxKind.ExclusiveOrExpression:
+ case SyntaxKind.LeftShiftExpression:
+ case SyntaxKind.BitwiseNotExpression:
case SyntaxKind.LogicalAndExpression:
case SyntaxKind.LogicalOrExpression:
+ case SyntaxKind.ExclusiveOrExpression:
+ case SyntaxKind.BitwiseAndExpression:
+ case SyntaxKind.BitwiseOrExpression:
+ case SyntaxKind.LogicalNotExpression:
case SyntaxKind.EqualsExpression:
case SyntaxKind.NotEqualsExpression:
case SyntaxKind.GreaterThanExpression:
case SyntaxKind.LessThanExpression:
case SyntaxKind.GreaterThanOrEqualExpression:
case SyntaxKind.LessThanOrEqualExpression:
+
+/* TODO
+ case SyntaxKind.QualifiedName:
+ case SyntaxKind.AliasQualifiedName:
+ case SyntaxKind.ConditionalExpression:
+ case SyntaxKind.PointerMemberAccessExpression:
+ case SyntaxKind.CastExpression:
+ case SyntaxKind.AsExpression:
case SyntaxKind.IsExpression:
- case SyntaxKind.LogicalNotExpression:
- case SyntaxKind.BitwiseNotExpression:
case SyntaxKind.PreIncrementExpression:
case SyntaxKind.PostIncrementExpression:
case SyntaxKind.PreDecrementExpression:
}
};
- // Keep in sync with OperationType enum in Evaluation.cs
- enum class OperationType
- {
- Addition = 1,
- Subtraction,
- Multiplication,
- Division,
- Remainder,
- BitwiseRightShift,
- BitwiseLeftShift,
- BitwiseComplement,
- LogicalAnd,
- LogicalOR,
- LogicalXOR,
- ConditionalLogicalAnd,
- ConditionalLogicalOR,
- LogicalNegation,
- Equality,
- Inequality,
- LessThan,
- GreaterThan,
- LessThanOrEqual,
- GreaterThanOrEqual
- };
struct AsyncAwaitInfoBlock
{
uint32_t yield_offset;
return ((MIConst)res["name"]).CString;
}
+ public string GetAndCheckValue(string caller_trace, string ExpectedResult1, string ExpectedResult2, string ExpectedType, string Expression)
+ {
+ var res = MIDebugger.Request(String.Format("-var-create - * \"{0}\"", Expression));
+ Assert.Equal(MIResultClass.Done, res.Class, @"__FILE__:__LINE__"+"\n"+caller_trace);
+
+ Assert.Equal(Expression, ((MIConst)res["exp"]).CString, @"__FILE__:__LINE__"+"\n"+caller_trace);
+ Assert.Equal(ExpectedType, ((MIConst)res["type"]).CString, @"__FILE__:__LINE__"+"\n"+caller_trace);
+ Assert.True(ExpectedResult1 == ((MIConst)res["value"]).CString ||
+ ExpectedResult2 == ((MIConst)res["value"]).CString, @"__FILE__:__LINE__"+"\n"+caller_trace);
+
+ return ((MIConst)res["name"]).CString;
+ }
+
public void CheckErrorAtRequest(string caller_trace, string Expression, string errMsgStart)
{
var res = MIDebugger.Request(String.Format("-var-create - * \"{0}\"", Expression));
TWO
};
+ public class TestOperators1
+ {
+ public int data;
+ public TestOperators1(int data_)
+ {
+ data = data_;
+ }
+
+ public static implicit operator TestOperators1(int value) => new TestOperators1(value);
+
+ public static int operator +(TestOperators1 d1, int d2) => 55;
+ public static int operator +(int d1, TestOperators1 d2) => 66;
+
+ public static int operator ~(TestOperators1 d1) => ~d1.data;
+ public static bool operator !(TestOperators1 d1) => true;
+ public static int operator +(TestOperators1 d1, TestOperators1 d2) => d1.data + d2.data;
+ public static int operator -(TestOperators1 d1, TestOperators1 d2) => d1.data - d2.data;
+ public static int operator *(TestOperators1 d1, TestOperators1 d2) => d1.data * d2.data;
+ public static int operator /(TestOperators1 d1, TestOperators1 d2) => d1.data / d2.data;
+ public static int operator %(TestOperators1 d1, TestOperators1 d2) => d1.data % d2.data;
+ public static int operator ^(TestOperators1 d1, TestOperators1 d2) => d1.data ^ d2.data;
+ public static int operator &(TestOperators1 d1, TestOperators1 d2) => d1.data & d2.data;
+ public static int operator |(TestOperators1 d1, TestOperators1 d2) => d1.data | d2.data;
+ public static int operator >>(TestOperators1 d1, int d2) => d1.data >> d2;
+ public static int operator <<(TestOperators1 d1, int d2) => d1.data << d2;
+ public static bool operator ==(TestOperators1 d1, TestOperators1 d2) => d1.data == d2.data;
+ public static bool operator !=(TestOperators1 d1, TestOperators1 d2) => d1.data != d2.data;
+ public static bool operator <(TestOperators1 d1, TestOperators1 d2) => d1.data < d2.data;
+ public static bool operator <=(TestOperators1 d1, TestOperators1 d2) => d1.data <= d2.data;
+ public static bool operator >(TestOperators1 d1, TestOperators1 d2) => d1.data > d2.data;
+ public static bool operator >=(TestOperators1 d1, TestOperators1 d2) => d1.data >= d2.data;
+ }
+
+ public struct TestOperators2
+ {
+ public int data;
+ public TestOperators2(int data_)
+ {
+ data = data_;
+ }
+ public static implicit operator TestOperators2(int value) => new TestOperators2(value);
+
+ public static int operator +(TestOperators2 d1, int d2) => 55;
+ public static int operator +(int d1, TestOperators2 d2) => 66;
+
+ public static int operator ~(TestOperators2 d1) => ~d1.data;
+ public static bool operator !(TestOperators2 d1) => true;
+ public static int operator +(TestOperators2 d1, TestOperators2 d2) => d1.data + d2.data;
+ public static int operator -(TestOperators2 d1, TestOperators2 d2) => d1.data - d2.data;
+ public static int operator *(TestOperators2 d1, TestOperators2 d2) => d1.data * d2.data;
+ public static int operator /(TestOperators2 d1, TestOperators2 d2) => d1.data / d2.data;
+ public static int operator %(TestOperators2 d1, TestOperators2 d2) => d1.data % d2.data;
+ public static int operator ^(TestOperators2 d1, TestOperators2 d2) => d1.data ^ d2.data;
+ public static int operator &(TestOperators2 d1, TestOperators2 d2) => d1.data & d2.data;
+ public static int operator |(TestOperators2 d1, TestOperators2 d2) => d1.data | d2.data;
+ public static int operator >>(TestOperators2 d1, int d2) => d1.data >> d2;
+ public static int operator <<(TestOperators2 d1, int d2) => d1.data << d2;
+ public static bool operator ==(TestOperators2 d1, TestOperators2 d2) => d1.data == d2.data;
+ public static bool operator !=(TestOperators2 d1, TestOperators2 d2) => d1.data != d2.data;
+ public static bool operator <(TestOperators2 d1, TestOperators2 d2) => d1.data < d2.data;
+ public static bool operator <=(TestOperators2 d1, TestOperators2 d2) => d1.data <= d2.data;
+ public static bool operator >(TestOperators2 d1, TestOperators2 d2) => d1.data > d2.data;
+ public static bool operator >=(TestOperators2 d1, TestOperators2 d2) => d1.data >= d2.data;
+ }
+
+ public struct TestOperators3
+ {
+ public int data;
+ public TestOperators3(int data_)
+ {
+ data = data_;
+ }
+
+ // Note, in order to test that was used proper operator, we use fixed return here.
+
+ public static implicit operator int(TestOperators3 value) => 777;
+
+ public static int operator +(TestOperators3 d1, int d2) => 555;
+ public static int operator +(int d1, TestOperators3 d2) => 666;
+ public static int operator >>(TestOperators3 d1, int d2) => 777;
+ public static int operator <<(TestOperators3 d1, int d2) => 888;
+ }
+
class Program
{
int int_i = 505;
Context.Continue(@"__FILE__:__LINE__");
});
-
- int int_i1 = 5;
- int int_i2 = 5;
- string str_s1 = "one";
- string str_s2 = "two";
+ // Test expression calculation.
+ TestOperators1 testClass = new TestOperators1(12);
+ TestOperators2 testStruct;
+ TestOperators3 testStruct2;
+ testStruct.data = 5;
+ string testString1 = null;
+ string testString2 = "test";
int break_line2 = 1; Label.Breakpoint("BREAK2");
Label.Checkpoint("expression_test", "static_test", (Object context) => {
Context Context = (Context)context;
Context.WasBreakpointHit(@"__FILE__:__LINE__", "BREAK2");
-/*
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "int", "1 + 1");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "6", "int", "int_i1 + 1");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "10", "int", "int_i1 + int_i2");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"onetwo\\\"", "", "\\\"one\\\" + \\\"two\\\"");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"onetwo\\\"", "", "str_s1 + \\\"two\\\"");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"onetwo\\\"", "", "str_s1 + str_s2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "int", "1 + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "float", "1u + 1f");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "long", "1u + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "decimal", "1m + 1m");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "decimal", "1m + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "decimal", "1 + 1m");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "66", "int", "1 + testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "55", "int", "testClass + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "66", "int", "1 + testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "55", "int", "testStruct + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "666", "int", "1 + testStruct2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "555", "int", "testStruct2 + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"stringC\\\"", "string", "\\\"string\\\" + 'C'");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"test\\\"", "string", "testString1 + testString2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"test\\\"", "string", "testString2 + testString1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"\\\"", "string", "testString1 + testString1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"testtest\\\"", "string", "testString2 + testString2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"test\\\"", "string", "\\\"\\\" + \\\"test\\\"");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"test\\\"", "string", "\\\"test\\\" + \\\"\\\"");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"\\\"", "string", "\\\"\\\" + \\\"\\\"");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"testtest\\\"", "string", "\\\"test\\\" + \\\"test\\\"");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1UL + 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true + 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 + not_var", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1u + testClass", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testClass + 1u", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1u + testStruct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testStruct + 1u", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testClass + testStruct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testStruct + testClass", "error CS0019");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "int", "3 - 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "decimal", "3m - 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true - 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 - not_var", "error");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "-11", "int", "1 - testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "11", "int", "testClass - 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "-4", "int", "1 - testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "4", "int", "testStruct - 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "-776", "int", "1 - testStruct2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "776", "int", "testStruct2 - 1");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "4", "int", "2 * 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "4", "decimal", "2m * 2m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true * 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 * not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "1", "int", "2 / 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "1", "decimal", "2m / 2m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true / 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 / not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "2 % 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "decimal", "2m % 2m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true % 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 % not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "4", "int", "1 << 2");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1m << 2m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true << 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 << not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "1", "int", "4 >> 2");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1m >> 2m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true >> 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 >> not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "-2", "int", "~1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "-13", "int", "~testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "-6", "int", "~testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "~1m", "error CS0023");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "~true", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "~not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "true && true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "true && false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "false && true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "false && false");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 && 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1m && 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true && not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "true || true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "true || false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "false || true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "false || false");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 || 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1m || 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true || not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "true ^ true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "true ^ false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "false ^ true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "false ^ false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "1 ^ 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "1", "int", "1 ^ 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "1", "int", "0 ^ 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "0 ^ 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "14", "int", "testClass ^ 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "14", "int", "2 ^ testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "testClass ^ testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "7", "int", "testStruct ^ 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "7", "int", "2 ^ testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "testStruct ^ testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testStruct2 ^ testStruct2", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1m ^ 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 ^ not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "true & true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "true & false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "false & true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "false & false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "1", "int", "3 & 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "5 & 8");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "10 & 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "0 & 7");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "0 & 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "testClass & 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "2 & testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "12", "int", "testClass & testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "testStruct & 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "2 & testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "5", "int", "testStruct & testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testStruct2 & testStruct2", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1m & 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 & not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "true | true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "true | false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "false | true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "false | false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "13", "int", "5 | 8");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "10", "int", "10 | 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "7", "int", "0 | 7");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "0", "int", "0 | 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "14", "int", "testClass | 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "14", "int", "2 | testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "12", "int", "testClass | testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "7", "int", "testStruct | 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "7", "int", "2 | testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "5", "int", "testStruct | testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testStruct2 | testStruct2", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1m | 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 | not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "!true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "!testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "!testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "!1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "!1m", "error CS0023");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "!not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "1 == 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "2 == 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "2m == 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 == not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "1 != 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "2 != 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "2m != 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 != not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "1 < 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "1 < 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "1m < 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true < false", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 < not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "2 > 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "1 > 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "1m > 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true > false", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 > not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "1 <= 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "1 <= 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "1 <= 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "1m <= 0m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true <= false", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 <= not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "2 >= 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "1 >= 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "0 >= 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "0m >= 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "true >= false", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 >= not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "4", "int", "2 << 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "888", "int", "testStruct2 << testStruct2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "24", "int", "testClass << 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "10", "int", "testStruct << 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "20", "int", "testStruct << 2");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1f << 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1f << 1f", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testClass << testClass", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testStruct << testStruct", "error CS0019");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "int", "4 >> 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "777", "int", "testStruct2 >> testStruct2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "6", "int", "testClass >> 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "2", "int", "testStruct >> 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "1", "int", "testStruct >> 2");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1f >> 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1f >> 1f", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testClass >> testClass", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testStruct >> testStruct", "error CS0019");
- Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "int_i1 +/ int_i2", "error CS1525:");
- Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "1 + not_var", "System.AggregateException"); // error
-*/
Context.Continue(@"__FILE__:__LINE__");
});
Context.GetAndCheckValue(@"__FILE__:__LINE__", "10", "int", "TestCallParent.GetNumber()");
// Call built-in types methods.
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"1.01\\\"", "string", "1.01M.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"1.01\\\"", "string", "decimalToString.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"2.02\\\"", "string", "2.02.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"2.02\\\"", "string", "doubleToString.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"3.03\\\"", "string", "3.03f.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"3.03\\\"", "string", "floatToString.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"1.01\\\"", "\\\"1,01\\\"", "string", "1.01M.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"1.01\\\"", "\\\"1,01\\\"", "string", "decimalToString.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"2.02\\\"", "\\\"2,02\\\"", "string", "2.02.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"2.02\\\"", "\\\"2,02\\\"", "string", "doubleToString.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"3.03\\\"", "\\\"3,03\\\"", "string", "3.03f.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"3.03\\\"", "\\\"3,03\\\"", "string", "floatToString.ToString()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"c\\\"", "string", "'c'.ToString()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"c\\\"", "string", "charToString.ToString()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"True\\\"", "string", "boolToString.ToString()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "8", "long", "-longUnary");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "8", "ulong", "+8UL");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "8", "ulong", "+ulongUnary");
- Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "-8UL", "error CS0023");
- Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "-ulongUnary", "error CS0023");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "-8UL", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "-ulongUnary", "error");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "10.5", "decimal", "+10.5m");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "1.01", "decimal", "+decimalUnary");
Assert.Equal(ExpectedType, evaluateResponse.body.type, @"__FILE__:__LINE__"+"\n"+caller_trace);
}
+ public void GetAndCheckValue(string caller_trace, Int64 frameId, string ExpectedResult1, string ExpectedResult2, string ExpectedType, string Expression)
+ {
+ EvaluateRequest evaluateRequest = new EvaluateRequest();
+ evaluateRequest.arguments.expression = Expression;
+ evaluateRequest.arguments.frameId = frameId;
+ var ret = VSCodeDebugger.Request(evaluateRequest);
+ Assert.True(ret.Success, @"__FILE__:__LINE__"+"\n"+caller_trace);
+
+ EvaluateResponse evaluateResponse =
+ JsonConvert.DeserializeObject<EvaluateResponse>(ret.ResponseStr);
+
+ Assert.True(ExpectedResult1 == evaluateResponse.body.result ||
+ ExpectedResult2 == evaluateResponse.body.result, @"__FILE__:__LINE__"+"\n"+caller_trace);
+ Assert.Equal(ExpectedType, evaluateResponse.body.type, @"__FILE__:__LINE__"+"\n"+caller_trace);
+ }
+
public void CheckErrorAtRequest(string caller_trace, Int64 frameId, string Expression, string errMsgStart)
{
EvaluateRequest evaluateRequest = new EvaluateRequest();
TWO
};
+ public class TestOperators1
+ {
+ public int data;
+ public TestOperators1(int data_)
+ {
+ data = data_;
+ }
+
+ public static implicit operator TestOperators1(int value) => new TestOperators1(value);
+
+ public static int operator +(TestOperators1 d1, int d2) => 55;
+ public static int operator +(int d1, TestOperators1 d2) => 66;
+
+ public static int operator ~(TestOperators1 d1) => ~d1.data;
+ public static bool operator !(TestOperators1 d1) => true;
+ public static int operator +(TestOperators1 d1, TestOperators1 d2) => d1.data + d2.data;
+ public static int operator -(TestOperators1 d1, TestOperators1 d2) => d1.data - d2.data;
+ public static int operator *(TestOperators1 d1, TestOperators1 d2) => d1.data * d2.data;
+ public static int operator /(TestOperators1 d1, TestOperators1 d2) => d1.data / d2.data;
+ public static int operator %(TestOperators1 d1, TestOperators1 d2) => d1.data % d2.data;
+ public static int operator ^(TestOperators1 d1, TestOperators1 d2) => d1.data ^ d2.data;
+ public static int operator &(TestOperators1 d1, TestOperators1 d2) => d1.data & d2.data;
+ public static int operator |(TestOperators1 d1, TestOperators1 d2) => d1.data | d2.data;
+ public static int operator >>(TestOperators1 d1, int d2) => d1.data >> d2;
+ public static int operator <<(TestOperators1 d1, int d2) => d1.data << d2;
+ public static bool operator ==(TestOperators1 d1, TestOperators1 d2) => d1.data == d2.data;
+ public static bool operator !=(TestOperators1 d1, TestOperators1 d2) => d1.data != d2.data;
+ public static bool operator <(TestOperators1 d1, TestOperators1 d2) => d1.data < d2.data;
+ public static bool operator <=(TestOperators1 d1, TestOperators1 d2) => d1.data <= d2.data;
+ public static bool operator >(TestOperators1 d1, TestOperators1 d2) => d1.data > d2.data;
+ public static bool operator >=(TestOperators1 d1, TestOperators1 d2) => d1.data >= d2.data;
+ }
+
+ public struct TestOperators2
+ {
+ public int data;
+ public TestOperators2(int data_)
+ {
+ data = data_;
+ }
+ public static implicit operator TestOperators2(int value) => new TestOperators2(value);
+
+ public static int operator +(TestOperators2 d1, int d2) => 55;
+ public static int operator +(int d1, TestOperators2 d2) => 66;
+
+ public static int operator ~(TestOperators2 d1) => ~d1.data;
+ public static bool operator !(TestOperators2 d1) => true;
+ public static int operator +(TestOperators2 d1, TestOperators2 d2) => d1.data + d2.data;
+ public static int operator -(TestOperators2 d1, TestOperators2 d2) => d1.data - d2.data;
+ public static int operator *(TestOperators2 d1, TestOperators2 d2) => d1.data * d2.data;
+ public static int operator /(TestOperators2 d1, TestOperators2 d2) => d1.data / d2.data;
+ public static int operator %(TestOperators2 d1, TestOperators2 d2) => d1.data % d2.data;
+ public static int operator ^(TestOperators2 d1, TestOperators2 d2) => d1.data ^ d2.data;
+ public static int operator &(TestOperators2 d1, TestOperators2 d2) => d1.data & d2.data;
+ public static int operator |(TestOperators2 d1, TestOperators2 d2) => d1.data | d2.data;
+ public static int operator >>(TestOperators2 d1, int d2) => d1.data >> d2;
+ public static int operator <<(TestOperators2 d1, int d2) => d1.data << d2;
+ public static bool operator ==(TestOperators2 d1, TestOperators2 d2) => d1.data == d2.data;
+ public static bool operator !=(TestOperators2 d1, TestOperators2 d2) => d1.data != d2.data;
+ public static bool operator <(TestOperators2 d1, TestOperators2 d2) => d1.data < d2.data;
+ public static bool operator <=(TestOperators2 d1, TestOperators2 d2) => d1.data <= d2.data;
+ public static bool operator >(TestOperators2 d1, TestOperators2 d2) => d1.data > d2.data;
+ public static bool operator >=(TestOperators2 d1, TestOperators2 d2) => d1.data >= d2.data;
+ }
+
+ public struct TestOperators3
+ {
+ public int data;
+ public TestOperators3(int data_)
+ {
+ data = data_;
+ }
+
+ // Note, in order to test that was used proper operator, we use fixed return here.
+
+ public static implicit operator int(TestOperators3 value) => 777;
+
+ public static int operator +(TestOperators3 d1, int d2) => 555;
+ public static int operator +(int d1, TestOperators3 d2) => 666;
+ public static int operator >>(TestOperators3 d1, int d2) => 777;
+ public static int operator <<(TestOperators3 d1, int d2) => 888;
+ }
+
class Program
{
int int_i = 505;
Context.Continue(@"__FILE__:__LINE__");
});
-
- int int_i1 = 5;
- int int_i2 = 5;
- string str_s1 = "one";
- string str_s2 = "two";
+ // Test expression calculation.
+ TestOperators1 testClass = new TestOperators1(12);
+ TestOperators2 testStruct;
+ TestOperators3 testStruct2;
+ testStruct.data = 5;
+ string testString1 = null;
+ string testString2 = "test";
int break_line2 = 1; Label.Breakpoint("BREAK2");
Label.Checkpoint("expression_test", "static_test", (Object context) => {
Int64 frameId = Context.DetectFrameId(@"__FILE__:__LINE__", "BREAK2");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "int", "1 + 1");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "6", "int", "int_i1 + 1");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10", "int", "int_i1 + int_i2");
-
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"onetwo\"", "", "\"one\" + \"two\"");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"onetwo\"", "", "str_s1 + \"two\"");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"onetwo\"", "", "str_s1 + str_s2");
-
- Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "int_i1 +/ int_i2", "error CS1525:");
- Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 + not_var", "System.AggregateException"); // error
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "float", "1u + 1f");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "long", "1u + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "decimal", "1m + 1m");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "decimal", "1m + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "decimal", "1 + 1m");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "66", "int", "1 + testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "55", "int", "testClass + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "66", "int", "1 + testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "55", "int", "testStruct + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "666", "int", "1 + testStruct2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "555", "int", "testStruct2 + 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"stringC\"", "string", "\"string\" + 'C'");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"test\"", "string", "testString1 + testString2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"test\"", "string", "testString2 + testString1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"\"", "string", "testString1 + testString1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"testtest\"", "string", "testString2 + testString2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"test\"", "string", "\"\" + \"test\"");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"test\"", "string", "\"test\" + \"\"");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"\"", "string", "\"\" + \"\"");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"testtest\"", "string", "\"test\" + \"test\"");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1UL + 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true + 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 + not_var", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1u + testClass", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testClass + 1u", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1u + testStruct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testStruct + 1u", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testClass + testStruct", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testStruct + testClass", "error CS0019");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "int", "3 - 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "decimal", "3m - 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true - 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 - not_var", "error");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "-11", "int", "1 - testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "11", "int", "testClass - 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "-4", "int", "1 - testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "4", "int", "testStruct - 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "-776", "int", "1 - testStruct2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "776", "int", "testStruct2 - 1");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "4", "int", "2 * 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "4", "decimal", "2m * 2m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true * 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 * not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "1", "int", "2 / 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "1", "decimal", "2m / 2m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true / 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 / not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "2 % 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "decimal", "2m % 2m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true % 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 % not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "4", "int", "1 << 2");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1m << 2m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true << 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 << not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "1", "int", "4 >> 2");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1m >> 2m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true >> 2", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 >> not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "-2", "int", "~1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "-13", "int", "~testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "-6", "int", "~testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "~1m", "error CS0023");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "~true", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "~not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "true && true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "true && false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "false && true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "false && false");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 && 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1m && 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true && not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "true || true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "true || false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "false || true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "false || false");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 || 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1m || 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true || not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "true ^ true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "true ^ false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "false ^ true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "false ^ false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "1 ^ 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "1", "int", "1 ^ 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "1", "int", "0 ^ 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "0 ^ 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "14", "int", "testClass ^ 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "14", "int", "2 ^ testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "testClass ^ testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "7", "int", "testStruct ^ 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "7", "int", "2 ^ testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "testStruct ^ testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testStruct2 ^ testStruct2", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1m ^ 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 ^ not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "true & true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "true & false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "false & true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "false & false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "1", "int", "3 & 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "5 & 8");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "10 & 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "0 & 7");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "0 & 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "testClass & 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "2 & testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "12", "int", "testClass & testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "testStruct & 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "2 & testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "5", "int", "testStruct & testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testStruct2 & testStruct2", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1m & 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 & not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "true | true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "true | false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "false | true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "false | false");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "13", "int", "5 | 8");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10", "int", "10 | 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "7", "int", "0 | 7");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "0", "int", "0 | 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "14", "int", "testClass | 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "14", "int", "2 | testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "12", "int", "testClass | testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "7", "int", "testStruct | 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "7", "int", "2 | testStruct");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "5", "int", "testStruct | testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testStruct2 | testStruct2", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1m | 1m", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 | not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "!true");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "!testClass");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "!testStruct");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "!1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "!1m", "error CS0023");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "!not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "1 == 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "2 == 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "2m == 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 == not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "1 != 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "2 != 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "2m != 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 != not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "1 < 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "1 < 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "1m < 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true < false", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 < not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "2 > 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "1 > 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "1m > 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true > false", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 > not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "1 <= 2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "1 <= 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "1 <= 0");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "1m <= 0m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true <= false", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 <= not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "2 >= 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "1 >= 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "0 >= 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "0m >= 1m");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "true >= false", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1 >= not_var", "error");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "4", "int", "2 << 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "888", "int", "testStruct2 << testStruct2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "24", "int", "testClass << 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10", "int", "testStruct << 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "20", "int", "testStruct << 2");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1f << 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1f << 1f", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testClass << testClass", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testStruct << testStruct", "error CS0019");
+
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "int", "4 >> 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "777", "int", "testStruct2 >> testStruct2");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "6", "int", "testClass >> 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "2", "int", "testStruct >> 1");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "1", "int", "testStruct >> 2");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1f >> 1", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "1f >> 1f", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testClass >> testClass", "error CS0019");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testStruct >> testStruct", "error CS0019");
Context.Continue(@"__FILE__:__LINE__");
});
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10", "int", "TestCallParent.GetNumber()");
// Call built-in types methods.
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"1.01\"", "string", "1.01M.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"1.01\"", "string", "decimalToString.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"2.02\"", "string", "2.02.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"2.02\"", "string", "doubleToString.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"3.03\"", "string", "3.03f.ToString()");
- Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"3.03\"", "string", "floatToString.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"1.01\"", "\"1,01\"", "string", "1.01M.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"1.01\"", "\"1,01\"", "string", "decimalToString.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"2.02\"", "\"2,02\"", "string", "2.02.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"2.02\"", "\"2,02\"", "string", "doubleToString.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"3.03\"", "\"3,03\"", "string", "3.03f.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"3.03\"", "\"3,03\"", "string", "floatToString.ToString()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"c\"", "string", "'c'.ToString()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"c\"", "string", "charToString.ToString()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"True\"", "string", "boolToString.ToString()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "8", "long", "-longUnary");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "8", "ulong", "+8UL");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "8", "ulong", "+ulongUnary");
- Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "-8UL", "error CS0023");
- Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "-ulongUnary", "error CS0023");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "-8UL", "error");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "-ulongUnary", "error");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10.5", "decimal", "+10.5m");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "1.01", "decimal", "+decimalUnary");