Răsfoiți Sursa

Converting operators to enums

Sebastien Ros 11 ani în urmă
părinte
comite
903ff6f3e2

+ 2 - 2
Jint.Tests/Parser/JavascriptParserTests.cs

@@ -89,10 +89,10 @@ namespace Jint.Tests.Parser
             Assert.Equal(1, body.Count());
             Assert.NotNull(binary = body.First().As<ExpressionStatement>().Expression.As<BinaryExpression>());
             Assert.Equal(3d, binary.Right.As<Literal>().Value);
-            Assert.Equal("*", binary.Operator);
+            Assert.Equal(BinaryOperator.Times, binary.Operator);
             Assert.Equal(1d, binary.Left.As<BinaryExpression>().Left.As<Literal>().Value);
             Assert.Equal(2d, binary.Left.As<BinaryExpression>().Right.As<Literal>().Value);
-            Assert.Equal("+", binary.Left.As<BinaryExpression>().Operator);
+            Assert.Equal(BinaryOperator.Plus, binary.Left.As<BinaryExpression>().Operator);
         }
 
         [Theory]

+ 56 - 2
Jint/Parser/Ast/AssignmentExpression.cs

@@ -1,7 +1,61 @@
+using System;
+
 namespace Jint.Parser.Ast
 {
-    public class AssignmentExpression : BinaryExpression
+    public enum AssignmentOperator
     {
-        
+        Assign,
+        PlusAssign,
+        MinusAssign,
+        TimesAssign,
+        DivideAssign,
+        ModuloAssign,
+        BitwiseAndAssign,
+        BitwiseOrAssign,
+        BitwiseXOrAssign,
+        LeftShiftAssign,
+        RightShiftAssign,
+        UnsignedRightShiftAssign,
+    }
+
+    public class AssignmentExpression : Expression
+    {
+        public AssignmentOperator Operator;
+        public Expression Left;
+        public Expression Right;
+
+        public static AssignmentOperator ParseAssignmentOperator(string op)
+        {
+            switch (op)
+            {
+                case "=":
+                    return AssignmentOperator.Assign;
+                case "+=":
+                    return AssignmentOperator.PlusAssign;
+                case "-=":
+                    return AssignmentOperator.MinusAssign;
+                case "*=":
+                    return AssignmentOperator.TimesAssign;
+                case "/=":
+                    return AssignmentOperator.DivideAssign;
+                case "%=":
+                    return AssignmentOperator.ModuloAssign;
+                case "&=":
+                    return AssignmentOperator.BitwiseAndAssign;
+                case "|=":
+                    return AssignmentOperator.BitwiseOrAssign;
+                case "^=":
+                    return AssignmentOperator.BitwiseXOrAssign;
+                case "<<=":
+                    return AssignmentOperator.LeftShiftAssign;
+                case ">>=":
+                    return AssignmentOperator.RightShiftAssign;
+                case ">>>=":
+                    return AssignmentOperator.UnsignedRightShiftAssign;
+
+                default:
+                    throw new ArgumentOutOfRangeException("Invalid assignment operator: " + op);
+            }
+        }
     }
 }

+ 80 - 1
Jint/Parser/Ast/BinaryExpression.cs

@@ -1,9 +1,88 @@
+using System;
+
 namespace Jint.Parser.Ast
 {
+    public enum BinaryOperator
+    {
+        Plus,
+        Minus,
+        Times,
+        Divide,
+        Modulo,
+        Equal,
+        NotEqual,
+        Greater,
+        GreaterOrEqual,
+        Less,
+        LessOrEqual,
+        StrictlyEqual,
+        StricltyNotEqual,
+        BitwiseAnd,
+        BitwiseOr,
+        BitwiseXOr,
+        LeftShift,
+        RightShift,
+        UnsignedRightShift,
+        InstanceOf,
+        In,
+    }
+
     public class BinaryExpression : Expression
     {
-        public string Operator;
+        public BinaryOperator Operator;
         public Expression Left;
         public Expression Right;
+
+        public static BinaryOperator ParseBinaryOperator(string op)
+        {
+            switch (op)
+            {
+                case "+":
+                    return BinaryOperator.Plus;
+                case "-":
+                    return BinaryOperator.Minus;
+                case "*":
+                    return BinaryOperator.Times;
+                case "/":
+                    return BinaryOperator.Divide;
+                case "%":
+                    return BinaryOperator.Modulo;
+                case "==":
+                    return BinaryOperator.Equal;
+                case "!=":
+                    return BinaryOperator.NotEqual;
+                case ">":
+                    return BinaryOperator.Greater;
+                case ">=":
+                    return BinaryOperator.GreaterOrEqual;
+                case "<":
+                    return BinaryOperator.Less;
+                case "<=":
+                    return BinaryOperator.LessOrEqual;
+                case "===":
+                    return BinaryOperator.StrictlyEqual;
+                case "!==":
+                    return BinaryOperator.StricltyNotEqual;
+                case "&":
+                    return BinaryOperator.BitwiseAnd;
+                case "|":
+                    return BinaryOperator.BitwiseOr;
+                case "^":
+                    return BinaryOperator.BitwiseXOr;
+                case "<<":
+                    return BinaryOperator.LeftShift;
+                case ">>":
+                    return BinaryOperator.RightShift;
+                case ">>>":
+                    return BinaryOperator.UnsignedRightShift;
+                case "instanceof":
+                    return BinaryOperator.InstanceOf;
+                case "in":
+                    return BinaryOperator.In;
+
+                default: 
+                    throw new ArgumentOutOfRangeException("Invalid binary operator: " + op);
+            }
+        }
     }
 }

+ 26 - 1
Jint/Parser/Ast/LogicalExpression.cs

@@ -1,6 +1,31 @@
+using System;
+
 namespace Jint.Parser.Ast
 {
-    public class LogicalExpression : BinaryExpression
+    public enum LogicalOperator
     {
+        LogicalAnd,
+        LogicalOr
+    }
+
+    public class LogicalExpression : Expression
+    {
+        public LogicalOperator Operator;
+        public Expression Left;
+        public Expression Right;
+        
+        public static LogicalOperator ParseLogicalOperator(string op)
+        {
+            switch (op)
+            {
+                case "&&":
+                    return LogicalOperator.LogicalAnd;
+                case "||":
+                    return LogicalOperator.LogicalOr;
+
+                default:
+                    throw new ArgumentOutOfRangeException("Invalid binary operator: " + op);
+            }
+        }
     }
 }

+ 2 - 1
Jint/Parser/Ast/SyntaxNode.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+
 namespace Jint.Parser.Ast
 {
     public class SyntaxNode
@@ -10,7 +11,7 @@ namespace Jint.Parser.Ast
         [DebuggerStepThrough]
         public T As<T>() where T : SyntaxNode
         {
-            return this as T;
+            return (T)this;
         }
     }
 }

+ 45 - 1
Jint/Parser/Ast/UnaryExpression.cs

@@ -1,9 +1,53 @@
+using System;
+
 namespace Jint.Parser.Ast
 {
+    public enum UnaryOperator
+    {
+        Plus,
+        Minus,
+        BitwiseNot,
+        LogicalNot,
+        Delete,
+        Void,
+        TypeOf,
+        Increment,
+        Decrement,
+    }
+
     public class UnaryExpression : Expression
     {
-        public string Operator;
+        public UnaryOperator Operator;
         public Expression Argument;
         public bool Prefix;
+
+        public static UnaryOperator ParseUnaryOperator(string op)
+        {
+            switch (op)
+            {
+                case "+":
+                    return UnaryOperator.Plus;
+                case "-":
+                    return UnaryOperator.Minus;
+                case "++":
+                    return UnaryOperator.Increment;
+                case "--":
+                    return UnaryOperator.Decrement;
+                case "~":
+                    return UnaryOperator.BitwiseNot;
+                case "!":
+                    return UnaryOperator.LogicalNot;
+                case "delete":
+                    return UnaryOperator.Delete;
+                case "void":
+                    return UnaryOperator.Void;
+                case "typeof":
+                    return UnaryOperator.TypeOf;
+
+                default:
+                    throw new ArgumentOutOfRangeException("Invalid unary operator: " + op);
+
+            }
+        }
     }
 }

+ 12 - 21
Jint/Parser/JavascriptParser.cs

@@ -1374,26 +1374,27 @@ namespace Jint.Parser
             return new AssignmentExpression
                 {
                     Type = SyntaxNodes.AssignmentExpression,
-                    Operator = op,
+                    Operator = AssignmentExpression.ParseAssignmentOperator(op),
                     Left = left,
                     Right = right
                 };
         }
 
-        public BinaryExpression CreateBinaryExpression(string op, Expression left, Expression right)
+        public Expression CreateBinaryExpression(string op, Expression left, Expression right)
         {
+            
             return (op == "||" || op == "&&")
-                       ? new LogicalExpression
+                       ? (Expression)new LogicalExpression
                            {
                                Type = SyntaxNodes.LogicalExpression,
-                               Operator = op,
+                               Operator = LogicalExpression.ParseLogicalOperator(op),
                                Left = left,
                                Right = right
                            }
                        : new BinaryExpression
                            {
                                Type = SyntaxNodes.BinaryExpression,
-                               Operator = op,
+                               Operator = BinaryExpression.ParseBinaryOperator(op),
                                Left = left,
                                Right = right
                            };
@@ -1644,7 +1645,7 @@ namespace Jint.Parser
             return new UpdateExpression
                 {
                     Type = SyntaxNodes.UpdateExpression,
-                    Operator = op,
+                    Operator = UnaryExpression.ParseUnaryOperator(op),
                     Argument = argument,
                     Prefix = false
                 };
@@ -1743,22 +1744,12 @@ namespace Jint.Parser
 
         public UnaryExpression CreateUnaryExpression(string op, Expression argument)
         {
-            if (op == "++" || op == "--")
-            {
-                return new UpdateExpression
-                    {
-                        Type = SyntaxNodes.UpdateExpression,
-                        Operator = op,
-                        Argument = argument,
-                        Prefix = true
-                    };
-            }
-            return new UnaryExpression
+            return new UpdateExpression
                 {
-                    Type = SyntaxNodes.UnaryExpression,
-                    Operator = op,
+                    Type = SyntaxNodes.UpdateExpression,
+                    Operator = UnaryExpression.ParseUnaryOperator(op),
                     Argument = argument,
-                    Prefix = true
+                    Prefix = (op == "++" || op == "--")
                 };
         }
 
@@ -2487,7 +2478,7 @@ namespace Jint.Parser
                 Token token = Lex();
                 expr = ParseUnaryExpression();
                 UnaryExpression unaryExpr = CreateUnaryExpression((string) token.Value, expr);
-                if (_strict && unaryExpr.Operator == "delete" && unaryExpr.Argument.Type == SyntaxNodes.Identifier)
+                if (_strict && unaryExpr.Operator == UnaryOperator.Delete && unaryExpr.Argument.Type == SyntaxNodes.Identifier)
                 {
                     ThrowErrorTolerant(Token.Empty, Messages.StrictDelete);
                 }

+ 45 - 44
Jint/Runtime/ExpressionIntepreter.cs

@@ -50,7 +50,7 @@ namespace Jint.Runtime
                 throw new JavaScriptException(_engine.ReferenceError);
             }
 
-            if (assignmentExpression.Operator == "=")
+            if (assignmentExpression.Operator == AssignmentOperator.Assign) // "="
             {
  
                 if(lref.IsStrict() && lref.GetBase().TryCast<EnvironmentRecord>() != null && (lref.GetReferencedName() == "eval" || lref.GetReferencedName() == "arguments"))
@@ -66,7 +66,7 @@ namespace Jint.Runtime
 
             switch (assignmentExpression.Operator)
             {
-                case "+=":
+                case AssignmentOperator.PlusAssign:
                     var lprim = TypeConverter.ToPrimitive(lval);
                     var rprim = TypeConverter.ToPrimitive(rval);
                     if (lprim.IsString() || rprim.IsString())
@@ -79,11 +79,11 @@ namespace Jint.Runtime
                     }
                     break;
 
-                case "-=":
+                case AssignmentOperator.MinusAssign:
                     lval = TypeConverter.ToNumber(lval) - TypeConverter.ToNumber(rval);
                     break;
 
-                case "*=":
+                case AssignmentOperator.TimesAssign:
                     if (lval == Undefined.Instance || rval == Undefined.Instance)
                     {
                         lval = Undefined.Instance;
@@ -94,11 +94,11 @@ namespace Jint.Runtime
                     }
                     break;
 
-                case "/=":
+                case AssignmentOperator.DivideAssign:
                     lval = Divide(lval, rval);
                     break;
 
-                case "%=":
+                case AssignmentOperator.ModuloAssign:
                     if (lval == Undefined.Instance || rval == Undefined.Instance)
                     {
                         lval = Undefined.Instance;
@@ -109,27 +109,27 @@ namespace Jint.Runtime
                     }
                     break;
 
-                case "&=":
+                case AssignmentOperator.BitwiseAndAssign:
                     lval = TypeConverter.ToInt32(lval) & TypeConverter.ToInt32(rval);
                     break;
 
-                case "|=":
+                case AssignmentOperator.BitwiseOrAssign:
                     lval = TypeConverter.ToInt32(lval) | TypeConverter.ToInt32(rval);
                     break;
 
-                case "^=":
+                case AssignmentOperator.BitwiseXOrAssign:
                     lval = TypeConverter.ToInt32(lval) ^ TypeConverter.ToInt32(rval);
                     break;
 
-                case "<<=":
+                case AssignmentOperator.LeftShiftAssign:
                     lval = TypeConverter.ToInt32(lval) << (int)(TypeConverter.ToUint32(rval) & 0x1F);
                     break;
 
-                case ">>=":
+                case AssignmentOperator.RightShiftAssign:
                     lval = TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F);
                     break;
 
-                case ">>>=":
+                case AssignmentOperator.UnsignedRightShiftAssign:
                     lval = (uint)TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F);
                     break;
                 
@@ -199,9 +199,10 @@ namespace Jint.Runtime
             JsValue right = _engine.GetValue(EvaluateExpression(expression.Right));
             JsValue value;
 
+              
             switch (expression.Operator)
             {
-                case "+":
+                case BinaryOperator.Plus:
                     var lprim = TypeConverter.ToPrimitive(left);
                     var rprim = TypeConverter.ToPrimitive(right);
                     if (lprim.IsString() || rprim.IsString())
@@ -214,11 +215,11 @@ namespace Jint.Runtime
                     }
                     break;
                 
-                case "-":
+                case BinaryOperator.Minus:
                     value = TypeConverter.ToNumber(left) - TypeConverter.ToNumber(right);
                     break;
                 
-                case "*":
+                case BinaryOperator.Times:
                     if (left == Undefined.Instance || right == Undefined.Instance)
                     {
                         value = Undefined.Instance;
@@ -229,11 +230,11 @@ namespace Jint.Runtime
                     }
                     break;
                 
-                case "/":
+                case BinaryOperator.Divide:
                     value = Divide(left, right);
                     break;
 
-                case "%":
+                case BinaryOperator.Modulo:
                     if (left == Undefined.Instance || right == Undefined.Instance)
                     {
                         value = Undefined.Instance;
@@ -244,15 +245,15 @@ namespace Jint.Runtime
                     }
                     break;
 
-                case "==":
+                case BinaryOperator.Equal:
                     value = Equal(left, right);
                     break;
                 
-                case "!=":
+                case BinaryOperator.NotEqual:
                     value = !Equal(left, right);
                     break;
                 
-                case ">":
+                case BinaryOperator.Greater:
                     value = Compare(right, left, false);
                     if (value == Undefined.Instance)
                     {
@@ -260,7 +261,7 @@ namespace Jint.Runtime
                     }
                     break;
 
-                case ">=":
+                case BinaryOperator.GreaterOrEqual:
                     value = Compare(left, right);
                     if (value == Undefined.Instance || value.AsBoolean())
                     {
@@ -272,7 +273,7 @@ namespace Jint.Runtime
                     }
                     break;
                 
-                case "<":
+                case BinaryOperator.Less:
                     value = Compare(left, right);
                     if (value == Undefined.Instance)
                     {
@@ -280,7 +281,7 @@ namespace Jint.Runtime
                     }
                     break;
                 
-                case "<=":
+                case BinaryOperator.LessOrEqual:
                     value = Compare(right, left, false);
                     if (value == Undefined.Instance || value.AsBoolean())
                     {
@@ -292,31 +293,31 @@ namespace Jint.Runtime
                     }
                     break;
                 
-                case "===":
+                case BinaryOperator.StrictlyEqual:
                     return StrictlyEqual(left, right);
                 
-                case "!==":
+                case BinaryOperator.StricltyNotEqual:
                     return !StrictlyEqual(left, right);
 
-                case "&":
+                case BinaryOperator.BitwiseAnd:
                     return TypeConverter.ToInt32(left) & TypeConverter.ToInt32(right);
 
-                case "|":
+                case BinaryOperator.BitwiseOr:
                     return TypeConverter.ToInt32(left) | TypeConverter.ToInt32(right);
 
-                case "^":
+                case BinaryOperator.BitwiseXOr:
                     return TypeConverter.ToInt32(left) ^ TypeConverter.ToInt32(right);
 
-                case "<<":
+                case BinaryOperator.LeftShift:
                     return TypeConverter.ToInt32(left) << (int)(TypeConverter.ToUint32(right) & 0x1F);
 
-                case ">>":
+                case BinaryOperator.RightShift:
                     return TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F);
 
-                case ">>>":
+                case BinaryOperator.UnsignedRightShift:
                     return (uint)TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F);
 
-                case "instanceof":
+                case BinaryOperator.InstanceOf:
                     var f = right.TryCast<FunctionInstance>();
 
                     if (f == null)
@@ -327,7 +328,7 @@ namespace Jint.Runtime
                     value = f.HasInstance(left);
                     break;
                 
-                case "in":
+                case BinaryOperator.In:
                     if (!right.IsObject())
                     {
                         throw new JavaScriptException(_engine.TypeError, "in can only be used with an object");
@@ -350,7 +351,7 @@ namespace Jint.Runtime
             switch (logicalExpression.Operator)
             {
 
-                case "&&":
+                case LogicalOperator.LogicalAnd:
                     if (!TypeConverter.ToBoolean(left))
                     {
                         return left;
@@ -358,7 +359,7 @@ namespace Jint.Runtime
 
                     return _engine.GetValue(EvaluateExpression(logicalExpression.Right));
 
-                case "||":
+                case LogicalOperator.LogicalOr:
                     if (TypeConverter.ToBoolean(left))
                     {
                         return left;
@@ -857,7 +858,7 @@ namespace Jint.Runtime
 
             switch (updateExpression.Operator)
             {
-                case "++":
+                case UnaryOperator.Increment:
                     r = value as Reference;
                     if (r != null
                         && r.IsStrict()
@@ -873,7 +874,7 @@ namespace Jint.Runtime
 
                     return updateExpression.Prefix ? newValue : oldValue;
 
-                case "--":
+                case UnaryOperator.Decrement:
                     r = value as Reference;
                     if (r != null
                         && r.IsStrict()
@@ -942,20 +943,20 @@ namespace Jint.Runtime
 
             switch (unaryExpression.Operator)
             {
-                case "+":
+                case UnaryOperator.Plus:
                     return TypeConverter.ToNumber(_engine.GetValue(value));
                     
-                case "-":
+                case UnaryOperator.Minus:
                     var n = TypeConverter.ToNumber(_engine.GetValue(value));
                     return double.IsNaN(n) ? double.NaN : n*-1;
                 
-                case "~":
+                case UnaryOperator.BitwiseNot:
                     return ~TypeConverter.ToInt32(_engine.GetValue(value));
                 
-                case "!":
+                case UnaryOperator.LogicalNot:
                     return !TypeConverter.ToBoolean(_engine.GetValue(value));
                 
-                case "delete":
+                case UnaryOperator.Delete:
                     r = value as Reference;
                     if (r == null)
                     {
@@ -982,11 +983,11 @@ namespace Jint.Runtime
                     var bindings = r.GetBase().TryCast<EnvironmentRecord>();
                     return bindings.DeleteBinding(r.GetReferencedName());
                 
-                case "void":
+                case UnaryOperator.Void:
                     _engine.GetValue(value);
                     return Undefined.Instance;
 
-                case "typeof":
+                case UnaryOperator.TypeOf:
                     r = value as Reference;
                     if (r != null)
                     {