package net.sf.eclipsefp.haskell.debug.ui.internal.debug;
import net.sf.eclipsefp.haskell.debug.core.internal.debug.HaskellDebugElement;
import net.sf.eclipsefp.haskell.debug.core.internal.debug.HaskellValue;
import net.sf.eclipsefp.haskell.debug.ui.internal.util.UITexts;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.ISuspendResume;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IWatchExpressionDelegate;
import org.eclipse.debug.core.model.IWatchExpressionListener;
import org.eclipse.debug.core.model.IWatchExpressionResult;
/**
* Delegate to evaluate haskell expression in GHCi debugging session
* @author JP Moresmau
*
*/
public class HaskellWatchExpressionDelegate implements IWatchExpressionDelegate {
@Override
public void evaluateExpression( final String expression, final IDebugElement context,
final IWatchExpressionListener listener ) {
HaskellDebugElement hde=(HaskellDebugElement)context;
/** this code allows expressions that are valid in the scope of the module to be evaluated
* however, it gets problematic when we also have breakpoints: the top level expression may also reach the breakpoint
* so when we reach the breakpoint once, we stop, try to reevaluate the top level expression which in turn reaches the breakpoint...
* the solution is to always :force the evals if we're not considered suspended
*/
boolean isSuspended=(hde instanceof ISuspendResume && ((ISuspendResume)hde).isSuspended()) || hde.getDebugTarget().isSuspended();
if (isSuspended|| hde.getDebugTarget().isAtEnd()){
try {
boolean force=!isSuspended;
HaskellValue val=hde.getDebugTarget().evaluate( expression,force );
listener.watchEvaluationFinished( new WatchExpressionResult( expression, val, null ));
} catch (DebugException de){
listener.watchEvaluationFinished( new WatchExpressionResult( expression, null, de ));
}
} else {
listener.watchEvaluationFinished( new WatchExpressionResult(expression,null,null) );
}
}
/**
* Wraps either:
* - a HaskellValue if we could evaluate the expression
* - A DebugException if there was an error
* - Nothing if we couldn't evaluate at all because we weren't suspended
* @author jean-philippem
*
*/
private class WatchExpressionResult implements IWatchExpressionResult{
private final HaskellValue val;
private final DebugException exception;
private final String expression;
public WatchExpressionResult( final String expression, final HaskellValue val,
final DebugException exception ) {
this.expression = expression;
this.val = val;
this.exception = exception;
}
@Override
public boolean hasErrors() {
return exception!=null;
}
@Override
public IValue getValue() {
return val;
}
@Override
public String getExpressionText() {
return expression;
}
@Override
public DebugException getException() {
return exception;
}
@Override
public String[] getErrorMessages() {
if (val==null && exception==null){
return new String[]{UITexts.evaluate_need_suspend};
}
return new String[0];
}
}
}