/* * Copyright 2003-2012 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.ide.typesystem.trace; import jetbrains.mps.newTypesystem.context.IncrementalTypecheckingContext; import jetbrains.mps.newTypesystem.operation.AbstractOperation; import jetbrains.mps.newTypesystem.state.State; import jetbrains.mps.typesystem.inference.util.ConcurrentSubtypingCache; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.typesystem.inference.ITypeContextOwner; import jetbrains.mps.typesystem.inference.ITypechecking; import jetbrains.mps.typesystem.inference.TypeCheckingContext; import jetbrains.mps.typesystem.inference.TypeContextManager; import jetbrains.mps.typesystem.inference.util.SubtypingCache; import java.util.List; /** * Created with IntelliJ IDEA. * User: fyodor * Date: 11/28/12 * Time: 2:07 PM * To change this template use File | Settings | File Templates. */ public class TypecheckingContextTracker implements ITypeContextOwner { private final TypeCheckingContext myTypecheckingContext; private final SNode myRootNode; private TypeCheckingContext myCurrentContext; private AbstractOperation myOperation; private AbstractOperation myOldOperation; private State myCurrentState; private State myStateCopy; private boolean generationMode = false; public TypecheckingContextTracker(SNode rootNode) { myRootNode = rootNode; myTypecheckingContext = initContext(); myOperation = myTypecheckingContext.getOperation(); myStateCopy = new State(myTypecheckingContext, myTypecheckingContext.getState().getOperation()); myCurrentState = myStateCopy; myCurrentContext = myTypecheckingContext; } private TypeCheckingContext initContext() { final TypeCheckingContext context = TypeContextManager.getInstance().acquireTypecheckingContext(myRootNode, this); TypeContextManager.getInstance().runTypeCheckingAction(this, myRootNode, new ITypechecking.Action() { @Override public void run(TypeCheckingContext context) { context.checkRootInTraceMode(true); } }); return context; } @Override public TypeCheckingContext createTypecheckingContext(SNode sNode, TypeContextManager typeContextManager) { return typeContextManager.createTracingTypeCheckingContext(sNode); } @Override public boolean reuseTypecheckingContext() { return true; } @Override public SubtypingCache createSubtypingCache() { return new ConcurrentSubtypingCache(); } public void setGenerationMode(boolean generationMode, SNode selectedNode) { if (generationMode == this.generationMode) { return; } this.generationMode = generationMode; myOldOperation = null; if (false && this.generationMode) { IncrementalTypecheckingContext context = (IncrementalTypecheckingContext) TypeContextManager.getInstance().createTypeCheckingContext(selectedNode); context.getTypeInGenerationMode(selectedNode); myOperation = context.getOperation(); myCurrentContext = context; myCurrentState = context.getState(); } else { myOperation = myTypecheckingContext.getOperation(); myCurrentContext = myTypecheckingContext; myCurrentState = myStateCopy; } } public State resetCurrentState(AbstractOperation fromDiff) { AbstractOperation rootDiff = myCurrentContext.getOperation(); if (myOldOperation == null) { myCurrentState.clear(false); myCurrentState.executeOperationsBeforeAnchor(rootDiff, fromDiff); } else { myCurrentState.updateState(myOldOperation, fromDiff); } return myCurrentState; } public State updateCurrentState(AbstractOperation fromDiff, AbstractOperation toDiff) { myCurrentState.updateState(fromDiff, toDiff); myOldOperation = toDiff; return myCurrentState; } public State updateCurrentState(AbstractOperation difference) { AbstractOperation nextDiff = findUltimateConsequence(difference); if (nextDiff != null && nextDiff != difference) { myCurrentState.updateState(difference, nextDiff); myOldOperation = nextDiff; return myCurrentState; } else { myOldOperation = difference; } return null; } private AbstractOperation findUltimateConsequence(AbstractOperation op) { if (op == null) { return null; } AbstractOperation result = op; List<AbstractOperation> consequences = result.getConsequences(); while (consequences != null && consequences.size() > 0) { result = consequences.get(consequences.size() - 1); consequences = result.getConsequences(); } return result; } public State getStateCopy() { return myStateCopy; } public State getCurrentState() { return myCurrentState; } public AbstractOperation getOperation () { return myOperation; } public void checkRoot(boolean refresh) { myTypecheckingContext.checkRootInTraceMode(refresh); } public void dispose() { TypeContextManager.getInstance().releaseTypecheckingContext(myRootNode, this); } }