in src/main/java/net/hydromatic/linq4j/expressions/BlockBuilder.java [97:158]
public Expression append(String name, BlockStatement block,
boolean optimize) {
if (statements.size() > 0) {
Statement lastStatement = statements.get(statements.size() - 1);
if (lastStatement instanceof GotoStatement) {
// convert "return expr;" into "expr;"
statements.set(statements.size() - 1, Expressions.statement(
((GotoStatement) lastStatement).expression));
}
}
Expression result = null;
final Map<ParameterExpression, Expression> replacements =
new IdentityHashMap<ParameterExpression, Expression>();
final Visitor visitor = new SubstituteVariableVisitor(replacements);
for (int i = 0; i < block.statements.size(); i++) {
Statement statement = block.statements.get(i);
if (!replacements.isEmpty()) {
// Save effort, and only substitute variables if there are some.
statement = statement.accept(visitor);
}
if (statement instanceof DeclarationStatement) {
DeclarationStatement declaration = (DeclarationStatement) statement;
if (variables.contains(declaration.parameter.name)) {
Expression x = append(
newName(declaration.parameter.name, optimize),
declaration.initializer);
statement = null;
result = x;
if (declaration.parameter != x) {
// declaration.parameter can be equal to x if exactly the same
// declaration was present in BlockBuilder
replacements.put(declaration.parameter, x);
}
} else {
add(statement);
}
} else {
add(statement);
}
if (i == block.statements.size() - 1) {
if (statement instanceof DeclarationStatement) {
result = ((DeclarationStatement) statement).parameter;
} else if (statement instanceof GotoStatement) {
statements.remove(statements.size() - 1);
result = append_(name, ((GotoStatement) statement).expression,
optimize);
if (isSimpleExpression(result)) {
// already simple; no need to declare a variable or
// even to evaluate the expression
} else {
DeclarationStatement declare = Expressions.declare(Modifier.FINAL,
newName(name, optimize), result);
add(declare);
result = declare.parameter;
}
} else {
// not an expression -- result remains null
}
}
}
return result;
}