Fix support of - and + prefix operators in JS parser

Treat number literal that represents minimum integer as integer node in
JS AST.

Treat +<number_literal> JS AST as unary node (+) containing single
number literal
This commit is contained in:
Alexey Andreev
2017-05-22 17:32:00 +03:00
parent 590954e9a8
commit 1dae687e7d
5 changed files with 28 additions and 32 deletions
@@ -681,7 +681,13 @@ public class JsAstMapper {
} }
private static JsExpression mapIntNumber(Node numberNode) { private static JsExpression mapIntNumber(Node numberNode) {
return new JsIntLiteral((int) numberNode.getDouble()); double value = numberNode.getDouble();
if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) {
return new JsIntLiteral((int) numberNode.getDouble());
}
else {
return new JsDoubleLiteral(numberNode.getDouble());
}
} }
private static JsExpression mapDoubleNumber(Node numberNode) { private static JsExpression mapDoubleNumber(Node numberNode) {
@@ -1032,8 +1038,17 @@ public class JsAstMapper {
private JsExpression mapUnaryVariant(Node unOp) throws JsParserException { private JsExpression mapUnaryVariant(Node unOp) throws JsParserException {
switch (unOp.getOperation()) { switch (unOp.getOperation()) {
case TokenStream.SUB: case TokenStream.SUB: {
Node operand = unOp.getFirstChild();
if (operand.getType() == TokenStream.NUMBER_INT) {
double value = operand.getDouble();
if (-value >= Integer.MIN_VALUE) {
return new JsIntLiteral((int) -value);
}
}
return mapPrefixOperation(JsUnaryOperator.NEG, unOp); return mapPrefixOperation(JsUnaryOperator.NEG, unOp);
}
case TokenStream.NOT: case TokenStream.NOT:
return mapPrefixOperation(JsUnaryOperator.NOT, unOp); return mapPrefixOperation(JsUnaryOperator.NOT, unOp);
@@ -1045,13 +1060,7 @@ public class JsAstMapper {
return mapPrefixOperation(JsUnaryOperator.TYPEOF, unOp); return mapPrefixOperation(JsUnaryOperator.TYPEOF, unOp);
case TokenStream.ADD: case TokenStream.ADD:
if (!isJsNumber(unOp.getFirstChild())) { return mapPrefixOperation(JsUnaryOperator.POS, unOp);
return mapPrefixOperation(JsUnaryOperator.POS, unOp);
}
else {
// Pretend we didn't see it.
return mapExpression(unOp.getFirstChild());
}
case TokenStream.VOID: case TokenStream.VOID:
return mapPrefixOperation(JsUnaryOperator.VOID, unOp); return mapPrefixOperation(JsUnaryOperator.VOID, unOp);
@@ -1098,11 +1107,6 @@ public class JsAstMapper {
withNode); withNode);
} }
private boolean isJsNumber(Node jsNode) {
int type = jsNode.getType();
return type == TokenStream.NUMBER || type == TokenStream.NUMBER;
}
private <T extends JsNode> T withLocation(T astNode, Node node) { private <T extends JsNode> T withLocation(T astNode, Node node) {
CodePosition location = node.getPosition(); CodePosition location = node.getPosition();
if (location != null) { if (location != null) {
@@ -106,8 +106,8 @@ public class IRFactory {
/** /**
* Number (for literals) * Number (for literals)
*/ */
public Node createNumber(int number, CodePosition location) { public Node createIntNumber(double number, CodePosition location) {
return Node.newNumber(number, location); return Node.newIntNumber(number, location);
} }
public Node createNumber(double number, CodePosition location) { public Node createNumber(double number, CodePosition location) {
@@ -45,14 +45,8 @@ package com.google.gwt.dev.js.rhino;
public class Node implements Cloneable { public class Node implements Cloneable {
private static class NumberNode extends Node { private static class NumberNode extends Node {
NumberNode(int type, double number, CodePosition position) {
NumberNode(int number, CodePosition location) { super(type, position);
super(TokenStream.NUMBER_INT, location);
this.number = number;
}
NumberNode(double number, CodePosition position) {
super(TokenStream.NUMBER, position);
this.number = number; this.number = number;
} }
@@ -181,12 +175,12 @@ public class Node implements Cloneable {
this.position = position; this.position = position;
} }
public static Node newNumber(int number, CodePosition position) { public static Node newIntNumber(double number, CodePosition position) {
return new NumberNode(number, position); return new NumberNode(TokenStream.NUMBER_INT, number, position);
} }
public static Node newNumber(double number, CodePosition position) { public static Node newNumber(double number, CodePosition position) {
return new NumberNode(number, position); return new NumberNode(TokenStream.NUMBER, number, position);
} }
public static Node newString(String str, CodePosition position) { public static Node newString(String str, CodePosition position) {
@@ -1068,8 +1068,7 @@ public class Parser extends Observable {
property = nf.createString(ts.getString(), ts.tokenPosition); property = nf.createString(ts.getString(), ts.tokenPosition);
break; break;
case TokenStream.NUMBER_INT: case TokenStream.NUMBER_INT:
int n = (int) ts.getNumber(); property = nf.createIntNumber(ts.getNumber(), ts.tokenPosition);
property = nf.createNumber(n, ts.tokenPosition);
break; break;
case TokenStream.NUMBER: case TokenStream.NUMBER:
double d = ts.getNumber(); double d = ts.getNumber();
@@ -1114,8 +1113,7 @@ public class Parser extends Observable {
return nf.createName(name, position); return nf.createName(name, position);
case TokenStream.NUMBER_INT: case TokenStream.NUMBER_INT:
int n = (int) ts.getNumber(); return nf.createIntNumber(ts.getNumber(), position);
return nf.createNumber(n, position);
case TokenStream.NUMBER: case TokenStream.NUMBER:
double d = ts.getNumber(); double d = ts.getNumber();
@@ -802,7 +802,7 @@ public class TokenStream {
this.number = dval; this.number = dval;
if (isInteger && this.number >= Integer.MIN_VALUE && this.number <= Integer.MAX_VALUE) { if (isInteger) {
return NUMBER_INT; return NUMBER_INT;
} }