/// <summary> /// Throws an exception if an index expression is not valid for subscripting an array. /// </summary> /// <param name="index">Index expression</param> /// <param name="array">Array that the expression is indexing</param> /// <exclude/> internal void CheckCompatible(IModelExpression index, IVariableArray array) { if (IsCompatibleWith(index)) { return; } string message = StringUtil.TypeToString(array.GetType()) + " " + array + " cannot be indexed by " + index + "."; if (index is Range) { string constructorName = "the constructor"; message += " Perhaps you omitted " + index + " as an argument to " + constructorName + "?"; } throw new ArgumentException(message, "index"); }
protected void GetJaggedArrayIndicesAndSizes(IVariableArray array, out IList <IVariableDeclaration[]> jaggedIndexVars, out IList <IExpression[]> jaggedSizes) { Set <IVariableDeclaration> allVars = new Set <IVariableDeclaration>(ReferenceEqualityComparer <IVariableDeclaration> .Instance); jaggedIndexVars = new List <IVariableDeclaration[]>(); jaggedSizes = new List <IExpression[]>(); while (true) { Type arrayType = array.GetExpression().GetExpressionType(); Type elementType = Util.GetElementType(arrayType, out int rank); if (!arrayType.IsAssignableFrom(Util.MakeArrayType(elementType, rank))) { break; } GetArrayIndicesAndSizes(array, out IVariableDeclaration[] indexVars, out IExpression[] sizes);
protected void GetArrayIndicesAndSizes(IVariableArray array, out IVariableDeclaration[] indexVars, out IExpression[] sizes) { IList <Range> ranges = array.Ranges; sizes = new IExpression[ranges.Count]; indexVars = new IVariableDeclaration[ranges.Count]; int i = 0; foreach (Range r in ranges) { SearchRange(r); indexVars[i] = r.GetIndexDeclaration(); sizes[i] = r.GetSizeExpression(); i++; } }
protected void GetJaggedArrayIndicesAndSizes(IVariableArray array, out IList <IVariableDeclaration[]> jaggedIndexVars, out IList <IExpression[]> jaggedSizes) { Set <IVariableDeclaration> allVars = new Set <IVariableDeclaration>(new IdentityComparer <IVariableDeclaration>()); jaggedIndexVars = new List <IVariableDeclaration[]>(); jaggedSizes = new List <IExpression[]>(); while (true) { Type arrayType = array.GetExpression().GetExpressionType(); Type elementType = Util.GetElementType(arrayType, out int rank); if (!arrayType.IsAssignableFrom(Util.MakeArrayType(elementType, rank))) { break; } IVariableDeclaration[] indexVars; IExpression[] sizes; GetArrayIndicesAndSizes(array, out indexVars, out sizes); foreach (IVariableDeclaration ivd in indexVars) { if (allVars.Contains(ivd)) { throw new CompilationFailedException("Array '" + array.Name + "' is indexed by range '" + ivd.Name + "' on multiple dimensions, which is not allowed. Use range cloning instead."); } allVars.Add(ivd); } jaggedIndexVars.Add(indexVars); jaggedSizes.Add(sizes); if (array is IVariableJaggedArray variableJaggedArray) { IVariable itemPrototype = variableJaggedArray.ItemPrototype; if (itemPrototype is IVariableArray variableArray) { array = variableArray; } else { break; } } else { break; } } }
private static IModelExpression ReplaceExpressions(IModelExpression expr, Dictionary <IModelExpression, IModelExpression> replacements) { if (replacements.ContainsKey(expr)) { return(replacements[expr]); } if (expr is Range) { return(ReplaceExpressions((Range)expr, replacements)); } else if (expr is Variable) { Variable v = (Variable)expr; if (v.IsArrayElement) { bool changed = false; IVariableArray newArray = (IVariableArray)ReplaceExpressions(v.ArrayVariable, replacements); if (!ReferenceEquals(newArray, v.ArrayVariable)) { changed = true; } IModelExpression[] newIndices = new IModelExpression[v.indices.Count]; for (int i = 0; i < newIndices.Length; i++) { newIndices[i] = ReplaceExpressions(v.indices[i], replacements); if (!ReferenceEquals(newIndices[i], v.indices[i])) { changed = true; } } if (changed) { return ((IModelExpression) Invoker.InvokeMember(newArray.GetType(), "get_Item", BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, newArray, newIndices)); } } } return(expr); }
/// <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); } }