/// <inheritdoc /> protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame) { Contract.Assume(frame.Length > Index); // By construction, the above preconditions should hold. try { // All operations should be in the checked context to fail on overflow! checked { var oldValue = Converter.ExpectNumber(frame[Index], position: 0); switch (OperatorKind) { case IncrementDecrementOperator.PrefixIncrement: { var newValue = NumberLiteral.Box(oldValue + 1); frame[Index] = newValue; return(newValue); } case IncrementDecrementOperator.PostfixIncrement: { var newValue = NumberLiteral.Box(oldValue + 1); frame[Index] = newValue; return(EvaluationResult.Create(oldValue)); } case IncrementDecrementOperator.PrefixDecrement: { var newValue = NumberLiteral.Box(oldValue - 1); frame[Index] = newValue; return(newValue); } case IncrementDecrementOperator.PostfixDecrement: { var newValue = NumberLiteral.Box(oldValue - 1); frame[Index] = newValue; return(EvaluationResult.Create(oldValue)); } default: var message = I($"Unknown operator kind '{OperatorKind}'"); Contract.Assert(false, message); throw new InvalidOperationException(message); } } } catch (OverflowException) { context.Logger.ReportArithmeticOverflow(context.LoggingContext, LocationForLogging(context, env), this.ToDisplayString(context)); } catch (ConvertException exception) { context.Errors.ReportUnexpectedValueTypeForName(env, Operand, exception.ExpectedTypesToString(context), exception.Value, Location); } return(EvaluationResult.Error); }
/// <inheritdoc /> protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame) { Contract.Assume(frame.Length > Index); // By construction, the above preconditions should hold. var value = RightExpression.Eval(context, env, frame); if (value.IsErrorValue) { return(EvaluationResult.Error); } if (OperatorKind == AssignmentOperator.Assignment) { frame[Index] = value; return(frame[Index]); } try { // All operations should be in the checked context to fail on overflow! checked { var arg = frame[Index]; switch (OperatorKind) { case AssignmentOperator.AdditionAssignment: if (Converter.TryGet <int>(arg, out int lIntValue) && Converter.TryGet <int>(value, out int rIntValue)) { frame[Index] = NumberLiteral.Box(lIntValue + rIntValue); break; } else if (Converter.TryGet <string>(arg, out string lStrValue) && Converter.TryGet <string>(value, out string rStrValue)) { frame[Index] = EvaluationResult.Create(lStrValue + rStrValue); break; } throw Converter.CreateException <int>(value, context: new ConversionContext(pos: Index)); case AssignmentOperator.SubtractionAssignment: frame[Index] = NumberLiteral.Box(Converter.ExpectNumber(arg, position: 0) - Converter.ExpectNumber(value, position: 1)); break; case AssignmentOperator.MultiplicationAssignment: frame[Index] = NumberLiteral.Box(Converter.ExpectNumber(arg, position: 0) * Converter.ExpectNumber(value, position: 1)); break; case AssignmentOperator.RemainderAssignment: frame[Index] = NumberLiteral.Box(Converter.ExpectNumber(arg, position: 0) % Converter.ExpectNumber(value, position: 1)); break; case AssignmentOperator.ExponentiationAssignment: frame[Index] = NumberOperations.Power( context, Converter.ExpectNumber(arg, position: 0), Converter.ExpectNumber(value, position: 1), LocationForLogging(context, env)); break; case AssignmentOperator.LeftShiftAssignment: frame[Index] = NumberLiteral.Box(Converter.ExpectNumber(frame[Index], position: 0) << Converter.ExpectNumber(value, position: 1)); break; case AssignmentOperator.RightShiftAssignment: frame[Index] = NumberLiteral.Box(NumberOperations.SignPropagatingRightShift( Converter.ExpectNumber(arg, position: 0), Converter.ExpectNumber(value, position: 1)).Value); break; case AssignmentOperator.UnsignedRightShiftAssignment: frame[Index] = NumberLiteral.Box(NumberOperations.ZeroFillingRightShift( Converter.ExpectNumber(arg, position: 0), Converter.ExpectNumber(value, position: 1)).Value); break; case AssignmentOperator.BitwiseAndAssignment: frame[Index] = Converter.ToEnumValueIfNeeded( arg.GetType(), Converter.ExpectNumberOrEnum(arg, position: 0) & Converter.ExpectNumberOrEnum(value, position: 1)); break; case AssignmentOperator.BitwiseXorAssignment: frame[Index] = Converter.ToEnumValueIfNeeded( arg.GetType(), Converter.ExpectNumberOrEnum(arg, position: 0) ^ Converter.ExpectNumberOrEnum(value, position: 1)); break; case AssignmentOperator.BitwiseOrAssignment: frame[Index] = Converter.ToEnumValueIfNeeded( arg.GetType(), Converter.ExpectNumberOrEnum(arg, position: 0) | Converter.ExpectNumberOrEnum(value, position: 1)); break; default: var message = I($"Unknown operator kind '{OperatorKind}'"); Contract.Assert(false, message); throw new InvalidOperationException(message); } } return(frame[Index]); } catch (OverflowException) { context.Logger.ReportArithmeticOverflow(context.LoggingContext, LocationForLogging(context, env), this.ToDisplayString(context)); } catch (ConvertException exception) { if (exception.ErrorContext.Pos == 0) { context.Errors.ReportUnexpectedValueTypeForName(env, LeftExpression, exception.ExpectedTypesToString(context), exception.Value, Location); } else { context.Errors.ReportUnexpectedValueType(env, RightExpression, exception.Value, exception.ExpectedTypesToString(context)); } } return(EvaluationResult.Error); }