Ejemplo n.º 1
0
        protected internal static JintExpression Build(Engine engine, Expression expression)
        {
            switch (expression.Type)
            {
            case Nodes.AssignmentExpression: return(JintAssignmentExpression.Build(engine, (AssignmentExpression)expression));

            case Nodes.ArrayExpression: return(new JintArrayExpression(engine, (ArrayExpression)expression));

            case Nodes.ArrowFunctionExpression: return(new JintArrowFunctionExpression(engine, (IFunction)expression));

            case Nodes.BinaryExpression: return(JintBinaryExpression.Build(engine, (BinaryExpression)expression));

            case Nodes.CallExpression: return(new JintCallExpression(engine, (CallExpression)expression));

            case Nodes.ConditionalExpression: return(new JintConditionalExpression(engine, (ConditionalExpression)expression));

            case Nodes.FunctionExpression: return(new JintFunctionExpression(engine, (IFunction)expression));

            case Nodes.Identifier: return(new JintIdentifierExpression(engine, (Identifier)expression));

            case Nodes.Literal: return(JintLiteralExpression.Build(engine, (Literal)expression));

            case Nodes.LogicalExpression:
                switch (((BinaryExpression)expression).Operator)
                {
                case BinaryOperator.LogicalAnd: return(new JintLogicalAndExpression(engine, (BinaryExpression)expression));

                case BinaryOperator.LogicalOr: return(new JintLogicalOrExpression(engine, (BinaryExpression)expression));

                default: return(ExceptionHelper.ThrowArgumentOutOfRangeException <JintExpression>());
                }

            case Nodes.MemberExpression: return(new JintMemberExpression(engine, (MemberExpression)expression));

            case Nodes.NewExpression: return(new JintNewExpression(engine, (NewExpression)expression));

            case Nodes.ObjectExpression: return(new JintObjectExpression(engine, (ObjectExpression)expression));

            case Nodes.SequenceExpression: return(new JintSequenceExpression(engine, (SequenceExpression)expression));

            case Nodes.ThisExpression: return(new JintThisExpression(engine, (ThisExpression)expression));

            case Nodes.UpdateExpression: return(new JintUpdateExpression(engine, (UpdateExpression)expression));

            case Nodes.UnaryExpression: return(JintUnaryExpression.Build(engine, (UnaryExpression)expression));

            case Nodes.SpreadElement: return(new JintSpreadExpression(engine, (SpreadElement)expression));

            case Nodes.TemplateLiteral: return(new JintTemplateLiteralExpression(engine, (TemplateLiteral)expression));

            case Nodes.TaggedTemplateExpression: return(new JintTaggedTemplateExpression(engine, (TaggedTemplateExpression)expression));

            default:
                return(ExceptionHelper.ThrowArgumentOutOfRangeException <JintExpression>(nameof(expression), $"unsupported expression type '{expression.Type}'"));
            }
        }
 protected internal static JintExpression Build(Engine engine, Expression expression)
 {
     return(expression.Type switch
     {
         Nodes.AssignmentExpression => JintAssignmentExpression.Build(engine, (AssignmentExpression)expression),
         Nodes.ArrayExpression => new JintArrayExpression(engine, (ArrayExpression)expression),
         Nodes.ArrowFunctionExpression => new JintArrowFunctionExpression(engine, (IFunction)expression),
         Nodes.BinaryExpression => JintBinaryExpression.Build(engine, (BinaryExpression)expression),
         Nodes.CallExpression => new JintCallExpression(engine, (CallExpression)expression),
         Nodes.ConditionalExpression => new JintConditionalExpression(engine, (ConditionalExpression)expression),
         Nodes.FunctionExpression => new JintFunctionExpression(engine, (IFunction)expression),
         Nodes.Identifier => new JintIdentifierExpression(engine, (Identifier)expression),
         Nodes.Literal => JintLiteralExpression.Build(engine, (Literal)expression),
         Nodes.LogicalExpression => ((BinaryExpression)expression).Operator switch
         {
             BinaryOperator.LogicalAnd => new JintLogicalAndExpression(engine, (BinaryExpression)expression),
             BinaryOperator.LogicalOr => new JintLogicalOrExpression(engine, (BinaryExpression)expression),
             _ => ExceptionHelper.ThrowArgumentOutOfRangeException <JintExpression>()
         },
Ejemplo n.º 3
0
 protected static bool Equal(JsValue x, JsValue y)
 {
     return(x.Type == y.Type
         ? JintBinaryExpression.StrictlyEqual(x, y)
         : EqualUnlikely(x, y));
 }
Ejemplo n.º 4
0
        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));
        }