JS(extractor): support nullish coalescing operators

This commit is contained in:
Esben Sparre Andreasen
2018-11-26 09:45:02 +01:00
parent 8d7ace25bf
commit a2a798e59c
13 changed files with 2726 additions and 8 deletions

View File

@@ -508,8 +508,12 @@ public class Parser {
private Token readToken_question() { // '?'
int next = charAt(this.pos + 1);
int next2 = charAt(this.pos + 2);
if (this.options.esnext() && next == '.' && !('0' <= next2 && next2 <= '9')) // '?.', but not '?.X' where X is a digit
return this.finishOp(TokenType.questiondot, 2);
if (this.options.esnext()) {
if (next == '.' && !('0' <= next2 && next2 <= '9')) // '?.', but not '?.X' where X is a digit
return this.finishOp(TokenType.questiondot, 2);
if (next == '?') // '??'
return this.finishOp(TokenType.questionquestion, 2);
}
return this.finishOp(TokenType.question, 1);
}

View File

@@ -123,6 +123,7 @@ public class TokenType {
}
},
prefix = new TokenType(new Properties("prefix").beforeExpr().prefix().startsExpr()),
questionquestion = new TokenType(binop("??", 1)),
logicalOR = new TokenType(binop("||", 1)),
logicalAND = new TokenType(binop("&&", 2)),
bitwiseOR = new TokenType(binop("|", 3)),

View File

@@ -331,9 +331,11 @@ public class CFGExtractor {
return nd.getKey().accept(this, v);
}
// for binary operators, the operands come first (but not for LogicalExpression, see above)
// for binary operators, the operands come first (but not for short-circuiting expressions), see above)
@Override
public Node visit(BinaryExpression nd, Void v) {
if ("??".equals(nd.getOperator()))
return nd;
return nd.getLeft().accept(this, v);
}
@@ -1583,8 +1585,16 @@ public class CFGExtractor {
@Override
public Void visit(BinaryExpression nd, SuccessorInfo i) {
this.seq(nd.getLeft(), nd.getRight(), nd);
succ(nd, i.getGuardedSuccessors(nd));
if ("??".equals(nd.getOperator())) {
// the nullish coalescing operator is short-circuiting, but we do not add guards for it
succ(nd, First.of(nd.getLeft()));
Object leftSucc = union(First.of(nd.getRight()), i.getAllSuccessors()); // short-circuiting happens with both truthy and falsy values
visit(nd.getLeft(), leftSucc, null);
nd.getRight().accept(this, i);
} else {
this.seq(nd.getLeft(), nd.getRight(), nd);
succ(nd, i.getGuardedSuccessors(nd));
}
return null;
}

View File

@@ -72,6 +72,7 @@ public class ExprKinds {
binOpKinds.put("&=", 58);
binOpKinds.put("**", 87);
binOpKinds.put("**=", 88);
binOpKinds.put("??", 107);
}
private static final Map<String, Integer> unOpKinds = new LinkedHashMap<String, Integer>();

View File

@@ -41,7 +41,7 @@ public class Main {
* such a way that it may produce different tuples for the same file under the same
* {@link ExtractorConfig}.
*/
public static final String EXTRACTOR_VERSION = "2018-11-22_a";
public static final String EXTRACTOR_VERSION = "2018-11-23";
public static final Pattern NEWLINE = Pattern.compile("\n");