protected override IStatement DoConvertStatement(IStatement ist) { if (ist is IExpressionStatement) { bool isAccumulator = false; IExpressionStatement ies = (IExpressionStatement)ist; if (ies.Expression is IAssignExpression) { IAssignExpression iae = (IAssignExpression)ies.Expression; AccumulationInfo ac = context.InputAttributes.Get <AccumulationInfo>(ies); if (ac != null) { // This statement defines an accumulator. // Delete the statement and replace with any remaining accumulations. if (!ac.isInitialized) { context.AddStatementBeforeCurrent(ac.initializer); } ac.isInitialized = false; context.AddStatementsBeforeCurrent(ac.statements); isAccumulator = true; } object ivd = Recognizer.GetVariableDeclaration(iae.Target); if (ivd == null) { ivd = Recognizer.GetFieldReference(iae.Target); } if (ivd != null) { MessageArrayInformation mai = context.InputAttributes.Get <MessageArrayInformation>(ivd); bool oneUse = (mai != null) && (mai.useCount == 1); List <AccumulationInfo> ais = context.InputAttributes.GetAll <AccumulationInfo>(ivd); foreach (AccumulationInfo ai in ais) { if (!context.InputAttributes.Has <OperatorStatement>(ist)) { if (oneUse) { return(null); // remove the statement } else { continue; } } // assuming that we only accumulate one statement, we should always initialize if (true || !ai.isInitialized) { // add the initializer in the same containers as the original accumulation statement int ancIndex = ai.containers.GetMatchingAncestorIndex(context); Containers missing = ai.containers.GetContainersNotInContext(context, ancIndex); context.AddStatementBeforeAncestorIndex(ancIndex, Containers.WrapWithContainers(ai.initializer, missing.outputs)); ai.isInitialized = true; } // This statement defines a variable that contributes to an accumulator. IList <IStatement> stmts = Builder.StmtCollection(); IExpression target = iae.Target; Type exprType = target.GetExpressionType(); IExpression accumulator = ai.accumulator; Type accumulatorType = ai.type; int rank; Type eltType = Util.GetElementType(exprType, out rank); if (rank == 1 && eltType == accumulatorType) { // This statement defines an array of items to be accumulated. VariableInformation varInfo = context.InputAttributes.Get <VariableInformation>(mai.ci.decl); int indexingDepth = Recognizer.GetIndexingDepth(iae.Target); if (mai.loopVarInfo != null) { indexingDepth -= mai.loopVarInfo.indexVarRefs.Length; } IExpression size = varInfo.sizes[indexingDepth][0]; IVariableDeclaration indexVar = varInfo.indexVars[indexingDepth][0]; IForStatement ifs = Builder.ForStmt(indexVar, size); target = Builder.ArrayIndex(target, Builder.VarRefExpr(indexVar)); ifs.Body.Statements.Add(ai.GetAccumulateStatement(context, accumulator, target)); stmts.Add(ifs); } else { Stack <IList <IExpression> > indexStack = new Stack <IList <IExpression> >(); while (exprType != accumulatorType && target is IArrayIndexerExpression) { // The accumulator is an array type, and this statement defines an element of the accumulator type. // Peel off the indices of the target. IArrayIndexerExpression iaie = (IArrayIndexerExpression)target; indexStack.Push(iaie.Indices); target = iaie.Target; accumulatorType = Util.GetElementType(accumulatorType); } while (indexStack.Count > 0) { // Attach the indices of the target to the accumulator, in reverse order that they were peeled. accumulator = Builder.ArrayIndex(accumulator, indexStack.Pop()); } if (exprType == accumulatorType) { if (oneUse && !isAccumulator) { // convert // msg = expr; // into // T temp = expr; // acc = SetToProduct(acc, temp); // and move into ai.statement. tempVarCount++; string name = "_temp" + tempVarCount; IVariableDeclaration tempVar = Builder.VarDecl(name, exprType); IStatement newStatement = Builder.AssignStmt(Builder.VarDeclExpr(tempVar), iae.Expression); context.AddStatementBeforeCurrent(newStatement); context.AddStatementBeforeCurrent(ai.GetAccumulateStatement(context, accumulator, Builder.VarRefExpr(tempVar))); return(null); } else { // must keep the original statement. // add // acc = SetToProduct(acc, msg); // to ai.statements. context.AddStatementAfterCurrent(ai.GetAccumulateStatement(context, accumulator, iae.Target)); } } else { Error("Unrecognized variable type: " + StringUtil.TypeToString(exprType)); } } Containers containers = new Containers(context); containers = containers.Remove(ai.containers); IList <IStatement> output2 = Builder.StmtCollection(); Containers.AddStatementWithContainers(output2, stmts, containers.inputs); foreach (IStatement ist2 in output2) { context.AddStatementAfterCurrent(ist2); } } } } if (!isAccumulator) { return(ist); } else { return(null); } } else { return(base.DoConvertStatement(ist)); } }