Commit 65d8606e authored by sarah.grebing's avatar sarah.grebing

Merge branch 'master' into '55-add-variable-view-to-goaloptionsview'

Reverse Merge Request

See merge request !25
parents 07477085 c70c5bf6
Pipeline #33092 passed with stages
# This is the Gradle build system for JVM applications
# https://gradle.org/
# https://github.com/gradle/gradle
image: key-dev-jdk10
image: key-dev-jdk8
cache:
paths:
......@@ -13,9 +13,7 @@ cache:
# runtime for each build is more reliable since the runtime is completely
# isolated from any previous builds.
variables:
GRADLE_OPTS: "-Dorg.gradle.daemon=false \
--add-modules java.xml.bind \
'-Dorg.gradle.jvmargs=--add-modules java.xml.bind'"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
GIT_SSL_NO_VERIFY: "true"
before_script:
......@@ -28,32 +26,6 @@ stages:
- test
- deploy
build:jdk9:
stage: build
image: key-dev-jdk9
script: gradle --build-cache assemble
allow_failure: true
cache:
key: "$CI_COMMIT_REF_NAME"
policy: push
paths:
- build
- .gradle
build:jdk10:
stage: build
image: key-dev-jdk10
script: gradle --build-cache assemble
allow_failure: true
cache:
key: "$CI_COMMIT_REF_NAME"
policy: push
paths:
- build
- .gradle
build:jdk8:
stage: build
variables:
......
......@@ -100,9 +100,7 @@ literals :
</pre>*/
matchPattern
:
MATCH (
derivable=DERIVABLE derivableExpression=expression
| (pattern=expression (USING LBRACKET argList RBRACKET)?)
MATCH ((pattern=expression (USING LBRACKET argList RBRACKET)?)
)
;
......@@ -122,8 +120,9 @@ casesStmt
casesList
: (TRY |
(CASE (expression
| (CLOSES INDENT closesGuard=stmtList DEDENT) ) ) )
(CASE (expression
|(CLOSES INDENT closesGuard=stmtList DEDENT)
|(derivable=DERIVABLE derivableExpression=expression) ) ))
COLON INDENT? body=stmtList DEDENT?
;
......
......@@ -160,6 +160,7 @@ public interface ASTTraversal<T> extends Visitor<T> {
return null;
}
@Override
default T visit(ForeachStatement foreach) {
foreach.getBody().accept(this);
......@@ -209,6 +210,14 @@ public interface ASTTraversal<T> extends Visitor<T> {
return null;
}
@Override
default T visit(DerivableCase derivableCase){
derivableCase.getExpression().accept(this);
derivableCase.getBody().accept(this);
return null;
}
@Override
default T visit(SubstituteExpression subst) {
subst.getSub().accept(this);
......
......@@ -92,6 +92,11 @@ public class DefaultASTVisitor<T> implements Visitor<T> {
return defaultVisit(defCase);
}
@Override
public T visit(DerivableCase derivableCase) {
return defaultVisit(derivableCase);
}
@Override
public T visit(CaseStatement caseStatement) {
return defaultVisit(caseStatement);
......
......@@ -370,16 +370,9 @@ public class TransformAst implements ScriptLanguageVisitor<Object> {
MatchExpression match = new MatchExpression();
match.setRuleContext(ctx);
if (ctx.derivable != null) {
match.setDerivable(true);
Expression<ParserRuleContext> e = (Expression<ParserRuleContext>) ctx.derivableExpression.accept(this);
e.setParent(match);
match.setDerivableTerm(e);
} else {
Expression<ParserRuleContext> e = (Expression<ParserRuleContext>) ctx.pattern.accept(this);
match.setPattern(e);
e.setParent(match);
}
Expression<ParserRuleContext> e = (Expression<ParserRuleContext>) ctx.pattern.accept(this);
match.setPattern(e);
e.setParent(match);
return match;
}
......@@ -416,7 +409,13 @@ public class TransformAst implements ScriptLanguageVisitor<Object> {
Statements closes = (Statements) ctx.closesGuard.accept(this);
((ClosesCase) cs).setClosesGuard(closes);
closes.setParent(cs);
} else {
} else if (ctx.derivable != null) {
cs = new DerivableCase();
Expression pattern = (Expression) ctx.derivableExpression.accept(this);
((DerivableCase) cs).setExpression(pattern);
pattern.setParent(cs);
} else
{
cs = new GuardedCaseStatement();
Expression<ParserRuleContext> guard = (Expression<ParserRuleContext>) ctx.expression().accept(this);
((GuardedCaseStatement) cs).setGuard(guard);
......
......@@ -53,6 +53,8 @@ public interface Visitor<T> {
T visit(DefaultCaseStatement defCase);
T visit(DerivableCase derivableCase);
//T visit(CaseStatement case_);
T visit(CallStatement call);
......
package edu.kit.iti.formal.psdbg.parser.ast;
import edu.kit.iti.formal.psdbg.parser.Visitor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class DerivableCase extends CaseStatement{
private Expression expression;
public DerivableCase(Statements copy, Expression copy1) {
super(copy);
this.expression=copy1;
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
@Override
public CaseStatement copy() {
DerivableCase dc = new DerivableCase(body.copy(), expression.copy());
dc.setRuleContext(this.getRuleContext());
return dc;
}
}
......@@ -30,6 +30,8 @@ import edu.kit.iti.formal.psdbg.parser.types.SimpleType;
import edu.kit.iti.formal.psdbg.parser.types.TermType;
import edu.kit.iti.formal.psdbg.parser.types.Type;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* A match expression contains an argument and a uses clause.
......@@ -41,6 +43,7 @@ import lombok.Data;
public class MatchExpression extends Expression<ScriptLanguageParser.MatchPatternContext> {
//private Signature signature = new Signature();
private Expression pattern;
@Deprecated @Getter @Setter
private boolean isDerivable = false;
@Deprecated
private Expression derivableTerm;
......
......@@ -3,11 +3,16 @@ package edu.kit.iti.formal.psdbg.interpreter;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import de.uka.ilkd.key.api.VariableAssignments;
import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.TermBuilder;
import de.uka.ilkd.key.parser.ParserException;
import de.uka.ilkd.key.proof.Node;
import de.uka.ilkd.key.proof.Proof;
import edu.kit.iti.formal.psdbg.interpreter.data.*;
import edu.kit.iti.formal.psdbg.interpreter.exceptions.InvalidTypeException;
import edu.kit.iti.formal.psdbg.interpreter.funchdl.CommandLookup;
import edu.kit.iti.formal.psdbg.interpreter.matcher.KeYMatcher;
import edu.kit.iti.formal.psdbg.parser.Visitor;
import edu.kit.iti.formal.psdbg.parser.ast.*;
import edu.kit.iti.formal.psdbg.parser.data.Value;
......@@ -15,7 +20,9 @@ import edu.kit.iti.formal.psdbg.parser.types.SimpleType;
import edu.kit.iti.formal.psdbg.parser.types.TermType;
import edu.kit.iti.formal.psdbg.parser.types.TypeFacade;
import lombok.Getter;
import lombok.Setter;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
......@@ -141,6 +148,8 @@ public class KeyInterpreter extends Interpreter<KeyData> {
}
@Override
public Object visit(LetStatement let) {
enterScope(let);
......
......@@ -42,6 +42,7 @@ public class TermValue {
}
}
public TermValue copy() {
TermValue tv = new TermValue();
......
......@@ -14,6 +14,7 @@ import edu.kit.iti.formal.psdbg.interpreter.data.KeyData;
import edu.kit.iti.formal.psdbg.interpreter.data.State;
import edu.kit.iti.formal.psdbg.interpreter.data.VariableAssignment;
import edu.kit.iti.formal.psdbg.parser.ast.CallStatement;
import javafx.scene.control.Alert;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.IOUtils;
......@@ -22,6 +23,8 @@ import org.apache.logging.log4j.Logger;
import org.key_project.util.collection.ImmutableList;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
......@@ -62,7 +65,26 @@ public class ProofScriptCommandBuilder implements CommandHandler<KeyData> {
VariableAssignment params, KeyData data) {
ProofScriptCommand c = commands.get(call.getCommand());
State<KeyData> state = interpreter.getCurrentState();
//multiple goals exist
if(state.getGoals().size() > 1) {
throw new IllegalStateException("Multiple open goals: Please use a selector.");
/*
//TODO: Utils showWarning
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Multiple open Goals");
alert.setHeaderText("Multiple open Goals");
alert.setContentText("There are multiple open goals so its undefined on which goal the command " + call.getCommand() +" should be applied. Please use a selector.");
alert.setWidth(400);
alert.setHeight(400);
alert.setHeight(600);
alert.setWidth(400);
alert.showAndWait();
*/
}
GoalNode<KeyData> expandedNode = state.getSelectedGoalNode();
KeyData kd = expandedNode.getData();
Map<String, Object> map = new HashMap<>();
params.asMap().forEach((k, v) -> {
......
......@@ -3,8 +3,10 @@ package edu.kit.iti.formal.psdbg.interpreter.matcher;
import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.logic.Name;
import de.uka.ilkd.key.logic.Term;
import de.uka.ilkd.key.logic.TermBuilder;
import de.uka.ilkd.key.logic.op.LogicVariable;
import de.uka.ilkd.key.logic.op.SchemaVariable;
import de.uka.ilkd.key.parser.ParserException;
import de.uka.ilkd.key.pp.LogicPrinter;
import de.uka.ilkd.key.proof.ApplyStrategy;
import de.uka.ilkd.key.proof.Goal;
......@@ -14,14 +16,12 @@ import de.uka.ilkd.key.rule.NoPosTacletApp;
import de.uka.ilkd.key.rule.Taclet;
import de.uka.ilkd.key.rule.TacletApp;
import edu.kit.iti.formal.psdbg.interpreter.MatcherApi;
import edu.kit.iti.formal.psdbg.interpreter.data.GoalNode;
import edu.kit.iti.formal.psdbg.interpreter.data.KeyData;
import edu.kit.iti.formal.psdbg.interpreter.data.SortType;
import edu.kit.iti.formal.psdbg.interpreter.data.VariableAssignment;
import edu.kit.iti.formal.psdbg.interpreter.data.*;
import edu.kit.iti.formal.psdbg.parser.ast.Signature;
import edu.kit.iti.formal.psdbg.parser.data.Value;
import edu.kit.iti.formal.psdbg.parser.types.SimpleType;
import edu.kit.iti.formal.psdbg.parser.types.TermType;
import edu.kit.iti.formal.psdbg.parser.types.TypeFacade;
import lombok.Getter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -54,12 +54,25 @@ public class KeYMatcher implements MatcherApi<KeyData> {
}
/**
* @param proof
* @param kd
* @param term
*
* @return null if the term is not derivable or the new state
*/
public static GoalNode<KeyData> isDerivable(Proof proof, GoalNode<KeyData> kd, Term term) {
public GoalNode<KeyData> isDerivable(GoalNode<KeyData> kd, Value pattern) {
Proof proof = kd.getData().getProof();
TermValue tv = (TermValue) pattern.getData();
Term term = tv.getTerm();
if(term == null) {
Services services = kd.getData().getProof().getServices();
try {
term = new TermBuilder(services.getTermFactory(), services).parseTerm(tv.getTermRepr());
} catch (ParserException e) {
throw new RuntimeException(e);
}
}
Taclet cut = proof.getEnv().getInitConfigForEnvironment().lookupActiveTaclet(CUT_TACLET_NAME);
TacletApp app = NoPosTacletApp.createNoPosTacletApp(cut);
SchemaVariable sv = (SchemaVariable) app.uninstantiatedVars().iterator().next();
......@@ -82,7 +95,14 @@ public class KeYMatcher implements MatcherApi<KeyData> {
boolean isDerivable = proof.getSubtreeGoals(toShow.node()).size() == 0;
if (isDerivable) {
KeyData kdataNew = new KeyData(kd.getData(), goalList.head());
//find the open goal node
Goal toSet= null;
if(goalList.head().node().isClosed()){
toSet = goalList.tail().head();
} else{
toSet = goalList.head();
}
KeyData kdataNew = new KeyData(kd.getData(), toSet);
GoalNode<KeyData> newGoalNode = new GoalNode<KeyData>(kd, kdataNew, kdataNew.isClosedNode());
return newGoalNode;
} else {
......
......@@ -29,12 +29,12 @@ public class KeyMatcherDerivableTest {
Term termQ = new TermBuilder(f.getEnvironment().getServices().getTermFactory(),
f.getEnvironment().getServices()).parseTerm("q");
System.out.println(termQ);
GoalNode<KeyData> a = KeYMatcher.isDerivable(proof, gn, termQ);
//GoalNode<KeyData> a = KeYMatcher.isDerivable(proof, gn, termQ);
System.out.println(proof);
Assert.assertNotNull(a);
// Assert.assertNotNull(a);
Assert.assertEquals(1, proof.getSubtreeGoals(proof.root()).size());
}
......
......@@ -47,6 +47,9 @@ public class KeyMatcherFacadeTest {
*/
@Test
public void matchTerms() throws Exception {
System.out.println(shouldMatchT("f(a)", "...f(a)..."));
System.out.println(shouldMatchT("h(a,a)", "...h(?X,?Y)..."));
System.out.println(shouldMatchT("f(a)", "?"));
System.out.println(shouldMatchT("f(a)", "f(a)"));
......@@ -59,6 +62,9 @@ public class KeyMatcherFacadeTest {
@Test
public void matchSeq() throws Exception {
//atm missing is catching the toplevel formula
shouldMatch("pred(a), pred(b), a=b, a=c ==> pred(c)", "pred(?X), ?X=?Y ==> ", "[?X=a, ?Y=b}, {?X=a, ?Y=c}]");
shouldMatch("pred(a), pred(b), a=b, a=c ==> pred(c)", "pred(?X), ?X=?Y ==> pred(?Y)", "[{?X=a, ?Y=c}]");
shouldMatch("!q==>p,!p","!q ==> p", "[{}]");
shouldMatch("!p ,p ==> q", "!p ==> q", "[{}]");
shouldMatch("!q ,p ==> q", "!p ==> q", "{NOMATCH}");
......
......@@ -12,7 +12,9 @@ import edu.kit.iti.formal.psdbg.parser.Visitor;
import edu.kit.iti.formal.psdbg.parser.ast.*;
import edu.kit.iti.formal.psdbg.parser.data.Value;
import edu.kit.iti.formal.psdbg.parser.types.SimpleType;
import edu.kit.iti.formal.psdbg.parser.types.TermType;
import edu.kit.iti.formal.psdbg.parser.types.Type;
import edu.kit.iti.formal.psdbg.parser.types.TypeFacade;
import lombok.Getter;
import lombok.Setter;
import org.antlr.v4.runtime.ParserRuleContext;
......@@ -209,6 +211,35 @@ public class Interpreter<T> extends DefaultASTVisitor<Object>
return null;
}
@Override
public Object visit(DerivableCase derivableCase) {
Expression pattern = derivableCase.getExpression();
State<T> currentStateToMatch = peekState();
GoalNode<T> selectedGoal = currentStateToMatch.getSelectedGoalNode();
assert currentStateToMatch.getGoals().contains(selectedGoal);
Value v = evaluate(pattern);
if(v.getType() == TypeFacade.ANY_TERM){
GoalNode<T> newGoalNode= matcherApi.isDerivable(selectedGoal, v);
try {
enterScope(derivableCase);
if (newGoalNode != null) {
currentStateToMatch.getGoals().remove(selectedGoal);
currentStateToMatch.getGoals().add(newGoalNode);
currentStateToMatch.setSelectedGoalNode(newGoalNode);
executeBody(derivableCase.getBody(), newGoalNode, new VariableAssignment());
return true;
} else {
return false;
}
} finally {
exitScope(derivableCase);
}
} else {
throw new RuntimeException("A derivable expression must contain a term. Received a"+v.getType());
}
}
/**
* @param casesStatement
* @return
......@@ -303,7 +334,6 @@ public class Interpreter<T> extends DefaultASTVisitor<Object>
GoalNode<T> selectedGoal = currentStateToMatch.getSelectedGoalNode();
assert currentStateToMatch.getGoals().contains(selectedGoal);
VariableAssignment va = evaluateMatchInGoal(matchExpression, selectedGoal);
try {
enterScope(guardedCaseStatement);
if (va != null) {
......
......@@ -16,7 +16,7 @@ import java.util.Collections;
import java.util.List;
/**
* Evaluator specially for Expressions in a case "declaration".
* Evaluator especially for Expressions in a case "declaration".
* Created by sarah on 5/22/17.
*/
public class MatchEvaluator extends DefaultASTVisitor<List<VariableAssignment>> implements ScopeObservable {
......@@ -190,9 +190,13 @@ public class MatchEvaluator extends DefaultASTVisitor<List<VariableAssignment>>
public List<VariableAssignment> visit(UnaryExpression e) {
Operator op = e.getOperator();
Expression expr = e.getExpression();
Value exValue = (Value) expr.accept(this);
Value ret = op.evaluate(exValue);
return null;
List<VariableAssignment> exValue = (List<VariableAssignment>) expr.accept(this);
if(exValue.isEmpty()){
return transformTruthValue(Value.TRUE);
}else{
return transformTruthValue(Value.FALSE);
}
}
......
......@@ -3,6 +3,7 @@ package edu.kit.iti.formal.psdbg.interpreter;
import edu.kit.iti.formal.psdbg.interpreter.data.GoalNode;
import edu.kit.iti.formal.psdbg.interpreter.data.VariableAssignment;
import edu.kit.iti.formal.psdbg.parser.ast.Signature;
import edu.kit.iti.formal.psdbg.parser.data.Value;
import java.util.List;
......@@ -27,4 +28,6 @@ public interface MatcherApi<T> {
*/
List<VariableAssignment> matchSeq(GoalNode<T> currentState, String pattern);
GoalNode<T> isDerivable(GoalNode<T> currentState, Value v);
}
......@@ -54,6 +54,11 @@ public class GoalNode<T> {
this.id = id;
}
private GoalNode(int id, GoalNode<T> parent, VariableAssignment ass, T data, boolean isClosed) {
this(parent, ass, data, isClosed);
this.id = id;
}
private GoalNode(int id, T data, boolean isClosed) {
this(data);
this.isClosed = isClosed;
......@@ -129,7 +134,8 @@ public class GoalNode<T> {
*/
public GoalNode<T> deepCopy() {
if (parent != null) {
return new GoalNode<T>(id, parent.deepCopy(), data, isClosed);
VariableAssignment deepCopy = parent.assignments.deepCopy();
return new GoalNode<T>(id, parent.deepCopy(), deepCopy, data, isClosed);
} else {
return new GoalNode<T>(id, data, isClosed);
}
......
......@@ -49,6 +49,13 @@ public class PseudoMatcher implements MatcherApi<String> {
}
return Collections.singletonList(va);
}
@Override
public GoalNode<String> isDerivable(GoalNode<String> currentState, Value v) {
return null;
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ import edu.kit.iti.formal.psdbg.gui.controller.DebuggerMain;
import edu.kit.iti.formal.psdbg.gui.model.MainScriptIdentifier;
import lombok.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
......@@ -24,7 +25,12 @@ public abstract class Example {
protected MainScriptIdentifier mainScriptIdentifier;
public static File newTempFile(URL url, String filename) throws IOException {
File f = new File(FileUtils.getTempDirectoryPath(), filename);
File psdbg = new File(FileUtils.getTempDirectoryPath(), "psdbg");
File examplefolder = new File(psdbg.getPath(), FilenameUtils.removeExtension(filename));
File f = new File(examplefolder, filename);
FileUtils.copyURLToFile(url, f);
return f;
}
......
......@@ -807,6 +807,7 @@ public class DebuggerMain implements Initializable {
if (javaFile != null) {
model.setJavaFile(javaFile);
model.setInitialDirectory(javaFile.getParentFile());
contractLoaderService.reset();
contractLoaderService.start();
}
}
......@@ -1166,7 +1167,6 @@ public class DebuggerMain implements Initializable {
} else {
throw new RuntimeException("Something went wrong when reloading");
}
}
/* public void handle(Events.TacletApplicationEvent tap){
......@@ -1408,7 +1408,31 @@ public class DebuggerMain implements Initializable {
protected void succeeded() {
statusBar.publishMessage("Contract loaded");
List<Contract> contracts = getValue();
ContractChooser cc = new ContractChooser(FACADE.getService(), contracts);
/*
String javaFile = model.getJavaFile().getName();
List<Contract> filteredContracts = new ArrayList<>();
for (Contract contract : contracts) {
String contractFile = contract.getKJT().getFullName();
if (javaFile == contractFile) {
filteredContracts.add(contract);
}
}
if (filteredContracts.size() == 0) {
Utils.showInfoDialog("No loadable contract", "No loadable contract",
"There's no loadable contract for the chosen java file.");
return;
}
*/
ContractChooser cc = null;
try {
cc = new ContractChooser(FACADE.getService(), FACADE.getContractsForJavaFile(model.getJavaFile()));
} catch (ProblemLoaderException e) {
e.printStackTrace();
}
cc.showAndWait().ifPresent(result -> {
model.setChosenContract(result);
......
package edu.kit.iti.formal.psdbg.gui.controller;
import com.google.common.eventbus.Subscribe;
import de.uka.ilkd.key.api.KeYApi;
import de.uka.ilkd.key.control.AbstractUserInterfaceControl;
import de.uka.ilkd.key.control.DefaultUserInterfaceControl;
import de.uka.ilkd.key.java.Services;
import de.uka.ilkd.key.logic.Sequent;
import de.uka.ilkd.key.logic.SequentFormula;
import de.uka.ilkd.key.macros.ProofMacro;
import de.uka.ilkd.key.macros.scripts.*;
import de.uka.ilkd.key.proof.Goal;
import de.uka.ilkd.key.proof.Node;
......@@ -26,7 +26,7 @@ import edu.kit.iti.formal.psdbg.interpreter.data.VariableAssignment;
import edu.kit.iti.formal.psdbg.interpreter.dbg.DebuggerFramework;
import edu.kit.iti.formal.psdbg.interpreter.dbg.PTreeNode;
import edu.kit.iti.formal.psdbg.interpreter.exceptions.ScriptCommandNotApplicableException;
import edu.kit.iti.formal.psdbg.interpreter.funchdl.MacroCommandHandler;
import edu.kit.iti.formal.psdbg.interpreter.funchdl.ProofScriptCommandBuilder;
import edu.kit.iti.formal.psdbg.parser.PrettyPrinter;
import edu.kit.iti.formal.psdbg.parser.ast.*;
import edu.kit.iti.formal.psdbg.parser.data.Value;
......@@ -43,6 +43,7 @@ import org.key_project.util.collection.ImmutableList;
import recoder.util.Debug;
import javax.annotation.Nullable;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;
......@@ -66,8 +67,8 @@ public class InteractiveModeController {
private PTreeNode<KeyData> nodeAtInteractionStart;
//needed for Undo-Operation
private ArrayList<CallStatement> savepointsstatement;
private ArrayList<Node> savepointslist;
private ArrayList<CallStatement> laststatementlist;
private ArrayList<Node> lastnodeslist;
private Proof currentProof;
private Services keYServices;
......@@ -99,8 +100,8 @@ public class InteractiveModeController {
gcs.setBody(v);
casesStatement.getCases().add(gcs);
});
savepointslist = new ArrayList<>();
savepointsstatement = new ArrayList<>();
lastnodeslist = new ArrayList<>();
laststatementlist = new ArrayList<>();
nodeAtInteractionStart = debuggerFramework.getStatePointer();
}
......@@ -110,13 +111,14 @@ public class InteractiveModeController {
* Undo the application of the last rule
*/
public void undo(javafx.event.ActionEvent actionEvent) {
if (savepointslist.isEmpty()) {
if (lastnodeslist.isEmpty()) {
Debug.log("Kein vorheriger Zustand.");
return;
}
val pruneNode = savepointslist.get(savepointslist.size() - 1);
savepointslist.remove(pruneNode);
val pruneNode = lastnodeslist.get(lastnodeslist.size() - 1);
lastnodeslist.remove(pruneNode);
ImmutableList<Goal> goalsbeforePrune = currentProof.getSubtreeGoals(pruneNode);
currentProof.pruneProof(pruneNode);
......@@ -127,19 +129,55 @@ public class InteractiveModeController {