Commit 814a7c3e authored by Alexander Weigl's avatar Alexander Weigl

Fixing details in Interpreter

* [FEATURE] CommandLookup
* [FEATURE] InterpreterTest for testing the interpreter; includes helper commands like assert/assertEq
* [FEATURE] Listeners for Evaluator and Interpreter
   * including History and Logger listener for the start
* [FEATURE] Interpreter has scrict or non-script mode (exception on not selected goals)
* [FEATURE] Interpreter has a logger instance
* [FEATURE] default ast visitor has defaultVisit method
parent 341605af
Pipeline #10642 passed with stage
in 2 minutes
target/
*.iml
.idea
package edu.kit.formal;
import edu.kit.formal.proofscriptparser.DefaultASTVisitor;
import edu.kit.formal.proofscriptparser.ast.ASTNode;
import lombok.Getter;
import lombok.Setter;
import java.util.logging.Logger;
/**
* @author Alexander Weigl
* @version 1 (21.05.17)
*/
public class ScopeLogger extends DefaultASTVisitor<Void> {
private Logger logger;
@Getter
@Setter
private String suffix = "", prefix = "";
public ScopeLogger(String name) {
logger = Logger.getLogger(name);
}
@Override
public Void defaultVisit(ASTNode node) {
logger.info(suffix + node.getNodeName() + " @" + node.getStartPosition().getCharInLine() + suffix);
logger.info(node.toString());
return null;
}
}
package edu.kit.formal.TestCommands;
import edu.kit.formal.interpreter.State;
/**
* Created by sarah on 5/17/17.
*/
public abstract class AbstractCommand {
public abstract State execute(State s);
}
package edu.kit.formal.TestCommands;
import edu.kit.formal.interpreter.State;
/**
* TestCommand
* Created by sarah on 5/17/17.
*/
public final class PrintCommand extends AbstractCommand {
public State execute(State s) {
System.out.println("Printing state " + s + " " + s.getSelectedGoalNode().toString());
return s;
}
}
package edu.kit.formal.TestCommands;
import edu.kit.formal.interpreter.GoalNode;
import edu.kit.formal.interpreter.State;
import edu.kit.formal.interpreter.Value;
import edu.kit.formal.interpreter.VariableAssignment;
import edu.kit.formal.proofscriptparser.ast.Type;
import java.math.BigInteger;
/**
* Created by sarah on 5/17/17.
*/
public class SplitCommand extends AbstractCommand {
@Override
public State execute(State s) {
GoalNode g = s.getSelectedGoalNode();
VariableAssignment assignments = g.getAssignments();
String seq1 = g.getSequent().concat("1");
String seq2 = g.getSequent().concat("2");
s.getGoals().remove(g);
s.getGoals().add(new GoalNode(g, seq1));
GoalNode g2 = new GoalNode(g, seq2);
g2.setVarValue("z", new Value(Type.INT, BigInteger.valueOf(10)));
s.getGoals().add(g2);
return s;
}
}
package edu.kit.formal.interpreter;
import edu.kit.formal.proofscriptparser.DefaultASTVisitor;
import edu.kit.formal.proofscriptparser.Visitor;
import edu.kit.formal.proofscriptparser.ast.*;
import lombok.Getter;
import lombok.Setter;
......@@ -14,17 +15,27 @@ import java.util.List;
* @author S.Grebing
* @author A. Weigl
*/
public class Evaluator extends DefaultASTVisitor<Value> {
public class Evaluator extends DefaultASTVisitor<Value> implements ScopeObservable {
private GoalNode currentState;
private List<VariableAssignment> matchedVariables = new ArrayList<>();
@Getter
@Setter
private MatcherApi matcher;
@Getter
private List<Visitor> entryListeners = new ArrayList<>(),
exitListeners = new ArrayList<>();
public Evaluator(GoalNode s) {
this.currentState = s;
}
public Evaluator(GoalNode g, MatcherApi matcherApi) {
this(g);
setMatcher(matcherApi);
}
/**
* Evaluation of an expression.
*
......
package edu.kit.formal.interpreter;
import edu.kit.formal.proofscriptparser.DefaultASTVisitor;
import edu.kit.formal.proofscriptparser.ast.*;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* Class handling evaluation of expressions (visitor for expressions)
*
* @author S.Grebing
*/
public class Evaluator extends DefaultASTVisitor<Value> {
<<<<<<< Updated upstream
private State currentState;
private Stack<List<GoalNode>> matchedGoals = new Stack<>();
private EvaluatorABI abi;
=======
private GoalNode currentState;
private List<VariableAssignment> matchedVariables = new ArrayList<>();
@Getter
@Setter
private MatcherApi matcher;
>>>>>>> Stashed changes
public Evaluator(State s) {
this.currentState = s;
}
/**
* Evaluation of an expression.
*
* @param truth
* @return
*/
public Value eval(Expression truth) {
return (Value) truth.accept(this);
}
@Override
public Value visit(BinaryExpression e) {
Value v1 = (Value) e.getLeft().accept(this);
Value v2 = (Value) e.getRight().accept(this);
Operator op = e.getOperator();
return op.evaluate(v1, v2);
}
/**
* TODO Connect with KeY
*
* @param match
* @return
*/
@Override
public Value visit(MatchExpression match) {
<<<<<<< Updated upstream
=======
Value pattern = (Value) match.getPattern().accept(this);
>>>>>>> Stashed changes
List<VariableAssignment> va = null;
if (pattern.getType() == Type.STRING) {
va = matcher.matchLabel(currentState, (String) pattern.getData());
} else if (pattern.getType() == Type.TERM) {
va = matcher.matchSeq(currentState, (String) pattern.getData());
}
return va != null && va.size() > 0 ? Value.TRUE : Value.FALSE;
}
/**
* TODO Connect with KeY
*
* @param term
* @return
*/
@Override
public Value visit(TermLiteral term) {
return null;
}
@Override
public Value visit(StringLiteral string) {
return Value.from(string);
}
@Override
public Value visit(Variable variable) {
//get variable value
String id = variable.getIdentifier();
Value v = currentState.lookupVarValue(id);
if (v != null) {
return v;
} else {
throw new RuntimeException("Variable " + variable + " was not initialized");
}
}
@Override
public Value visit(BooleanLiteral bool) {
return bool.isValue() ? Value.TRUE : Value.FALSE;
}
@Override
public Value visit(IntegerLiteral integer) {
return Value.from(integer);
}
@Override
public Value visit(UnaryExpression e) {
Operator op = e.getOperator();
Expression expr = e.getExpression();
Value exValue = (Value) expr.accept(this);
return op.evaluate(exValue);
}
}
......@@ -39,7 +39,7 @@ public class GoalNode {
public String toString() {
String s = "Seq: " + sequent + "\n" +
assignments.toString();
assignments.asMap();
return s;
}
......@@ -53,7 +53,6 @@ public class GoalNode {
return v;
} else {
throw new RuntimeException("Value of variable " + varname + " is not defined in goal node " + this.toString());
}
}
......@@ -78,6 +77,7 @@ public class GoalNode {
/**
* Add a variable declaration to the type map (TODO Default value in map?)
*
* @param name
* @param t
*/
......
package edu.kit.formal.interpreter;
import edu.kit.formal.proofscriptparser.DefaultASTVisitor;
import edu.kit.formal.proofscriptparser.ast.ASTNode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.LinkedList;
import java.util.List;
/**
* @author Alexander Weigl
* @version 1 (21.05.17)
*/
@RequiredArgsConstructor
public class HistoryListener extends DefaultASTVisitor<Void> {
@Getter
private final List<ASTNode> queueNode = new LinkedList<>();
private final List<AbstractState> queueState = new LinkedList<>();
private final Interpreter interpreter;
@Override
public Void defaultVisit(ASTNode node) {
queueState.add(interpreter.getCurrentState());
queueNode.add(node);
return null;
}
}
package edu.kit.formal.interpreter;
import edu.kit.formal.interpreter.funchdl.BuiltinCommands;
import edu.kit.formal.interpreter.funchdl.CommandLookup;
import edu.kit.formal.interpreter.funchdl.DefaultLookup;
import edu.kit.formal.proofscriptparser.Facade;
import edu.kit.formal.proofscriptparser.ast.ProofScript;
......@@ -19,10 +22,15 @@ public class Main {
//lese P ein
//Erzeuge Interpreter
//rufe interpret(AST) auf interpreter auf
Facade f = new Facade();
try {
List<ProofScript> l = f.getAST(testFile);
Interpreter inter = new Interpreter();
List<ProofScript> l = Facade.getAST(testFile);
DefaultLookup lookup = new DefaultLookup();
lookup.getBuilders().add(
new BuiltinCommands.PrintCommand());
lookup.getBuilders().add(
new BuiltinCommands.SplitCommand());
Interpreter inter = new Interpreter(lookup);
inter.interpret(l, "TestSeq");
} catch (IOException e) {
e.printStackTrace();
......
package edu.kit.formal.interpreter;
import edu.kit.formal.proofscriptparser.Visitor;
import edu.kit.formal.proofscriptparser.ast.ASTNode;
import org.antlr.v4.runtime.ParserRuleContext;
import java.util.List;
/**
* @author Alexander Weigl
* @version 1 (21.05.17)
*/
public interface ScopeObservable {
/**
* If new Block is entered, a new state has to be created
* (copy of current state) and pushed to the stack
*/
default <T extends ParserRuleContext> void enterScope(ASTNode<T> node) {
callListeners(getEntryListeners(), node);
}
/**
* If block is extied the top state on the
* stack has to be removed
*/
default <T extends ParserRuleContext> void exitScope(ASTNode<T> node) {
callListeners(getExitListeners(), node);
}
List<Visitor> getExitListeners();
List<Visitor> getEntryListeners();
default <T extends ParserRuleContext> void callListeners(List<Visitor> listeners, ASTNode<T> node) {
if (listeners.size() != 0) {
listeners.forEach(node::accept);
}
}
}
......@@ -25,8 +25,6 @@ public class State extends AbstractState {
public State(List<GoalNode> goals, GoalNode selected) {
this.goals = goals;
this.selectedGoalNode = selected;
}
@Override
......@@ -42,7 +40,7 @@ public class State extends AbstractState {
@Override
public GoalNode getSelectedGoalNode() {
if (selectedGoalNode == null) {
return null;
throw new IllegalStateException("no selected node");
} else {
return selectedGoalNode;
}
......
......@@ -71,9 +71,6 @@ public class Value<T> {
@Override
public String toString() {
return "Value{" +
"type=" + type +
", data=" + data +
'}';
return data + ":" + type;
}
}
......@@ -130,4 +130,16 @@ public class VariableAssignment {
copy.types = typeMapCopy;
return copy;
}
private Map<String, Value> asMap(Map<String, Value> map) {
if (parent != null) {
parent.asMap(map);
}
map.putAll(this.values);
return map;
}
public Map<String, Value> asMap() {
return asMap(new HashMap<>());
}
}
package edu.kit.formal.interpreter.funchdl;
import edu.kit.formal.interpreter.*;
import edu.kit.formal.proofscriptparser.ast.CallStatement;
import edu.kit.formal.proofscriptparser.ast.Parameters;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.math.BigInteger;
import java.util.ArrayList;
/**
* @author Alexander Weigl
* @version 1 (21.05.17)
*/
public abstract class BuiltinCommands {
@RequiredArgsConstructor
public abstract static class BuiltinCommand implements CommandHandler {
@Getter
private final String name;
@Override
public boolean handles(CallStatement call) throws IllegalArgumentException {
return name.equals(call.getCommand());
}
}
public static class PrintCommand extends BuiltinCommand {
public PrintCommand() {
super("print_state");
}
@Override
public void evaluate(Interpreter interpreter, CallStatement call, VariableAssignment params) {
for (GoalNode gn : interpreter.getCurrentGoals()) {
System.out.format("%s %s%n %s%n", gn == interpreter.getSelectedNode() ? "*" : " ", gn.getSequent(), gn.getAssignments().asMap());
}
}
}
public static class SplitCommand extends BuiltinCommand {
public SplitCommand() {
super("split");
}
/**
* Created by sarah on 5/17/17.
*/
@Override
public void evaluate(Interpreter interpreter, CallStatement call, VariableAssignment params) {
Value<BigInteger> val = (Value<BigInteger>) params.getValues().getOrDefault("#1", Value.from(2));
int num = val.getData().intValue();
GoalNode g = interpreter.getSelectedNode();
AbstractState s = interpreter.getCurrentState();
State state = new State(new ArrayList<>(s.getGoals()), null);
state.getGoals().remove(s.getSelectedGoalNode());
for (char i = 0; i < num; i++) {
state.getGoals().add(new GoalNode(g, g.getSequent() + "." + (char) ('a' + i)));
}
interpreter.pushState(state);
}
}
}
package edu.kit.formal.interpreter.funchdl;
import edu.kit.formal.interpreter.Interpreter;
/**
* @author Alexander Weigl
* @version 1 (20.05.17)
*/
public interface CommandCall {
void evaluate(Interpreter state);
}
package edu.kit.formal.interpreter.funchdl;
import edu.kit.formal.interpreter.Interpreter;
import edu.kit.formal.interpreter.VariableAssignment;
import edu.kit.formal.proofscriptparser.ast.CallStatement;
import edu.kit.formal.proofscriptparser.ast.Parameters;
/**
* @author Alexander Weigl
* @version 1 (20.05.17)
*/
public interface CommandHandler {
/**
* determines if this handler can handle the given command
*
* @param call
* @return
* @throws IllegalArgumentException
*/
boolean handles(CallStatement call) throws IllegalArgumentException;
/**
* @param interpreter
* @param call
* @param params
*/
void evaluate(Interpreter interpreter,
CallStatement call,
VariableAssignment params);
}
package edu.kit.formal.interpreter.funchdl;
import edu.kit.formal.interpreter.Interpreter;
import edu.kit.formal.interpreter.VariableAssignment;
import edu.kit.formal.proofscriptparser.ast.CallStatement;
/**
* @author Alexander Weigl
* @version 1 (20.05.17)
*/
public interface CommandLookup {
void callCommand(Interpreter i, CallStatement c, VariableAssignment p);
}
package edu.kit.formal.interpreter.funchdl;
import edu.kit.formal.interpreter.Interpreter;
import edu.kit.formal.interpreter.VariableAssignment;
import edu.kit.formal.proofscriptparser.ast.CallStatement;
import lombok.Getter;
import java.util.*;
/**
* @author Alexander Weigl
* @version 1 (20.05.17)
*/
public class DefaultLookup implements CommandLookup {
@Getter
private final List<CommandHandler> builders = new ArrayList<>(1024);
public DefaultLookup() {
}
public void callCommand(Interpreter interpreter,
CallStatement call,
VariableAssignment params) {
CommandHandler b = getBuilder(call);
b.evaluate(interpreter, call, params);
}
private CommandHandler getBuilder(CallStatement callStatement) {
CommandHandler found = null;
for (CommandHandler b : builders) {
if (b.handles(callStatement)) {
if (found == null) {
found = b;
} else {
throw new IllegalStateException("Call on line"
+ callStatement.getStartPosition().getLineNumber()
+ " is ambigue.");
}
}
}
if (found != null) return found;
throw new IllegalStateException();
}
}
package edu.kit.formal.interpreter.funchdl;
import de.uka.ilkd.key.api.ProofScriptCommandCall;
import de.uka.ilkd.key.macros.scripts.EngineState;
import de.uka.ilkd.key.macros.scripts.ProofScriptCommand;
import edu.kit.formal.interpreter.Interpreter;
import edu.kit.formal.interpreter.VariableAssignment;
import edu.kit.formal.proofscriptparser.ast.CallStatement;
import lombok.RequiredArgsConstructor;
import java.util.Map;
/**
* @author Alexander Weigl
* @version 1 (21.05.17)
*/
@RequiredArgsConstructor
public class ProofScriptCommandBuilder implements CommandHandler {
private final Map<String, ProofScriptCommand> scripts;
@Override
public boolean handles(CallStatement call) {
return scripts.containsKey(call.getCommand());
}
@Override
public void evaluate(Interpreter interpreter,
CallStatement call,
VariableAssignment params) {
ProofScriptCommand c = scripts.get(call.getCommand());
EngineState state = null;
Map<String, String> map;
//ProofScriptCommandCall cc = c.evaluateArguments(state, map);
}
}
......@@ -23,7 +23,6 @@ package edu.kit.formal.proofscriptparser;
*/
import edu.kit.formal.proofscriptparser.ast.*;
/**
......@@ -31,80 +30,103 @@ import edu.kit.formal.proofscriptparser.ast.*;
* @version 1 (28.04.17)
*/
public class DefaultASTVisitor<T> implements Visitor<T> {
@Override public T visit(ProofScript proofScript) {
public T defaultVisit(ASTNode node) {
return null;
}
@Override public T visit(AssignmentStatement assignmentStatement) {
return null;
@Override
public T visit(ProofScript proofScript) {
return defaultVisit(proofScript);
}
@Override public T visit(BinaryExpression binaryExpression) {
return null;
@Override
public T visit(AssignmentStatement assignment) {
return defaultVisit(assignment);
}
@Override public T visit(MatchExpression matchExpression) {
return null;
@Override
public T visit(BinaryExpression binaryExpression) {
return defaultVisit(binaryExpression);
}
@Override public T visit(TermLiteral termLiteral) {
return null;
@Override
public T visit(MatchExpression matchExpression) {
return defaultVisit(matchExpression);
}
@Override public T visit(StringLiteral stringLiteral) {
return null;
@Override
public T visit(TermLiteral termLiteral) {
return defaultVisit(termLiteral);
}