Beispiel #1
0
 private void SearchVariableAttributes(Variable variable)
 {
     foreach (var attr in variable.GetAttributes <ICompilerAttribute>())
     {
         if (attr is ValueRange vr)
         {
             SearchRange(vr.Range);
         }
         else if (attr is DistributedCommunication dc)
         {
             toSearch.Push(dc.arrayIndicesToSendExpression);
             toSearch.Push(dc.arrayIndicesToReceiveExpression);
             var attr2 = new DistributedCommunicationExpression(dc.arrayIndicesToSendExpression.GetExpression(), dc.arrayIndicesToReceiveExpression.GetExpression());
             // find the base variable
             Variable parent = variable;
             while (parent.ArrayVariable != null)
             {
                 parent = (Variable)parent.ArrayVariable;
             }
             var parentDecl = parent.GetDeclaration();
             if (Attributes.Has <DistributedCommunicationExpression>(parentDecl))
             {
                 throw new Exception($"{parent} has multiple DistributedCommunication attributes");
             }
             Attributes.Set(parentDecl, attr2);
         }
     }
 }
 protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie)
 {
     // Insert an Increment statement to support Sequential loops
     // if we find the pattern:
     // forwardExpr = ReplicateOp_Divide.UsesAverageConditional(backwardExpr[index], marginalExpr, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index]);
     if (Recognizer.IsStaticMethod(imie, typeof(ReplicateOp_Divide), "UsesAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[1];
         IExpression          indexExpr    = imie.Arguments[2];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[3];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr);
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = Replicate2BufferOp.UsesAverageConditional(backwardExpr, *, marginalExpr, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // marginalExpr = MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index]);
     if (Recognizer.IsStaticMethod(imie, typeof(Replicate2BufferOp), "UsesAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indexExpr    = imie.Arguments[3];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[4];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, Builder.ArrayIndex(backwardExpr, indexExpr));
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = JaggedSubarrayOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(JaggedSubarrayOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indexExpr    = imie.Arguments[4];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[5];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             IExpression[] args2             = new IExpression[] { marginalExpr, forwardExpr, backwardExpr, indicesExpr, indexExpr };
             Type[]        argTypes          = Array.ConvertAll(args2, e => e.GetExpressionType());
             Exception     exception;
             MethodInfo    method = (MethodInfo)Reflection.Invoker.GetBestMethod(itr.DotNetType, "MarginalIncrement",
                                                                                 BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, argTypes, out exception);
             if (method == null)
             {
                 Error("Cannot find a compatible MarginalIncrement method for JaggedSubarrayOp", exception);
             }
             else
             {
                 IExpression rhs       = Builder.StaticGenericMethod(method, args2);
                 IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
                 var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
                 var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
                 context.OutputAttributes.Set(increment, attr);
                 onUpdate[backwardDecl] = increment;
             }
         }
     }
     // if we find the pattern:
     // forwardExpr = JaggedSubarrayWithMarginalOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrementItems(backwardExpr[index], forwardExpr,  indices, index, marginalExpr)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(JaggedSubarrayWithMarginalOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indexExpr    = imie.Arguments[4];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[5];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             IExpression[] args2             = new IExpression[] { backwardExpr, forwardExpr, indicesExpr, indexExpr, marginalExpr };
             Type[]        argTypes          = Array.ConvertAll(args2, e => e.GetExpressionType());
             Exception     exception;
             MethodInfo    method = (MethodInfo)Reflection.Invoker.GetBestMethod(itr.DotNetType, "MarginalIncrementItems",
                                                                                 BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, argTypes, out exception);
             if (method == null)
             {
                 Error("Cannot find a compatible MarginalIncrementItems method for JaggedSubarrayWithMarginalOp", exception);
             }
             else
             {
                 IExpression rhs       = Builder.StaticGenericMethod(method, args2);
                 IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
                 var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
                 var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
                 context.OutputAttributes.Set(increment, attr);
                 object backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
                 onUpdate[backwardDecl] = increment;
                 IVariableDeclaration marginalVar = Recognizer.GetVariableDeclaration(marginalExpr);
                 suppressUpdate[marginalVar] = attr;
             }
             var indicesVar = Recognizer.GetDeclaration(indicesExpr);
             if (indicesVar != null)
             {
                 DistributedCommunicationExpression dce = context.GetAttribute <DistributedCommunicationExpression>(indicesVar);
                 if (dce != null)
                 {
                     context.OutputAttributes.Set(imie, dce);
                 }
             }
         }
     }
     // if we find the pattern:
     // backwardExpr = JaggedSubarrayWithMarginalOp<>.ArrayAverageConditional(forwardExpr, marginalExpr, backwardExpr)
     // then when forwardExpr is updated, we insert the following statement:
     // MarginalIncrementArray
     if (Recognizer.IsStaticGenericMethod(imie, typeof(JaggedSubarrayWithMarginalOp <>), "ArrayAverageConditional"))
     {
         IExpression forwardExpr  = imie.Arguments[0];
         IExpression marginalExpr = imie.Arguments[1];
         IExpression backwardExpr = imie.Arguments[2];
         if (true)
         {
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             IExpression[] args2             = new IExpression[] { forwardExpr, backwardExpr, marginalExpr };
             Type[]        argTypes          = Array.ConvertAll(args2, e => e.GetExpressionType());
             Exception     exception;
             MethodInfo    method = (MethodInfo)Reflection.Invoker.GetBestMethod(itr.DotNetType, "MarginalIncrementArray",
                                                                                 BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, argTypes, out exception);
             if (method == null)
             {
                 Error("Cannot find a compatible MarginalIncrementArray method for JaggedSubarrayWithMarginalOp", exception);
             }
             else
             {
                 IExpression rhs       = Builder.StaticGenericMethod(method, args2);
                 IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
                 var         attr      = new IncrementStatement(null, false);
                 context.OutputAttributes.Set(increment, attr);
                 object forwardDecl = Recognizer.GetArrayDeclaration(forwardExpr);
                 onUpdate[forwardDecl] = increment;
             }
             IVariableDeclaration marginalVar = Recognizer.GetVariableDeclaration(marginalExpr);
             // only suppress when we also have MarginalIncrementItems
             //suppressUpdate.Add(marginalVar);
         }
     }
     // if we find the pattern:
     // forwardExpr = GetItemsOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsOp <>), "ItemsAverageConditional") ||
         Recognizer.IsStaticGenericMethod(imie, typeof(GetJaggedItemsOp <>), "ItemsAverageConditional") ||
         Recognizer.IsStaticGenericMethod(imie, typeof(GetDeepJaggedItemsOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indexExpr    = imie.Arguments[4];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[5];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr, indicesExpr, indexExpr);
             //IStatement increment = Builder.ExprStatement(rhs);
             IStatement increment = Builder.AssignStmt(marginalExpr, rhs);
             var        seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var        attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = GetItemsOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsWithDictionaryOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          dictExpr     = imie.Arguments[4];
         IExpression          indexExpr    = imie.Arguments[5];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[6];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr, indicesExpr, dictExpr, indexExpr);
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // partialExpr = GetItemsOp2<>.Partial(backwardExpr[index], to_array, indices, index, partialExpr);
     // then when backwardExpr is updated, we insert the following statement:
     // to_array[indices[index]] = ArrayIncrement(partialExpr, backwardExpr[index])
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsOp2 <>), "Partial"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          to_array     = imie.Arguments[1];
         IExpression          indicesExpr  = imie.Arguments[2];
         IExpression          indexExpr    = imie.Arguments[3];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[4];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("ArrayIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression resultExpr = Builder.ArrayIndex(to_array, Builder.ArrayIndex(indicesExpr, indexExpr));
             IExpression rhs        = Builder.StaticGenericMethod(method, forwardExpr, backwardExpr, resultExpr);
             IStatement  increment  = Builder.AssignStmt(resultExpr, rhs);
             var         seq        = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr       = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = GetItemsJaggedOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, indices2, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, indices2, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsFromJaggedOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indices2Expr = imie.Arguments[4];
         IExpression          indexExpr    = imie.Arguments[5];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[6];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr, indicesExpr, indices2Expr, indexExpr);
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     // if we find the pattern:
     // forwardExpr = GetItemsDeepJaggedOp<>.ItemsAverageConditional(backwardExpr[index], *, marginalExpr, indices, indices2, indices3, index, forwardExpr)
     // then when backwardExpr is updated, we insert the following statement:
     // MarginalIncrement(marginalExpr, forwardExpr, backwardExpr[index], indices, indices2, indices3, index)
     if (Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsFromDeepJaggedOp <>), "ItemsAverageConditional"))
     {
         IExpression          backwardExpr = imie.Arguments[0];
         object               backwardDecl = Recognizer.GetArrayDeclaration(backwardExpr);
         IExpression          marginalExpr = imie.Arguments[2];
         IExpression          indicesExpr  = imie.Arguments[3];
         IExpression          indices2Expr = imie.Arguments[4];
         IExpression          indices3Expr = imie.Arguments[5];
         IExpression          indexExpr    = imie.Arguments[6];
         IVariableDeclaration indexVar     = Recognizer.GetVariableDeclaration(indexExpr);
         IExpression          forwardExpr  = imie.Arguments[7];
         if (indexVar != null && context.InputAttributes.Has <Sequential>(indexVar))
         {
             if (!compiler.UseSerialSchedules)
             {
                 context.Warning(indexVar.Name + " is marked Sequential but engine.Compiler.UseSerialSchedules = false");
             }
             IMethodReferenceExpression imre = imie.Method;
             ITypeReference             itr  = ((ITypeReferenceExpression)imre.Target).Type;
             MethodInfo method = itr.GenericType.DotNetType.GetMethod("MarginalIncrement");
             method = method.MakeGenericMethod(imre.Method.MethodInfo.GetGenericArguments());
             IExpression rhs       = Builder.StaticGenericMethod(method, marginalExpr, forwardExpr, backwardExpr, indicesExpr, indices2Expr, indices3Expr, indexExpr);
             IStatement  increment = Builder.AssignStmt(marginalExpr, rhs);
             var         seq       = context.InputAttributes.Get <Sequential>(indexVar);
             var         attr      = new IncrementStatement(indexVar, seq.BackwardPass);
             context.OutputAttributes.Set(increment, attr);
             onUpdate[backwardDecl] = increment;
         }
     }
     return(base.ConvertMethodInvoke(imie));
 }
Beispiel #3
0
        /// <summary>
        /// Define a variable in the MSL.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="variable"></param>
        ///
        private void SearchVariable <T>(Variable <T> variable)
        {
            if (searched.Contains(variable))
            {
                return;
            }
            if (variable.IsBase && variable.NameInGeneratedCode != null)
            {
                string name = variable.NameInGeneratedCode;
                foreach (IModelExpression expr in searched)
                {
                    if (name.Equals(expr.Name))
                    {
                        throw new InferCompilerException("Model contains multiple items with the name '" + name + "'.  Names must be unique.");
                    }
                }
            }
            if (variable.IsLoopIndex)
            {
                return;             // do nothing
            }
            searched.Add(variable); // must do this first to prevent re-entry
            SearchContainers(variable.Containers);
            List <IStatementBlock> stBlocks = new List <IStatementBlock>();

            if (variable.IsArrayElement)
            {
                SearchItem(variable);
            }
            else
            {
                // base variable
                // Process dependencies
                if (variable.initialiseTo != null)
                {
                    toSearch.Push(variable.initialiseTo);
                }
                if (variable.initialiseBackwardTo != null)
                {
                    toSearch.Push(variable.initialiseBackwardTo);
                }

                if (!variable.Inline)
                {
                    // Determine if the variable should be inlined
                    bool inline;
                    if (variable.definition != null)
                    {
                        inline = variable.definition.CanBeInlined();
                    }
                    else
                    {
                        inline = (variable.conditionalDefinitions.Values.Count == 1);
                        foreach (MethodInvoke condDef in variable.conditionalDefinitions.Values)
                        {
                            inline = inline && condDef.CanBeInlined();
                        }
                        if (variable is HasItemVariables)
                        {
                            ICollection <IVariable> items = ((HasItemVariables)variable).GetItemsUntyped().Values;
                            if (items.Count > 0)
                            {
                                inline = false;
                            }
                        }
                    }
                    variable.Inline = inline;
                }

                if (variable is IVariableArray)
                {
                    IVariableArray iva = (IVariableArray)variable;
                    IList <IVariableDeclaration[]> jaggedIndexVars;
                    IList <IExpression[]>          jaggedSizes;
                    GetJaggedArrayIndicesAndSizes(iva, out jaggedIndexVars, out jaggedSizes);
                }
                // ivde is null if randVar has been declared at this point.
                if (variable.definition != null)
                {
                    SearchMethodInvoke(variable.definition);
                }

                foreach (var attr in variable.GetAttributes <ICompilerAttribute>())
                {
                    if (attr is ValueRange)
                    {
                        ValueRange vr = (ValueRange)attr;
                        SearchRange(vr.Range);
                    }
                    else if (attr is DistributedCommunication)
                    {
                        DistributedCommunication dc = (DistributedCommunication)attr;
                        toSearch.Push(dc.arrayIndicesToSendExpression);
                        toSearch.Push(dc.arrayIndicesToReceiveExpression);
                        var attr2 = new DistributedCommunicationExpression(dc.arrayIndicesToSendExpression.GetExpression(), dc.arrayIndicesToReceiveExpression.GetExpression());
                        // find the base variable
                        Variable parent = variable;
                        while (parent.ArrayVariable != null)
                        {
                            parent = (Variable)parent.ArrayVariable;
                        }
                        var parentDecl = parent.GetDeclaration();
                        if (Attributes.Has <DistributedCommunicationExpression>(parentDecl))
                        {
                            throw new Exception($"{parent} has multiple DistributedCommunication attributes");
                        }
                        Attributes.Set(parentDecl, attr2);
                    }
                }
            }
            foreach (MethodInvoke condDef in variable.conditionalDefinitions.Values)
            {
                SearchMethodInvoke(condDef);
            }

            if (variable is HasItemVariables)
            {
                // fill the array via the definition of its item variable, if any.
                ICollection <IVariable> ie = ((HasItemVariables)variable).GetItemsUntyped().Values;
                foreach (IVariable irv in ie)
                {
                    toSearch.Push(irv);
                }
            }

            foreach (MethodInvoke constraint in variable.constraints)
            {
                SearchMethodInvoke(constraint);
            }
            foreach (MethodInvoke factor in variable.childFactors)
            {
                SearchMethodInvoke(factor);
            }
        }