Example #1
0
 protected override IExpression ConvertAssign(IAssignExpression iae)
 {
     foreach (IStatement stmt in context.FindAncestors <IStatement>())
     {
         // an initializer statement may perform a copy, but it is not valid to replace the lhs
         // in that case.
         if (context.InputAttributes.Has <Initializer>(stmt))
         {
             return(iae);
         }
     }
     // Look for assignments where the right hand side is a SetTo call
     if (iae.Expression is IMethodInvokeExpression imie)
     {
         bool isCopy                          = Recognizer.IsStaticGenericMethod(imie, new Func <PlaceHolder, PlaceHolder>(Clone.Copy));
         bool isSetTo                         = Recognizer.IsStaticGenericMethod(imie, typeof(ArrayHelper), "SetTo");
         bool isSetAllElementsTo              = Recognizer.IsStaticGenericMethod(imie, typeof(ArrayHelper), "SetAllElementsTo");
         bool isGetItemsPoint                 = Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsPointOp <>), "ItemsAverageConditional");
         bool isGetJaggedItemsPoint           = Recognizer.IsStaticGenericMethod(imie, typeof(GetJaggedItemsPointOp <>), "ItemsAverageConditional");
         bool isGetDeepJaggedItemsPoint       = Recognizer.IsStaticGenericMethod(imie, typeof(GetDeepJaggedItemsPointOp <>), "ItemsAverageConditional");
         bool isGetItemsFromJaggedPoint       = Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsFromJaggedPointOp <>), "ItemsAverageConditional");
         bool isGetItemsFromDeepJaggedPoint   = Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsFromDeepJaggedPointOp <>), "ItemsAverageConditional");
         bool isGetJaggedItemsFromJaggedPoint = Recognizer.IsStaticGenericMethod(imie, typeof(GetJaggedItemsFromJaggedPointOp <>), "ItemsAverageConditional");
         if (isCopy || isSetTo || isSetAllElementsTo || isGetItemsPoint ||
             isGetJaggedItemsPoint || isGetDeepJaggedItemsPoint || isGetJaggedItemsFromJaggedPoint ||
             isGetItemsFromJaggedPoint || isGetItemsFromDeepJaggedPoint)
         {
             IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iae.Target);
             // Find the condition context
             var ifs         = context.FindAncestors <IConditionStatement>();
             var condContext = new List <IConditionStatement>();
             foreach (var ifSt in ifs)
             {
                 if (!CodeRecognizer.IsStochastic(context, ifSt.Condition))
                 {
                     condContext.Add(ifSt);
                 }
             }
             var         copyAttr = context.InputAttributes.GetOrCreate <CopyOfAttribute>(ivd, () => new CopyOfAttribute());
             IExpression rhs;
             if (isSetTo || isSetAllElementsTo)
             {
                 // Mark as copy of the second argument
                 rhs = imie.Arguments[1];
             }
             else
             {
                 // Mark as copy of the first argument
                 rhs = imie.Arguments[0];
             }
             InitialiseTo init = context.InputAttributes.Get <InitialiseTo>(ivd);
             if (init != null)
             {
                 IVariableDeclaration ivdRhs  = Recognizer.GetVariableDeclaration(rhs);
                 InitialiseTo         initRhs = (ivdRhs == null) ? null : context.InputAttributes.Get <InitialiseTo>(ivdRhs);
                 if (initRhs == null || !initRhs.initialMessagesExpression.Equals(init.initialMessagesExpression))
                 {
                     // Do not replace a variable with a unique initialiser
                     return(iae);
                 }
             }
             var initBack = context.InputAttributes.Get <InitialiseBackwardTo>(ivd);
             if (initBack != null && !(initBack.initialMessagesExpression is IArrayCreateExpression))
             {
                 IVariableDeclaration ivdRhs  = Recognizer.GetVariableDeclaration(rhs);
                 InitialiseBackwardTo initRhs = (ivdRhs == null) ? null : context.InputAttributes.Get <InitialiseBackwardTo>(ivdRhs);
                 if (initRhs == null || !initRhs.initialMessagesExpression.Equals(init.initialMessagesExpression))
                 {
                     // Do not replace a variable with a unique initialiser
                     return(iae);
                 }
             }
             if (isCopy || isSetTo)
             {
                 RemoveMatchingSuffixes(iae.Target, rhs, condContext, out IExpression lhsPrefix, out IExpression rhsPrefix);
                 copyAttr.copyMap[lhsPrefix] = new CopyOfAttribute.CopyContext {
                     Expression = rhsPrefix, ConditionContext = condContext
                 };
             }
             else if (isSetAllElementsTo)
             {
                 copyAttr.copiedInEveryElementMap[iae.Target] = new CopyOfAttribute.CopyContext {
                     Expression = rhs, ConditionContext = condContext
                 };
             }
             else if (isGetItemsPoint || isGetJaggedItemsPoint || isGetDeepJaggedItemsPoint || isGetItemsFromJaggedPoint || isGetItemsFromDeepJaggedPoint || isGetJaggedItemsFromJaggedPoint)
             {
                 var target     = ((IArrayIndexerExpression)iae.Target).Target;
                 int inputDepth = imie.Arguments.Count - 3;
                 List <IExpression> indexExprs = new List <IExpression>();
                 for (int i = 0; i < inputDepth; i++)
                 {
                     indexExprs.Add(imie.Arguments[1 + i]);
                 }
                 int outputDepth;
                 if (isGetDeepJaggedItemsPoint)
                 {
                     outputDepth = 3;
                 }
                 else if (isGetJaggedItemsPoint || isGetJaggedItemsFromJaggedPoint)
                 {
                     outputDepth = 2;
                 }
                 else
                 {
                     outputDepth = 1;
                 }
                 copyAttr.copyAtIndexMap[target] = new CopyOfAttribute.CopyContext2
                 {
                     Depth             = outputDepth,
                     ConditionContext  = condContext,
                     ExpressionAtIndex = (lhsIndices) =>
                     {
                         return(Builder.JaggedArrayIndex(rhs, indexExprs.ListSelect(indexExpr =>
                                                                                    new[] { Builder.JaggedArrayIndex(indexExpr, lhsIndices) })));
                     }
                 };
             }
             else
             {
                 throw new NotImplementedException();
             }
         }
     }
     return(iae);
 }
Example #2
0
        /// <summary>
        /// Add the definition of a random variable to the MSL, inside of the necessary containers.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="variable"></param>
        /// <remarks>
        /// A scalar variable is declared and defined in one line such as: <c>int x = factor(...);</c>.
        /// An array variable is first declared with an initializer such as: <c>int[] array = new int[4];</c>.
        /// Then it is defined either with a bulk factor such as: <c>array = factor(...);</c>,
        /// or it is defined via its item variable.
        /// An item variable is defined by 'for' loop whose body is: <c>array[i] = factor(...);</c>.
        /// </remarks>
        protected void BuildRandVar <T>(Variable <T> variable)
        {
            if (!variable.IsDefined)
            {
                throw new InferCompilerException("Variable '" + variable + "' has no definition");
            }
            if (variable.IsArrayElement)
            {
                for (int initType = 0; initType < 2; initType++)
                {
                    IModelExpression init = (initType == 0) ? variable.initialiseTo : variable.initialiseBackwardTo;
                    if (init != null)
                    {
                        IExpression initExpr = init.GetExpression();
                        // find the base variable
                        Variable parent = variable;
                        while (parent.ArrayVariable != null)
                        {
                            IVariableDeclaration[] indexVars = new IVariableDeclaration[parent.indices.Count];
                            for (int i = 0; i < indexVars.Length; i++)
                            {
                                IModelExpression expr = parent.indices[i];
                                if (!(expr is Range))
                                {
                                    throw new Exception(parent + ".InitializeTo is not allowed since the indices are not ranges");
                                }
                                indexVars[i] = ((Range)expr).GetIndexDeclaration();
                            }
                            initExpr = VariableInformation.MakePlaceHolderArrayCreate(initExpr, indexVars);
                            parent   = (Variable)parent.ArrayVariable;
                        }
                        IVariableDeclaration parentDecl = (IVariableDeclaration)parent.GetDeclaration();
                        ICompilerAttribute   attr;
                        if (initType == 0)
                        {
                            attr = new InitialiseTo(initExpr);
                        }
                        else
                        {
                            attr = new InitialiseBackwardTo(initExpr);
                        }
                        Attributes.Set(parentDecl, attr);
                    }
                }
                return;
            }
            IVariableDeclaration ivd = (IVariableDeclaration)variable.GetDeclaration();

            if (variable.initialiseTo != null)
            {
                Attributes.Set(ivd, new InitialiseTo(variable.initialiseTo.GetExpression()));
            }
            if (variable.initialiseBackwardTo != null)
            {
                Attributes.Set(ivd, new InitialiseBackwardTo(variable.initialiseBackwardTo.GetExpression()));
            }
            List <IStatementBlock> stBlocks = new List <IStatementBlock>();

            stBlocks.AddRange(variable.Containers);

            IVariableDeclarationExpression ivde = Builder.VarDeclExpr(ivd);

            if (variable is IVariableArray iva)
            {
                IList <IStatement>             sc = Builder.StmtCollection();
                IList <IVariableDeclaration[]> jaggedIndexVars;
                IList <IExpression[]>          jaggedSizes;
                GetJaggedArrayIndicesAndSizes(iva, out jaggedIndexVars, out jaggedSizes);
                // check that containers are all unique and distinct from jaggedIndexVars
                Set <IVariableDeclaration> loopVars = new Set <IVariableDeclaration>();
                foreach (IStatementBlock stBlock in stBlocks)
                {
                    if (stBlock is ForEachBlock fb)
                    {
                        IVariableDeclaration loopVar = fb.Range.GetIndexDeclaration();
                        if (loopVars.Contains(loopVar))
                        {
                            throw new InvalidOperationException("Variable '" + ivd.Name + "' uses range '" + loopVar.Name + "' twice. Use a cloned range instead.");
                        }
                        loopVars.Add(loopVar);
                    }
                }
                foreach (IVariableDeclaration[] bracket in jaggedIndexVars)
                {
                    foreach (IVariableDeclaration indexVar in bracket)
                    {
                        if (loopVars.Contains(indexVar))
                        {
                            throw new InvalidOperationException("Variable '" + ivd.Name + "' uses range '" + indexVar.Name + "' twice. Use a cloned range instead.");
                        }
                    }
                }
                Builder.NewJaggedArray(sc, ivd, jaggedIndexVars, jaggedSizes);
                if (!variable.Inline)
                {
                    BuildStatementBlocks(stBlocks, true);
                    foreach (IStatement stmt in sc)
                    {
                        AddStatement(stmt);
                    }
                    BuildStatementBlocks(stBlocks, false);
                }
                ivde = null; // prevent re-declaration
            }
            if (ivde != null)
            {
                if (!variable.Inline)
                {
                    BuildStatementBlocks(stBlocks, true);
                    AddStatement(Builder.ExprStatement(ivde));
                    BuildStatementBlocks(stBlocks, false);
                }
                ivde = null;
            }
            if (ivde != null)
            {
                throw new InferCompilerException("Variable '" + variable + "' has no definition");
            }
        }