Beispiel #1
0
        /// <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");
            }
        }
Beispiel #2
0
        public static bool Shift(ExecutedBlock toShift, ExecutedBlock target, ExecutionView view)
        {
            var shiftTransformation = new ShiftBehindTransformation(toShift, target);

            view.Apply(shiftTransformation);

            return(!view.IsAborted);
        }
Beispiel #3
0
 /// <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;
 }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        /// <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;
            }
        }
Beispiel #6
0
        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));
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        /// <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);
        }
Beispiel #11
0
        /// <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);
        }
Beispiel #12
0
        /// <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);
        }
Beispiel #13
0
        /// <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);
        }
Beispiel #15
0
        /// <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);
        }
Beispiel #16
0
        /// <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);
        }
Beispiel #18
0
        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);
        }
Beispiel #19
0
 /// <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);
 }
Beispiel #20
0
        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));
        }
Beispiel #21
0
 public InstanceScopes(Dictionary <Instance, VariableName> variables, ExecutedBlock scopeBlock)
 {
     InstanceVariables = variables;
     ScopeBlock        = scopeBlock;
 }
Beispiel #22
0
        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);
                }
            }
        }
Beispiel #23
0
 internal ShiftBehindTransformation(ExecutedBlock shifted, ExecutedBlock target)
 {
     _shifted = shifted;
     _target  = target;
 }
Beispiel #24
0
 /// <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));
 }
Beispiel #25
0
 /// <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;
 }
Beispiel #27
0
        /// <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);
        }
Beispiel #28
0
 /// <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));
 }