private Result assertThat(String expr, String type, String decls) throws UnableToCompleteException { ConstantsAssumption.Updater updater = new ConstantsAssumption.Updater(new ConstantsAssumption()); String codeSnippet = decls; codeSnippet += "return " + expr + ";"; JProgram program = compileSnippet(type, codeSnippet); JMethod mainMethod = findMainMethod(program); JBlock block = ((JMethodBody) mainMethod.getBody()).getBlock(); List<JStatement> statements = block.getStatements(); // TODO: not a pretty assumption detection. for (JStatement stmt : statements) { if (!(stmt instanceof JDeclarationStatement)) { continue; } JDeclarationStatement decl = (JDeclarationStatement) stmt; if (decl.getInitializer() != null) { updater.set(decl.getVariableRef().getTarget(), (JValueLiteral) decl.getInitializer()); } } JReturnStatement returnStatement = (JReturnStatement) statements.get(statements.size() - 1); return new Result(ExpressionEvaluator.evaluate(returnStatement.getExpr(), updater.unwrap())); }
@Override public void endVisit(JDeclarationStatement x, Context ctx) { super.endVisit(x, ctx); lValues.pop(); // The variable may have been pruned. if (isVariablePruned(x.getVariableRef().getTarget())) { JExpression replacement = makeReplacementForAssignment(x.getSourceInfo(), x.getVariableRef(), x.getInitializer()); ctx.replaceMe(replacement.makeStatement()); } }
/** * Creates a JMultiExpression from a set of JExpressionStatements, optionally terminated by a * JReturnStatement. If the method doesn't match this pattern, it returns <code>null</code>. * * <p>If a method has a non-void return statement and can be represented as a multi-expression, * the output of the multi-expression will be the return expression of the method. If the method * is void, the output of the multi-expression should be considered undefined. */ private List<JExpression> extractExpressionsFromBody(JMethodBody body) { List<JExpression> expressions = Lists.newArrayList(); CloneCalleeExpressionVisitor cloner = new CloneCalleeExpressionVisitor(); for (JStatement stmt : body.getStatements()) { if (stmt instanceof JDeclarationStatement) { JDeclarationStatement declStatement = (JDeclarationStatement) stmt; if (!(declStatement.getVariableRef() instanceof JLocalRef)) { return null; } JExpression initializer = declStatement.getInitializer(); if (initializer == null) { continue; } JLocal local = (JLocal) declStatement.getVariableRef().getTarget(); JExpression clone = new JBinaryOperation( stmt.getSourceInfo(), local.getType(), JBinaryOperator.ASG, new JLocalRef(declStatement.getVariableRef().getSourceInfo(), local), cloner.cloneExpression(initializer)); expressions.add(clone); } else if (stmt instanceof JExpressionStatement) { JExpressionStatement exprStmt = (JExpressionStatement) stmt; JExpression expr = exprStmt.getExpr(); JExpression clone = cloner.cloneExpression(expr); expressions.add(clone); } else if (stmt instanceof JReturnStatement) { JReturnStatement returnStatement = (JReturnStatement) stmt; JExpression expr = returnStatement.getExpr(); if (expr != null) { JExpression clone = cloner.cloneExpression(expr); clone = maybeCast(clone, body.getMethod().getType()); expressions.add(clone); } // We hit an unconditional return; no need to evaluate anything else. break; } else { // Any other kind of statement won't be inlinable. return null; } } return expressions; }
@Override public boolean visit(JDeclarationStatement x, Context ctx) { super.visit(x, ctx); lValues.push(x.getVariableRef()); return true; }