better support for the &&=, ||=, and ??= operators

This commit is contained in:
Erik Krogh Kristensen
2020-08-13 09:22:32 +02:00
parent fd9eb1d40b
commit d95d427c5b
6 changed files with 728 additions and 2 deletions

View File

@@ -1551,8 +1551,27 @@ public class CFGExtractor {
@Override
public Void visit(AssignmentExpression nd, SuccessorInfo i) {
visitAssign(nd, nd.getLeft(), nd.getRight());
succ(nd, i.getGuardedSuccessors(nd));
// `a &&= b` expands to `a || (a = b);`
// The CFG is a conditional assignment, so we go through the assignment `nd` last.
if ("&&=".equals(nd.getOperator()) || "||=".equals(nd.getOperator()) || "??=".equals(nd.getOperator())) {
if ("&&=".equals(nd.getOperator())) {
// from lhs to rhs on truthy. from lhs to false-branch on falsy.
visit(nd.getLeft(), First.of(nd.getRight()), i.getSuccessors(false));
} else if ("||=".equals(nd.getOperator())) {
// from lhs to true-branch on truthy. from lhs to rhs on falsy.
visit(nd.getLeft(), i.getSuccessors(true), First.of(nd.getRight()));
} else { // "??="
// the union of the above - truthyness is unknown.
visit(nd.getLeft(), union(First.of(nd.getRight()), i.getAllSuccessors()), null);
}
visit(nd.getRight(), First.of(nd), null); // from right to assignment.
succ(nd, i.getGuardedSuccessors(nd));
} else {
visitAssign(nd, nd.getLeft(), nd.getRight());
succ(nd, i.getGuardedSuccessors(nd));
}
return null;
}

View File

@@ -852,6 +852,9 @@ public class TypeScriptASTConverter {
case ">>=":
case "<<=":
case ">>>=":
case "??=":
case "&&=":
case "||=":
return new AssignmentExpression(loc, operator, convertLValue(left), right);
default: