Exemple #1
0
 protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
 {
     // register the whole expression only
     // indices are not registered as separate expressions
     ProcessExpression(iaie);
     return(iaie);
 }
Exemple #2
0
 private IExpression GetMessageExpression(IExpression expr, IDictionary <IVariableDeclaration, IVariableDeclaration> msgVars)
 {
     if (expr is IVariableReferenceExpression)
     {
         IVariableReferenceExpression ivre = (IVariableReferenceExpression)expr;
         IVariableDeclaration         ivd  = ivre.Variable.Resolve();
         IVariableDeclaration         msgVar;
         if (msgVars.TryGetValue(ivd, out msgVar))
         {
             return(Builder.VarRefExpr(msgVar));
         }
         else
         {
             return(null);
         }
     }
     else if (expr is IArrayIndexerExpression)
     {
         IArrayIndexerExpression iaie      = (IArrayIndexerExpression)expr;
         IExpression             targetMsg = GetMessageExpression(iaie.Target, msgVars);
         if (targetMsg == null)
         {
             return(null);
         }
         else
         {
             return(Builder.ArrayIndex(targetMsg, iaie.Indices));
         }
     }
     else
     {
         throw new ArgumentException("Unrecognized method argument expression");
     }
 }
        /// <summary>
        /// Register a use of a variable at a specific indexing depth
        /// </summary>
        /// <param name="iaie"></param>
        /// <returns></returns>
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            IExpression expr = (IArrayIndexerExpression)base.ConvertArrayIndexer(iaie);

            // Only register the full indexer expression, not its sub-expressions
            if (Recognizer.IsBeingIndexed(context) || Recognizer.IsBeingMutated(context, expr))
            {
                return(expr);
            }
            List <IList <IExpression> > indices = Recognizer.GetIndices(expr, out IExpression target);

            if (target is IVariableReferenceExpression)
            {
                IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target);
                if (ivd != null)
                {
                    if (usageInfo.TryGetValue(ivd, out UsageInfo info))
                    {
                        info.indexingDepths.Add(indices.Count);
                        RegisterUse(info, expr);
                    }
                }
            }
            return(expr);
        }
Exemple #4
0
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            var indices = Recognizer.GetIndices(iaie, out IExpression target);

            if (target is IVariableReferenceExpression)
            {
                // Only convert indices that could matter.
                IVariableDeclaration ivd  = Recognizer.GetVariableDeclaration(target);
                HoistingInfo         info = GetOrCreateHoistingInfo(ivd);
                int indexingDepth         = indices.Count;
                for (int bracket = 0; bracket < indexingDepth; bracket++)
                {
                    for (int dim = 0; dim < indices[bracket].Count; dim++)
                    {
                        if (info.maxDepthWhereDimensionCouldMatter.Length <= bracket ||
                            info.maxDepthWhereDimensionCouldMatter[bracket][dim] >= indexingDepth)
                        {
                            ConvertExpression(indices[bracket][dim]);
                        }
                    }
                }
                return(iaie);
            }
            else
            {
                return(base.ConvertArrayIndexer(iaie));
            }
        }
 private static void WriteArrayIndexerExpression(LanguageWriter w, IArrayIndexerExpression exp)
 {
     w.WriteExpression(exp.Target);
     w.Write("[");
     w.WriteExpressionCollection(exp.Indices);
     w.Write("]");
 }
Exemple #6
0
 /// <summary>
 /// Use wildcards to replace any indices in expr which involve local variables of the gateBlock
 /// </summary>
 /// <param name="gateBlock"></param>
 /// <param name="expr"></param>
 /// <returns></returns>
 private IExpression ReplaceLocalIndices(GateBlock gateBlock, IExpression expr)
 {
     if (expr is IArrayIndexerExpression)
     {
         IArrayIndexerExpression iaie    = (IArrayIndexerExpression)expr;
         IExpression             target  = ReplaceLocalIndices(gateBlock, iaie.Target);
         List <IExpression>      indices = new List <IExpression>();
         bool replaced = !ReferenceEquals(target, iaie.Target);
         foreach (IExpression index in iaie.Indices)
         {
             if (ContainsLocalVars(gateBlock, index))
             {
                 indices.Add(Builder.StaticMethod(new Func <int>(GateAnalysisTransform.AnyIndex)));
                 replaced = true;
             }
             else
             {
                 indices.Add(index);
             }
         }
         if (replaced)
         {
             expr = Builder.ArrayIndex(target, indices);
         }
     }
     return(expr);
 }
Exemple #7
0
        /// <summary>
        /// Determine if all literal indices beyond the usageDepth are zero
        /// </summary>
        /// <param name="target"></param>
        /// <param name="targetDepth"></param>
        /// <param name="usageDepth"></param>
        /// <returns></returns>
        private static bool CheckExtraLiteralsAreZero(IExpression target, int targetDepth, int usageDepth)
        {
            bool extraLiteralsAreZero = true;
            int  depth = targetDepth;

            while (depth > usageDepth)
            {
                IArrayIndexerExpression iaie = (IArrayIndexerExpression)target;
                foreach (IExpression index in iaie.Indices)
                {
                    if (index is ILiteralExpression)
                    {
                        int value = (int)((ILiteralExpression)index).Value;
                        if (value != 0)
                        {
                            extraLiteralsAreZero = false;
                            break;
                        }
                    }
                }
                target = iaie.Target;
                depth--;
            }
            return(extraLiteralsAreZero);
        }
Exemple #8
0
 public override void VisitArrayIndexerExpression(IArrayIndexerExpression value)
 {
     VisitExpression(value.Target);
     _formatter.Write("[");
     VisitExpressionCollection(value.Indices, true);
     _formatter.Write("]");
 }
Exemple #9
0
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            bool isPartOfLhs = Recognizer.IsBeingMutated(context, iaie);

            AddUsage(iaie, isPartOfLhs);
            // loop over prefixes of the expression
            IArrayIndexerExpression prefix = iaie;
            bool isPrefix = false;

            while (true)
            {
                foreach (IExpression index in prefix.Indices)
                {
                    ConvertExpression(index);
                }
                if (isPrefix && false)
                {
                    bool anyIndexIsPartitioned = prefix.Indices.Any(index => Recognizer.GetVariables(index).Any(ivd => context.InputAttributes.Has <Partitioned>(ivd)));
                    if (anyIndexIsPartitioned)
                    {
                        AddUsage(prefix, false);
                    }
                }
                if (prefix.Target is IArrayIndexerExpression target)
                {
                    prefix   = target;
                    isPrefix = true;
                }
                else
                {
                    break;
                }
            }
            return(iaie);
        }
Exemple #10
0
        public override bool Equals(object obj)
        {
            if (this == obj)
            {
                return(true);
            }

            IArrayIndexerExpression expression = obj as IArrayIndexerExpression;

            if (expression == null ||
                (!Target.Equals(expression.Target)) ||
                Indices.Count != expression.Indices.Count)
            {
                return(false);
            }

            for (int i = 0; i < Indices.Count; i++)
            {
                if (!(Indices[i].Equals(expression.Indices[i])))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemple #11
0
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            bool isDef = Recognizer.IsBeingMutated(context, iaie);

            base.ConvertArrayIndexer(iaie);
            RegisterDepth(iaie, isDef);
            return(iaie);
        }
Exemple #12
0
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            // convert the indices first
            IExpression expr = base.ConvertArrayIndexer(iaie);

            // Check if this is the top level indexer
            if (Recognizer.IsBeingIndexed(context))
            {
                return(expr);
            }
            if (Recognizer.IsBeingMutated(context, iaie))
            {
                return(expr);
            }
            IExpression target;
            List <IList <IExpression> > indices = Recognizer.GetIndices(expr, out target);

            if (!(target is IVariableReferenceExpression))
            {
                return(expr);
            }
            IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target);

            if (ivd == null)
            {
                return(expr);
            }
            VariableToChannelInformation vtci;

            if (usesOfVariable.TryGetValue(ivd, out vtci))
            {
                IExpression usageIndex = Builder.LiteralExpr(GetUseNumber(ivd, vtci));
                ChannelInfo ci         = context.OutputAttributes.Get <ChannelInfo>(vtci.usesDecl);
                IExpression newExpr    = Builder.VarRefExpr(vtci.usesDecl);
                if (vtci.usageDepth > indices.Count)
                {
                    Error("usageDepth (" + vtci.usageDepth + ") > indices.Count (" + indices.Count + ")");
                }
                // append the indices up to the usageDepth
                for (int i = 0; i < vtci.usageDepth; i++)
                {
                    if (indices.Count <= i)
                    {
                        return(newExpr);
                    }
                    newExpr = Builder.ArrayIndex(newExpr, indices[i]);
                }
                newExpr = Builder.ArrayIndex(newExpr, usageIndex);
                // append the remaining indices
                for (int i = vtci.usageDepth; i < indices.Count; i++)
                {
                    newExpr = Builder.ArrayIndex(newExpr, indices[i]);
                }
                return(newExpr);
            }
            return(expr);
        }
Exemple #13
0
        /// <summary>
        /// Return the common parent of the two expressions, and indicate if the expressions overlap
        /// </summary>
        /// <param name="eb1"></param>
        /// <param name="eb2"></param>
        /// <returns></returns>
        /// <remarks>
        /// When finding the common parent, we want to preserve any array slicing.  Indexing brackets are not removed if present in both expressions.
        /// Mismatching indices are replaced by AnyIndex.
        /// Examples:
        /// i = loop index inside the gate block
        /// j = loop index outside the gate block, or a method parameter
        /// (a,a[i]) => (a,true)
        /// (a,a[j]) => (a,true)
        /// (a[i],a[0]) => (a[*],true)
        /// (a[i],a[j]) => (a[*],true)
        /// (a[j],a[0]) => (a[*],assumeMatch)
        /// (a[0],a[1]) => (a[*],false)
        /// (a[0][0],a[1][0]) => (a[*][0],false)
        /// (a[0][0],a[1][1]) => (a[*][*],false)
        /// </remarks>
        private static ExpressionWithBindings GetCommonParent(ExpressionWithBindings eb1, ExpressionWithBindings eb2)
        {
            List <IExpression> prefixes1 = Recognizer.GetAllPrefixes(eb1.Expression);
            List <IExpression> prefixes2 = Recognizer.GetAllPrefixes(eb2.Expression);

            if (!prefixes1[0].Equals(prefixes2[0]))
            {
                throw new Exception("Expressions have no overlap: " + eb1 + "," + eb2);
            }
            IExpression parent = prefixes1[0];
            int         count  = System.Math.Min(prefixes1.Count, prefixes2.Count);

            for (int i = 1; i < count; i++)
            {
                IExpression prefix1 = prefixes1[i];
                IExpression prefix2 = prefixes2[i];
                if (prefix1 is IArrayIndexerExpression)
                {
                    IArrayIndexerExpression iaie1 = (IArrayIndexerExpression)prefix1;
                    if (prefix2 is IArrayIndexerExpression)
                    {
                        IArrayIndexerExpression iaie2 = (IArrayIndexerExpression)prefix2;
                        if (iaie1.Indices.Count != iaie2.Indices.Count)
                        {
                            throw new Exception("Array rank mismatch: " + eb1 + "," + eb2);
                        }
                        IList <IExpression> indices = Builder.ExprCollection();
                        for (int ind = 0; ind < iaie1.Indices.Count; ind++)
                        {
                            IExpression index1 = iaie1.Indices[ind];
                            IExpression index2 = iaie2.Indices[ind];
                            IExpression index  = Unify(index1, eb1.Bindings, index2, eb2.Bindings);
                            indices.Add(index);
                        }
                        parent = Builder.ArrayIndex(parent, indices);
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    throw new Exception("Unhandled expression type: " + prefix1);
                }
            }
            ExpressionWithBindings result = new ExpressionWithBindings();

            result.Expression = parent;
            if (eb1.Bindings.Count > 0 && eb2.Bindings.Count > 0)
            {
                result.Bindings.AddRange(eb1.Bindings);
                result.Bindings.AddRange(eb2.Bindings);
            }
            return(result);
        }
Exemple #14
0
 public IExpression Replace(BasicTransformContext context, IExpression expr)
 {
     if (copyMap.ContainsKey(expr))
     {
         var cc = copyMap[expr];
         if (cc.IsValidContext(context))
         {
             return(cc.Expression);
         }
     }
     if (expr is IArrayIndexerExpression)
     {
         IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr;
         if (copiedInEveryElementMap.ContainsKey(iaie.Target))
         {
             var cc = copiedInEveryElementMap[iaie.Target];
             if (cc.IsValidContext(context))
             {
                 return(cc.Expression);
             }
         }
         if (copyAtIndexMap.ContainsKey(iaie.Target))
         {
             var cc = copyAtIndexMap[iaie.Target];
             if (cc.Depth == 1 && cc.IsValidContext(context))
             {
                 return(cc.ExpressionAtIndex(new[] { iaie.Indices }));
             }
         }
         if (iaie.Target is IArrayIndexerExpression)
         {
             var iaie2 = (IArrayIndexerExpression)iaie.Target;
             if (copyAtIndexMap.ContainsKey(iaie2.Target))
             {
                 var cc = copyAtIndexMap[iaie2.Target];
                 if (cc.Depth == 2 && cc.IsValidContext(context))
                 {
                     return(cc.ExpressionAtIndex(new[] { iaie2.Indices, iaie.Indices }));
                 }
             }
             if (iaie2.Target is IArrayIndexerExpression)
             {
                 var iaie3 = (IArrayIndexerExpression)iaie2.Target;
                 if (copyAtIndexMap.ContainsKey(iaie3.Target))
                 {
                     var cc = copyAtIndexMap[iaie3.Target];
                     if (cc.Depth == 3 && cc.IsValidContext(context))
                     {
                         return(cc.ExpressionAtIndex(new[] { iaie3.Indices, iaie2.Indices, iaie.Indices }));
                     }
                 }
             }
         }
     }
     return(null);
 }
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            bool isDef = Recognizer.IsBeingMutated(context, iaie);

            iaie = (IArrayIndexerExpression)base.ConvertArrayIndexer(iaie);
            if (isDef)
            {
                return(iaie);
            }
            return(GetClone(iaie));
        }
Exemple #16
0
        protected override IStatement ConvertFor(IForStatement ifs)
        {
            // convert the initializer, condition, and increment outside of the container.
            context.SetPrimaryOutput(ifs);
            ConvertStatement(ifs.Initializer);
            ConvertExpression(ifs.Condition);
            ConvertStatement(ifs.Increment);

            // convert the body inside of a new ContainerInfo.
            bool wasPartitioned          = this.InPartitionedLoop;
            IVariableDeclaration loopVar = Recognizer.LoopVariable(ifs);
            bool isPartitioned           = InPartitionedLoop || context.InputAttributes.Has <Partitioned>(loopVar) || (this.compiler.UseLocals && this.compiler.OptimiseInferenceCode);

            if (isPartitioned)
            {
                this.InPartitionedLoop = true;
                containerInfos.Push(new ContainerInfo());
            }
            openContainers.Push(ifs);
            ConvertBlock(ifs.Body);
            openContainers.Pop();
            if (isPartitioned)
            {
                ContainerInfo containerInfo = containerInfos.Pop();
                var           localInfos    = new Dictionary <IExpression, LocalInfo>();
                localInfoOfStmt[ifs] = localInfos;
                // find the longest common prefix of each variable's expressions
                foreach (var entry in containerInfo.usageInfoOfVariable)
                {
                    object    decl      = entry.Key;
                    UsageInfo usageInfo = entry.Value;
                    CombineLocalInfos(usageInfo.localInfos);
                    foreach (var pair in usageInfo.localInfos)
                    {
                        IExpression expr      = pair.Key;
                        LocalInfo   localInfo = pair.Value;
                        IExpression prefix    = GetPrefixInParent(expr, loopVar);
                        if (!ReferenceEquals(prefix, expr))
                        {
                            // expr refers to this loop variable
                            IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr;
                            if (usageInfo.localInfos.Count == 1)
                            {
                                localInfos.Add(expr, localInfo);
                            }
                        }
                        // add the prefix to the parent containerInfo
                        var info = AddLocalInfo(decl, prefix, localInfo, ifs);
                    }
                }
                this.InPartitionedLoop = wasPartitioned;
            }
            return(ifs);
        }
 private void AppendIndexString(StringBuilder sb, IArrayIndexerExpression iaie)
 {
     for (int i = 0; i < iaie.Indices.Count; i++)
     {
         if (i > 0)
         {
             sb.Append("_");
         }
         IExpression indExpr = iaie.Indices[i];
         sb.Append(indExpr.ToString());
     }
 }
Exemple #18
0
 /// <summary>
 /// Find the longest prefix that does not have any index expression containing the current loop variable.
 /// </summary>
 /// <param name="expr"></param>
 /// <param name="excludedLoopVar"></param>
 /// <returns></returns>
 private IExpression GetPrefixInParent(IExpression expr, IVariableDeclaration excludedLoopVar)
 {
     if (expr is IArrayIndexerExpression)
     {
         IExpression expr2 = expr;
         while (expr2 is IArrayIndexerExpression)
         {
             IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr2;
             bool hasExcludedLoopVar      = iaie.Indices.Any(index => Recognizer.GetVariables(index).Any(excludedLoopVar.Equals));
             if (hasExcludedLoopVar)
             {
                 return(GetPrefixInParent(iaie.Target, excludedLoopVar));
             }
             expr2 = iaie.Target;
         }
     }
     return(expr);
 }
Exemple #19
0
        /// <summary>
        /// Modify array index expressions which are copies of other variables.
        /// </summary>
        /// <param name="iaie"></param>
        /// <returns></returns>
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            // should not convert if on LHS
            IExpression copyExpr = GetCopyExpr(iaie);

            if (copyExpr != null)
            {
                return(copyExpr);
            }
            var aie = base.ConvertArrayIndexer(iaie);

            // If part of the expression has been replaced, check the whole again
            if (!ReferenceEquals(aie, iaie))
            {
                return(ConvertArrayIndexer((IArrayIndexerExpression)aie));
            }
            return(aie);
        }
Exemple #20
0
        /// <summary>
        /// Modify array index expressions which are copies of other variables.
        /// </summary>
        /// <param name="iaie"></param>
        /// <returns></returns>
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            // should not convert if on LHS
            IExpression copyExpr = GetCopyExpr(iaie);

            if (copyExpr != null)
            {
                return(copyExpr);
            }
            formalTypeStack.Push(typeof(int));
            IList <IExpression> newIndices = ConvertCollection(iaie.Indices);

            formalTypeStack.Pop();
            Type arrayType;

            if (iaie.Indices.Count == 1)
            {
                var elementType = FormalTypeStackApplies() ? formalTypeStack.Peek() : iaie.GetExpressionType();
                // This must be IReadOnlyList not IList to allow covariance.
                arrayType = typeof(IReadOnlyList <>).MakeGenericType(elementType);
            }
            else
            {
                arrayType = iaie.Target.GetExpressionType();
            }
            formalTypeStack.Push(arrayType);
            IExpression newTarget = ConvertExpression(iaie.Target);

            formalTypeStack.Pop();
            if (ReferenceEquals(newTarget, iaie.Target) &&
                ReferenceEquals(newIndices, iaie.Indices))
            {
                return(iaie);
            }
            IArrayIndexerExpression aie = Builder.ArrayIndxrExpr();

            aie.Target = newTarget;
            aie.Indices.AddRange(newIndices);
            Context.InputAttributes.CopyObjectAttributesTo(iaie, context.OutputAttributes, aie);
            // Since part of the expression has been replaced, check the whole again
            return(ConvertArrayIndexer(aie));
        }
Exemple #21
0
 protected override IExpression ConvertAssign(IAssignExpression iae)
 {
     iae = (IAssignExpression)base.ConvertAssign(iae);
     if (iae.Target is IArrayIndexerExpression && iae.Expression is IObjectCreateExpression)
     {
         IArrayIndexerExpression target = (IArrayIndexerExpression)iae.Target;
         IExpression             parent = target.Target;
         IObjectCreateExpression ioce   = (IObjectCreateExpression)iae.Expression;
         Type type = Builder.ToType(ioce.Type);
         if (MessageTransform.IsFileArray(type) && MessageTransform.IsFileArray(parent.GetExpressionType()) && ioce.Arguments.Count == 2)
         {
             // change new FileArray(name, dimensions) into FileArray(parent, index, dimensions)
             IList <IExpression> args = Builder.ExprCollection();
             args.Add(target.Target);
             args.AddRange(target.Indices);
             args.Add(ioce.Arguments[1]);
             return(Builder.AssignExpr(target, Builder.NewObject(type, args)));
         }
     }
     return(iae);
 }
Exemple #22
0
        /// <summary>
        /// Converts an array indexed expression.
        /// </summary>
        /// <param name="iaie"></param>
        /// <returns></returns>
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            IExpression expr = base.ConvertArrayIndexer(iaie);

            // Check if this is the top level indexer
            if (Recognizer.IsBeingIndexed(context))
            {
                return(expr);
            }
            IExpression target;
            List <IList <IExpression> > indices = Recognizer.GetIndices(expr, out target);

            if (!(target is IVariableReferenceExpression))
            {
                return(expr);
            }
            IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target);

            if (ivd == null)
            {
                return(expr);
            }
            VariableToChannelInformation vtci = Context.InputAttributes.Get <VariableToChannelInformation>(ivd);

            if (vtci == null)
            {
                return(expr);
            }
            if (vtci.usageChannel == null)
            {
                return(expr);
            }
            bool isDef = Recognizer.IsBeingMutated(context, expr);

            if (isDef)
            {
                return(expr);
            }
            return(vtci.usageChannel.ReplaceWithUsesChannel(expr, Builder.LiteralExpr(vtci.shareAllUses ? 0 : vtci.useCount++)));
        }
Exemple #23
0
 private void RemoveMatchingSuffixes(IExpression expr1, IExpression expr2, List <IConditionStatement> condContext, out IExpression prefix1, out IExpression prefix2)
 {
     if (expr1 is IArrayIndexerExpression)
     {
         IArrayIndexerExpression iaie1 = (IArrayIndexerExpression)expr1;
         if (expr2 is IArrayIndexerExpression)
         {
             IArrayIndexerExpression iaie2 = (IArrayIndexerExpression)expr2;
             if (iaie1.Indices.Count == iaie2.Indices.Count)
             {
                 bool allIndicesAreEqual = true;
                 for (int i = 0; i < iaie1.Indices.Count; i++)
                 {
                     IExpression index1 = iaie1.Indices[i];
                     IExpression index2 = iaie2.Indices[i];
                     // indices only match if they are loop variables, because then we know that this is the only assignment for the whole array.
                     // literal indices, on the other hand, can appear in multiple assignments, e.g. array[0] = Copy(x0[0]), array[1] = Copy(x1[0]).
                     if (!(index1 is IVariableReferenceExpression) ||
                         !(index2 is IVariableReferenceExpression) ||
                         !index1.Equals(index2) ||
                         AnyConditionsDependOnLoopVariable(condContext, Recognizer.GetVariableDeclaration(index1)))
                     {
                         allIndicesAreEqual = false;
                     }
                 }
                 if (allIndicesAreEqual)
                 {
                     RemoveMatchingSuffixes(iaie1.Target, iaie2.Target, condContext, out prefix1, out prefix2);
                     if (prefix1.GetExpressionType().Equals(prefix2.GetExpressionType()))
                     {
                         return;
                     }
                 }
             }
         }
     }
     prefix1 = expr1;
     prefix2 = expr2;
 }
 /// <summary>
 /// Split expr into a target and extra indices, where target will be replicated and extra indices will be added later.
 /// </summary>
 /// <param name="loop">The loop we are replicating over</param>
 /// <param name="expr">Expression being replicated</param>
 /// <param name="indices">Modified to contain the extra indices</param>
 /// <param name="target">Prefix of expr to replicate</param>
 protected void AddUnreplicatedIndices(IForStatement loop, IExpression expr, List <IEnumerable <IExpression> > indices, out IExpression target)
 {
     if (expr is IArrayIndexerExpression)
     {
         IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr;
         AddUnreplicatedIndices(loop, iaie.Target, indices, out target);
         if (indices.Count == 0)
         {
             // determine if iaie.Indices can be replicated
             bool canReplicate = true;
             foreach (IExpression index in iaie.Indices)
             {
                 if (NeedsContainer(loop, index))
                 {
                     canReplicate = false;
                     break;
                 }
             }
             IVariableDeclaration loopVar = Recognizer.LoopVariable(loop);
             bool isPartitioned           = context.InputAttributes.Has <Partitioned>(loopVar);
             if (isPartitioned && !AnyPartitionedExpr(iaie.Indices))
             {
                 canReplicate = false;
             }
             if (canReplicate)
             {
                 target = expr;
                 return;
             }
             // fall through
         }
         indices.Add(iaie.Indices);
     }
     else
     {
         target = expr;
     }
 }
Exemple #25
0
        private IExpression ConvertIndices(IExpression expr)
        {
            if (!(expr is IArrayIndexerExpression iaie))
            {
                return(expr);
            }
            var newTarget = ConvertIndices(iaie.Target);

            formalTypeStack.Push(typeof(int));
            IList <IExpression> newIndices = ConvertCollection(iaie.Indices);

            formalTypeStack.Pop();
            if (ReferenceEquals(newTarget, iaie.Target) &&
                ReferenceEquals(newIndices, iaie.Indices))
            {
                return(iaie);
            }
            IArrayIndexerExpression aie = Builder.ArrayIndxrExpr();

            aie.Target = newTarget;
            aie.Indices.AddRange(newIndices);
            Context.InputAttributes.CopyObjectAttributesTo(iaie, context.OutputAttributes, aie);
            return(aie);
        }
Exemple #26
0
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            IExpression target;
            var         indices = Recognizer.GetIndices(iaie, out target);

            if (target is IVariableReferenceExpression)
            {
                int indexingDepth        = indices.Count;
                IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target);
                HoistingInfo         info;
                if (analysis.infoOfVariable.TryGetValue(ivd, out info) && info.newVariable != null &&
                    IsReducibleAtDepth(info, indexingDepth))
                {
                    int         arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length;
                    IExpression newExpr    = Builder.VarRefExpr(info.newVariable);
                    for (int bracket = 0; bracket < indexingDepth; bracket++)
                    {
                        if (info.maxDepthWhereDimensionCouldMatter[bracket].Any(d => d == arrayDepth))
                        {
                            List <IExpression> newIndices = new List <IExpression>();
                            for (int dim = 0; dim < indices[bracket].Count; dim++)
                            {
                                if (info.maxDepthWhereDimensionCouldMatter[bracket][dim] == arrayDepth)
                                {
                                    newIndices.Add(indices[bracket][dim]);
                                }
                            }
                            newExpr = Builder.ArrayIndex(newExpr, newIndices);
                        }
                    }
                    return(newExpr);
                }
                // fall through
            }
            return(base.ConvertArrayIndexer(iaie));
        }
 public virtual IExpression TransformArrayIndexerExpression(IArrayIndexerExpression value)
 {
     this.InsituTransformExpressionCollection(value.Indices);
     value.Target = this.TransformExpression(value.Target);
     return value;
 }
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            IArrayIndexerExpression aie     = (IArrayIndexerExpression)base.ConvertArrayIndexer(iaie);
            IExpression             topExpr = context.FindAncestor <IAssignExpression>();
            bool isDef = false;

            if (topExpr == null)
            {
                topExpr = context.FindAncestor <IMethodInvokeExpression>();
                if (Recognizer.IsStaticMethod(topExpr, typeof(InferNet)))
                {
                    return(aie);
                }
            }
            else
            {
                isDef = ((IAssignExpression)topExpr).Target == iaie;
            }
            if (topExpr == null)
            {
                return(aie);
            }
            // Find the variable algorithm
            IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iaie.Target);

            if (ivd == null)
            {
                //Error("Cannot find array indexer target variable: " + iaie.Target);
                return(iaie);
            }
            IAlgorithm varAlg = GetAlgorithm(ivd);
            //Console.WriteLine("varAlg=" + varAlg + " " + ivd);
            // Find the factor algorithm
            IAlgorithm factorAlg = GetAlgorithm(topExpr);

            // If the algorithsm are the same, do nothing.
            if (varAlg.Equals(factorAlg))
            {
                return(aie);
            }

            // Otherwise, look up conversion operator
            ChannelInfo ci = context.InputAttributes.Get <ChannelInfo>(ivd);

            if (ci == null)
            {
                Error("Channel information not found for '" + ivd.Name + "'.");
                return(aie);
            }
            Type            chType      = ci.varInfo.marginalPrototypeExpression.GetExpressionType();
            List <object>   extraArgs   = new List <object>();
            MethodReference opMethodRef = null;

            try
            {
                opMethodRef = factorAlg.GetAlgorithmConversionOperator(chType, varAlg, isDef, extraArgs);
            }
            catch (Exception ex)
            {
                Error("No conversion operator defined from " + factorAlg + " to " + varAlg, ex);
                return(aie);
            }
            if (opMethodRef == null)
            {
                return(aie);
            }
            // Create new channel
            DuplicateInfo dupInfo = context.InputAttributes.GetOrCreate <DuplicateInfo>(ivd, () => new DuplicateInfo());

            dupInfo.dupCount++;
            IVariableDeclaration vd = Builder.VarDecl(ivd.Name + "_dup" + dupInfo.dupCount, ivd.VariableType);

            Context.InputAttributes.CopyObjectAttributesTo(ivd, context.OutputAttributes, vd);
            Context.OutputAttributes.Remove <Algorithm>(vd);
            Context.OutputAttributes.Set(vd, new Algorithm(factorAlg));
            //ci.AddDeclaration(context);
            IExpression opMethodCall = null;

            IExpression[] args = new IExpression[extraArgs.Count + 1];
            IExpression   lhs  = Builder.ArrayIndex(Builder.VarRefExpr(vd), Builder.LiteralExpr(0));

            args[0] = aie;
            if (isDef)
            {
                args[0] = lhs;
                lhs     = aie;
            }
            for (int i = 0; i < extraArgs.Count; i++)
            {
                args[i + 1] = Builder.LiteralExpr(extraArgs[i]);
            }
            if (opMethodRef.TypeParameterCount == 0)
            {
                opMethodCall = Builder.StaticMethod(opMethodRef.GetMethodInfo(), args);
            }
            else
            {
                // TODO: insert argument types
                opMethodCall = Builder.StaticGenericMethod(opMethodRef.GetMethodInfo(), args);
            }
            //context.AddExpression(Builder.AssignExpr(lhs,opMethodCall));
            return(Builder.ArrayIndex(Builder.VarRefExpr(vd), Builder.LiteralExpr(0)));
        }
 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));
     }
 }
            private void WriteArrayIndexerExpression(IArrayIndexerExpression expression, IFormatter formatter)
            {
                this.WriteTargetExpression(expression.Target, formatter);
                formatter.Write("[");

                for (int i = 0; i < expression.Indices.Count; i++)
                {
                    if (i != 0)
                    {
                        formatter.Write(", ");
                    }

                    this.WriteExpression(expression.Indices[i], formatter);
                }

                formatter.Write("]");
            }
 public virtual void VisitArrayIndexerExpression(IArrayIndexerExpression value)
 {
     this.VisitExpressionCollection(value.Indices);
     this.VisitExpression(value.Target);
 }
        /// <summary>
        /// This method does all the work of converting literal indexing expressions.
        /// </summary>
        /// <param name="iaie"></param>
        /// <returns></returns>
        protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie)
        {
            IndexAnalysisTransform.IndexInfo info;
            if (!analysis.indexInfoOf.TryGetValue(iaie, out info))
            {
                return(base.ConvertArrayIndexer(iaie));
            }
            // Determine if this is a definition i.e. the variable is on the left hand side of an assignment
            // This must be done before base.ConvertArrayIndexer changes the expression!
            bool isDef = Recognizer.IsBeingMutated(context, iaie);

            if (info.clone != null)
            {
                if (isDef)
                {
                    // check that extra literal indices in the target are zero.
                    // for example, if iae is x[i][0] = (...) then it is safe to add x_uses[i] = Rep(x[i])
                    // if iae is x[i][1] = (...) then it is safe to add x_uses[i][1] = Rep(x[i][1])
                    // but not x_uses[i] = Rep(x[i]) since this will be a duplicate.
                    bool   extraLiteralsAreZero = true;
                    int    parentIndex          = context.InputStack.Count - 2;
                    object parent = context.GetAncestor(parentIndex);
                    while (parent is IArrayIndexerExpression)
                    {
                        IArrayIndexerExpression parent_iaie = (IArrayIndexerExpression)parent;
                        foreach (IExpression index in parent_iaie.Indices)
                        {
                            if (index is ILiteralExpression)
                            {
                                int value = (int)((ILiteralExpression)index).Value;
                                if (value != 0)
                                {
                                    extraLiteralsAreZero = false;
                                    break;
                                }
                            }
                        }
                        parentIndex--;
                        parent = context.GetAncestor(parentIndex);
                    }
                    if (false && extraLiteralsAreZero)
                    {
                        // change:
                        //   array[0] = f()
                        // into:
                        //   array_item0 = f()
                        //   array[0] = Copy(array_item0)
                        IExpression copy = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy <PlaceHolder>), new Type[] { iaie.GetExpressionType() },
                                                                       info.clone);
                        IStatement copySt = Builder.AssignStmt(iaie, copy);
                        context.AddStatementAfterCurrent(copySt);
                    }
                }
                return(info.clone);
            }

            if (isDef)
            {
                // do not clone the lhs of an array create assignment.
                IAssignExpression assignExpr = context.FindAncestor <IAssignExpression>();
                if (assignExpr.Expression is IArrayCreateExpression)
                {
                    return(iaie);
                }
            }

            IVariableDeclaration originalBaseVar = Recognizer.GetVariableDeclaration(iaie);

            // If the variable is not stochastic, return
            if (!CodeRecognizer.IsStochastic(context, originalBaseVar))
            {
                return(iaie);
            }

            IExpression          newExpr    = null;
            IVariableDeclaration baseVar    = originalBaseVar;
            IVariableDeclaration newvd      = null;
            IExpression          rhsExpr    = null;
            Containers           containers = info.containers;
            Type tp = iaie.GetExpressionType();

            if (tp == null)
            {
                Error("Could not determine type of expression: " + iaie);
                return(iaie);
            }
            var stmts      = Builder.StmtCollection();
            var stmtsAfter = Builder.StmtCollection();

            // does the expression have the form array[indices[k]][indices2[k]][indices3[k]]?
            if (newvd == null && UseGetItems && iaie.Target is IArrayIndexerExpression &&
                iaie.Indices.Count == 1 && iaie.Indices[0] is IArrayIndexerExpression)
            {
                IArrayIndexerExpression index3 = (IArrayIndexerExpression)iaie.Indices[0];
                IArrayIndexerExpression iaie2  = (IArrayIndexerExpression)iaie.Target;
                if (index3.Indices.Count == 1 && index3.Indices[0] is IVariableReferenceExpression &&
                    iaie2.Target is IArrayIndexerExpression &&
                    iaie2.Indices.Count == 1 && iaie2.Indices[0] is IArrayIndexerExpression)
                {
                    IArrayIndexerExpression index2 = (IArrayIndexerExpression)iaie2.Indices[0];
                    IArrayIndexerExpression iaie3  = (IArrayIndexerExpression)iaie2.Target;
                    if (index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression &&
                        iaie3.Indices.Count == 1 && iaie3.Indices[0] is IArrayIndexerExpression)
                    {
                        IArrayIndexerExpression      index      = (IArrayIndexerExpression)iaie3.Indices[0];
                        IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0];
                        IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex);
                        if (index.Indices.Count == 1 && index2.Indices[0].Equals(innerIndex) &&
                            index3.Indices[0].Equals(innerIndex) &&
                            innerLoop != null && AreLoopsDisjoint(innerLoop, iaie3.Target, index.Target))
                        {
                            // expression has the form array[indices[k]][indices2[k]][indices3[k]]
                            if (isDef)
                            {
                                Error("fancy indexing not allowed on left hand side");
                                return(iaie);
                            }
                            WarnIfLocal(index.Target, iaie3.Target, iaie);
                            WarnIfLocal(index2.Target, iaie3.Target, iaie);
                            WarnIfLocal(index3.Target, iaie3.Target, iaie);
                            containers = RemoveReferencesTo(containers, innerIndex);
                            IExpression loopSize = Recognizer.LoopSizeExpression(innerLoop);
                            var         indices  = Recognizer.GetIndices(iaie);
                            // Build name of replacement variable from index values
                            StringBuilder sb = new StringBuilder("_item");
                            AppendIndexString(sb, iaie3);
                            AppendIndexString(sb, iaie2);
                            AppendIndexString(sb, iaie);
                            string name = ToString(iaie3.Target) + sb.ToString();
                            VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar);
                            newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSize, Recognizer.GetVariableDeclaration(innerIndex), indices);
                            if (!context.InputAttributes.Has <DerivedVariable>(newvd))
                            {
                                context.InputAttributes.Set(newvd, new DerivedVariable());
                            }
                            IExpression getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <IReadOnlyList <PlaceHolder> > >, IReadOnlyList <int>, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromDeepJagged),
                                                                               new Type[] { tp }, iaie3.Target, index.Target, index2.Target, index3.Target);
                            context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems);
                            stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems));
                            newExpr = Builder.ArrayIndex(Builder.VarRefExpr(newvd), innerIndex);
                            rhsExpr = getItems;
                        }
                    }
                }
            }
            // does the expression have the form array[indices[k]][indices2[k]]?
            if (newvd == null && UseGetItems && iaie.Target is IArrayIndexerExpression &&
                iaie.Indices.Count == 1 && iaie.Indices[0] is IArrayIndexerExpression)
            {
                IArrayIndexerExpression index2 = (IArrayIndexerExpression)iaie.Indices[0];
                IArrayIndexerExpression target = (IArrayIndexerExpression)iaie.Target;
                if (index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression &&
                    target.Indices.Count == 1 && target.Indices[0] is IArrayIndexerExpression)
                {
                    IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index2.Indices[0];
                    IArrayIndexerExpression      index      = (IArrayIndexerExpression)target.Indices[0];
                    IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex);
                    if (index.Indices.Count == 1 && index.Indices[0].Equals(innerIndex) &&
                        innerLoop != null && AreLoopsDisjoint(innerLoop, target.Target, index.Target))
                    {
                        // expression has the form array[indices[k]][indices2[k]]
                        if (isDef)
                        {
                            Error("fancy indexing not allowed on left hand side");
                            return(iaie);
                        }
                        var innerLoops = new List <IForStatement>();
                        innerLoops.Add(innerLoop);
                        var indexTarget  = index.Target;
                        var index2Target = index2.Target;
                        // check if the index array is jagged, i.e. array[indices[k][j]]
                        while (indexTarget is IArrayIndexerExpression && index2Target is IArrayIndexerExpression)
                        {
                            IArrayIndexerExpression indexTargetExpr  = (IArrayIndexerExpression)indexTarget;
                            IArrayIndexerExpression index2TargetExpr = (IArrayIndexerExpression)index2Target;
                            if (indexTargetExpr.Indices.Count == 1 && indexTargetExpr.Indices[0] is IVariableReferenceExpression &&
                                index2TargetExpr.Indices.Count == 1 && index2TargetExpr.Indices[0] is IVariableReferenceExpression)
                            {
                                IVariableReferenceExpression innerIndexTarget  = (IVariableReferenceExpression)indexTargetExpr.Indices[0];
                                IVariableReferenceExpression innerIndex2Target = (IVariableReferenceExpression)index2TargetExpr.Indices[0];
                                IForStatement indexTargetLoop = Recognizer.GetLoopForVariable(context, innerIndexTarget);
                                if (indexTargetLoop != null && AreLoopsDisjoint(indexTargetLoop, target.Target, indexTargetExpr.Target) &&
                                    innerIndexTarget.Equals(innerIndex2Target))
                                {
                                    innerLoops.Add(indexTargetLoop);
                                    indexTarget  = indexTargetExpr.Target;
                                    index2Target = index2TargetExpr.Target;
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        WarnIfLocal(indexTarget, target.Target, iaie);
                        WarnIfLocal(index2Target, target.Target, iaie);
                        innerLoops.Reverse();
                        var loopSizes    = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopSizeExpression(ifs) });
                        var newIndexVars = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopVariable(ifs) });
                        // Build name of replacement variable from index values
                        StringBuilder sb = new StringBuilder("_item");
                        AppendIndexString(sb, target);
                        AppendIndexString(sb, iaie);
                        string name = ToString(target.Target) + sb.ToString();
                        VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar);
                        var indices = Recognizer.GetIndices(iaie);
                        newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSizes, newIndexVars, indices);
                        if (!context.InputAttributes.Has <DerivedVariable>(newvd))
                        {
                            context.InputAttributes.Set(newvd, new DerivedVariable());
                        }
                        IExpression getItems;
                        if (innerLoops.Count == 1)
                        {
                            getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromJagged),
                                                                   new Type[] { tp }, target.Target, indexTarget, index2Target);
                        }
                        else if (innerLoops.Count == 2)
                        {
                            getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <IReadOnlyList <int> >, IReadOnlyList <IReadOnlyList <int> >, PlaceHolder[][]>(Collection.GetJaggedItemsFromJagged),
                                                                   new Type[] { tp }, target.Target, indexTarget, index2Target);
                        }
                        else
                        {
                            throw new NotImplementedException($"innerLoops.Count = {innerLoops.Count}");
                        }
                        context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems);
                        stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems));
                        var newIndices = newIndexVars.ListSelect(ivds => Util.ArrayInit(ivds.Length, i => Builder.VarRefExpr(ivds[i])));
                        newExpr = Builder.JaggedArrayIndex(Builder.VarRefExpr(newvd), newIndices);
                        rhsExpr = getItems;
                    }
                    else if (HasAnyCommonLoops(index, index2))
                    {
                        Warning($"This model will consume excess memory due to the indexing expression {iaie} since {index} and {index2} have larger depth than the compiler can handle.");
                    }
                }
            }
            if (newvd == null)
            {
                IArrayIndexerExpression originalExpr = iaie;
                if (UseGetItems)
                {
                    iaie = (IArrayIndexerExpression)base.ConvertArrayIndexer(iaie);
                }
                if (!object.ReferenceEquals(iaie.Target, originalExpr.Target) && false)
                {
                    // TODO: determine if this warning is useful or not
                    string warningText = "This model may consume excess memory due to the jagged indexing expression {0}";
                    Warning(string.Format(warningText, originalExpr));
                }

                // get the baseVar of the new expression.
                baseVar = Recognizer.GetVariableDeclaration(iaie);
                VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar);

                var indices = Recognizer.GetIndices(iaie);
                // Build name of replacement variable from index values
                StringBuilder sb = new StringBuilder("_item");
                AppendIndexString(sb, iaie);
                string name = ToString(iaie.Target) + sb.ToString();

                // does the expression have the form array[indices[k]]?
                if (UseGetItems && iaie.Indices.Count == 1 && iaie.Indices[0] is IArrayIndexerExpression)
                {
                    IArrayIndexerExpression index = (IArrayIndexerExpression)iaie.Indices[0];
                    if (index.Indices.Count == 1 && index.Indices[0] is IVariableReferenceExpression)
                    {
                        // expression has the form array[indices[k]]
                        IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0];
                        IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex);
                        if (innerLoop != null && AreLoopsDisjoint(innerLoop, iaie.Target, index.Target))
                        {
                            if (isDef)
                            {
                                Error("fancy indexing not allowed on left hand side");
                                return(iaie);
                            }
                            var innerLoops = new List <IForStatement>();
                            innerLoops.Add(innerLoop);
                            var indexTarget = index.Target;
                            // check if the index array is jagged, i.e. array[indices[k][j]]
                            while (indexTarget is IArrayIndexerExpression)
                            {
                                IArrayIndexerExpression index2 = (IArrayIndexerExpression)indexTarget;
                                if (index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression)
                                {
                                    IVariableReferenceExpression innerIndex2 = (IVariableReferenceExpression)index2.Indices[0];
                                    IForStatement innerLoop2 = Recognizer.GetLoopForVariable(context, innerIndex2);
                                    if (innerLoop2 != null && AreLoopsDisjoint(innerLoop2, iaie.Target, index2.Target))
                                    {
                                        innerLoops.Add(innerLoop2);
                                        indexTarget = index2.Target;
                                        // This limit must match the number of handled cases below.
                                        if (innerLoops.Count == 3)
                                        {
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    break;
                                }
                            }
                            WarnIfLocal(indexTarget, iaie.Target, originalExpr);
                            innerLoops.Reverse();
                            var loopSizes    = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopSizeExpression(ifs) });
                            var newIndexVars = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopVariable(ifs) });
                            newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSizes, newIndexVars, indices);
                            if (!context.InputAttributes.Has <DerivedVariable>(newvd))
                            {
                                context.InputAttributes.Set(newvd, new DerivedVariable());
                            }
                            IExpression getItems;
                            if (innerLoops.Count == 1)
                            {
                                getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItems),
                                                                       new Type[] { tp }, iaie.Target, indexTarget);
                            }
                            else if (innerLoops.Count == 2)
                            {
                                getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <IReadOnlyList <int> >, PlaceHolder[][]>(Collection.GetJaggedItems),
                                                                       new Type[] { tp }, iaie.Target, indexTarget);
                            }
                            else if (innerLoops.Count == 3)
                            {
                                getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <IReadOnlyList <IReadOnlyList <int> > >, PlaceHolder[][][]>(Collection.GetDeepJaggedItems),
                                                                       new Type[] { tp }, iaie.Target, indexTarget);
                            }
                            else
                            {
                                throw new NotImplementedException($"innerLoops.Count = {innerLoops.Count}");
                            }
                            context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems);
                            stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems));
                            var newIndices = newIndexVars.ListSelect(ivds => Util.ArrayInit(ivds.Length, i => Builder.VarRefExpr(ivds[i])));
                            newExpr = Builder.JaggedArrayIndex(Builder.VarRefExpr(newvd), newIndices);
                            rhsExpr = getItems;
                        }
                    }
                }
                if (newvd == null)
                {
                    if (UseGetItems && info.count < 2)
                    {
                        return(iaie);
                    }
                    try
                    {
                        newvd = varInfo.DeriveIndexedVariable(stmts, context, name, indices, copyInitializer: isDef);
                    }
                    catch (Exception ex)
                    {
                        Error(ex.Message, ex);
                        return(iaie);
                    }
                    context.OutputAttributes.Remove <DerivedVariable>(newvd);
                    newExpr = Builder.VarRefExpr(newvd);
                    rhsExpr = iaie;
                    if (isDef)
                    {
                        // change:
                        //   array[0] = f()
                        // into:
                        //   array_item0 = f()
                        //   array[0] = Copy(array_item0)
                        IExpression copy   = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy), new Type[] { tp }, newExpr);
                        IStatement  copySt = Builder.AssignStmt(iaie, copy);
                        stmtsAfter.Add(copySt);
                        if (!context.InputAttributes.Has <DerivedVariable>(baseVar))
                        {
                            context.InputAttributes.Set(baseVar, new DerivedVariable());
                        }
                    }
                    else if (!info.IsAssignedTo)
                    {
                        // change:
                        //   x = f(array[0])
                        // into:
                        //   array_item0 = Copy(array[0])
                        //   x = f(array_item0)
                        IExpression copy   = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy), new Type[] { tp }, iaie);
                        IStatement  copySt = Builder.AssignStmt(Builder.VarRefExpr(newvd), copy);
                        //if (attr != null) context.OutputAttributes.Set(copySt, attr);
                        stmts.Add(copySt);
                        context.InputAttributes.Set(newvd, new DerivedVariable());
                    }
                }
            }

            // Reduce memory consumption by declaring the clone outside of unnecessary loops.
            // This way, the item is cloned outside the loop and then replicated, instead of replicating the entire array and cloning the item.
            containers = Containers.RemoveUnusedLoops(containers, context, rhsExpr);
            if (context.InputAttributes.Has <DoNotSendEvidence>(originalBaseVar))
            {
                containers = Containers.RemoveStochasticConditionals(containers, context);
            }
            if (true)
            {
                IStatement st = GetBindingSetContainer(FilterBindingSet(info.bindings,
                                                                        binding => Containers.ContainsExpression(containers.inputs, context, binding.GetExpression())));
                if (st != null)
                {
                    containers.Add(st);
                }
            }
            // To put the declaration in the desired containers, we find an ancestor which includes as many of the containers as possible,
            // then wrap the declaration with the remaining containers.
            int        ancIndex = containers.GetMatchingAncestorIndex(context);
            Containers missing  = containers.GetContainersNotInContext(context, ancIndex);

            stmts = Containers.WrapWithContainers(stmts, missing.outputs);
            context.AddStatementsBeforeAncestorIndex(ancIndex, stmts);
            stmtsAfter = Containers.WrapWithContainers(stmtsAfter, missing.outputs);
            context.AddStatementsAfterAncestorIndex(ancIndex, stmtsAfter);
            context.InputAttributes.Set(newvd, containers);
            info.clone = newExpr;
            return(newExpr);
        }
        protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie)
        {
            IExpression result = base.ConvertMethodInvoke(imie);

            if (result is IMethodInvokeExpression)
            {
                imie = (IMethodInvokeExpression)result;
            }
            else
            {
                return(result);
            }
            if (UseJaggedSubarray && Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <int>, IReadOnlyList <PlaceHolder> >(Collection.Subarray)))
            {
                // check for the form Subarray(arrayExpr, indices[i]) where arrayExpr does not depend on i
                IExpression arrayExpr = imie.Arguments[0];
                IExpression arg1      = imie.Arguments[1];
                if (arg1 is IArrayIndexerExpression)
                {
                    IArrayIndexerExpression index = (IArrayIndexerExpression)arg1;
                    if (index.Indices.Count == 1 && index.Indices[0] is IVariableReferenceExpression)
                    {
                        // index has the form indices[i]
                        List <IStatement> targetLoops = Containers.GetLoopsNeededForExpression(context, arrayExpr, -1, false);
                        List <IStatement> indexLoops  = Containers.GetLoopsNeededForExpression(context, index.Target, -1, false);
                        Set <IStatement>  parentLoops = new Set <IStatement>();
                        parentLoops.AddRange(targetLoops);
                        parentLoops.AddRange(indexLoops);
                        IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0];
                        IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex);
                        foreach (IStatement loop in parentLoops)
                        {
                            if (Containers.ContainersAreEqual(loop, innerLoop))
                            {
                                // arrayExpr depends on i
                                return(imie);
                            }
                        }
                        IVariableDeclaration arrayVar = Recognizer.GetVariableDeclaration(arrayExpr);
                        // If the variable is not stochastic, return
                        if (arrayVar == null)
                        {
                            return(imie);
                        }
                        VariableInformation arrayInfo = VariableInformation.GetVariableInformation(context, arrayVar);
                        if (!arrayInfo.IsStochastic)
                        {
                            return(imie);
                        }
                        object indexVar = Recognizer.GetDeclaration(index);
                        VariableInformation indexInfo = VariableInformation.GetVariableInformation(context, indexVar);
                        int         depth             = Recognizer.GetIndexingDepth(index);
                        IExpression resultSize        = indexInfo.sizes[depth][0];
                        var         indices           = Recognizer.GetIndices(index);
                        int         replaceCount      = 0;
                        resultSize = indexInfo.ReplaceIndexVars(context, resultSize, indices, null, ref replaceCount);
                        indexInfo.DefineIndexVarsUpToDepth(context, depth + 1);
                        IVariableDeclaration resultIndex = indexInfo.indexVars[depth][0];
                        Type arrayType   = arrayExpr.GetExpressionType();
                        Type elementType = Util.GetElementType(arrayType);

                        // create a new variable arrayExpr_indices = JaggedSubarray(arrayExpr, indices)
                        string name = ToString(arrayExpr) + "_" + ToString(index.Target);

                        var stmts        = Builder.StmtCollection();
                        var arrayIndices = Recognizer.GetIndices(arrayExpr);
                        var bracket      = Builder.ExprCollection();
                        bracket.Add(Builder.ArrayIndex(index, Builder.VarRefExpr(resultIndex)));
                        arrayIndices.Add(bracket);
                        IExpression          loopSize = Recognizer.LoopSizeExpression(innerLoop);
                        IVariableDeclaration temp     = arrayInfo.DeriveArrayVariable(stmts, context, name, resultSize, resultIndex, arrayIndices);
                        VariableInformation  tempInfo = VariableInformation.GetVariableInformation(context, temp);
                        stmts.Clear();
                        IVariableDeclaration newvd = tempInfo.DeriveArrayVariable(stmts, context, name, loopSize, Recognizer.GetVariableDeclaration(innerIndex));
                        if (!context.InputAttributes.Has <DerivedVariable>(newvd))
                        {
                            context.InputAttributes.Set(newvd, new DerivedVariable());
                        }
                        IExpression rhs = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, int[][], PlaceHolder[][]>(Collection.JaggedSubarray),
                                                                      new Type[] { elementType }, arrayExpr, index.Target);
                        context.InputAttributes.CopyObjectAttributesTo <Algorithm>(newvd, context.OutputAttributes, rhs);
                        stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), rhs));

                        // Reduce memory consumption by declaring the clone outside of unnecessary loops.
                        // This way, the item is cloned outside the loop and then replicated, instead of replicating the entire array and cloning the item.
                        Containers containers = new Containers(context);
                        containers = RemoveReferencesTo(containers, innerIndex);
                        containers = Containers.RemoveUnusedLoops(containers, context, rhs);
                        if (context.InputAttributes.Has <DoNotSendEvidence>(arrayVar))
                        {
                            containers = Containers.RemoveStochasticConditionals(containers, context);
                        }
                        // To put the declaration in the desired containers, we find an ancestor which includes as many of the containers as possible,
                        // then wrap the declaration with the remaining containers.
                        int        ancIndex = containers.GetMatchingAncestorIndex(context);
                        Containers missing  = containers.GetContainersNotInContext(context, ancIndex);
                        stmts = Containers.WrapWithContainers(stmts, missing.outputs);
                        context.AddStatementsBeforeAncestorIndex(ancIndex, stmts);
                        context.InputAttributes.Set(newvd, containers);

                        // convert into arrayExpr_indices[i]
                        IExpression newExpr = Builder.ArrayIndex(Builder.VarRefExpr(newvd), innerIndex);
                        newExpr = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy <PlaceHolder>), new Type[] { newExpr.GetExpressionType() }, newExpr);
                        return(newExpr);
                    }
                }
            }
            return(imie);
        }