/// <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]); } } }