private void VisitIncrementDecrementExpression(UnaryExpressionAst unaryExpressionAst)
{
var token = unaryExpressionAst.TokenKind;
// first validate the expression. Shouldn't fail, but let's be sure
var validTokens = new [] { TokenKind.PostfixPlusPlus, TokenKind.PostfixMinusMinus,
TokenKind.PlusPlus, TokenKind.MinusMinus};
if (!validTokens.Contains(token))
{
throw new PSInvalidOperationException("The unary expression is not a decrement/increment expression. " +
"Please report this issue.");
}
bool postfix = token == TokenKind.PostfixPlusPlus || token == TokenKind.PostfixMinusMinus;
bool increment = token == TokenKind.PostfixPlusPlus || token == TokenKind.PlusPlus;
// It's the duty of the AstBuilderto check wether the child expression is a settable expression
SettableExpression affectedExpression = SettableExpression.Create(unaryExpressionAst.Child, this);
object objValue = PSObject.Unwrap(affectedExpression.GetValue());
objValue = objValue ?? 0; // if the value is null, then we "convert" to integer 0, says the specification
// check for non-numerics
var valueType = objValue.GetType();
if (!valueType.IsNumeric())
{
var msg = String.Format("The operator '{0}' can only be used for numbers. The operand is '{1}'",
increment ? "++" : "--", valueType.FullName);
throw new RuntimeException(msg, "OperatorRequiresNumber", ErrorCategory.InvalidOperation, objValue);
}
// if it's a postfix operation, then we need to write the numeric value to pipeline
if (postfix && _writeSideEffectsToPipeline)
{
_pipelineCommandRuntime.WriteObject(objValue);
}
// now actually change the value, check for overflow
dynamic dynValue = (dynamic)objValue;
try
{
dynValue = checked(dynValue + (increment ? 1 : -1));
}
catch (OverflowException) // cast to double on overflow
{
dynValue = LanguagePrimitives.ConvertTo<double>(objValue) + (increment ? 1 : -1);
}
// set the new value
affectedExpression.SetValue((object)dynValue);
// if it was a prefix, then we need to write the new value to pipeline
if (!postfix && _writeSideEffectsToPipeline)
{
_pipelineCommandRuntime.WriteObject(dynValue);
}
}