Skip to content

Commit

Permalink
Starlark: make IfStatement immutable
Browse files Browse the repository at this point in the history
Immutable objects are harder to construct, but safer/easier to work with.

Closes #11751.

PiperOrigin-RevId: 320958936
  • Loading branch information
stepancheg authored and copybara-github committed Jul 13, 2020
1 parent d8c8a2b commit 5e486a2
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,23 @@ public final class IfStatement extends Statement {
private final Expression condition;
// These blocks may be non-null but empty after a misparse:
private final ImmutableList<Statement> thenBlock; // non-empty
@Nullable ImmutableList<Statement> elseBlock; // non-empty if non-null; set after construction

@Nullable
final ImmutableList<Statement> elseBlock; // non-empty if non-null; set after construction

IfStatement(
FileLocations locs,
TokenKind token,
int ifOffset,
Expression condition,
List<Statement> thenBlock) {
List<Statement> thenBlock,
@Nullable List<Statement> elseBlock) {
super(locs);
this.token = token;
this.ifOffset = ifOffset;
this.condition = condition;
this.thenBlock = ImmutableList.copyOf(thenBlock);
this.elseBlock = elseBlock != null ? ImmutableList.copyOf(elseBlock) : null;
}

/**
Expand All @@ -63,10 +67,6 @@ public ImmutableList<Statement> getElseBlock() {
return elseBlock;
}

void setElseBlock(List<Statement> elseBlock) {
this.elseBlock = ImmutableList.copyOf(elseBlock);
}

@Override
public int getStartOffset() {
return ifOffset;
Expand Down
35 changes: 24 additions & 11 deletions src/main/java/com/google/devtools/build/lib/syntax/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -1118,24 +1118,37 @@ private IfStatement parseIfStatement() {
Expression cond = parseTest();
expect(TokenKind.COLON);
List<Statement> body = parseSuite();
IfStatement ifStmt = new IfStatement(locs, TokenKind.IF, ifOffset, cond, body);
IfStatement tail = ifStmt;

ArrayList<Integer> elifOffsets = new ArrayList<>();
ArrayList<Expression> elifConditions = new ArrayList<>();
ArrayList<List<Statement>> elifBodies = new ArrayList<>();

while (token.kind == TokenKind.ELIF) {
int elifOffset = expect(TokenKind.ELIF);
cond = parseTest();
elifOffsets.add(expect(TokenKind.ELIF));
elifConditions.add(parseTest());
expect(TokenKind.COLON);
body = parseSuite();
IfStatement elif = new IfStatement(locs, TokenKind.ELIF, elifOffset, cond, body);
tail.setElseBlock(ImmutableList.of(elif));
tail = elif;
elifBodies.add(parseSuite());
}

List<Statement> tail;
if (token.kind == TokenKind.ELSE) {
expect(TokenKind.ELSE);
expect(TokenKind.COLON);
body = parseSuite();
tail.setElseBlock(body);
tail = parseSuite();
} else {
tail = null;
}
return ifStmt;

for (int i = elifOffsets.size() - 1; i >= 0; --i) {
int elifOffset = elifOffsets.get(i);
Expression elifCondition = elifConditions.get(i);
List<Statement> elifThenBlock = elifBodies.get(i);
IfStatement elif =
new IfStatement(locs, TokenKind.ELIF, elifOffset, elifCondition, elifThenBlock, tail);
tail = ImmutableList.of(elif);
}

return new IfStatement(locs, TokenKind.IF, ifOffset, cond, body, tail);
}

// for_stmt = FOR IDENTIFIER IN expr ':' suite
Expand Down

0 comments on commit 5e486a2

Please sign in to comment.