/* * 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; import jetbrains.mps.lang.dataFlow.framework.instructions.*; import java.util.*; public class AnalyzerRunner<E> { protected Program myProgram; protected DataFlowAnalyzer<E> myAnalyzer; public AnalyzerRunner(Program program, DataFlowAnalyzer<E> analyzer) { myProgram = program; myAnalyzer = analyzer; } public AnalysisResult<E> analyze() { Map<ProgramState, E> stateValues = doAnalyze(); Map<Instruction, E> result = new HashMap<Instruction, E>(); for (Instruction i : myProgram.getInstructions()) { List<E> input = new ArrayList<E>(); input.add(stateValues.get(new ProgramState(i, true))); input.add(stateValues.get(new ProgramState(i, false))); result.put(i, myAnalyzer.merge(myProgram, input)); } return new AnalysisResult<E>(myProgram, myAnalyzer, stateValues, result); } private Map<ProgramState, E> doAnalyze() { Map<ProgramState, E> stateValues = new ProgramStateMap<E>(myProgram); for (ProgramState ps : myProgram.getStates()) { stateValues.put(ps, myAnalyzer.initial(myProgram)); } AnalysisDirection direction = myAnalyzer.getDirection(); Map<ProgramState, List<ProgramState>> dependencies = new ProgramStateMap<List<ProgramState>>(myProgram); Map<ProgramState, List<ProgramState>> dependents = new ProgramStateMap<List<ProgramState>>(myProgram); for (ProgramState ps : myProgram.getStates()) { dependencies.put(ps, direction.dependencies(ps)); dependents.put(ps, direction.dependents(ps)); } Queue<ProgramState> workList = new LinkedList<ProgramState>(); for (Instruction i : myProgram.getInstructions()) { workList.add(new ProgramState(i, false)); workList.add(new ProgramState(i, true)); } while (!workList.isEmpty()) { ProgramState current = workList.remove(); List<E> input = new ArrayList<E>(); for (ProgramState s : dependencies.get(current)) { input.add(stateValues.get(s)); } E oldValue = stateValues.get(current); E mergedValue = myAnalyzer.merge(myProgram, input); E newValue; if (myAnalyzer instanceof DataFlowAnalyzerBase) { newValue = ((DataFlowAnalyzerBase<E>) myAnalyzer).fun(mergedValue, current, Collections.unmodifiableMap(stateValues)); } else { newValue = myAnalyzer.fun(mergedValue, current); } if (!newValue.equals(oldValue)) { stateValues.put(current, newValue); for (ProgramState s : dependents.get(current)) { workList.add(s); } } } return stateValues; } public Program getProgramCopy() { return myProgram; } }