Преглед изворни кода

Implementing logical expressions

Sebastien Ros пре 12 година
родитељ
комит
a068d4e61d

+ 1 - 1
Jint/Engine.cs

@@ -257,7 +257,7 @@ namespace Jint
                     return _expressions.EvaluateLiteral(expression.As<Literal>());
 
                 case SyntaxNodes.LogicalExpression:
-                    return null;
+                    return _expressions.EvaluateLogicalExpression(expression.As<LogicalExpression>());
 
                 case SyntaxNodes.MemberExpression:
                     return _expressions.EvaluateMemberExpression(expression.As<MemberExpression>());

+ 1 - 0
Jint/Jint.csproj

@@ -74,6 +74,7 @@
     <Compile Include="Parser\Ast\CatchClause.cs" />
     <Compile Include="Parser\Ast\ConditionalExpression.cs" />
     <Compile Include="Parser\Ast\ContinueStatement.cs" />
+    <Compile Include="Parser\Ast\LogicalExpression.cs" />
     <Compile Include="Parser\Ast\DebuggerStatement.cs" />
     <Compile Include="Parser\Ast\DoWhileStatement.cs" />
     <Compile Include="Parser\Ast\EmptyStatement.cs" />

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

@@ -1,4 +1,3 @@
-using System;
 namespace Jint.Parser.Ast
 {
     public class BinaryExpression : Expression

+ 6 - 0
Jint/Parser/Ast/LogicalExpression.cs

@@ -0,0 +1,6 @@
+namespace Jint.Parser.Ast
+{
+    public class LogicalExpression : BinaryExpression
+    {
+    }
+}

+ 15 - 8
Jint/Parser/JavascriptParser.cs

@@ -1357,14 +1357,21 @@ namespace Jint.Parser
 
         public BinaryExpression CreateBinaryExpression(string op, Expression left, Expression right)
         {
-            SyntaxNodes type = (op == "||" || op == "&&") ? SyntaxNodes.LogicalExpression : SyntaxNodes.BinaryExpression;
-            return new BinaryExpression
-                {
-                    Type = type,
-                    Operator = op,
-                    Left = left,
-                    Right = right
-                };
+            return (op == "||" || op == "&&")
+                       ? new LogicalExpression
+                           {
+                               Type = SyntaxNodes.LogicalExpression,
+                               Operator = op,
+                               Left = left,
+                               Right = right
+                           }
+                       : new BinaryExpression
+                           {
+                               Type = SyntaxNodes.BinaryExpression,
+                               Operator = op,
+                               Left = left,
+                               Right = right
+                           };
         }
 
         public BlockStatement CreateBlockStatement(IEnumerable<Statement> body)

+ 35 - 3
Jint/Runtime/ExpressionIntepreter.cs

@@ -67,7 +67,7 @@ namespace Jint.Runtime
                     break;
 
                 case "-=":
-                    lval = TypeConverter.ToNumber(lval) + TypeConverter.ToNumber(rval);
+                    lval = TypeConverter.ToNumber(lval) - TypeConverter.ToNumber(rval);
                     break;
 
                 case "*=":
@@ -119,6 +119,10 @@ namespace Jint.Runtime
                     lval = TypeConverter.ToInt32(lval) << (int)(TypeConverter.ToUint32(rval) & 0x1F);
                     break;
 
+                case ">>=":
+                    lval = TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F);
+                    break;
+
                 case ">>>=":
                     lval = (uint)TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F);
                     break;
@@ -252,6 +256,34 @@ namespace Jint.Runtime
             return value;
         }
 
+        public object EvaluateLogicalExpression(LogicalExpression logicalExpression)
+        {
+            var left = _engine.GetValue(EvaluateExpression(logicalExpression.Left));
+
+            switch (logicalExpression.Operator)
+            {
+
+                case "&&":
+                    if (!TypeConverter.ToBoolean(left))
+                    {
+                        return left;
+                    }
+
+                    return _engine.GetValue(EvaluateExpression(logicalExpression.Right));
+
+                case "||":
+                    if (TypeConverter.ToBoolean(left))
+                    {
+                        return left;
+                    }
+
+                    return _engine.GetValue(EvaluateExpression(logicalExpression.Right));
+
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
         public static bool StriclyEqual(object x, object y)
         {
             var typea = TypeConverter.GetType(x);
@@ -505,7 +537,7 @@ namespace Jint.Runtime
 
         public object EvaluateNewExpression(NewExpression newExpression)
         {
-            var arguments = newExpression.Arguments.Select(EvaluateExpression).ToArray();
+            var arguments = newExpression.Arguments.Select(EvaluateExpression).Select(_engine.GetValue).ToArray();
             
             // todo: optimize by defining a common abstract class or interface
             var callee = (IConstructor)_engine.GetValue(EvaluateExpression(newExpression.Callee));
@@ -521,7 +553,7 @@ namespace Jint.Runtime
 
         public object EvaluateArrayExpression(ArrayExpression arrayExpression)
         {
-            var arguments = arrayExpression.Elements.Select(EvaluateExpression).ToArray();
+            var arguments = arrayExpression.Elements.Select(EvaluateExpression).Select(_engine.GetValue).ToArray();
 
             // construct the new instance using the Function's constructor method
             var instance = _engine.Array.Construct(arguments);

+ 39 - 6
Jint/Runtime/TypeConverter.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Globalization;
 using Jint.Native;
 using Jint.Native.Object;
 
@@ -19,9 +20,10 @@ namespace Jint.Runtime
                 return input;
             }
 
-            if (input is IPrimitiveType)
+            var primitive = input as IPrimitiveType;
+            if (primitive != null)
             {
-                return input;
+                return primitive.PrimitiveValue;
             }
 
             var o = input as ObjectInstance;
@@ -85,7 +87,12 @@ namespace Jint.Runtime
 
             if (o is int)
             {
-                return ToBoolean((double) (int) o);
+                return ToBoolean((double)(int)o);
+            }
+
+            if (o is uint)
+            {
+                return ToBoolean((double)(uint)o);
             }
 
             return true;
@@ -108,6 +115,11 @@ namespace Jint.Runtime
                 return (int) o;
             }
 
+            if (o is uint)
+            {
+                return (uint) o;
+            }
+
             if (o == Undefined.Instance)
             {
                 return double.NaN;
@@ -126,7 +138,13 @@ namespace Jint.Runtime
             var s = o as string;
             if (s != null)
             {
-                return double.Parse(s);
+                double n;
+                if (double.TryParse(s, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out n))
+                {
+                    return n;
+                }
+
+                return double.NaN;
             }
 
             return ToNumber(ToPrimitive(o, TypeCode.Double));
@@ -144,6 +162,11 @@ namespace Jint.Runtime
                 return (int) o;
             }
 
+            if (o is uint)
+            {
+                return (int) (uint) o;
+            }
+
             var number = ToNumber(o);
             if (double.IsNaN(number))
             {
@@ -162,7 +185,12 @@ namespace Jint.Runtime
         {
             if (o is int)
             {
-                return (int) o;
+                return (int)o;
+            }
+
+            if (o is uint)
+            {
+                return (int) (uint) o;
             }
 
             var n = ToNumber(o);
@@ -259,7 +287,12 @@ namespace Jint.Runtime
 
             if (o is int)
             {
-                return ToString((double) (int) o);
+                return ToString((double)(int)o);
+            }
+
+            if (o is uint)
+            {
+                return ToString((double)(uint)o);
             }
 
             return ToString(ToPrimitive(o, TypeCode.String));