// body.
var:
for (Var v : vars) {
if ("arguments".equals(v.name)) { continue; } // special in function body
Symbol s = v.s.getSymbol(v.name);
Expression value;
int initPos;
boolean isConst;
AncestorChain<Identifier> write;
switch (s.writes.size()) {
case 1:
write = s.writes.get(0);
if (write.parent.node instanceof Declaration) {
initPos = write.parent.node instanceof FunctionDeclaration
? -1 // hoisted
: positions.get(write);
AncestorChain<Declaration> d = write.parent.cast(Declaration.class);
value = d.node.getInitializer();
isConst = isConst(value);
if (!isConst
&& (!isSinglyInlineable(value) || s.reads.size() > 1)) {
continue var;
}
} else {
continue var;
}
break;
case 0:
initPos = -1;
value = null;
write = null;
isConst = true;
break;
default:
continue var;
}
// If there is at most one assignment at the top level of the function
// and all reads occur after that, and the value is constant, then
// inline uses.
// TODO: we can safely inline the reads that are okay.
// TODO: check that reads are in the same function
// or before the first call or member dereference op.
int nInlined = 0;
for (AncestorChain<Identifier> read : s.reads) {
// If the read occur afterwards lexically, then, since we
// know the declaration appears at the top of a run of
// declarations in a function body, then it isn't being read by
// any of the earlier declarations ; so the read must happen
// after the var is initialized.
if (positions.get(read) < initPos) { continue; }
if (write != null && !inSameFn(write, read)) {
// Can't reuse reference values across function boundaries.
if (!isConst) { continue; }
// If the use is across function boundaries, and there might have
// been a non-local transfer of control, then we can't inline.
if (initPos > v.s.earliestNonLocalXfer) { continue; }
}
AncestorChain<Reference> toReplace = read.parent.cast(Reference.class);
Expression repl;
if (value == null) {
FilePosition fp = toReplace.node.getFilePosition();
repl = Operation.create(fp, Operator.VOID, new IntegerLiteral(fp, 0));
} else {
repl = (Expression) value.clone();