protected override object EvaluateInternal() { var lref = _left.Evaluate() as Reference ?? ExceptionHelper.ThrowReferenceError <Reference>(_engine); var rval = _right.GetValue(); var lval = _engine.GetValue(lref, false); switch (_operator) { case AssignmentOperator.PlusAssign: if (AreIntegerOperands(lval, rval)) { lval = (long)lval.AsInteger() + rval.AsInteger(); } else { var lprim = TypeConverter.ToPrimitive(lval); var rprim = TypeConverter.ToPrimitive(rval); if (lprim.IsString() || rprim.IsString()) { if (!(lprim is JsString jsString)) { jsString = new JsString.ConcatenatedString(TypeConverter.ToString(lprim)); } lval = jsString.Append(rprim); } else { lval = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim); } } break; case AssignmentOperator.MinusAssign: lval = AreIntegerOperands(lval, rval) ? JsNumber.Create(lval.AsInteger() - rval.AsInteger()) : JsNumber.Create(TypeConverter.ToNumber(lval) - TypeConverter.ToNumber(rval)); break; case AssignmentOperator.TimesAssign: if (AreIntegerOperands(lval, rval)) { lval = (long)lval.AsInteger() * rval.AsInteger(); } else if (lval.IsUndefined() || rval.IsUndefined()) { lval = Undefined.Instance; } else { lval = TypeConverter.ToNumber(lval) * TypeConverter.ToNumber(rval); } break; case AssignmentOperator.DivideAssign: lval = Divide(lval, rval); break; case AssignmentOperator.ModuloAssign: if (lval.IsUndefined() || rval.IsUndefined()) { lval = Undefined.Instance; } else { lval = TypeConverter.ToNumber(lval) % TypeConverter.ToNumber(rval); } break; case AssignmentOperator.BitwiseAndAssign: lval = TypeConverter.ToInt32(lval) & TypeConverter.ToInt32(rval); break; case AssignmentOperator.BitwiseOrAssign: lval = TypeConverter.ToInt32(lval) | TypeConverter.ToInt32(rval); break; case AssignmentOperator.BitwiseXOrAssign: lval = TypeConverter.ToInt32(lval) ^ TypeConverter.ToInt32(rval); break; case AssignmentOperator.LeftShiftAssign: lval = TypeConverter.ToInt32(lval) << (int)(TypeConverter.ToUint32(rval) & 0x1F); break; case AssignmentOperator.RightShiftAssign: lval = TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F); break; case AssignmentOperator.UnsignedRightShiftAssign: lval = (uint)TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F); break; default: return(ExceptionHelper.ThrowNotImplementedException <object>()); } _engine.PutValue(lref, lval); _engine._referencePool.Return(lref); return(lval); }
protected override ExpressionResult EvaluateInternal(EvaluationContext context) { var lref = _left.Evaluate(context).Value as Reference; if (lref is null) { ExceptionHelper.ThrowReferenceError(context.Engine.Realm, "not a valid reference"); } var engine = context.Engine; var lval = context.Engine.GetValue(lref, false); var handledByOverload = false; if (context.OperatorOverloadingAllowed) { string operatorClrName = null; switch (_operator) { case AssignmentOperator.PlusAssign: operatorClrName = "op_Addition"; break; case AssignmentOperator.MinusAssign: operatorClrName = "op_Subtraction"; break; case AssignmentOperator.TimesAssign: operatorClrName = "op_Multiply"; break; case AssignmentOperator.DivideAssign: operatorClrName = "op_Division"; break; case AssignmentOperator.ModuloAssign: operatorClrName = "op_Modulus"; break; case AssignmentOperator.BitwiseAndAssign: operatorClrName = "op_BitwiseAnd"; break; case AssignmentOperator.BitwiseOrAssign: operatorClrName = "op_BitwiseOr"; break; case AssignmentOperator.BitwiseXOrAssign: operatorClrName = "op_ExclusiveOr"; break; case AssignmentOperator.LeftShiftAssign: operatorClrName = "op_LeftShift"; break; case AssignmentOperator.RightShiftAssign: operatorClrName = "op_RightShift"; break; case AssignmentOperator.UnsignedRightShiftAssign: operatorClrName = "op_UnsignedRightShift"; break; case AssignmentOperator.ExponentiationAssign: case AssignmentOperator.Assign: default: break; } if (operatorClrName != null) { var rval = _right.GetValue(context).Value; if (JintBinaryExpression.TryOperatorOverloading(context, lval, rval, operatorClrName, out var result)) { lval = JsValue.FromObject(context.Engine, result); handledByOverload = true; } } } if (!handledByOverload) { switch (_operator) { case AssignmentOperator.PlusAssign: { var rval = _right.GetValue(context).Value; if (AreIntegerOperands(lval, rval)) { lval = (long)lval.AsInteger() + rval.AsInteger(); } else { var lprim = TypeConverter.ToPrimitive(lval); var rprim = TypeConverter.ToPrimitive(rval); if (lprim.IsString() || rprim.IsString()) { if (!(lprim is JsString jsString)) { jsString = new JsString.ConcatenatedString(TypeConverter.ToString(lprim)); } lval = jsString.Append(rprim); } else if (!AreIntegerOperands(lval, rval)) { lval = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim); } else { lval = TypeConverter.ToBigInt(lprim) + TypeConverter.ToBigInt(rprim); } } break; } case AssignmentOperator.MinusAssign: { var rval = _right.GetValue(context).Value; if (AreIntegerOperands(lval, rval)) { lval = JsNumber.Create(lval.AsInteger() - rval.AsInteger()); } else if (!AreIntegerOperands(lval, rval)) { lval = JsNumber.Create(TypeConverter.ToNumber(lval) - TypeConverter.ToNumber(rval)); } else { lval = JsNumber.Create(TypeConverter.ToBigInt(lval) - TypeConverter.ToBigInt(rval)); } break; } case AssignmentOperator.TimesAssign: { var rval = _right.GetValue(context).Value; if (AreIntegerOperands(lval, rval)) { lval = (long)lval.AsInteger() * rval.AsInteger(); } else if (lval.IsUndefined() || rval.IsUndefined()) { lval = Undefined.Instance; } else if (!AreIntegerOperands(lval, rval)) { lval = TypeConverter.ToNumber(lval) * TypeConverter.ToNumber(rval); } else { lval = TypeConverter.ToBigInt(lval) * TypeConverter.ToBigInt(rval); } break; } case AssignmentOperator.DivideAssign: { var rval = _right.GetValue(context).Value; lval = Divide(context, lval, rval); break; } case AssignmentOperator.ModuloAssign: { var rval = _right.GetValue(context).Value; if (lval.IsUndefined() || rval.IsUndefined()) { lval = Undefined.Instance; } else if (!AreIntegerOperands(lval, rval)) { lval = TypeConverter.ToNumber(lval) % TypeConverter.ToNumber(rval); } else { lval = TypeConverter.ToNumber(lval) % TypeConverter.ToNumber(rval); } break; } case AssignmentOperator.BitwiseAndAssign: { var rval = _right.GetValue(context).Value; lval = TypeConverter.ToInt32(lval) & TypeConverter.ToInt32(rval); break; } case AssignmentOperator.BitwiseOrAssign: { var rval = _right.GetValue(context).Value; lval = TypeConverter.ToInt32(lval) | TypeConverter.ToInt32(rval); break; } case AssignmentOperator.BitwiseXOrAssign: { var rval = _right.GetValue(context).Value; lval = TypeConverter.ToInt32(lval) ^ TypeConverter.ToInt32(rval); break; } case AssignmentOperator.LeftShiftAssign: { var rval = _right.GetValue(context).Value; lval = TypeConverter.ToInt32(lval) << (int)(TypeConverter.ToUint32(rval) & 0x1F); break; } case AssignmentOperator.RightShiftAssign: { var rval = _right.GetValue(context).Value; lval = TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F); break; } case AssignmentOperator.UnsignedRightShiftAssign: { var rval = _right.GetValue(context).Value; lval = (uint)TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F); break; } case AssignmentOperator.NullishAssign: { if (!lval.IsNullOrUndefined()) { return(NormalCompletion(lval)); } var rval = NamedEvaluation(context, _right); lval = rval; break; } case AssignmentOperator.AndAssign: { if (!TypeConverter.ToBoolean(lval)) { return(NormalCompletion(lval)); } var rval = NamedEvaluation(context, _right); lval = rval; break; } case AssignmentOperator.OrAssign: { if (TypeConverter.ToBoolean(lval)) { return(NormalCompletion(lval)); } var rval = NamedEvaluation(context, _right); lval = rval; break; } case AssignmentOperator.ExponentiationAssign: { var rval = _right.GetValue(context).Value; if (!lval.IsBigInt() && !rval.IsBigInt()) { lval = JsNumber.Create(System.Math.Pow(TypeConverter.ToNumber(lval), TypeConverter.ToNumber(rval))); } else { var exponent = TypeConverter.ToBigInt(rval); if (exponent > int.MaxValue || exponent < int.MinValue) { ExceptionHelper.ThrowTypeError(context.Engine.Realm, "Cannot do exponentation with exponent not fitting int32"); } lval = JsBigInt.Create(BigInteger.Pow(TypeConverter.ToBigInt(lval), (int)exponent)); } break; } default: ExceptionHelper.ThrowNotImplementedException(); return(default); } } engine.PutValue(lref, lval); engine._referencePool.Return(lref); return(NormalCompletion(lval)); }