Commit 0c1e07d3 authored by Alexander Weigl's avatar Alexander Weigl
Browse files

Refactoring; Contrapositon works!

* remove errorstate and abstractstate
* parameterization of interpreter (related) classes
* interpreter.data package
* finished Rule and ProofScriptCommandBuilder
* VariableAssignment use Variable as key data type
* Contrapositon as test case
parent 61d52f08
Pipeline #10765 failed with stage
in 2 minutes and 29 seconds
...@@ -179,6 +179,13 @@ ...@@ -179,6 +179,13 @@
<scope>system</scope> <scope>system</scope>
<systemPath>${basedir}/lib/recoderKey.jar</systemPath> <systemPath>${basedir}/lib/recoderKey.jar</systemPath>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
</dependencies> </dependencies>
......
package edu.kit.formal.interpreter;
import java.util.List;
/**
* Represents a script state
*/
public abstract class AbstractState {
/**
* Returns whether the state is an ErrorState
*
* @return
*/
public abstract boolean isErrorState();
/**
* Returns all GoalNodes in a state
*
* @return
*/
public abstract List<GoalNode> getGoals();
/**
* Returns the selected GoalNode to which the next statement should be applied
* Can be null if no selector was applied or state is an ErrorState
*
* @return GoalNode or null
*/
public abstract GoalNode getSelectedGoalNode();
public abstract State copy();
}
package edu.kit.formal.interpreter;
import java.util.List;
/**
* State representing error states
*
* @author S.Grebing
*/
public class ErrorState extends AbstractState {
@Override
public boolean isErrorState() {
return true;
}
@Override
public List<GoalNode> getGoals() {
return null;
}
@Override
public GoalNode getSelectedGoalNode() {
return null;
}
@Override
public State copy() {
return null;
}
}
package edu.kit.formal.interpreter; package edu.kit.formal.interpreter;
import edu.kit.formal.interpreter.data.GoalNode;
import edu.kit.formal.interpreter.data.Value;
import edu.kit.formal.interpreter.data.VariableAssignment;
import edu.kit.formal.proofscriptparser.DefaultASTVisitor; import edu.kit.formal.proofscriptparser.DefaultASTVisitor;
import edu.kit.formal.proofscriptparser.Visitor; import edu.kit.formal.proofscriptparser.Visitor;
import edu.kit.formal.proofscriptparser.ast.*; import edu.kit.formal.proofscriptparser.ast.*;
...@@ -15,19 +18,19 @@ import java.util.List; ...@@ -15,19 +18,19 @@ import java.util.List;
* @author S.Grebing * @author S.Grebing
* @author A. Weigl * @author A. Weigl
*/ */
public class Evaluator extends DefaultASTVisitor<Value> implements ScopeObservable { public class Evaluator<T> extends DefaultASTVisitor<Value> implements ScopeObservable {
@Getter @Getter
private final List<VariableAssignment> matchedVariables = new ArrayList<>();
private final GoalNode goal;
private final VariableAssignment state; private final VariableAssignment state;
@Getter @Getter
private final GoalNode<T> goal;
@Getter
@Setter @Setter
private MatcherApi matcher; private MatcherApi<T> matcher;
@Getter @Getter
private List<Visitor> entryListeners = new ArrayList<>(), private List<Visitor> entryListeners = new ArrayList<>(),
exitListeners = new ArrayList<>(); exitListeners = new ArrayList<>();
public Evaluator(VariableAssignment assignment, GoalNode node) { public Evaluator(VariableAssignment assignment, GoalNode<T> node) {
state = new VariableAssignment(assignment); // unmodifiable version of assignment state = new VariableAssignment(assignment); // unmodifiable version of assignment
goal = node; goal = node;
} }
...@@ -58,6 +61,10 @@ public class Evaluator extends DefaultASTVisitor<Value> implements ScopeObservab ...@@ -58,6 +61,10 @@ public class Evaluator extends DefaultASTVisitor<Value> implements ScopeObservab
*/ */
@Override @Override
public Value visit(MatchExpression match) { public Value visit(MatchExpression match) {
if (match.getSignature() != null && !match.getSignature().isEmpty()) {
throw new IllegalStateException("not supported");
}
Value pattern = (Value) match.getPattern().accept(this); Value pattern = (Value) match.getPattern().accept(this);
List<VariableAssignment> va = null; List<VariableAssignment> va = null;
...@@ -73,6 +80,7 @@ public class Evaluator extends DefaultASTVisitor<Value> implements ScopeObservab ...@@ -73,6 +80,7 @@ public class Evaluator extends DefaultASTVisitor<Value> implements ScopeObservab
/** /**
* TODO Connect with KeY * TODO Connect with KeY
* TODO remove return * TODO remove return
*
* @param term * @param term
* @return * @return
*/ */
...@@ -89,8 +97,7 @@ public class Evaluator extends DefaultASTVisitor<Value> implements ScopeObservab ...@@ -89,8 +97,7 @@ public class Evaluator extends DefaultASTVisitor<Value> implements ScopeObservab
@Override @Override
public Value visit(Variable variable) { public Value visit(Variable variable) {
//get variable value //get variable value
String id = variable.getIdentifier(); Value v = state.getValue(variable);
Value v = state.lookupVarValue(id);
if (v != null) { if (v != null) {
return v; return v;
} else { } else {
......
package edu.kit.formal.interpreter;
import de.uka.ilkd.key.api.KeYApi;
import de.uka.ilkd.key.api.ProjectedNode;
import de.uka.ilkd.key.api.ProofApi;
import de.uka.ilkd.key.api.ProofManagementApi;
import de.uka.ilkd.key.proof.io.ProblemLoaderException;
import edu.kit.formal.interpreter.data.GoalNode;
import edu.kit.formal.interpreter.data.KeyData;
import edu.kit.formal.proofscriptparser.Facade;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* @author Alexander Weigl
* @version 1 (28.05.17)
*/
public class Execute {
private InterpreterBuilder interpreterBuilder = new InterpreterBuilder();
private List<String> keyFiles;
private File scriptFile;
public static void main(String[] args) throws IOException, ParseException {
Execute execute = new Execute();
execute.init(args);
execute.run();
}
public Interpreter<KeyData> run() {
try {
ProofManagementApi pma = KeYApi.loadFromKeyFile(new File(keyFiles.get(0)));
ProofApi pa = pma.getLoadedProof();
ProjectedNode root = pa.getFirstOpenGoal();
interpreterBuilder.proof(pa).macros().scriptCommands();
pa.getProof().getProofIndependentSettings().getGeneralSettings().setOneStepSimplification(false);
Interpreter<KeyData> inter = interpreterBuilder.build();
KeyData keyData = new KeyData(root.getProofNode(), pa.getEnv(), pa.getProof());
inter.interpret(Facade.getAST(scriptFile), new GoalNode<>(null, keyData));
return inter;
} catch (ProblemLoaderException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public void init(String[] args) throws ParseException, IOException {
Options o = argparse();
DefaultParser parser = new DefaultParser();
CommandLine cli = parser.parse(o, args);
keyFiles = cli.getArgList();
scriptFile = new File(cli.getOptionValue("s"));
if (cli.getOptionValue('p') != null)
interpreterBuilder.scriptSearchPath(new File(cli.getOptionValue('p')));
}
public static Options argparse() {
Options options = new Options();
options.addOption("h", "--help", false, "print help text");
options.addOption("p", "--script-path", true, "include folder for scripts");
options.addOption("l", "--linter", false, "run linter before execute");
options.addOption("s", "--script", true, "script file");
return options;
}
}
...@@ -17,7 +17,7 @@ public class HistoryListener extends DefaultASTVisitor<Void> { ...@@ -17,7 +17,7 @@ public class HistoryListener extends DefaultASTVisitor<Void> {
@Getter @Getter
private final List<ASTNode> queueNode = new LinkedList<>(); private final List<ASTNode> queueNode = new LinkedList<>();
@Getter @Getter
private final List<AbstractState> queueState = new LinkedList<>(); private final List<State> queueState = new LinkedList<>();
private final Interpreter interpreter; private final Interpreter interpreter;
......
...@@ -3,6 +3,9 @@ package edu.kit.formal.interpreter; ...@@ -3,6 +3,9 @@ package edu.kit.formal.interpreter;
import de.uka.ilkd.key.api.ScriptApi; import de.uka.ilkd.key.api.ScriptApi;
import de.uka.ilkd.key.macros.scripts.EngineState; import de.uka.ilkd.key.macros.scripts.EngineState;
import edu.kit.formal.interpreter.data.GoalNode;
import edu.kit.formal.interpreter.data.Value;
import edu.kit.formal.interpreter.data.VariableAssignment;
import edu.kit.formal.interpreter.funchdl.CommandLookup; import edu.kit.formal.interpreter.funchdl.CommandLookup;
import edu.kit.formal.proofscriptparser.DefaultASTVisitor; import edu.kit.formal.proofscriptparser.DefaultASTVisitor;
import edu.kit.formal.proofscriptparser.Visitor; import edu.kit.formal.proofscriptparser.Visitor;
...@@ -18,19 +21,19 @@ import java.util.logging.Logger; ...@@ -18,19 +21,19 @@ import java.util.logging.Logger;
* *
* @author S.Grebing * @author S.Grebing
*/ */
public class Interpreter extends DefaultASTVisitor<Void> public class Interpreter<T> extends DefaultASTVisitor<Void>
implements ScopeObservable { implements ScopeObservable {
private static final int MAX_ITERATIONS = 5; private static final int MAX_ITERATIONS = 5;
private static Logger logger = Logger.getLogger("interpreter"); private static Logger logger = Logger.getLogger("interpreter");
//TODO later also include information about source line for each state (for debugging purposes and rewind purposes) //TODO later also include information about source line for each state (for debugging purposes and rewind purposes)
private Stack<AbstractState> stateStack = new Stack<>(); private Stack<State<T>> stateStack = new Stack<>();
@Getter @Getter
private List<Visitor> entryListeners = new ArrayList<>(), private List<Visitor> entryListeners = new ArrayList<>(),
exitListeners = new ArrayList<>(); exitListeners = new ArrayList<>();
@Getter @Getter
@Setter @Setter
private MatcherApi matcherApi; private MatcherApi<T> matcherApi;
@Getter @Getter
private CommandLookup functionLookup; private CommandLookup functionLookup;
...@@ -38,16 +41,21 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -38,16 +41,21 @@ public class Interpreter extends DefaultASTVisitor<Void>
@Getter @Getter
@Setter @Setter
private boolean scrictSelectedGoalMode = false; private boolean scrictSelectedGoalMode = false;
private EngineState engineState;
@Getter
private ScriptApi scriptApi; private ScriptApi scriptApi;
public Interpreter(CommandLookup lookup) { public Interpreter(CommandLookup lookup) {
functionLookup = lookup; functionLookup = lookup;
} }
//starting point is a statement list /**
public void interpret(List<ProofScript> scripts, String sequent) { * starting point is a statement list
newState(new GoalNode(null, sequent)); */
public void interpret(List<ProofScript> scripts, GoalNode<T> startGoal) {
newState(startGoal);
//execute first script (RULE: The first script in the file is main script) //execute first script (RULE: The first script in the file is main script)
ProofScript m = scripts.get(0); ProofScript m = scripts.get(0);
//later through interface with getMainScript(); //later through interface with getMainScript();
...@@ -83,21 +91,21 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -83,21 +91,21 @@ public class Interpreter extends DefaultASTVisitor<Void>
public Void visit(AssignmentStatement assignmentStatement) { public Void visit(AssignmentStatement assignmentStatement) {
enterScope(assignmentStatement); enterScope(assignmentStatement);
GoalNode node = getSelectedNode(); GoalNode<T> node = getSelectedNode();
Type t = assignmentStatement.getType(); Type t = assignmentStatement.getType();
Variable var = assignmentStatement.getLhs(); Variable var = assignmentStatement.getLhs();
Expression expr = assignmentStatement.getRhs(); Expression expr = assignmentStatement.getRhs();
if (t != null) { if (t != null) {
node.addVarDecl(var.getIdentifier(), t); node.declareVariable(var, t);
} }
if (expr != null) { if (expr != null) {
Type type = node.lookUpType(var.getIdentifier()); Type type = node.getVariableType(var);
if (type == null) { if (type == null) {
throw new RuntimeException("Type of Variable " + var.getIdentifier() + " is not declared yet"); throw new RuntimeException("Type of Variable " + var + " is not declared yet");
} else { } else {
Value v = evaluate(expr); Value v = evaluate(expr);
node.setVarValue(var.getIdentifier(), v); node.setVariableValue(var, v);
} }
} }
exitScope(assignmentStatement); exitScope(assignmentStatement);
...@@ -110,7 +118,7 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -110,7 +118,7 @@ public class Interpreter extends DefaultASTVisitor<Void>
return evaluate(getSelectedNode(), expr); return evaluate(getSelectedNode(), expr);
} }
private Value evaluate(GoalNode g, Expression expr) { private Value evaluate(GoalNode<T> g, Expression expr) {
enterScope(expr); enterScope(expr);
Evaluator evaluator = new Evaluator(g.getAssignments(), g); Evaluator evaluator = new Evaluator(g.getAssignments(), g);
evaluator.setMatcher(matcherApi); evaluator.setMatcher(matcherApi);
...@@ -138,27 +146,27 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -138,27 +146,27 @@ public class Interpreter extends DefaultASTVisitor<Void>
} }
/** /**
*
* @param casesStatement * @param casesStatement
* @return * @return
*/ */
@Override @Override
public Void visit(CasesStatement casesStatement) { public Void visit(CasesStatement casesStatement) {
enterScope(casesStatement); enterScope(casesStatement);
AbstractState beforeCases = stateStack.pop(); State<T> beforeCases = stateStack.pop();
List<GoalNode> allGoalsBeforeCases = beforeCases.getGoals(); List<GoalNode<T>> allGoalsBeforeCases = beforeCases.getGoals();
//global List after all Case Statements //global List after all Case Statements
List<GoalNode> goalsAfterCases = new ArrayList<>(); List<GoalNode<T>> goalsAfterCases = new ArrayList<>();
//copy the list of goal nodes for keeping track of goals //copy the list of goal nodes for keeping track of goals
Set<GoalNode> remainingGoalsSet = new HashSet<>(allGoalsBeforeCases); Set<GoalNode<T>> remainingGoalsSet = new HashSet<>(allGoalsBeforeCases);
//handle cases //handle cases
List<CaseStatement> cases = casesStatement.getCases(); List<CaseStatement> cases = casesStatement.getCases();
for (CaseStatement aCase : cases) { for (CaseStatement aCase : cases) {
Map<GoalNode, VariableAssignment> matchedGoals = matchGoal(remainingGoalsSet, aCase); Map<GoalNode<T>, VariableAssignment> matchedGoals =
matchGoal(remainingGoalsSet, aCase);
if (matchedGoals != null) { if (matchedGoals != null) {
remainingGoalsSet.removeAll(matchedGoals.keySet()); remainingGoalsSet.removeAll(matchedGoals.keySet());
goalsAfterCases.addAll(executeCase(aCase.getBody(), matchedGoals)); goalsAfterCases.addAll(executeCase(aCase.getBody(), matchedGoals));
...@@ -170,7 +178,7 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -170,7 +178,7 @@ public class Interpreter extends DefaultASTVisitor<Void>
if (!remainingGoalsSet.isEmpty()) { if (!remainingGoalsSet.isEmpty()) {
VariableAssignment va = new VariableAssignment(); VariableAssignment va = new VariableAssignment();
Statements defaultCase = casesStatement.getDefaultCase(); Statements defaultCase = casesStatement.getDefaultCase();
for (GoalNode goal : remainingGoalsSet) { for (GoalNode<T> goal : remainingGoalsSet) {
goalsAfterCases.addAll(executeBody(defaultCase, goal, va).getGoals()); goalsAfterCases.addAll(executeBody(defaultCase, goal, va).getGoals());
} }
...@@ -180,14 +188,14 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -180,14 +188,14 @@ public class Interpreter extends DefaultASTVisitor<Void>
//exit scope and create a new state using the union of all newly created goals //exit scope and create a new state using the union of all newly created goals
State newStateAfterCases; State<T> newStateAfterCases;
if (!goalsAfterCases.isEmpty()) { if (!goalsAfterCases.isEmpty()) {
//goalsAfterCases.forEach(node -> node.exitNewVarScope()); //goalsAfterCases.forEach(node -> node.exitScope());
if (goalsAfterCases.size() == 1) { if (goalsAfterCases.size() == 1) {
newStateAfterCases = new State(goalsAfterCases, goalsAfterCases.get(0)); newStateAfterCases = new State<T>(goalsAfterCases, 0);
} else { } else {
newStateAfterCases = new State(goalsAfterCases, null); newStateAfterCases = new State<T>(goalsAfterCases, null);
} }
stateStack.push(newStateAfterCases); stateStack.push(newStateAfterCases);
} }
...@@ -203,12 +211,12 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -203,12 +211,12 @@ public class Interpreter extends DefaultASTVisitor<Void>
* @param aCase * @param aCase
* @return * @return
*/ */
private Map<GoalNode, VariableAssignment> matchGoal(Collection<GoalNode> allGoalsBeforeCases, CaseStatement aCase) { private Map<GoalNode<T>, VariableAssignment> matchGoal(Set<GoalNode<T>> allGoalsBeforeCases, CaseStatement aCase) {
HashMap<GoalNode, VariableAssignment> matchedGoals = new HashMap<>(); HashMap<GoalNode<T>, VariableAssignment> matchedGoals = new HashMap<>();
Expression matchExpression = aCase.getGuard(); Expression matchExpression = aCase.getGuard();
for (GoalNode goal : allGoalsBeforeCases) { for (GoalNode<T> goal : allGoalsBeforeCases) {
VariableAssignment va = evaluateMatchInGoal(matchExpression, goal); VariableAssignment va = evaluateMatchInGoal(matchExpression, goal);
if (va != null) { if (va != null) {
matchedGoals.put(goal, va); matchedGoals.put(goal, va);
...@@ -225,7 +233,7 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -225,7 +233,7 @@ public class Interpreter extends DefaultASTVisitor<Void>
* @param goal * @param goal
* @return null, if match was false, return teh first Assignment when match was true * @return null, if match was false, return teh first Assignment when match was true
*/ */
private VariableAssignment evaluateMatchInGoal(Expression matchExpression, GoalNode goal) { private VariableAssignment evaluateMatchInGoal(Expression matchExpression, GoalNode<T> goal) {
enterScope(matchExpression); enterScope(matchExpression);
MatchEvaluator mEval = new MatchEvaluator(goal.getAssignments(), goal, matcherApi); MatchEvaluator mEval = new MatchEvaluator(goal.getAssignments(), goal, matcherApi);
mEval.getEntryListeners().addAll(entryListeners); mEval.getEntryListeners().addAll(entryListeners);
...@@ -258,17 +266,18 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -258,17 +266,18 @@ public class Interpreter extends DefaultASTVisitor<Void>
/** /**
* For each selected goal put a state onto the stack and visit the body of the case * For each selected goal put a state onto the stack and visit the body of the case
* @param *
* @param
* @param caseStmts * @param caseStmts
* @param goalsToApply @return * @param goalsToApply @return
*/ */
private List<GoalNode> executeCase(Statements caseStmts, Map<GoalNode, VariableAssignment> goalsToApply) { private List<GoalNode<T>> executeCase(Statements caseStmts,
Map<GoalNode<T>, VariableAssignment> goalsToApply) {
enterScope(caseStmts); enterScope(caseStmts);
List<GoalNode> goalsAfterCases = new ArrayList<>(); List<GoalNode<T>> goalsAfterCases = new ArrayList<>();
for (Map.Entry<GoalNode, VariableAssignment> next : goalsToApply.entrySet()) { for (Map.Entry<GoalNode<T>, VariableAssignment> next : goalsToApply.entrySet()) {
State<T> s = executeBody(caseStmts, next.getKey(), next.getValue());
AbstractState s = executeBody(caseStmts, next.getKey(), next.getValue());
goalsAfterCases.addAll(s.getGoals()); goalsAfterCases.addAll(s.getGoals());
} }
exitScope(caseStmts); exitScope(caseStmts);
...@@ -277,10 +286,10 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -277,10 +286,10 @@ public class Interpreter extends DefaultASTVisitor<Void>
} }
private AbstractState executeBody(Statements caseStmts, GoalNode goalNode, VariableAssignment va) { private State<T> executeBody(Statements caseStmts, GoalNode<T> goalNode, VariableAssignment va) {
goalNode.enterNewVarScope(va); goalNode.enterScope(va);
AbstractState s = newState(goalNode); State<T> s = newState(goalNode);
caseStmts.accept(this); caseStmts.accept(this);
popState(s); popState(s);
return s; return s;
...@@ -315,10 +324,10 @@ public class Interpreter extends DefaultASTVisitor<Void> ...@@ -315,10 +324,10 @@ public class Interpreter extends DefaultASTVisitor<Void>
//neuer VarScope //neuer VarScope
//enter new variable scope //enter new variable scope
VariableAssignment params = evaluateParameters(call.getParameters()); VariableAssignment params = evaluateParameters(call.getParameters());
GoalNode g = getSelectedNode();