/*
* Copyright 2003-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.lang.dataFlow.framework.instructions;
import jetbrains.mps.lang.dataFlow.framework.Program;
import jetbrains.mps.lang.dataFlow.framework.ProgramState;
import jetbrains.mps.lang.dataFlow.framework.Program.TryFinallyInfo;
import java.util.*;
public abstract class Instruction {
protected Program myProgram;
protected Object mySource;
protected String myRuleReference;
protected final Set<Instruction> myJumps = new HashSet<Instruction>();
protected final Map<Object, Object> myUserObjects = new HashMap<Object, Object>();
protected TryFinallyInfo myBlockInfo;
protected int myIndex;
public Instruction() {
}
public Instruction(String ruleNodeReference) {
myRuleReference = ruleNodeReference;
}
public Program getProgram() {
return myProgram;
}
public void setProgram(Program p) {
myProgram = p;
}
public Object getSource() {
return mySource;
}
public void setSource(Object source) {
mySource = source;
}
public boolean isStart() {
return getIndex() == 0;
}
public void addJump(Instruction instruction) {
myJumps.add(instruction);
}
public void removeJump(Instruction instruction) {
myJumps.remove(instruction);
}
public Set<Instruction> getJumps() {
return myJumps;
}
public void buildCaches() {
TryFinallyInfo bestMatch = null;
for (TryFinallyInfo info : getProgram().getBlockInfos()) {
if (myIndex > info.getTry().getIndex() && myIndex < info.getEndTry().getIndex()) {
bestMatch = info;
}
}
myBlockInfo = bestMatch;
}
public TryFinallyInfo getEnclosingBlock() {
return myBlockInfo;
}
public Set<Instruction> succ() {
Set<Instruction> result = new HashSet<Instruction>();
for (ProgramState ps : new ProgramState(this, false).succ()) {
result.add(ps.getInstruction());
}
for (ProgramState ps : new ProgramState(this, true).succ()) {
result.add(ps.getInstruction());
}
return result;
}
public Set<Instruction> pred() {
Set<Instruction> result = new HashSet<Instruction>();
for (ProgramState ps : new ProgramState(this, false).pred()) {
result.add(ps.getInstruction());
}
for (ProgramState ps : new ProgramState(this, true).pred()) {
result.add(ps.getInstruction());
}
return result;
}
public List<ProgramState> succ(ProgramState s) {
List<ProgramState> result = new ArrayList<ProgramState>();
result.add(new ProgramState(getProgram().get(getIndex() + 1), s.isReturnMode()));
return result;
}
public List<ProgramState> pred(ProgramState s) {
List<ProgramState> result = new ArrayList<ProgramState>();
if (this != getProgram().getStart()) {
Instruction prev = getProgram().get(getIndex() - 1);
if (!(prev instanceof RetInstruction) &&
!(prev instanceof JumpInstruction) &&
!(prev instanceof EndTryInstruction && s.isReturnMode())) {
result.add(new ProgramState(prev, s.isReturnMode()));
}
}
for (Instruction jump : myJumps) {
result.add(new ProgramState(jump, s.isReturnMode()));
}
return result;
}
public int getIndex() {
return myIndex;
}
public void setIndex(int index) {
myIndex = index;
}
public boolean isBefore(Instruction i) {
return getIndex() < i.getIndex();
}
public boolean isAfter(Instruction i) {
return getIndex() > i.getIndex();
}
public abstract String commandPresentation();
public void putUserObject(Object key, Object value) {
myUserObjects.put(key, value);
}
public Object getUserObject(Object key) {
return myUserObjects.get(key);
}
public String toString() {
return getIndex() + ": " + commandPresentation();
}
public String getRuleReference() {
return myRuleReference;
}
public void setRuleReference(String ruleReference) {
myRuleReference = ruleReference;
}
}