public <T> CtTargetedExpression<T, CtExpression<?>> guardedStageMethodCall(
CtInvocation<T> invocation, CtMethod<T> stageMethod) {
if (!stageMethods.containsKey(stageMethod))
throw new StageGraphCompilationException(stageMethod + " doesn't belong to " + this);
@SuppressWarnings("unchecked")
Map<CtMethod<T>, CtMethod<T>> stageMethods =
(Map<CtMethod<T>, CtMethod<T>>) (Map) this.stageMethods;
return f().Code().createInvocation(null, stageMethods.computeIfAbsent(stageMethod, m -> {
CtMethod<T> guarded = createSimpleMethod(m.getType(), m.getSimpleName() + "Guarded");
addGuardingPrologue(guarded);
guarded.setParameters(new ArrayList<>(m.getParameters()));
List<CtExpression<?>> arguments = m.getParameters().stream()
.map(p -> p.getReference())
.map(pr -> f().Code().createVariableRead(pr, false))
.collect(toList());
CtInvocation<T> innerInvocation =
f().Code().createInvocation(null, m.getReference(), arguments);
if (m.getType().equals(f().Type().VOID_PRIMITIVE)) {
guarded.getBody().addStatement(innerInvocation);
} else {
CtReturn<T> ctReturn = f().Core().createReturn();
ctReturn.setReturnedExpression(innerInvocation);
guarded.getBody().addStatement(ctReturn);
}
return guarded;
}).getReference(), invocation.getArguments());
}