/// <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); }
/// <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); }
/// <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); }