/// <summary> /// Initialize new <see cref="InstanceScope"/> object /// </summary> /// <param name="variable">Variable holding <see cref="ScopedInstance"/></param> /// <param name="scopedInstance">Instance which scope is belonging to</param> /// <param name="start">Scope start</param> /// <param name="end">Scope end</param> public InstanceScope(VariableName variable, Instance scopedInstance, ExecutedBlock start, ExecutedBlock end) { Variable = variable; ScopedInstance = scopedInstance; Start = start; End = end; if (Variable == null) { throw new ArgumentNullException("variable"); } if (ScopedInstance == null) { throw new ArgumentNullException("scopedInstance"); } if (Start == null) { throw new ArgumentNullException("start"); } if (End == null) { throw new ArgumentNullException("end"); } }
public static bool Shift(ExecutedBlock toShift, ExecutedBlock target, ExecutionView view) { var shiftTransformation = new ShiftBehindTransformation(toShift, target); view.Apply(shiftTransformation); return(!view.IsAborted); }
/// <summary> /// Initializes a new instance of the <see cref="EditsProvider" /> class. /// </summary> /// <param name="transformProvider">The call transformation provider.</param> /// <param name="block">The block.</param> /// <exception cref="System.ArgumentNullException">transformProvider</exception> internal EditsProvider(CallTransformProvider transformProvider, ExecutedBlock block) { if (transformProvider == null) { throw new ArgumentNullException("transformProvider"); } TransformProvider = transformProvider; _block = block; }
/// <summary> /// Get block according to given changes log. /// </summary> /// <param name="changes">The changes log.</param> /// <param name="changedBlock">The changed block.</param> /// <param name="defaultBlock">The default block.</param> /// <returns>Desired block.</returns> private ExecutedBlock fromChanges(Dictionary <ExecutedBlock, ExecutedBlock> changes, ExecutedBlock changedBlock, ExecutedBlock defaultBlock) { ExecutedBlock block; if (!changes.TryGetValue(changedBlock, out block)) { block = defaultBlock; } return(block); }
/// <summary> /// Set edge from block1 to block2 into view. /// </summary> /// <param name="block1">Block which next will be block2.</param> /// <param name="block2">Block which previous will be block1.</param> private void setEdge(ExecutedBlock block1, ExecutedBlock block2) { if (block1 != null) { _nextChanges[block1] = block2; } if (block2 != null) { _previouChanges[block2] = block1; } }
private bool canCross(ExecutedBlock shiftedBlock, HashSet <Instance> borderInstances, ExecutionView view) { foreach (var instance in view.AffectedInstances(shiftedBlock)) { if (borderInstances.Contains(instance)) { //there is collision with border return(false); } } return(true); }
private VariableName instanceScopes(ExecutedBlock scopeBlock, Instance instance) { //we need to find last call because of keeping semantic of instance var lastCall = View.LastCallBlock(instance); var lastCallSameLevel = View.GetBlockInLevelOf(scopeBlock.Call, lastCall); //detect if it is possible to get valid scope with correct semantic if (lastCall == scopeBlock) { //scope cannot be shifted behind last call return(null); } if (lastCall != null) { if (View.IsBefore(lastCall, scopeBlock)) { //there is no limit caused by lastCall, //because lastCall cannot be shifted behind instances scope end //it is automatical upper limit } else { if (lastCallSameLevel == null) { //last call is in another call tree and after scopeBlock - it cannot be shifted return(null); } if (!ShiftBehindTransformation.Shift(scopeBlock, lastCallSameLevel, View)) { //scope block cannot be shifted behind last call return(null); } } } //find scope that is already opened before scopeBlock var scopeVariable = findPreviousValidScope(scopeBlock, instance); if (scopeVariable != null) { //we have find scope variable before scopeBlock return(scopeVariable); } //find scope that will be opened afte scope block return(findNextValidScope(scopeBlock, instance)); }
private IEnumerable <Transformation> getScopeTransformations(ExecutedBlock scopeCandidate, IEnumerable <ExecutedBlock> scopeEnds) { var transformations = new List <Transformation>(); var testView = View.Clone(); foreach (var scopeEnd in scopeEnds) { //we need to have every scope end behind scopeCandidate if (!ensurePosition(scopeCandidate, scopeEnd, testView, transformations)) { return(null); } } return(transformations); }
private bool ensurePosition(ExecutedBlock beforeBlock, ExecutedBlock afterBlock, ExecutionView view, List <Transformation> transformations) { if (view.IsBefore(beforeBlock, afterBlock)) { //no transformation is required return(true); } //we need to get after block behind before block var shiftTransform = new ShiftBehindTransformation(afterBlock, beforeBlock); transformations.Add(shiftTransform); view.Apply(shiftTransform); return(!view.IsAborted); }
/// <summary> /// Gets ancestor block (of given block) that is contained in given call. /// </summary> /// <param name="call">The call.</param> /// <param name="block">The block.</param> /// <returns>Ancestor block.</returns> public ExecutedBlock GetBlockInLevelOf(CallContext call, ExecutedBlock block) { var current = block; while (current != null) { if (call == current.Call) { return(current); } current = current.Call.CallingBlock; } //call is not in blocks call hierarchy return(null); }
/// <summary> /// Shift given block behind target block /// </summary> /// <param name="block">The shifted block.</param> /// <param name="target">The target block.</param> public void ShiftBehind(ExecutedBlock block, ExecutedBlock target) { //cut block from current position var nextBlock = NextBlock(block); var previousBlock = PreviousBlock(block); setEdge(previousBlock, nextBlock); //paste it behind target var nextTargetBlock = NextBlock(target); setEdge(target, block); setEdge(block, nextTargetBlock); var shiftTransform = block.Info.BlockTransformProvider.ShiftBehind(target.Info.BlockTransformProvider); Apply(shiftTransform); }
/// <summary> /// Get first of given blocks in current view ordering. /// </summary> /// <param name="blocks">Blocks where first one is searched.</param> /// <returns>First of given blocks.</returns> internal ExecutedBlock EarliestBlock(IEnumerable <ExecutedBlock> blocks) { ExecutedBlock first = null; foreach (var block in blocks) { if (block == null) { continue; } if (first == null || IsBefore(block, first)) { first = block; } } return(first); }
/// <summary> /// Get last of given blocks in current view ordering. /// </summary> /// <param name="blocks">Blocks where last one is searched.</param> /// <returns>Last of given blocks.</returns> public ExecutedBlock LatestBlock(IEnumerable <ExecutedBlock> blocks) { ExecutedBlock last = null; foreach (var block in blocks) { if (block == null) { continue; } if (last == null || IsBefore(last, block)) { last = block; } } return(last); }
private VariableName findPreviousValidScope(ExecutedBlock scopeBlock, Instance instance) { //find variable with valid scope var block = View.PreviousBlock(scopeBlock); var scopeEnds = new HashSet <VariableName>(); ExecutedBlock firstScopeEnd = null; while (block != null) { scopeEnds.UnionWith(block.ScopeEnds(instance)); foreach (var start in block.ScopeStarts(instance)) { if (!scopeEnds.Contains(start)) { //we have found variable with valid scope return(start); } } if (firstScopeEnd == null && scopeEnds.Count > 0) { //if there is no valid variable scope with wanted instance, //then we can try to shift first scope end founded firstScopeEnd = block; } //shift to next block block = View.PreviousBlock(block); } if (firstScopeEnd != null) { if (ShiftBehindTransformation.Shift(firstScopeEnd, scopeBlock, View)) { //scope end was shifted return(firstScopeEnd.ScopeEnds(instance).First()); } } return(null); }
/// <summary> /// Shift given shiftedBlock behind target, if possible /// </summary> /// <param name="shiftedBlock"></param> /// <param name="target"></param> /// <param name="view"></param> private bool shiftBehind(ExecutedBlock shiftedBlock, ExecutedBlock target, ExecutionView view) { //cumulative list of blocks that has to be shifted //It has reverse ordering of transformations that will be generated var shiftedBlocks = new List <ExecutedBlock>(); shiftedBlocks.Add(shiftedBlock); var borderInstances = new HashSet <Instance>(); borderInstances.UnionWith(view.AffectedInstances(shiftedBlock)); //find all colliding blocks, so we can move them with shifted block if possible var currentBlock = shiftedBlock; while (currentBlock != target) { currentBlock = view.NextBlock(currentBlock); if (!canCross(currentBlock, borderInstances, view)) { //this block cannot be crossed borderInstances.UnionWith(view.AffectedInstances(currentBlock)); shiftedBlocks.Add(currentBlock); } } //shifting is not possible, due to collisions between blocks if (!canCross(target, borderInstances, view)) { return(false); } shiftedBlocks.Reverse(); foreach (var block in shiftedBlocks) { view.ShiftBehind(block, target); } return(true); }
/// <summary> /// Gets call where appeared ancestors of both given blocks. /// </summary> /// <param name="block1">The block1.</param> /// <param name="block2">The block2.</param> /// <returns>Desired call.</returns> public CallContext GetCommonCall(ExecutedBlock block1, ExecutedBlock block2) { //table of registered calls used for finding common call var calls = new HashSet <CallContext>(); //register calls from blocks var current1 = block1.Call; var current2 = block2.Call; //common stepping because of optimiztion of same level cases while (current1 != null && current2 != null) { if (current1 != null) { if (calls.Add(current1)) { return(current1); } else { current1 = current1.Caller; } } if (current2 != null) { if (calls.Add(current2)) { return(current2); } else { current2 = current2.Caller; } } } //this could happened only if blocks are from different runs return(null); }
private VariableName findNextValidScope(ExecutedBlock scopeBlock, Instance instance) { //find scope start var scopeStartBlock = View.NextBlock(scopeBlock); while (scopeStartBlock != null) { var starts = scopeStartBlock.ScopeStarts(instance); if (starts.Any()) { if (ShiftBehindTransformation.Shift(scopeBlock, scopeStartBlock, View)) { return(starts.First()); } break; } scopeStartBlock = View.NextBlock(scopeStartBlock); } //cannot find valid scope return(null); }
private InstanceScopes getScopes(ExecutedBlock lastCall, ScopeStepper scopeStepper, TransformationAccepter transformationAccepter) { IEnumerable <InstanceScope> scopes; while ((scopes = scopeStepper.Step(View)) != null) { if (!hasCommonCall(scopes)) { continue; } var scopeEnds = from scope in scopes select scope.End; var scopeStarts = from scope in scopes select scope.Start; //we want to place scope as top as possible //then all scope ends has to be placed behind that place var scopeCandidates = scopeStarts.Concat(new[] { lastCall }); var scopeCandidate = View.LatestBlock(scopeCandidates); var transformations = getScopeTransformations(scopeCandidate, scopeEnds); if (transformations == null) { //cannot transform so that scope ends will be behind scopeCandidate continue; } //it is not required to check scopeStarts positions - because shifting only //latest one cannot affect other scope starts //we have common scope after making all transformations if (transformationAccepter(transformations)) { return(createInstanceScopes(scopes, scopeCandidate)); } } //cannot shift to common scope return(null); }
/// <summary> /// Get enumeration of <see cref="Instance"/> affected by given block in current view. /// </summary> /// <param name="block">The block.</param> /// <returns>Affected instances</returns> public IEnumerable <Instance> AffectedInstances(ExecutedBlock block) { return(block.AffectedInstances); }
private InstanceScopes createInstanceScopes(IEnumerable <InstanceScope> scopes, ExecutedBlock scopeBlock) { if (scopeBlock == null || scopes.Count() != _instances.Length) { return(null); } var scopeIndex = new Dictionary <Instance, VariableName>(); foreach (var scope in scopes) { scopeIndex.Add(scope.ScopedInstance, scope.Variable); } return(new InstanceScopes(scopeIndex, scopeBlock)); }
public InstanceScopes(Dictionary <Instance, VariableName> variables, ExecutedBlock scopeBlock) { InstanceVariables = variables; ScopeBlock = scopeBlock; }
private void initializeScopes(ExecutionView view, ExecutedBlock earliestStart) { var current = earliestStart; //initialize active scope index var activeScopes = new Dictionary <Instance, Dictionary <VariableName, ExecutedBlock> >(); foreach (var instance in _monitoredInstances) { if (instance.CreationBlock == null) { //earliest start cannot be determined - we have to traverse from begining current = view.EntryBlock; } activeScopes.Add(instance, new Dictionary <VariableName, ExecutedBlock>()); } //search block for scopes ExecutedBlock lastBlock = null; while (current != null) { foreach (var instance in _monitoredInstances) { var scopeStarts = view.ScopeStarts(current, instance); var scopeEnds = view.ScopeEnds(current, instance); //activate new scope starts var scopesIndex = activeScopes[instance]; foreach (var variable in scopeStarts) { scopesIndex[variable] = current; } foreach (var variable in scopeEnds) { ExecutedBlock scopeStart; if (!scopesIndex.TryGetValue(variable, out scopeStart)) { //there is no matching start continue; } scopesIndex.Remove(variable); if (scopeStart == current) { //empty scope continue; } var scope = new InstanceScope(variable, instance, scopeStart, current); _scopes.Add(instance, scope); } } lastBlock = current; current = view.NextBlock(current); } //handle non-closed scopes foreach (var instance in _monitoredInstances) { //activate new scope starts var scopesIndex = activeScopes[instance]; foreach (var scopePair in scopesIndex) { var scope = new InstanceScope(scopePair.Key, instance, scopePair.Value, lastBlock); //empty scope is allowed here, because it is not closed _scopes.Add(instance, scope); } } }
internal ShiftBehindTransformation(ExecutedBlock shifted, ExecutedBlock target) { _shifted = shifted; _target = target; }
/// <summary> /// Get <see cref="ExecutedBlock"/> after given block in current view. /// </summary> /// <param name="block">The block which next block is required.</param> /// <returns>Next block.</returns> public ExecutedBlock NextBlock(ExecutedBlock block) { return(fromChanges(_nextChanges, block, block.NextBlock)); }
/// <summary> /// Get <see cref="ExecutedBlock"/> before given block in current view. /// </summary> /// <param name="block">The block which previous block is required.</param> /// <returns>Previous block.</returns> public ExecutedBlock PreviousBlock(ExecutedBlock block) { return(fromChanges(_previouChanges, block, block.PreviousBlock)); }
internal ScopeBlockTransformation(ExecutedBlock scopeBlock, Instance instance) { _instance = instance; _scopeBlock = scopeBlock; }
/// <summary> /// Prepends the call before given block. /// </summary> /// <param name="block">The block.</param> /// <param name="call">The prepended call.</param> public void PrependCall(ExecutedBlock block, CallEditInfo call) { var prependTransform = block.Info.BlockTransformProvider.PrependCall(call); Apply(prependTransform); }
/// <summary> /// Get scope ends of instance for given block in current view. /// </summary> /// <param name="block">The block.</param> /// <param name="instance">Instance which scope ends are requested.</param> /// <returns>Enumeration of variables which scope ends at given block.</returns> internal IEnumerable <VariableName> ScopeEnds(ExecutedBlock block, Instance instance) { return(block.ScopeEnds(instance)); }