8185252: Unary minus and plus use wrong node Kind
authorhannesw
Thu, 10 Aug 2017 15:19:17 +0200
changeset 46169 b385216af0ed
parent 46168 a586a1c1a9e3
child 46170 684380faae7c
8185252: Unary minus and plus use wrong node Kind Reviewed-by: sundar, hannesw Contributed-by: priya.lakshmi.muthuswamy@oracle.com
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TreeImpl.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/UnaryNode.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java
nashorn/test/script/nosecurity/JDK-8185252.js
nashorn/test/script/nosecurity/JDK-8185252.js.EXPECTED
nashorn/test/script/nosecurity/parserapi.js.EXPECTED
nashorn/test/script/nosecurity/parservisitor.js.EXPECTED
nashorn/test/script/nosecurity/treeapi/array_access.js.EXPECTED
nashorn/test/script/nosecurity/treeapi/unary.js.EXPECTED
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TreeImpl.java	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TreeImpl.java	Thu Aug 10 15:19:17 2017 +0200
@@ -75,6 +75,8 @@
                 return Kind.MULTIPLY;
             case ASSIGN_MUL:
                 return Kind.MULTIPLY_ASSIGNMENT;
+            case POS:
+                return Kind.UNARY_PLUS;
             case ADD:
                 return Kind.PLUS;
             case INCPREFIX:
@@ -83,6 +85,8 @@
                 return Kind.POSTFIX_INCREMENT;
             case ASSIGN_ADD:
                 return Kind.PLUS_ASSIGNMENT;
+            case NEG:
+                return Kind.UNARY_MINUS;
             case SUB:
                 return Kind.MINUS;
             case DECPREFIX:
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Aug 10 15:19:17 2017 +0200
@@ -1027,7 +1027,7 @@
             }
 
             @Override
-            public boolean enterSUB(final UnaryNode unaryNode) {
+            public boolean enterNEG(final UnaryNode unaryNode) {
                 loadSUB(unaryNode, resultBounds);
                 return false;
             }
@@ -1105,7 +1105,7 @@
             }
 
             @Override
-            public boolean enterADD(final UnaryNode unaryNode) {
+            public boolean enterPOS(final UnaryNode unaryNode) {
                 loadADD(unaryNode, resultBounds);
                 return false;
             }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java	Thu Aug 10 15:19:17 2017 +0200
@@ -231,7 +231,7 @@
             LiteralNode<?> literalNode;
 
             switch (parent.tokenType()) {
-            case ADD:
+            case POS:
                 if (rhsInteger) {
                     literalNode = LiteralNode.newInstance(token, finish, rhs.getInt32());
                 } else if (rhsType.isLong()) {
@@ -240,7 +240,7 @@
                     literalNode = LiteralNode.newInstance(token, finish, rhs.getNumber());
                 }
                 break;
-            case SUB:
+            case NEG:
                 if (rhsInteger && rhs.getInt32() != 0) { // @see test/script/basic/minuszero.js
                     literalNode = LiteralNode.newInstance(token, finish, -rhs.getInt32());
                 } else if (rhsType.isLong() && rhs.getLong() != 0L) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java	Thu Aug 10 15:19:17 2017 +0200
@@ -317,7 +317,7 @@
     }
 
     @Override
-    public Node leaveADD(final UnaryNode unaryNode) {
+    public Node leavePOS(final UnaryNode unaryNode) {
         return unaryNodeWeight(unaryNode);
     }
 
@@ -348,7 +348,7 @@
     }
 
     @Override
-    public Node leaveSUB(final UnaryNode unaryNode) {
+    public Node leaveNEG(final UnaryNode unaryNode) {
         return unaryNodeWeight(unaryNode);
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/UnaryNode.java	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/UnaryNode.java	Thu Aug 10 15:19:17 2017 +0200
@@ -58,8 +58,8 @@
     private static final List<TokenType> CAN_OVERFLOW =
             Collections.unmodifiableList(
                 Arrays.asList(new TokenType[] {
-                    TokenType.ADD,
-                    TokenType.SUB, //negate
+                    TokenType.POS,
+                    TokenType.NEG, //negate
                     TokenType.DECPREFIX,
                     TokenType.DECPOSTFIX,
                     TokenType.INCPREFIX,
@@ -125,7 +125,7 @@
     @Override
     public Type getWidestOperationType() {
         switch (tokenType()) {
-        case ADD:
+        case POS:
             final Type operandType = getExpression().getType();
             if(operandType == Type.BOOLEAN) {
                 return Type.INT;
@@ -134,7 +134,7 @@
             }
             assert operandType.isNumeric();
             return operandType;
-        case SUB:
+        case NEG:
             // This might seems overly conservative until you consider that -0 can only be represented as a double.
             return Type.NUMBER;
         case NOT:
@@ -182,8 +182,8 @@
         switch (tokenType()) {
         case NEW:
             return false;
-        case ADD:
-        case SUB:
+        case POS:
+        case NEG:
         case NOT:
         case BIT_NOT:
             return expression.isLocal() && expression.getType().isJSPrimitive();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Thu Aug 10 15:19:17 2017 +0200
@@ -47,8 +47,8 @@
     @Override
     public boolean enterUnaryNode(final UnaryNode unaryNode) {
         switch (unaryNode.tokenType()) {
-        case ADD:
-            return enterADD(unaryNode);
+        case POS:
+            return enterPOS(unaryNode);
         case BIT_NOT:
             return enterBIT_NOT(unaryNode);
         case DELETE:
@@ -57,8 +57,8 @@
             return enterNEW(unaryNode);
         case NOT:
             return enterNOT(unaryNode);
-        case SUB:
-            return enterSUB(unaryNode);
+        case NEG:
+            return enterNEG(unaryNode);
         case TYPEOF:
             return enterTYPEOF(unaryNode);
         case VOID:
@@ -76,8 +76,8 @@
     @Override
     public final Node leaveUnaryNode(final UnaryNode unaryNode) {
         switch (unaryNode.tokenType()) {
-        case ADD:
-            return leaveADD(unaryNode);
+        case POS:
+            return leavePOS(unaryNode);
         case BIT_NOT:
             return leaveBIT_NOT(unaryNode);
         case DELETE:
@@ -86,8 +86,8 @@
             return leaveNEW(unaryNode);
         case NOT:
             return leaveNOT(unaryNode);
-        case SUB:
-            return leaveSUB(unaryNode);
+        case NEG:
+            return leaveNEG(unaryNode);
         case TYPEOF:
             return leaveTYPEOF(unaryNode);
         case VOID:
@@ -280,7 +280,7 @@
      * @param  unaryNode the node
      * @return true if traversal should continue and node children be traversed, false otherwise
      */
-    public boolean enterADD(final UnaryNode unaryNode) {
+    public boolean enterPOS(final UnaryNode unaryNode) {
         return enterDefault(unaryNode);
     }
 
@@ -290,7 +290,7 @@
      * @param  unaryNode the node
      * @return processed node, which will replace the original one, or the original node
      */
-     public Node leaveADD(final UnaryNode unaryNode) {
+     public Node leavePOS(final UnaryNode unaryNode) {
         return leaveDefault(unaryNode);
     }
 
@@ -400,7 +400,7 @@
      * @param  unaryNode the node
      * @return true if traversal should continue and node children be traversed, false otherwise
      */
-    public boolean enterSUB(final UnaryNode unaryNode) {
+    public boolean enterNEG(final UnaryNode unaryNode) {
         return enterDefault(unaryNode);
     }
 
@@ -410,7 +410,7 @@
      * @param  unaryNode the node
      * @return processed node, which will replace the original one, or the original node
      */
-    public Node leaveSUB(final UnaryNode unaryNode) {
+    public Node leaveNEG(final UnaryNode unaryNode) {
         return leaveDefault(unaryNode);
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Thu Aug 10 15:19:17 2017 +0200
@@ -4391,10 +4391,15 @@
             appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
             return LiteralNode.newInstance(unaryToken, finish, true);
         }
+        case ADD:
+        case SUB: {
+            final TokenType opType = type;
+            next();
+            final Expression expr = unaryExpression();
+            return new UnaryNode(Token.recast(unaryToken, (opType == TokenType.ADD) ? TokenType.POS : TokenType.NEG), expr);
+        }
         case VOID:
         case TYPEOF:
-        case ADD:
-        case SUB:
         case BIT_NOT:
         case NOT:
             next();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java	Thu Aug 10 15:19:17 2017 +0200
@@ -63,10 +63,12 @@
     RPAREN         (BRACKET, ")",     0, true),
     MUL            (BINARY,  "*",    13, true),
     ASSIGN_MUL     (BINARY,  "*=",    2, false),
+    POS            (UNARY,   "+",    14, false),
     ADD            (BINARY,  "+",    12, true),
     INCPREFIX      (UNARY,   "++",   15, true),
     ASSIGN_ADD     (BINARY,  "+=",    2, false),
     COMMARIGHT     (BINARY,  ",",     1, true),
+    NEG            (UNARY,   "-",    14, false),
     SUB            (BINARY,  "-",    12, true),
     DECPREFIX      (UNARY,   "--",   15, true),
     ASSIGN_SUB     (BINARY,  "-=",    2, false),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/JDK-8185252.js	Thu Aug 10 15:19:17 2017 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test that Unary minus and plus uses UNARY_MINUS and UNARY_PLUS node Kind
+ *
+ * @test
+ * @bug 8185252
+ * @option -scripting
+ * @run
+ */
+
+var parser = Java.type('jdk.nashorn.api.tree.Parser');
+var tree = Java.type('jdk.nashorn.api.tree.Tree');
+var list = Java.type('java.util.List');
+var visitor = Java.type('jdk.nashorn.api.tree.SimpleTreeVisitorES5_1');
+var cls = Java.type('java.lang.Class')
+
+function convert (value) {
+    if (!value || typeof(value) != 'object') {
+        return value;
+    }
+    var  obj = Object.bindProperties({}, value)
+    var result = {}
+    for (var i in obj) {
+        if (i == "lineMap") {
+            continue;
+        }
+
+        var val = obj[i]
+        // skip these ES6 specific properties to reduce noise
+        // in the output - unless there were set to true
+        if (typeof(val) == 'boolean' && val == false) {
+            switch (i) {
+                case "computed":
+                case "static":
+                case "restParameter":
+                case "this":
+                case "super":
+                case "star":
+                case "default":
+                case "starDefaultStar":
+                case "arrow":
+                case "generator":
+                case "let":
+                case "const":
+                    continue;
+             }
+        }
+
+        if (typeof(val) == 'object') {
+            if (val instanceof cls) {
+                continue;
+            }
+            if (val instanceof tree) {
+                result[i] = convert(val)
+            }
+            else if (val instanceof list) {
+                var lst = []
+                for (var j in val) {
+                    lst.push(convert(val[j]))
+                }
+                result[i] = lst
+            }
+            else {
+                result[i] = String(val)
+            }
+        } else if (typeof(val) != 'function') {
+            result[i] = String(val)
+        }
+    }
+    return result
+}
+
+function parse(name, code, args, visitor, listener) {
+    var tree =  parser.create(args).parse(name, code, listener || null)
+    var results = []
+    tree.accept(visitor, results)
+    print(JSON.stringify(results, null, 2))
+}
+
+
+var code = <<EOF
+
++1;
+-1;
+
+EOF
+
+parse("JDK-8185252.js", code, "-nse", new (Java.extend(visitor, {
+    visitUnary: function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/JDK-8185252.js.EXPECTED	Thu Aug 10 15:19:17 2017 +0200
@@ -0,0 +1,24 @@
+[
+  {
+    "expression": {
+      "endPosition": "3",
+      "kind": "NUMBER_LITERAL",
+      "value": "1",
+      "startPosition": "2"
+    },
+    "endPosition": "3",
+    "kind": "UNARY_PLUS",
+    "startPosition": "1"
+  },
+  {
+    "expression": {
+      "endPosition": "7",
+      "kind": "NUMBER_LITERAL",
+      "value": "1",
+      "startPosition": "6"
+    },
+    "endPosition": "7",
+    "kind": "UNARY_MINUS",
+    "startPosition": "5"
+  }
+]
--- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED	Thu Aug 10 15:19:17 2017 +0200
@@ -3983,7 +3983,7 @@
           "startPosition": "1164"
         },
         "endPosition": "1165",
-        "kind": "PLUS",
+        "kind": "UNARY_PLUS",
         "startPosition": "1163"
       },
       "endPosition": "1165",
@@ -3999,7 +3999,7 @@
           "startPosition": "1168"
         },
         "endPosition": "1169",
-        "kind": "MINUS",
+        "kind": "UNARY_MINUS",
         "startPosition": "1167"
       },
       "endPosition": "1169",
--- a/nashorn/test/script/nosecurity/parservisitor.js.EXPECTED	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/test/script/nosecurity/parservisitor.js.EXPECTED	Thu Aug 10 15:19:17 2017 +0200
@@ -75,8 +75,8 @@
 in visitUnary POSTFIX_DECREMENT x
 in visitUnary PREFIX_INCREMENT x
 in visitUnary PREFIX_DECREMENT x
-in visitUnary PLUS x
-in visitUnary MINUS x
+in visitUnary UNARY_PLUS x
+in visitUnary UNARY_MINUS x
 in visitUnary BITWISE_COMPLEMENT x
 in visitUnary LOGICAL_COMPLEMENT x
 in visitUnary DELETE x
--- a/nashorn/test/script/nosecurity/treeapi/array_access.js.EXPECTED	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/array_access.js.EXPECTED	Thu Aug 10 15:19:17 2017 +0200
@@ -73,7 +73,7 @@
         "startPosition": "121"
       },
       "endPosition": "122",
-      "kind": "MINUS",
+      "kind": "UNARY_MINUS",
       "startPosition": "120"
     },
     "startPosition": "114"
--- a/nashorn/test/script/nosecurity/treeapi/unary.js.EXPECTED	Tue Aug 08 22:52:18 2017 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/unary.js.EXPECTED	Thu Aug 10 15:19:17 2017 +0200
@@ -84,7 +84,7 @@
       "startPosition": "50"
     },
     "endPosition": "51",
-    "kind": "PLUS",
+    "kind": "UNARY_PLUS",
     "startPosition": "49"
   },
   {
@@ -95,7 +95,7 @@
       "startPosition": "54"
     },
     "endPosition": "55",
-    "kind": "MINUS",
+    "kind": "UNARY_MINUS",
     "startPosition": "53"
   },
   {