示例#1
0
        /// <summary>
        /// Get the set of ranges used as indices in the arguments of the MethodInvoke, that are not included in its ForEach containers.
        /// </summary>
        /// <returns></returns>
        internal Set <Range> GetLocalRangeSet()
        {
            Set <Range> ranges = new Set <Range>();

            foreach (IModelExpression arg in returnValueAndArgs())
            {
                ForEachRange(arg, ranges.Add);
            }
            foreach (IStatementBlock b in Containers)
            {
                if (b is HasRange)
                {
                    HasRange br = (HasRange)b;
                    ranges.Remove(br.Range);
                }
            }
            return(ranges);
        }
示例#2
0
        /// <summary>
        /// Get the set of ranges used as indices in the arguments of the MethodInvoke, that are not included in its ForEach containers.
        /// </summary>
        /// <returns></returns>
        internal List <Range> GetLocalRangeList()
        {
            List <Range> ranges = new List <Range>();

            foreach (IModelExpression arg in returnValueAndArgs())
            {
                ForEachRange(arg, delegate(Range r) { if (!ranges.Contains(r))
                                                      {
                                                          ranges.Add(r);
                                                      }
                             });
            }
            foreach (IStatementBlock b in Containers)
            {
                if (b is HasRange)
                {
                    HasRange br = (HasRange)b;
                    ranges.Remove(br.Range);
                }
            }
            return(ranges);
        }
示例#3
0
        /// <summary>
        /// Add a statement of the form x = f(...) to the MSL.
        /// </summary>
        /// <param name="method">Stores the method to call, the argument variables, and target variable.</param>
        /// <remarks>
        /// If any variable in the statement is an item variable, then we surround the statement with a loop over its range.
        /// Since there may be multiple item variables, and each item may depend on multiple ranges, we may end up with multiple loops.
        /// </remarks>
        private void BuildMethodInvoke(MethodInvoke method)
        {
            if (method.ReturnValue is Variable && ((Variable)method.ReturnValue).Inline)
            {
                return;
            }
            // Open containing blocks
            List <IStatementBlock> stBlocks    = method.Containers;
            List <Range>           localRanges = new List <Range>();
            // each argument of method puts a partial order on the ranges.
            // e.g.  array[i,j][k]  requires i < k, j < k  but says nothing about i and j
            // we assemble these constraints into a total order.
            Dictionary <Range, int> indexOfRange = new Dictionary <Range, int>();
            Dictionary <IModelExpression, List <List <Range> > > dict = MethodInvoke.GetRangeBrackets(method.returnValueAndArgs());

            foreach (IModelExpression arg in method.returnValueAndArgs())
            {
                MethodInvoke.ForEachRange(arg,
                                          delegate(Range r) { if (!localRanges.Contains(r))
                                                              {
                                                                  localRanges.Add(r);
                                                              }
                                          });
            }
            ParameterInfo[] pis = method.method.GetParameters();
            for (int i = 0; i < pis.Length; i++)
            {
                IModelExpression arg = method.Arguments[i];
                ParameterInfo    pi  = pis[i];
                if (pi.IsOut && arg is HasObservedValue && ((HasObservedValue)arg).IsObserved)
                {
                    throw new NotImplementedException(string.Format("Out parameter '{0}' of {1} cannot be observed.  Use ConstrainEqual or observe a copy of the variable.", pi.Name, method));
                }
            }
            foreach (IStatementBlock b in method.Containers)
            {
                if (b is HasRange)
                {
                    HasRange br = (HasRange)b;
                    localRanges.Remove(br.Range);
                }
            }
            localRanges.Sort(delegate(Range a, Range b) { return(MethodInvoke.CompareRanges(dict, a, b)); });
            // convert from List<Range> to List<IStatementBlock>
            List <IStatementBlock> localRangeBlocks = new List <IStatementBlock>(localRanges.Select(r => r));

            BuildStatementBlocks(stBlocks, true);
            BuildStatementBlocks(localRangeBlocks, true);

            // Invoke method
            IExpression methodExpr = method.GetExpression();
            IStatement  st         = Builder.ExprStatement(methodExpr);

            if (methodExpr is IAssignExpression && method.ReturnValue is HasObservedValue && ((HasObservedValue)method.ReturnValue).IsObserved)
            {
                Attributes.Set(st, new Constraint());
            }
            AddStatement(st);
            foreach (ICompilerAttribute attr in method.attributes)
            {
                Attributes.Add(methodExpr, attr);
            }

            BuildStatementBlocks(localRangeBlocks, false);
            BuildStatementBlocks(stBlocks, false);
        }