Commit 4ed3bd10 authored by Alexander Weigl's avatar Alexander Weigl
Browse files

better status bar

parent 282daaef
Pipeline #15114 passed with stages
in 6 minutes and 44 seconds
...@@ -6,12 +6,14 @@ import edu.kit.iti.formal.psdbg.interpreter.graphs.ControlFlowNode; ...@@ -6,12 +6,14 @@ import edu.kit.iti.formal.psdbg.interpreter.graphs.ControlFlowNode;
import edu.kit.iti.formal.psdbg.interpreter.graphs.ControlFlowTypes; import edu.kit.iti.formal.psdbg.interpreter.graphs.ControlFlowTypes;
import edu.kit.iti.formal.psdbg.parser.ast.ProofScript; import edu.kit.iti.formal.psdbg.parser.ast.ProofScript;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
...@@ -25,39 +27,37 @@ import java.util.function.Consumer; ...@@ -25,39 +27,37 @@ import java.util.function.Consumer;
* <li>{@link StateWrapper}: signals the PTreeNodes</li> * <li>{@link StateWrapper}: signals the PTreeNodes</li>
* <li></li> * <li></li>
* </ol> * </ol>
*<code><pre> * <code><pre>
+------------------------------------------------------------------------------------------+ * +------------------------------------------------------------------------------------------+
| | * | |
| DebuggerFramework<T> | * | DebuggerFramework<T> |
| +------------+ * | +------------+
| | execute(DebuggerCommand) * | | execute(DebuggerCommand)
| | Commands: StepOver, StepInto, * | | Commands: StepOver, StepInto,
| +------------------+ +-----------------+ +---------------------------+ | StepReturn, StepBack * | +------------------+ +-----------------+ +---------------------------+ | StepReturn, StepBack
| | | | | | | | * | | | | | | | |
| | Interpreter<T> +-------> StateWrapper<T> +-------> PTreeManager<T> +---------> * | | Interpreter<T> +-------> StateWrapper<T> +-------> PTreeManager<T> +--------->
| | | | | | | | * | | | | | | | |
| +---------+--------+ +-----------------+ +---------------------------+ | statePointerChanged(PTreeNode<T>) * | +---------+--------+ +-----------------+ +---------------------------+ | statePointerChanged(PTreeNode<T>)
| | | * | | |
| | Listener emitNode | * | | Listener emitNode |
| | | * | | |
| | | * | | |
| +---------v------------+ | * | +---------v------------+ |
| | <--------------------------------------------------------------------+ releaseForever() * | | <--------------------------------------------------------------------+ releaseForever()
| | BlockerListener | | release() * | | BlockerListener | | release()
| | | | releaseUntil(BlockerPredicate) * | | | | releaseUntil(BlockerPredicate)
| +----------------------+ | getBreakpoints() * | +----------------------+ | getBreakpoints()
| | * | |
| | * | |
| +----------------+ +---------------------+ | * | +----------------+ +---------------------+ |
| | | | | | * | | | | | |
| | Breakpoint | | BlockerPredicate | | * | | Breakpoint | | BlockerPredicate | |
| | | | | | * | | | | | |
| +----------------+ +---------------------+ | * | +----------------+ +---------------------+ |
| | * | |
+------------------------------------------------------------------------------------------+ * +------------------------------------------------------------------------------------------+
</pre></code> * </pre></code>
*
*
* *
* @author Alexander Weigl * @author Alexander Weigl
* @version 1 (27.10.17) * @version 1 (27.10.17)
...@@ -65,11 +65,12 @@ import java.util.function.Consumer; ...@@ -65,11 +65,12 @@ import java.util.function.Consumer;
public class DebuggerFramework<T> { public class DebuggerFramework<T> {
private final Interpreter<T> interpreter; private final Interpreter<T> interpreter;
@Getter /*@Getter
private final List<Consumer<PTreeNode<T>>> beforeExecutionListener = new LinkedList<>(); private final List<Consumer<PTreeNode<T>>> beforeExecutionListener = new LinkedList<>();
@Getter @Getter
private final List<Consumer<PTreeNode<T>>> afterExecutionListener = new LinkedList<>(); private final List<Consumer<PTreeNode<T>>> afterExecutionListener = new LinkedList<>();
*/
@Getter @Getter
private final List<Consumer<PTreeNode<T>>> currentStatePointerListener = new LinkedList<>(); private final List<Consumer<PTreeNode<T>>> currentStatePointerListener = new LinkedList<>();
...@@ -82,20 +83,35 @@ public class DebuggerFramework<T> { ...@@ -82,20 +83,35 @@ public class DebuggerFramework<T> {
private final StateWrapper<T> stateWrapper; private final StateWrapper<T> stateWrapper;
private final ProofScript mainScript;
@Getter @Setter
private BiConsumer<DebuggerFramework<T>, Throwable> errorListener = (df, exc) -> {
};
@Getter @Setter
private Consumer<DebuggerFramework<T>> succeedListener = (df) -> {
};
private Blocker.BreakpointLine<T> breakpointBlocker; private Blocker.BreakpointLine<T> breakpointBlocker;
@Nullable
@Getter
private Throwable error;
public DebuggerFramework(@Nonnull Interpreter<T> interpreter, public DebuggerFramework(@Nonnull Interpreter<T> interpreter,
@Nonnull ProofScript main, @Nonnull ProofScript main,
MutableValueGraph<ControlFlowNode, ControlFlowTypes> cfg) { MutableValueGraph<ControlFlowNode, ControlFlowTypes> cfg) {
this.interpreter = interpreter; this.interpreter = interpreter;
mainScript = main;
blocker = new BlockListener<>(interpreter); blocker = new BlockListener<>(interpreter);
breakpointBlocker = new Blocker.BreakpointLine<>(interpreter); breakpointBlocker = new Blocker.BreakpointLine<>(interpreter);
blocker.getPredicates().add(breakpointBlocker); blocker.getPredicates().add(breakpointBlocker);
stateWrapper = new StateWrapper<>(interpreter); stateWrapper = new StateWrapper<>(interpreter);
ptreeManager = new ProofTreeManager<>(cfg); ptreeManager = new ProofTreeManager<>(cfg);
stateWrapper.setEmitNode(ptreeManager::receiveNode); stateWrapper.setEmitNode(ptreeManager::receiveNode);
interpreterThread = new Thread(() -> interpreter.interpret(main)); interpreterThread = new Thread(this::run);
} }
public List<Consumer<PTreeNode<T>>> getStatePointerListener() { public List<Consumer<PTreeNode<T>>> getStatePointerListener() {
...@@ -115,6 +131,17 @@ public class DebuggerFramework<T> { ...@@ -115,6 +131,17 @@ public class DebuggerFramework<T> {
interpreterThread.start(); interpreterThread.start();
} }
private void run() {
try {
interpreter.interpret(mainScript);
succeedListener.accept(this);
} catch (Exception e) {
error = e;
errorListener.accept(this, e);
}
}
/** /**
* stops the interpreter in the background on the next {@link edu.kit.iti.formal.psdbg.parser.ast.ASTNode}. * stops the interpreter in the background on the next {@link edu.kit.iti.formal.psdbg.parser.ast.ASTNode}.
* Does not stop the KeY framework in the background. * Does not stop the KeY framework in the background.
...@@ -187,4 +214,12 @@ public class DebuggerFramework<T> { ...@@ -187,4 +214,12 @@ public class DebuggerFramework<T> {
public Set<Breakpoint> getBreakpoints() { public Set<Breakpoint> getBreakpoints() {
return breakpointBlocker.getBreakpoints(); return breakpointBlocker.getBreakpoints();
} }
public Thread getInterpreterThread() {
return interpreterThread;
}
public boolean hasError() {
return error != null;
}
} }
...@@ -6,8 +6,8 @@ import edu.kit.iti.formal.psdbg.interpreter.data.State; ...@@ -6,8 +6,8 @@ import edu.kit.iti.formal.psdbg.interpreter.data.State;
import edu.kit.iti.formal.psdbg.parser.DefaultASTVisitor; import edu.kit.iti.formal.psdbg.parser.DefaultASTVisitor;
import edu.kit.iti.formal.psdbg.parser.Visitor; import edu.kit.iti.formal.psdbg.parser.Visitor;
import edu.kit.iti.formal.psdbg.parser.ast.ASTNode; import edu.kit.iti.formal.psdbg.parser.ast.ASTNode;
import edu.kit.iti.formal.psdbg.parser.ast.CallStatement;
import edu.kit.iti.formal.psdbg.parser.ast.ProofScript; import edu.kit.iti.formal.psdbg.parser.ast.ProofScript;
import edu.kit.iti.formal.psdbg.parser.ast.Statement;
import edu.kit.iti.formal.psdbg.parser.ast.Statements; import edu.kit.iti.formal.psdbg.parser.ast.Statements;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
...@@ -66,7 +66,9 @@ public class StateWrapper<T> implements InterpreterObserver<T> { ...@@ -66,7 +66,9 @@ public class StateWrapper<T> implements InterpreterObserver<T> {
contextStack.add(node); contextStack.add(node);
State<T> currentInterpreterStateCopy = getInterpreterStateCopy(); State<T> currentInterpreterStateCopy = getInterpreterStateCopy();
lastNode.setStateBeforeStmt(currentInterpreterStateCopy); lastNode.setStateBeforeStmt(currentInterpreterStateCopy);
if (node instanceof CallStatement) {
lastNode.setAtomic(interpreter.getFunctionLookup().isAtomic((CallStatement) node));
}
//add node to state graph //add node to state graph
return lastNode; return lastNode;
} }
......
...@@ -6,12 +6,14 @@ import de.uka.ilkd.key.api.ProofApi; ...@@ -6,12 +6,14 @@ import de.uka.ilkd.key.api.ProofApi;
import de.uka.ilkd.key.proof.init.ProofInputException; import de.uka.ilkd.key.proof.init.ProofInputException;
import de.uka.ilkd.key.proof.io.ProblemLoaderException; import de.uka.ilkd.key.proof.io.ProblemLoaderException;
import de.uka.ilkd.key.speclang.Contract; import de.uka.ilkd.key.speclang.Contract;
import edu.kit.iti.formal.psdbg.ShortCommandPrinter;
import edu.kit.iti.formal.psdbg.StepIntoCommand; import edu.kit.iti.formal.psdbg.StepIntoCommand;
import edu.kit.iti.formal.psdbg.examples.Examples; import edu.kit.iti.formal.psdbg.examples.Examples;
import edu.kit.iti.formal.psdbg.gui.ProofScriptDebugger; import edu.kit.iti.formal.psdbg.gui.ProofScriptDebugger;
import edu.kit.iti.formal.psdbg.gui.controls.*; import edu.kit.iti.formal.psdbg.gui.controls.*;
import edu.kit.iti.formal.psdbg.gui.model.DebuggerMainModel; import edu.kit.iti.formal.psdbg.gui.model.DebuggerMainModel;
import edu.kit.iti.formal.psdbg.gui.model.InspectionModel; import edu.kit.iti.formal.psdbg.gui.model.InspectionModel;
import edu.kit.iti.formal.psdbg.gui.model.InterpreterThreadState;
import edu.kit.iti.formal.psdbg.interpreter.InterpreterBuilder; import edu.kit.iti.formal.psdbg.interpreter.InterpreterBuilder;
import edu.kit.iti.formal.psdbg.interpreter.KeYProofFacade; import edu.kit.iti.formal.psdbg.interpreter.KeYProofFacade;
import edu.kit.iti.formal.psdbg.interpreter.KeyInterpreter; import edu.kit.iti.formal.psdbg.interpreter.KeyInterpreter;
...@@ -39,11 +41,17 @@ import org.apache.logging.log4j.Logger; ...@@ -39,11 +41,17 @@ import org.apache.logging.log4j.Logger;
import org.dockfx.DockNode; import org.dockfx.DockNode;
import org.dockfx.DockPane; import org.dockfx.DockPane;
import org.dockfx.DockPos; import org.dockfx.DockPos;
import org.reactfx.util.FxTimer;
import org.reactfx.util.Timer;
import javax.annotation.Nullable;
import java.io.File; import java.io.File;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL; import java.net.URL;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.ResourceBundle; import java.util.ResourceBundle;
...@@ -132,6 +140,8 @@ public class DebuggerMain implements Initializable { ...@@ -132,6 +140,8 @@ public class DebuggerMain implements Initializable {
@FXML @FXML
private Menu examplesMenu; private Menu examplesMenu;
private Timer interpreterThreadTimer;
@Override @Override
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
Events.register(this); Events.register(this);
...@@ -194,6 +204,8 @@ public class DebuggerMain implements Initializable { ...@@ -194,6 +204,8 @@ public class DebuggerMain implements Initializable {
proofTreeDock, proofTreeDock,
DockPos.LEFT); DockPos.LEFT);
statusBar.interpreterStatusModelProperty().bind(model.interpreterStateProperty());
renewThreadStateTimer();
} }
...@@ -427,6 +439,8 @@ public class DebuggerMain implements Initializable { ...@@ -427,6 +439,8 @@ public class DebuggerMain implements Initializable {
ib.setScripts(scripts); ib.setScripts(scripts);
KeyInterpreter interpreter = ib.build(); KeyInterpreter interpreter = ib.build();
DebuggerFramework<KeyData> df = new DebuggerFramework<>(interpreter, ms, null); DebuggerFramework<KeyData> df = new DebuggerFramework<>(interpreter, ms, null);
df.setSucceedListener(this::onInterpreterSucceed);
df.setErrorListener(this::onInterpreterError);
if (addInitBreakpoint) { if (addInitBreakpoint) {
df.releaseUntil(new Blocker.CounterBlocker(1)); // just execute df.releaseUntil(new Blocker.CounterBlocker(1)); // just execute
} }
...@@ -441,6 +455,84 @@ public class DebuggerMain implements Initializable { ...@@ -441,6 +455,84 @@ public class DebuggerMain implements Initializable {
} }
} }
private void onInterpreterSucceed(DebuggerFramework<KeyData> keyDataDebuggerFramework) {
scriptController.getDebugPositionHighlighter().remove();
statusBar.publishMessage("Interpreter finished.");
}
@FXML
public void debugPrintDot(@Nullable ActionEvent ae) {
if (model.getDebuggerFramework() == null) {
statusBar.publishErrorMessage("can print debug info, no debugger started!");
return;
}
try (PrintWriter out = new PrintWriter(new FileWriter("debug.dot"))) {
out.println("digraph G {");
for (PTreeNode<KeyData> n : model.getDebuggerFramework().getStates()) {
out.format("%d [label=\"%s@%s (G: %d)\"]%n", n.hashCode(),
n.getStatement().accept(new ShortCommandPrinter()),
n.getStatement().getStartPosition().getLineNumber(),
n.getStateBeforeStmt().getGoals().size()
);
if (n.getStepOver() != null)
out.format("%d -> %d [label=\"SO\"]%n", n.hashCode(), n.getStepOver().hashCode());
if (n.getStepInto() != null)
out.format("%d -> %d [label=\"SI\"]%n", n.hashCode(), n.getStepInto().hashCode());
if (n.getStepInvOver() != null)
out.format("%d -> %d [label=\"<SO\"]%n", n.hashCode(), n.getStepInvOver().hashCode());
if (n.getStepInvInto() != null)
out.format("%d -> %d [label=\"<SI\"]%n", n.hashCode(), n.getStepInvInto().hashCode());
if (n.getStepReturn() != null)
out.format("%d -> %d [label=\"R\"]%n", n.hashCode(), n.getStepReturn().hashCode());
}
out.println("}");
} catch (IOException e) {
statusBar.publishErrorMessage(e.getMessage());
}
}
private void onInterpreterError(DebuggerFramework<KeyData> keyDataDebuggerFramework, Throwable throwable) {
Utils.showExceptionDialog("Error during Execution", "Error during Script Execution",
"Here should be some really good text...\nNothing will be the same. Everything broken.",
throwable
);
}
private void renewThreadStateTimer() {
if (interpreterThreadTimer != null) {
interpreterThreadTimer.stop();
}
interpreterThreadTimer = FxTimer.runPeriodically(Duration.ofMillis(500),
() -> {
if (model.getDebuggerFramework() == null) {
model.setInterpreterState(InterpreterThreadState.NO_THREAD);
} else {
Thread t = model.getDebuggerFramework().getInterpreterThread();
switch (t.getState()) {
case NEW:
case BLOCKED:
case WAITING:
case TIMED_WAITING:
model.setInterpreterState(InterpreterThreadState.WAIT);
break;
case TERMINATED:
if (model.getDebuggerFramework().hasError())
model.setInterpreterState(InterpreterThreadState.ERROR);
else
model.setInterpreterState(InterpreterThreadState.FINISHED);
break;
default:
model.setInterpreterState(InterpreterThreadState.RUNNING);
}
}
});
}
@FXML @FXML
public void executeStepwise() { public void executeStepwise() {
executeScript(true); executeScript(true);
......
package edu.kit.iti.formal.psdbg.gui.controls; package edu.kit.iti.formal.psdbg.gui.controls;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView;
import edu.kit.iti.formal.psdbg.gui.controller.Events; import edu.kit.iti.formal.psdbg.gui.controller.Events;
import edu.kit.iti.formal.psdbg.gui.model.InterpreterThreadState;
import edu.kit.iti.formal.psdbg.gui.model.MainScriptIdentifier; import edu.kit.iti.formal.psdbg.gui.model.MainScriptIdentifier;
import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.Transition;
import javafx.beans.property.IntegerProperty; import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.Control; import javafx.scene.control.Control;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator; import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Separator;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.paint.Color;
import javafx.util.Duration;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.controlsfx.control.StatusBar; import org.controlsfx.control.StatusBar;
...@@ -22,29 +35,49 @@ import org.controlsfx.control.StatusBar; ...@@ -22,29 +35,49 @@ import org.controlsfx.control.StatusBar;
*/ */
public class DebuggerStatusBar extends StatusBar { public class DebuggerStatusBar extends StatusBar {
private static final Logger LOGGER = LogManager.getLogger(DebuggerStatusBar.class); private static final Logger LOGGER = LogManager.getLogger(DebuggerStatusBar.class);
//private final Dialog<Void> loggerDialog = createDialog(); //private final Dialog<Void> loggerDialog = createDialog();
//private final ContextMenu contextMenu = createContextMenu(); //private final ContextMenu contextMenu = createContextMenu();
//private final Appender loggerHandler = createAppender(); //private final Appender loggerHandler = createAppender();
//private LogCatchHandlerFX logCatchHandler = new LogCatchHandlerFX(); //private LogCatchHandlerFX logCatchHandler = new LogCatchHandlerFX();
private ObjectProperty<InterpreterThreadState> interpreterStatusModel = new SimpleObjectProperty<>();
private ObjectProperty<MainScriptIdentifier> mainScriptIdentifier = new SimpleObjectProperty<>(); private ObjectProperty<MainScriptIdentifier> mainScriptIdentifier = new SimpleObjectProperty<>();
private IntegerProperty numberOfGoals = new SimpleIntegerProperty(0); private IntegerProperty numberOfGoals = new SimpleIntegerProperty(0);
private Label lblCurrentNodes = new Label("#nodes: %s");
private Label lblMainscript = new Label();
private MaterialDesignIconView interpreterStatusView =
new MaterialDesignIconView(MaterialDesignIcon.MATERIAL_UI, "2.3em");
private ProgressIndicator progressIndicator = new ProgressIndicator();
private EventHandler<MouseEvent> toolTipHandler = event ->
publishMessage(((Control) event.getTarget()).getTooltip().getText());
public DebuggerStatusBar() { public DebuggerStatusBar() {
//listenOnField("psdbg"); //listenOnField("psdbg");
getRightItems().addAll( getRightItems().addAll(
lblMainscript lblMainscript,
new Separator(),
interpreterStatusView
//lblCurrentNodes, //lblCurrentNodes,
//progressIndicator //progressIndicator
); );
/*setOnMouseClicked(event -> { interpreterStatusModel.addListener((p, o, n) -> {
if (event.getButton() == MouseButton.SECONDARY) { interpreterStatusView.setIcon(n.getIcon());
contextMenu.show(this, event.getScreenX(), event.getScreenY()); if (n == InterpreterThreadState.ERROR)
} interpreterStatusView.setFill(Color.web("orangered"));
});*/ else
interpreterStatusView.setFill(Color.web("cornflowerblue"));
});
numberOfGoals.addListener((observable, oldValue, newValue) -> { numberOfGoals.addListener((observable, oldValue, newValue) -> {
lblCurrentNodes.setText("#nodes: " + newValue); lblCurrentNodes.setText("#nodes: " + newValue);
}); });
...@@ -83,28 +116,10 @@ public class DebuggerStatusBar extends StatusBar { ...@@ -83,28 +116,10 @@ public class DebuggerStatusBar extends StatusBar {
this.numberOfGoals.set(numberOfGoals); this.numberOfGoals.set(numberOfGoals);
} }
private Label lblCurrentNodes = new Label("#nodes: %s");
private Label lblMainscript = new Label();
private ProgressIndicator progressIndicator = new ProgressIndicator();
private EventHandler<MouseEvent> toolTipHandler = event -> {
publishMessage(((Control) event.getTarget()).getTooltip().getText());
};
public IntegerProperty numberOfGoalsProperty() { public IntegerProperty numberOfGoalsProperty() {
return numberOfGoals; return numberOfGoals;
} }
/*
private Appender createAppender() {
PatternLayout layout = PatternLayout.createDefaultLayout();
return new AbstractAppender("", null, layout) {
@Override
public void append(LogEvent event) {
publishMessage(event.getMessage().getFormattedMessage());
}
};
}*/
public void publishMessage(String format, Object... args) { public void publishMessage(String format, Object... args) {
String msg = String.format(format, args); String msg = String.format(format, args);
setText(msg); setText(msg);
...@@ -114,25 +129,6 @@ public class DebuggerStatusBar extends StatusBar { ...@@ -114,25 +129,6 @@ public class DebuggerStatusBar extends StatusBar {
return toolTipHandler; return toolTipHandler;
} }