Esempio n. 1
0
        /// <summary>
        /// Handles the computation internally, i.e. calls dependencies, creates output, manages delays, etc
        /// </summary>
        /// <param name="transformationRule">The transformation rule</param>
        /// <param name="input">The input elements for this computation</param>
        /// <param name="context">The transformation context</param>
        /// <param name="computations">The computations for the input</param>
        /// <param name="originalTransformationRule">The transformation rule of the original call</param>
        /// <param name="comp">The computation</param>
        /// <param name="compCon">The computation context</param>
        private void HandleComputation(GeneralTransformationRule transformationRule, object[] input, IEnumerable context, List <ITraceEntry> computations, GeneralTransformationRule originalTransformationRule, Computation comp, ComputationContext compCon)
        {
            // The transformation output is only generated when we are handling the base transformation rule,
            // because this is always required
            if (compCon.IsDelayed)
            {
                Stack <Computation> dependantComputes = new Stack <Computation>();
                var ruleStack = Transformation.ComputeInstantiatingTransformationRulePath(comp);
                if (transformationRule != originalTransformationRule)
                {
                    ReorderStack(originalTransformationRule, comp, ruleStack);
                }
                var delayLevel = comp.Context.MinOutputDelayLevel;

                var         computes = new List <Computation>();
                Computation lastComp = null;

                while (ruleStack.Count > 0)
                {
                    var rule  = ruleStack.Pop();
                    var comp2 = FindOrCreateDependentComputation(input, computations, comp, dependantComputes, rule);

                    // in case comp2 is not yet handled, a delay does not yet exist and thus
                    // DelayLevel < minDelayLevel
                    delayLevel = Math.Max(delayLevel, Math.Max(comp2.OutputDelayLevel, comp2.Context.MinOutputDelayLevel));
                    if (lastComp != null)
                    {
                        lastComp.SetBaseComputation(comp2);
                    }
                    lastComp = comp2;
                    computes.Add(comp2);
                }

                // delay the call of dependencies
                // this prevents the issue arising from computations calling their parents that come later in the stack
                foreach (var comp2 in dependantComputes)
                {
                    CallDependencies(comp2, true);
                }

                if (delayLevel <= currentOutputDelay)
                {
                    var createRule = computes[0];

                    // Generate the output
                    var output = createRule.CreateOutput(context);

                    for (int i = computes.Count - 1; i >= 0; i--)
                    {
                        computes[i].InitializeOutput(output);
                    }
                    if (callTransformations)
                    {
                        for (int i = computes.Count - 1; i >= 0; i--)
                        {
                            computes[i].Transform();
                        }
                    }
                }
                else
                {
                    //Save computations into Delay
                    Delay(delayLevel, computes, context);
                }

                if (!callTransformations)
                {
                    for (int i = computes.Count - 1; i >= 0; i--)
                    {
                        AddToComputationOrder(computes[i], currentTransformationDelay);
                    }
                }

                for (int i = computes.Count - 1; i >= 0; i--)
                {
                    dependencyCallQueue.Enqueue(computes[i]);
                }
            }
        }