protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { // register the whole expression only // indices are not registered as separate expressions ProcessExpression(iaie); return(iaie); }
private IExpression GetMessageExpression(IExpression expr, IDictionary <IVariableDeclaration, IVariableDeclaration> msgVars) { if (expr is IVariableReferenceExpression) { IVariableReferenceExpression ivre = (IVariableReferenceExpression)expr; IVariableDeclaration ivd = ivre.Variable.Resolve(); IVariableDeclaration msgVar; if (msgVars.TryGetValue(ivd, out msgVar)) { return(Builder.VarRefExpr(msgVar)); } else { return(null); } } else if (expr is IArrayIndexerExpression) { IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr; IExpression targetMsg = GetMessageExpression(iaie.Target, msgVars); if (targetMsg == null) { return(null); } else { return(Builder.ArrayIndex(targetMsg, iaie.Indices)); } } else { throw new ArgumentException("Unrecognized method argument expression"); } }
/// <summary> /// Register a use of a variable at a specific indexing depth /// </summary> /// <param name="iaie"></param> /// <returns></returns> protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { IExpression expr = (IArrayIndexerExpression)base.ConvertArrayIndexer(iaie); // Only register the full indexer expression, not its sub-expressions if (Recognizer.IsBeingIndexed(context) || Recognizer.IsBeingMutated(context, expr)) { return(expr); } List <IList <IExpression> > indices = Recognizer.GetIndices(expr, out IExpression target); if (target is IVariableReferenceExpression) { IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); if (ivd != null) { if (usageInfo.TryGetValue(ivd, out UsageInfo info)) { info.indexingDepths.Add(indices.Count); RegisterUse(info, expr); } } } return(expr); }
protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { var indices = Recognizer.GetIndices(iaie, out IExpression target); if (target is IVariableReferenceExpression) { // Only convert indices that could matter. IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); HoistingInfo info = GetOrCreateHoistingInfo(ivd); int indexingDepth = indices.Count; for (int bracket = 0; bracket < indexingDepth; bracket++) { for (int dim = 0; dim < indices[bracket].Count; dim++) { if (info.maxDepthWhereDimensionCouldMatter.Length <= bracket || info.maxDepthWhereDimensionCouldMatter[bracket][dim] >= indexingDepth) { ConvertExpression(indices[bracket][dim]); } } } return(iaie); } else { return(base.ConvertArrayIndexer(iaie)); } }
private static void WriteArrayIndexerExpression(LanguageWriter w, IArrayIndexerExpression exp) { w.WriteExpression(exp.Target); w.Write("["); w.WriteExpressionCollection(exp.Indices); w.Write("]"); }
/// <summary> /// Use wildcards to replace any indices in expr which involve local variables of the gateBlock /// </summary> /// <param name="gateBlock"></param> /// <param name="expr"></param> /// <returns></returns> private IExpression ReplaceLocalIndices(GateBlock gateBlock, IExpression expr) { if (expr is IArrayIndexerExpression) { IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr; IExpression target = ReplaceLocalIndices(gateBlock, iaie.Target); List <IExpression> indices = new List <IExpression>(); bool replaced = !ReferenceEquals(target, iaie.Target); foreach (IExpression index in iaie.Indices) { if (ContainsLocalVars(gateBlock, index)) { indices.Add(Builder.StaticMethod(new Func <int>(GateAnalysisTransform.AnyIndex))); replaced = true; } else { indices.Add(index); } } if (replaced) { expr = Builder.ArrayIndex(target, indices); } } return(expr); }
/// <summary> /// Determine if all literal indices beyond the usageDepth are zero /// </summary> /// <param name="target"></param> /// <param name="targetDepth"></param> /// <param name="usageDepth"></param> /// <returns></returns> private static bool CheckExtraLiteralsAreZero(IExpression target, int targetDepth, int usageDepth) { bool extraLiteralsAreZero = true; int depth = targetDepth; while (depth > usageDepth) { IArrayIndexerExpression iaie = (IArrayIndexerExpression)target; foreach (IExpression index in iaie.Indices) { if (index is ILiteralExpression) { int value = (int)((ILiteralExpression)index).Value; if (value != 0) { extraLiteralsAreZero = false; break; } } } target = iaie.Target; depth--; } return(extraLiteralsAreZero); }
public override void VisitArrayIndexerExpression(IArrayIndexerExpression value) { VisitExpression(value.Target); _formatter.Write("["); VisitExpressionCollection(value.Indices, true); _formatter.Write("]"); }
protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { bool isPartOfLhs = Recognizer.IsBeingMutated(context, iaie); AddUsage(iaie, isPartOfLhs); // loop over prefixes of the expression IArrayIndexerExpression prefix = iaie; bool isPrefix = false; while (true) { foreach (IExpression index in prefix.Indices) { ConvertExpression(index); } if (isPrefix && false) { bool anyIndexIsPartitioned = prefix.Indices.Any(index => Recognizer.GetVariables(index).Any(ivd => context.InputAttributes.Has <Partitioned>(ivd))); if (anyIndexIsPartitioned) { AddUsage(prefix, false); } } if (prefix.Target is IArrayIndexerExpression target) { prefix = target; isPrefix = true; } else { break; } } return(iaie); }
public override bool Equals(object obj) { if (this == obj) { return(true); } IArrayIndexerExpression expression = obj as IArrayIndexerExpression; if (expression == null || (!Target.Equals(expression.Target)) || Indices.Count != expression.Indices.Count) { return(false); } for (int i = 0; i < Indices.Count; i++) { if (!(Indices[i].Equals(expression.Indices[i]))) { return(false); } } return(true); }
protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { bool isDef = Recognizer.IsBeingMutated(context, iaie); base.ConvertArrayIndexer(iaie); RegisterDepth(iaie, isDef); return(iaie); }
protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { // convert the indices first IExpression expr = base.ConvertArrayIndexer(iaie); // Check if this is the top level indexer if (Recognizer.IsBeingIndexed(context)) { return(expr); } if (Recognizer.IsBeingMutated(context, iaie)) { return(expr); } IExpression target; List <IList <IExpression> > indices = Recognizer.GetIndices(expr, out target); if (!(target is IVariableReferenceExpression)) { return(expr); } IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); if (ivd == null) { return(expr); } VariableToChannelInformation vtci; if (usesOfVariable.TryGetValue(ivd, out vtci)) { IExpression usageIndex = Builder.LiteralExpr(GetUseNumber(ivd, vtci)); ChannelInfo ci = context.OutputAttributes.Get <ChannelInfo>(vtci.usesDecl); IExpression newExpr = Builder.VarRefExpr(vtci.usesDecl); if (vtci.usageDepth > indices.Count) { Error("usageDepth (" + vtci.usageDepth + ") > indices.Count (" + indices.Count + ")"); } // append the indices up to the usageDepth for (int i = 0; i < vtci.usageDepth; i++) { if (indices.Count <= i) { return(newExpr); } newExpr = Builder.ArrayIndex(newExpr, indices[i]); } newExpr = Builder.ArrayIndex(newExpr, usageIndex); // append the remaining indices for (int i = vtci.usageDepth; i < indices.Count; i++) { newExpr = Builder.ArrayIndex(newExpr, indices[i]); } return(newExpr); } return(expr); }
/// <summary> /// Return the common parent of the two expressions, and indicate if the expressions overlap /// </summary> /// <param name="eb1"></param> /// <param name="eb2"></param> /// <returns></returns> /// <remarks> /// When finding the common parent, we want to preserve any array slicing. Indexing brackets are not removed if present in both expressions. /// Mismatching indices are replaced by AnyIndex. /// Examples: /// i = loop index inside the gate block /// j = loop index outside the gate block, or a method parameter /// (a,a[i]) => (a,true) /// (a,a[j]) => (a,true) /// (a[i],a[0]) => (a[*],true) /// (a[i],a[j]) => (a[*],true) /// (a[j],a[0]) => (a[*],assumeMatch) /// (a[0],a[1]) => (a[*],false) /// (a[0][0],a[1][0]) => (a[*][0],false) /// (a[0][0],a[1][1]) => (a[*][*],false) /// </remarks> private static ExpressionWithBindings GetCommonParent(ExpressionWithBindings eb1, ExpressionWithBindings eb2) { List <IExpression> prefixes1 = Recognizer.GetAllPrefixes(eb1.Expression); List <IExpression> prefixes2 = Recognizer.GetAllPrefixes(eb2.Expression); if (!prefixes1[0].Equals(prefixes2[0])) { throw new Exception("Expressions have no overlap: " + eb1 + "," + eb2); } IExpression parent = prefixes1[0]; int count = System.Math.Min(prefixes1.Count, prefixes2.Count); for (int i = 1; i < count; i++) { IExpression prefix1 = prefixes1[i]; IExpression prefix2 = prefixes2[i]; if (prefix1 is IArrayIndexerExpression) { IArrayIndexerExpression iaie1 = (IArrayIndexerExpression)prefix1; if (prefix2 is IArrayIndexerExpression) { IArrayIndexerExpression iaie2 = (IArrayIndexerExpression)prefix2; if (iaie1.Indices.Count != iaie2.Indices.Count) { throw new Exception("Array rank mismatch: " + eb1 + "," + eb2); } IList <IExpression> indices = Builder.ExprCollection(); for (int ind = 0; ind < iaie1.Indices.Count; ind++) { IExpression index1 = iaie1.Indices[ind]; IExpression index2 = iaie2.Indices[ind]; IExpression index = Unify(index1, eb1.Bindings, index2, eb2.Bindings); indices.Add(index); } parent = Builder.ArrayIndex(parent, indices); } else { break; } } else { throw new Exception("Unhandled expression type: " + prefix1); } } ExpressionWithBindings result = new ExpressionWithBindings(); result.Expression = parent; if (eb1.Bindings.Count > 0 && eb2.Bindings.Count > 0) { result.Bindings.AddRange(eb1.Bindings); result.Bindings.AddRange(eb2.Bindings); } return(result); }
public IExpression Replace(BasicTransformContext context, IExpression expr) { if (copyMap.ContainsKey(expr)) { var cc = copyMap[expr]; if (cc.IsValidContext(context)) { return(cc.Expression); } } if (expr is IArrayIndexerExpression) { IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr; if (copiedInEveryElementMap.ContainsKey(iaie.Target)) { var cc = copiedInEveryElementMap[iaie.Target]; if (cc.IsValidContext(context)) { return(cc.Expression); } } if (copyAtIndexMap.ContainsKey(iaie.Target)) { var cc = copyAtIndexMap[iaie.Target]; if (cc.Depth == 1 && cc.IsValidContext(context)) { return(cc.ExpressionAtIndex(new[] { iaie.Indices })); } } if (iaie.Target is IArrayIndexerExpression) { var iaie2 = (IArrayIndexerExpression)iaie.Target; if (copyAtIndexMap.ContainsKey(iaie2.Target)) { var cc = copyAtIndexMap[iaie2.Target]; if (cc.Depth == 2 && cc.IsValidContext(context)) { return(cc.ExpressionAtIndex(new[] { iaie2.Indices, iaie.Indices })); } } if (iaie2.Target is IArrayIndexerExpression) { var iaie3 = (IArrayIndexerExpression)iaie2.Target; if (copyAtIndexMap.ContainsKey(iaie3.Target)) { var cc = copyAtIndexMap[iaie3.Target]; if (cc.Depth == 3 && cc.IsValidContext(context)) { return(cc.ExpressionAtIndex(new[] { iaie3.Indices, iaie2.Indices, iaie.Indices })); } } } } } return(null); }
protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { bool isDef = Recognizer.IsBeingMutated(context, iaie); iaie = (IArrayIndexerExpression)base.ConvertArrayIndexer(iaie); if (isDef) { return(iaie); } return(GetClone(iaie)); }
protected override IStatement ConvertFor(IForStatement ifs) { // convert the initializer, condition, and increment outside of the container. context.SetPrimaryOutput(ifs); ConvertStatement(ifs.Initializer); ConvertExpression(ifs.Condition); ConvertStatement(ifs.Increment); // convert the body inside of a new ContainerInfo. bool wasPartitioned = this.InPartitionedLoop; IVariableDeclaration loopVar = Recognizer.LoopVariable(ifs); bool isPartitioned = InPartitionedLoop || context.InputAttributes.Has <Partitioned>(loopVar) || (this.compiler.UseLocals && this.compiler.OptimiseInferenceCode); if (isPartitioned) { this.InPartitionedLoop = true; containerInfos.Push(new ContainerInfo()); } openContainers.Push(ifs); ConvertBlock(ifs.Body); openContainers.Pop(); if (isPartitioned) { ContainerInfo containerInfo = containerInfos.Pop(); var localInfos = new Dictionary <IExpression, LocalInfo>(); localInfoOfStmt[ifs] = localInfos; // find the longest common prefix of each variable's expressions foreach (var entry in containerInfo.usageInfoOfVariable) { object decl = entry.Key; UsageInfo usageInfo = entry.Value; CombineLocalInfos(usageInfo.localInfos); foreach (var pair in usageInfo.localInfos) { IExpression expr = pair.Key; LocalInfo localInfo = pair.Value; IExpression prefix = GetPrefixInParent(expr, loopVar); if (!ReferenceEquals(prefix, expr)) { // expr refers to this loop variable IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr; if (usageInfo.localInfos.Count == 1) { localInfos.Add(expr, localInfo); } } // add the prefix to the parent containerInfo var info = AddLocalInfo(decl, prefix, localInfo, ifs); } } this.InPartitionedLoop = wasPartitioned; } return(ifs); }
private void AppendIndexString(StringBuilder sb, IArrayIndexerExpression iaie) { for (int i = 0; i < iaie.Indices.Count; i++) { if (i > 0) { sb.Append("_"); } IExpression indExpr = iaie.Indices[i]; sb.Append(indExpr.ToString()); } }
/// <summary> /// Find the longest prefix that does not have any index expression containing the current loop variable. /// </summary> /// <param name="expr"></param> /// <param name="excludedLoopVar"></param> /// <returns></returns> private IExpression GetPrefixInParent(IExpression expr, IVariableDeclaration excludedLoopVar) { if (expr is IArrayIndexerExpression) { IExpression expr2 = expr; while (expr2 is IArrayIndexerExpression) { IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr2; bool hasExcludedLoopVar = iaie.Indices.Any(index => Recognizer.GetVariables(index).Any(excludedLoopVar.Equals)); if (hasExcludedLoopVar) { return(GetPrefixInParent(iaie.Target, excludedLoopVar)); } expr2 = iaie.Target; } } return(expr); }
/// <summary> /// Modify array index expressions which are copies of other variables. /// </summary> /// <param name="iaie"></param> /// <returns></returns> protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { // should not convert if on LHS IExpression copyExpr = GetCopyExpr(iaie); if (copyExpr != null) { return(copyExpr); } var aie = base.ConvertArrayIndexer(iaie); // If part of the expression has been replaced, check the whole again if (!ReferenceEquals(aie, iaie)) { return(ConvertArrayIndexer((IArrayIndexerExpression)aie)); } return(aie); }
/// <summary> /// Modify array index expressions which are copies of other variables. /// </summary> /// <param name="iaie"></param> /// <returns></returns> protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { // should not convert if on LHS IExpression copyExpr = GetCopyExpr(iaie); if (copyExpr != null) { return(copyExpr); } formalTypeStack.Push(typeof(int)); IList <IExpression> newIndices = ConvertCollection(iaie.Indices); formalTypeStack.Pop(); Type arrayType; if (iaie.Indices.Count == 1) { var elementType = FormalTypeStackApplies() ? formalTypeStack.Peek() : iaie.GetExpressionType(); // This must be IReadOnlyList not IList to allow covariance. arrayType = typeof(IReadOnlyList <>).MakeGenericType(elementType); } else { arrayType = iaie.Target.GetExpressionType(); } formalTypeStack.Push(arrayType); IExpression newTarget = ConvertExpression(iaie.Target); formalTypeStack.Pop(); if (ReferenceEquals(newTarget, iaie.Target) && ReferenceEquals(newIndices, iaie.Indices)) { return(iaie); } IArrayIndexerExpression aie = Builder.ArrayIndxrExpr(); aie.Target = newTarget; aie.Indices.AddRange(newIndices); Context.InputAttributes.CopyObjectAttributesTo(iaie, context.OutputAttributes, aie); // Since part of the expression has been replaced, check the whole again return(ConvertArrayIndexer(aie)); }
protected override IExpression ConvertAssign(IAssignExpression iae) { iae = (IAssignExpression)base.ConvertAssign(iae); if (iae.Target is IArrayIndexerExpression && iae.Expression is IObjectCreateExpression) { IArrayIndexerExpression target = (IArrayIndexerExpression)iae.Target; IExpression parent = target.Target; IObjectCreateExpression ioce = (IObjectCreateExpression)iae.Expression; Type type = Builder.ToType(ioce.Type); if (MessageTransform.IsFileArray(type) && MessageTransform.IsFileArray(parent.GetExpressionType()) && ioce.Arguments.Count == 2) { // change new FileArray(name, dimensions) into FileArray(parent, index, dimensions) IList <IExpression> args = Builder.ExprCollection(); args.Add(target.Target); args.AddRange(target.Indices); args.Add(ioce.Arguments[1]); return(Builder.AssignExpr(target, Builder.NewObject(type, args))); } } return(iae); }
/// <summary> /// Converts an array indexed expression. /// </summary> /// <param name="iaie"></param> /// <returns></returns> protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { IExpression expr = base.ConvertArrayIndexer(iaie); // Check if this is the top level indexer if (Recognizer.IsBeingIndexed(context)) { return(expr); } IExpression target; List <IList <IExpression> > indices = Recognizer.GetIndices(expr, out target); if (!(target is IVariableReferenceExpression)) { return(expr); } IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); if (ivd == null) { return(expr); } VariableToChannelInformation vtci = Context.InputAttributes.Get <VariableToChannelInformation>(ivd); if (vtci == null) { return(expr); } if (vtci.usageChannel == null) { return(expr); } bool isDef = Recognizer.IsBeingMutated(context, expr); if (isDef) { return(expr); } return(vtci.usageChannel.ReplaceWithUsesChannel(expr, Builder.LiteralExpr(vtci.shareAllUses ? 0 : vtci.useCount++))); }
private void RemoveMatchingSuffixes(IExpression expr1, IExpression expr2, List <IConditionStatement> condContext, out IExpression prefix1, out IExpression prefix2) { if (expr1 is IArrayIndexerExpression) { IArrayIndexerExpression iaie1 = (IArrayIndexerExpression)expr1; if (expr2 is IArrayIndexerExpression) { IArrayIndexerExpression iaie2 = (IArrayIndexerExpression)expr2; if (iaie1.Indices.Count == iaie2.Indices.Count) { bool allIndicesAreEqual = true; for (int i = 0; i < iaie1.Indices.Count; i++) { IExpression index1 = iaie1.Indices[i]; IExpression index2 = iaie2.Indices[i]; // indices only match if they are loop variables, because then we know that this is the only assignment for the whole array. // literal indices, on the other hand, can appear in multiple assignments, e.g. array[0] = Copy(x0[0]), array[1] = Copy(x1[0]). if (!(index1 is IVariableReferenceExpression) || !(index2 is IVariableReferenceExpression) || !index1.Equals(index2) || AnyConditionsDependOnLoopVariable(condContext, Recognizer.GetVariableDeclaration(index1))) { allIndicesAreEqual = false; } } if (allIndicesAreEqual) { RemoveMatchingSuffixes(iaie1.Target, iaie2.Target, condContext, out prefix1, out prefix2); if (prefix1.GetExpressionType().Equals(prefix2.GetExpressionType())) { return; } } } } } prefix1 = expr1; prefix2 = expr2; }
/// <summary> /// Split expr into a target and extra indices, where target will be replicated and extra indices will be added later. /// </summary> /// <param name="loop">The loop we are replicating over</param> /// <param name="expr">Expression being replicated</param> /// <param name="indices">Modified to contain the extra indices</param> /// <param name="target">Prefix of expr to replicate</param> protected void AddUnreplicatedIndices(IForStatement loop, IExpression expr, List <IEnumerable <IExpression> > indices, out IExpression target) { if (expr is IArrayIndexerExpression) { IArrayIndexerExpression iaie = (IArrayIndexerExpression)expr; AddUnreplicatedIndices(loop, iaie.Target, indices, out target); if (indices.Count == 0) { // determine if iaie.Indices can be replicated bool canReplicate = true; foreach (IExpression index in iaie.Indices) { if (NeedsContainer(loop, index)) { canReplicate = false; break; } } IVariableDeclaration loopVar = Recognizer.LoopVariable(loop); bool isPartitioned = context.InputAttributes.Has <Partitioned>(loopVar); if (isPartitioned && !AnyPartitionedExpr(iaie.Indices)) { canReplicate = false; } if (canReplicate) { target = expr; return; } // fall through } indices.Add(iaie.Indices); } else { target = expr; } }
private IExpression ConvertIndices(IExpression expr) { if (!(expr is IArrayIndexerExpression iaie)) { return(expr); } var newTarget = ConvertIndices(iaie.Target); formalTypeStack.Push(typeof(int)); IList <IExpression> newIndices = ConvertCollection(iaie.Indices); formalTypeStack.Pop(); if (ReferenceEquals(newTarget, iaie.Target) && ReferenceEquals(newIndices, iaie.Indices)) { return(iaie); } IArrayIndexerExpression aie = Builder.ArrayIndxrExpr(); aie.Target = newTarget; aie.Indices.AddRange(newIndices); Context.InputAttributes.CopyObjectAttributesTo(iaie, context.OutputAttributes, aie); return(aie); }
protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { IExpression target; var indices = Recognizer.GetIndices(iaie, out target); if (target is IVariableReferenceExpression) { int indexingDepth = indices.Count; IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); HoistingInfo info; if (analysis.infoOfVariable.TryGetValue(ivd, out info) && info.newVariable != null && IsReducibleAtDepth(info, indexingDepth)) { int arrayDepth = info.maxDepthWhereDimensionCouldMatter.Length; IExpression newExpr = Builder.VarRefExpr(info.newVariable); for (int bracket = 0; bracket < indexingDepth; bracket++) { if (info.maxDepthWhereDimensionCouldMatter[bracket].Any(d => d == arrayDepth)) { List <IExpression> newIndices = new List <IExpression>(); for (int dim = 0; dim < indices[bracket].Count; dim++) { if (info.maxDepthWhereDimensionCouldMatter[bracket][dim] == arrayDepth) { newIndices.Add(indices[bracket][dim]); } } newExpr = Builder.ArrayIndex(newExpr, newIndices); } } return(newExpr); } // fall through } return(base.ConvertArrayIndexer(iaie)); }
public virtual IExpression TransformArrayIndexerExpression(IArrayIndexerExpression value) { this.InsituTransformExpressionCollection(value.Indices); value.Target = this.TransformExpression(value.Target); return value; }
protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { IArrayIndexerExpression aie = (IArrayIndexerExpression)base.ConvertArrayIndexer(iaie); IExpression topExpr = context.FindAncestor <IAssignExpression>(); bool isDef = false; if (topExpr == null) { topExpr = context.FindAncestor <IMethodInvokeExpression>(); if (Recognizer.IsStaticMethod(topExpr, typeof(InferNet))) { return(aie); } } else { isDef = ((IAssignExpression)topExpr).Target == iaie; } if (topExpr == null) { return(aie); } // Find the variable algorithm IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iaie.Target); if (ivd == null) { //Error("Cannot find array indexer target variable: " + iaie.Target); return(iaie); } IAlgorithm varAlg = GetAlgorithm(ivd); //Console.WriteLine("varAlg=" + varAlg + " " + ivd); // Find the factor algorithm IAlgorithm factorAlg = GetAlgorithm(topExpr); // If the algorithsm are the same, do nothing. if (varAlg.Equals(factorAlg)) { return(aie); } // Otherwise, look up conversion operator ChannelInfo ci = context.InputAttributes.Get <ChannelInfo>(ivd); if (ci == null) { Error("Channel information not found for '" + ivd.Name + "'."); return(aie); } Type chType = ci.varInfo.marginalPrototypeExpression.GetExpressionType(); List <object> extraArgs = new List <object>(); MethodReference opMethodRef = null; try { opMethodRef = factorAlg.GetAlgorithmConversionOperator(chType, varAlg, isDef, extraArgs); } catch (Exception ex) { Error("No conversion operator defined from " + factorAlg + " to " + varAlg, ex); return(aie); } if (opMethodRef == null) { return(aie); } // Create new channel DuplicateInfo dupInfo = context.InputAttributes.GetOrCreate <DuplicateInfo>(ivd, () => new DuplicateInfo()); dupInfo.dupCount++; IVariableDeclaration vd = Builder.VarDecl(ivd.Name + "_dup" + dupInfo.dupCount, ivd.VariableType); Context.InputAttributes.CopyObjectAttributesTo(ivd, context.OutputAttributes, vd); Context.OutputAttributes.Remove <Algorithm>(vd); Context.OutputAttributes.Set(vd, new Algorithm(factorAlg)); //ci.AddDeclaration(context); IExpression opMethodCall = null; IExpression[] args = new IExpression[extraArgs.Count + 1]; IExpression lhs = Builder.ArrayIndex(Builder.VarRefExpr(vd), Builder.LiteralExpr(0)); args[0] = aie; if (isDef) { args[0] = lhs; lhs = aie; } for (int i = 0; i < extraArgs.Count; i++) { args[i + 1] = Builder.LiteralExpr(extraArgs[i]); } if (opMethodRef.TypeParameterCount == 0) { opMethodCall = Builder.StaticMethod(opMethodRef.GetMethodInfo(), args); } else { // TODO: insert argument types opMethodCall = Builder.StaticGenericMethod(opMethodRef.GetMethodInfo(), args); } //context.AddExpression(Builder.AssignExpr(lhs,opMethodCall)); return(Builder.ArrayIndex(Builder.VarRefExpr(vd), Builder.LiteralExpr(0))); }
protected override IStatement DoConvertStatement(IStatement ist) { if (ist is IExpressionStatement) { bool isAccumulator = false; IExpressionStatement ies = (IExpressionStatement)ist; if (ies.Expression is IAssignExpression) { IAssignExpression iae = (IAssignExpression)ies.Expression; AccumulationInfo ac = context.InputAttributes.Get <AccumulationInfo>(ies); if (ac != null) { // This statement defines an accumulator. // Delete the statement and replace with any remaining accumulations. if (!ac.isInitialized) { context.AddStatementBeforeCurrent(ac.initializer); } ac.isInitialized = false; context.AddStatementsBeforeCurrent(ac.statements); isAccumulator = true; } object ivd = Recognizer.GetVariableDeclaration(iae.Target); if (ivd == null) { ivd = Recognizer.GetFieldReference(iae.Target); } if (ivd != null) { MessageArrayInformation mai = context.InputAttributes.Get <MessageArrayInformation>(ivd); bool oneUse = (mai != null) && (mai.useCount == 1); List <AccumulationInfo> ais = context.InputAttributes.GetAll <AccumulationInfo>(ivd); foreach (AccumulationInfo ai in ais) { if (!context.InputAttributes.Has <OperatorStatement>(ist)) { if (oneUse) { return(null); // remove the statement } else { continue; } } // assuming that we only accumulate one statement, we should always initialize if (true || !ai.isInitialized) { // add the initializer in the same containers as the original accumulation statement int ancIndex = ai.containers.GetMatchingAncestorIndex(context); Containers missing = ai.containers.GetContainersNotInContext(context, ancIndex); context.AddStatementBeforeAncestorIndex(ancIndex, Containers.WrapWithContainers(ai.initializer, missing.outputs)); ai.isInitialized = true; } // This statement defines a variable that contributes to an accumulator. IList <IStatement> stmts = Builder.StmtCollection(); IExpression target = iae.Target; Type exprType = target.GetExpressionType(); IExpression accumulator = ai.accumulator; Type accumulatorType = ai.type; int rank; Type eltType = Util.GetElementType(exprType, out rank); if (rank == 1 && eltType == accumulatorType) { // This statement defines an array of items to be accumulated. VariableInformation varInfo = context.InputAttributes.Get <VariableInformation>(mai.ci.decl); int indexingDepth = Recognizer.GetIndexingDepth(iae.Target); if (mai.loopVarInfo != null) { indexingDepth -= mai.loopVarInfo.indexVarRefs.Length; } IExpression size = varInfo.sizes[indexingDepth][0]; IVariableDeclaration indexVar = varInfo.indexVars[indexingDepth][0]; IForStatement ifs = Builder.ForStmt(indexVar, size); target = Builder.ArrayIndex(target, Builder.VarRefExpr(indexVar)); ifs.Body.Statements.Add(ai.GetAccumulateStatement(context, accumulator, target)); stmts.Add(ifs); } else { Stack <IList <IExpression> > indexStack = new Stack <IList <IExpression> >(); while (exprType != accumulatorType && target is IArrayIndexerExpression) { // The accumulator is an array type, and this statement defines an element of the accumulator type. // Peel off the indices of the target. IArrayIndexerExpression iaie = (IArrayIndexerExpression)target; indexStack.Push(iaie.Indices); target = iaie.Target; accumulatorType = Util.GetElementType(accumulatorType); } while (indexStack.Count > 0) { // Attach the indices of the target to the accumulator, in reverse order that they were peeled. accumulator = Builder.ArrayIndex(accumulator, indexStack.Pop()); } if (exprType == accumulatorType) { if (oneUse && !isAccumulator) { // convert // msg = expr; // into // T temp = expr; // acc = SetToProduct(acc, temp); // and move into ai.statement. tempVarCount++; string name = "_temp" + tempVarCount; IVariableDeclaration tempVar = Builder.VarDecl(name, exprType); IStatement newStatement = Builder.AssignStmt(Builder.VarDeclExpr(tempVar), iae.Expression); context.AddStatementBeforeCurrent(newStatement); context.AddStatementBeforeCurrent(ai.GetAccumulateStatement(context, accumulator, Builder.VarRefExpr(tempVar))); return(null); } else { // must keep the original statement. // add // acc = SetToProduct(acc, msg); // to ai.statements. context.AddStatementAfterCurrent(ai.GetAccumulateStatement(context, accumulator, iae.Target)); } } else { Error("Unrecognized variable type: " + StringUtil.TypeToString(exprType)); } } Containers containers = new Containers(context); containers = containers.Remove(ai.containers); IList <IStatement> output2 = Builder.StmtCollection(); Containers.AddStatementWithContainers(output2, stmts, containers.inputs); foreach (IStatement ist2 in output2) { context.AddStatementAfterCurrent(ist2); } } } } if (!isAccumulator) { return(ist); } else { return(null); } } else { return(base.DoConvertStatement(ist)); } }
private void WriteArrayIndexerExpression(IArrayIndexerExpression expression, IFormatter formatter) { this.WriteTargetExpression(expression.Target, formatter); formatter.Write("["); for (int i = 0; i < expression.Indices.Count; i++) { if (i != 0) { formatter.Write(", "); } this.WriteExpression(expression.Indices[i], formatter); } formatter.Write("]"); }
public virtual void VisitArrayIndexerExpression(IArrayIndexerExpression value) { this.VisitExpressionCollection(value.Indices); this.VisitExpression(value.Target); }
/// <summary> /// This method does all the work of converting literal indexing expressions. /// </summary> /// <param name="iaie"></param> /// <returns></returns> protected override IExpression ConvertArrayIndexer(IArrayIndexerExpression iaie) { IndexAnalysisTransform.IndexInfo info; if (!analysis.indexInfoOf.TryGetValue(iaie, out info)) { return(base.ConvertArrayIndexer(iaie)); } // Determine if this is a definition i.e. the variable is on the left hand side of an assignment // This must be done before base.ConvertArrayIndexer changes the expression! bool isDef = Recognizer.IsBeingMutated(context, iaie); if (info.clone != null) { if (isDef) { // check that extra literal indices in the target are zero. // for example, if iae is x[i][0] = (...) then it is safe to add x_uses[i] = Rep(x[i]) // if iae is x[i][1] = (...) then it is safe to add x_uses[i][1] = Rep(x[i][1]) // but not x_uses[i] = Rep(x[i]) since this will be a duplicate. bool extraLiteralsAreZero = true; int parentIndex = context.InputStack.Count - 2; object parent = context.GetAncestor(parentIndex); while (parent is IArrayIndexerExpression) { IArrayIndexerExpression parent_iaie = (IArrayIndexerExpression)parent; foreach (IExpression index in parent_iaie.Indices) { if (index is ILiteralExpression) { int value = (int)((ILiteralExpression)index).Value; if (value != 0) { extraLiteralsAreZero = false; break; } } } parentIndex--; parent = context.GetAncestor(parentIndex); } if (false && extraLiteralsAreZero) { // change: // array[0] = f() // into: // array_item0 = f() // array[0] = Copy(array_item0) IExpression copy = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy <PlaceHolder>), new Type[] { iaie.GetExpressionType() }, info.clone); IStatement copySt = Builder.AssignStmt(iaie, copy); context.AddStatementAfterCurrent(copySt); } } return(info.clone); } if (isDef) { // do not clone the lhs of an array create assignment. IAssignExpression assignExpr = context.FindAncestor <IAssignExpression>(); if (assignExpr.Expression is IArrayCreateExpression) { return(iaie); } } IVariableDeclaration originalBaseVar = Recognizer.GetVariableDeclaration(iaie); // If the variable is not stochastic, return if (!CodeRecognizer.IsStochastic(context, originalBaseVar)) { return(iaie); } IExpression newExpr = null; IVariableDeclaration baseVar = originalBaseVar; IVariableDeclaration newvd = null; IExpression rhsExpr = null; Containers containers = info.containers; Type tp = iaie.GetExpressionType(); if (tp == null) { Error("Could not determine type of expression: " + iaie); return(iaie); } var stmts = Builder.StmtCollection(); var stmtsAfter = Builder.StmtCollection(); // does the expression have the form array[indices[k]][indices2[k]][indices3[k]]? if (newvd == null && UseGetItems && iaie.Target is IArrayIndexerExpression && iaie.Indices.Count == 1 && iaie.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index3 = (IArrayIndexerExpression)iaie.Indices[0]; IArrayIndexerExpression iaie2 = (IArrayIndexerExpression)iaie.Target; if (index3.Indices.Count == 1 && index3.Indices[0] is IVariableReferenceExpression && iaie2.Target is IArrayIndexerExpression && iaie2.Indices.Count == 1 && iaie2.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index2 = (IArrayIndexerExpression)iaie2.Indices[0]; IArrayIndexerExpression iaie3 = (IArrayIndexerExpression)iaie2.Target; if (index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression && iaie3.Indices.Count == 1 && iaie3.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index = (IArrayIndexerExpression)iaie3.Indices[0]; IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0]; IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); if (index.Indices.Count == 1 && index2.Indices[0].Equals(innerIndex) && index3.Indices[0].Equals(innerIndex) && innerLoop != null && AreLoopsDisjoint(innerLoop, iaie3.Target, index.Target)) { // expression has the form array[indices[k]][indices2[k]][indices3[k]] if (isDef) { Error("fancy indexing not allowed on left hand side"); return(iaie); } WarnIfLocal(index.Target, iaie3.Target, iaie); WarnIfLocal(index2.Target, iaie3.Target, iaie); WarnIfLocal(index3.Target, iaie3.Target, iaie); containers = RemoveReferencesTo(containers, innerIndex); IExpression loopSize = Recognizer.LoopSizeExpression(innerLoop); var indices = Recognizer.GetIndices(iaie); // Build name of replacement variable from index values StringBuilder sb = new StringBuilder("_item"); AppendIndexString(sb, iaie3); AppendIndexString(sb, iaie2); AppendIndexString(sb, iaie); string name = ToString(iaie3.Target) + sb.ToString(); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar); newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSize, Recognizer.GetVariableDeclaration(innerIndex), indices); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <IReadOnlyList <PlaceHolder> > >, IReadOnlyList <int>, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromDeepJagged), new Type[] { tp }, iaie3.Target, index.Target, index2.Target, index3.Target); context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems)); newExpr = Builder.ArrayIndex(Builder.VarRefExpr(newvd), innerIndex); rhsExpr = getItems; } } } } // does the expression have the form array[indices[k]][indices2[k]]? if (newvd == null && UseGetItems && iaie.Target is IArrayIndexerExpression && iaie.Indices.Count == 1 && iaie.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index2 = (IArrayIndexerExpression)iaie.Indices[0]; IArrayIndexerExpression target = (IArrayIndexerExpression)iaie.Target; if (index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression && target.Indices.Count == 1 && target.Indices[0] is IArrayIndexerExpression) { IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index2.Indices[0]; IArrayIndexerExpression index = (IArrayIndexerExpression)target.Indices[0]; IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); if (index.Indices.Count == 1 && index.Indices[0].Equals(innerIndex) && innerLoop != null && AreLoopsDisjoint(innerLoop, target.Target, index.Target)) { // expression has the form array[indices[k]][indices2[k]] if (isDef) { Error("fancy indexing not allowed on left hand side"); return(iaie); } var innerLoops = new List <IForStatement>(); innerLoops.Add(innerLoop); var indexTarget = index.Target; var index2Target = index2.Target; // check if the index array is jagged, i.e. array[indices[k][j]] while (indexTarget is IArrayIndexerExpression && index2Target is IArrayIndexerExpression) { IArrayIndexerExpression indexTargetExpr = (IArrayIndexerExpression)indexTarget; IArrayIndexerExpression index2TargetExpr = (IArrayIndexerExpression)index2Target; if (indexTargetExpr.Indices.Count == 1 && indexTargetExpr.Indices[0] is IVariableReferenceExpression && index2TargetExpr.Indices.Count == 1 && index2TargetExpr.Indices[0] is IVariableReferenceExpression) { IVariableReferenceExpression innerIndexTarget = (IVariableReferenceExpression)indexTargetExpr.Indices[0]; IVariableReferenceExpression innerIndex2Target = (IVariableReferenceExpression)index2TargetExpr.Indices[0]; IForStatement indexTargetLoop = Recognizer.GetLoopForVariable(context, innerIndexTarget); if (indexTargetLoop != null && AreLoopsDisjoint(indexTargetLoop, target.Target, indexTargetExpr.Target) && innerIndexTarget.Equals(innerIndex2Target)) { innerLoops.Add(indexTargetLoop); indexTarget = indexTargetExpr.Target; index2Target = index2TargetExpr.Target; } else { break; } } else { break; } } WarnIfLocal(indexTarget, target.Target, iaie); WarnIfLocal(index2Target, target.Target, iaie); innerLoops.Reverse(); var loopSizes = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopSizeExpression(ifs) }); var newIndexVars = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopVariable(ifs) }); // Build name of replacement variable from index values StringBuilder sb = new StringBuilder("_item"); AppendIndexString(sb, target); AppendIndexString(sb, iaie); string name = ToString(target.Target) + sb.ToString(); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar); var indices = Recognizer.GetIndices(iaie); newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSizes, newIndexVars, indices); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression getItems; if (innerLoops.Count == 1) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromJagged), new Type[] { tp }, target.Target, indexTarget, index2Target); } else if (innerLoops.Count == 2) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <IReadOnlyList <int> >, IReadOnlyList <IReadOnlyList <int> >, PlaceHolder[][]>(Collection.GetJaggedItemsFromJagged), new Type[] { tp }, target.Target, indexTarget, index2Target); } else { throw new NotImplementedException($"innerLoops.Count = {innerLoops.Count}"); } context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems)); var newIndices = newIndexVars.ListSelect(ivds => Util.ArrayInit(ivds.Length, i => Builder.VarRefExpr(ivds[i]))); newExpr = Builder.JaggedArrayIndex(Builder.VarRefExpr(newvd), newIndices); rhsExpr = getItems; } else if (HasAnyCommonLoops(index, index2)) { Warning($"This model will consume excess memory due to the indexing expression {iaie} since {index} and {index2} have larger depth than the compiler can handle."); } } } if (newvd == null) { IArrayIndexerExpression originalExpr = iaie; if (UseGetItems) { iaie = (IArrayIndexerExpression)base.ConvertArrayIndexer(iaie); } if (!object.ReferenceEquals(iaie.Target, originalExpr.Target) && false) { // TODO: determine if this warning is useful or not string warningText = "This model may consume excess memory due to the jagged indexing expression {0}"; Warning(string.Format(warningText, originalExpr)); } // get the baseVar of the new expression. baseVar = Recognizer.GetVariableDeclaration(iaie); VariableInformation varInfo = VariableInformation.GetVariableInformation(context, baseVar); var indices = Recognizer.GetIndices(iaie); // Build name of replacement variable from index values StringBuilder sb = new StringBuilder("_item"); AppendIndexString(sb, iaie); string name = ToString(iaie.Target) + sb.ToString(); // does the expression have the form array[indices[k]]? if (UseGetItems && iaie.Indices.Count == 1 && iaie.Indices[0] is IArrayIndexerExpression) { IArrayIndexerExpression index = (IArrayIndexerExpression)iaie.Indices[0]; if (index.Indices.Count == 1 && index.Indices[0] is IVariableReferenceExpression) { // expression has the form array[indices[k]] IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0]; IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); if (innerLoop != null && AreLoopsDisjoint(innerLoop, iaie.Target, index.Target)) { if (isDef) { Error("fancy indexing not allowed on left hand side"); return(iaie); } var innerLoops = new List <IForStatement>(); innerLoops.Add(innerLoop); var indexTarget = index.Target; // check if the index array is jagged, i.e. array[indices[k][j]] while (indexTarget is IArrayIndexerExpression) { IArrayIndexerExpression index2 = (IArrayIndexerExpression)indexTarget; if (index2.Indices.Count == 1 && index2.Indices[0] is IVariableReferenceExpression) { IVariableReferenceExpression innerIndex2 = (IVariableReferenceExpression)index2.Indices[0]; IForStatement innerLoop2 = Recognizer.GetLoopForVariable(context, innerIndex2); if (innerLoop2 != null && AreLoopsDisjoint(innerLoop2, iaie.Target, index2.Target)) { innerLoops.Add(innerLoop2); indexTarget = index2.Target; // This limit must match the number of handled cases below. if (innerLoops.Count == 3) { break; } } else { break; } } else { break; } } WarnIfLocal(indexTarget, iaie.Target, originalExpr); innerLoops.Reverse(); var loopSizes = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopSizeExpression(ifs) }); var newIndexVars = innerLoops.ListSelect(ifs => new[] { Recognizer.LoopVariable(ifs) }); newvd = varInfo.DeriveArrayVariable(stmts, context, name, loopSizes, newIndexVars, indices); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression getItems; if (innerLoops.Count == 1) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItems), new Type[] { tp }, iaie.Target, indexTarget); } else if (innerLoops.Count == 2) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <IReadOnlyList <int> >, PlaceHolder[][]>(Collection.GetJaggedItems), new Type[] { tp }, iaie.Target, indexTarget); } else if (innerLoops.Count == 3) { getItems = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <IReadOnlyList <IReadOnlyList <int> > >, PlaceHolder[][][]>(Collection.GetDeepJaggedItems), new Type[] { tp }, iaie.Target, indexTarget); } else { throw new NotImplementedException($"innerLoops.Count = {innerLoops.Count}"); } context.InputAttributes.CopyObjectAttributesTo <Algorithm>(baseVar, context.OutputAttributes, getItems); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), getItems)); var newIndices = newIndexVars.ListSelect(ivds => Util.ArrayInit(ivds.Length, i => Builder.VarRefExpr(ivds[i]))); newExpr = Builder.JaggedArrayIndex(Builder.VarRefExpr(newvd), newIndices); rhsExpr = getItems; } } } if (newvd == null) { if (UseGetItems && info.count < 2) { return(iaie); } try { newvd = varInfo.DeriveIndexedVariable(stmts, context, name, indices, copyInitializer: isDef); } catch (Exception ex) { Error(ex.Message, ex); return(iaie); } context.OutputAttributes.Remove <DerivedVariable>(newvd); newExpr = Builder.VarRefExpr(newvd); rhsExpr = iaie; if (isDef) { // change: // array[0] = f() // into: // array_item0 = f() // array[0] = Copy(array_item0) IExpression copy = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy), new Type[] { tp }, newExpr); IStatement copySt = Builder.AssignStmt(iaie, copy); stmtsAfter.Add(copySt); if (!context.InputAttributes.Has <DerivedVariable>(baseVar)) { context.InputAttributes.Set(baseVar, new DerivedVariable()); } } else if (!info.IsAssignedTo) { // change: // x = f(array[0]) // into: // array_item0 = Copy(array[0]) // x = f(array_item0) IExpression copy = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy), new Type[] { tp }, iaie); IStatement copySt = Builder.AssignStmt(Builder.VarRefExpr(newvd), copy); //if (attr != null) context.OutputAttributes.Set(copySt, attr); stmts.Add(copySt); context.InputAttributes.Set(newvd, new DerivedVariable()); } } } // Reduce memory consumption by declaring the clone outside of unnecessary loops. // This way, the item is cloned outside the loop and then replicated, instead of replicating the entire array and cloning the item. containers = Containers.RemoveUnusedLoops(containers, context, rhsExpr); if (context.InputAttributes.Has <DoNotSendEvidence>(originalBaseVar)) { containers = Containers.RemoveStochasticConditionals(containers, context); } if (true) { IStatement st = GetBindingSetContainer(FilterBindingSet(info.bindings, binding => Containers.ContainsExpression(containers.inputs, context, binding.GetExpression()))); if (st != null) { containers.Add(st); } } // To put the declaration in the desired containers, we find an ancestor which includes as many of the containers as possible, // then wrap the declaration with the remaining containers. int ancIndex = containers.GetMatchingAncestorIndex(context); Containers missing = containers.GetContainersNotInContext(context, ancIndex); stmts = Containers.WrapWithContainers(stmts, missing.outputs); context.AddStatementsBeforeAncestorIndex(ancIndex, stmts); stmtsAfter = Containers.WrapWithContainers(stmtsAfter, missing.outputs); context.AddStatementsAfterAncestorIndex(ancIndex, stmtsAfter); context.InputAttributes.Set(newvd, containers); info.clone = newExpr; return(newExpr); }
protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie) { IExpression result = base.ConvertMethodInvoke(imie); if (result is IMethodInvokeExpression) { imie = (IMethodInvokeExpression)result; } else { return(result); } if (UseJaggedSubarray && Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <int>, IReadOnlyList <PlaceHolder> >(Collection.Subarray))) { // check for the form Subarray(arrayExpr, indices[i]) where arrayExpr does not depend on i IExpression arrayExpr = imie.Arguments[0]; IExpression arg1 = imie.Arguments[1]; if (arg1 is IArrayIndexerExpression) { IArrayIndexerExpression index = (IArrayIndexerExpression)arg1; if (index.Indices.Count == 1 && index.Indices[0] is IVariableReferenceExpression) { // index has the form indices[i] List <IStatement> targetLoops = Containers.GetLoopsNeededForExpression(context, arrayExpr, -1, false); List <IStatement> indexLoops = Containers.GetLoopsNeededForExpression(context, index.Target, -1, false); Set <IStatement> parentLoops = new Set <IStatement>(); parentLoops.AddRange(targetLoops); parentLoops.AddRange(indexLoops); IVariableReferenceExpression innerIndex = (IVariableReferenceExpression)index.Indices[0]; IForStatement innerLoop = Recognizer.GetLoopForVariable(context, innerIndex); foreach (IStatement loop in parentLoops) { if (Containers.ContainersAreEqual(loop, innerLoop)) { // arrayExpr depends on i return(imie); } } IVariableDeclaration arrayVar = Recognizer.GetVariableDeclaration(arrayExpr); // If the variable is not stochastic, return if (arrayVar == null) { return(imie); } VariableInformation arrayInfo = VariableInformation.GetVariableInformation(context, arrayVar); if (!arrayInfo.IsStochastic) { return(imie); } object indexVar = Recognizer.GetDeclaration(index); VariableInformation indexInfo = VariableInformation.GetVariableInformation(context, indexVar); int depth = Recognizer.GetIndexingDepth(index); IExpression resultSize = indexInfo.sizes[depth][0]; var indices = Recognizer.GetIndices(index); int replaceCount = 0; resultSize = indexInfo.ReplaceIndexVars(context, resultSize, indices, null, ref replaceCount); indexInfo.DefineIndexVarsUpToDepth(context, depth + 1); IVariableDeclaration resultIndex = indexInfo.indexVars[depth][0]; Type arrayType = arrayExpr.GetExpressionType(); Type elementType = Util.GetElementType(arrayType); // create a new variable arrayExpr_indices = JaggedSubarray(arrayExpr, indices) string name = ToString(arrayExpr) + "_" + ToString(index.Target); var stmts = Builder.StmtCollection(); var arrayIndices = Recognizer.GetIndices(arrayExpr); var bracket = Builder.ExprCollection(); bracket.Add(Builder.ArrayIndex(index, Builder.VarRefExpr(resultIndex))); arrayIndices.Add(bracket); IExpression loopSize = Recognizer.LoopSizeExpression(innerLoop); IVariableDeclaration temp = arrayInfo.DeriveArrayVariable(stmts, context, name, resultSize, resultIndex, arrayIndices); VariableInformation tempInfo = VariableInformation.GetVariableInformation(context, temp); stmts.Clear(); IVariableDeclaration newvd = tempInfo.DeriveArrayVariable(stmts, context, name, loopSize, Recognizer.GetVariableDeclaration(innerIndex)); if (!context.InputAttributes.Has <DerivedVariable>(newvd)) { context.InputAttributes.Set(newvd, new DerivedVariable()); } IExpression rhs = Builder.StaticGenericMethod(new Func <IReadOnlyList <PlaceHolder>, int[][], PlaceHolder[][]>(Collection.JaggedSubarray), new Type[] { elementType }, arrayExpr, index.Target); context.InputAttributes.CopyObjectAttributesTo <Algorithm>(newvd, context.OutputAttributes, rhs); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(newvd), rhs)); // Reduce memory consumption by declaring the clone outside of unnecessary loops. // This way, the item is cloned outside the loop and then replicated, instead of replicating the entire array and cloning the item. Containers containers = new Containers(context); containers = RemoveReferencesTo(containers, innerIndex); containers = Containers.RemoveUnusedLoops(containers, context, rhs); if (context.InputAttributes.Has <DoNotSendEvidence>(arrayVar)) { containers = Containers.RemoveStochasticConditionals(containers, context); } // To put the declaration in the desired containers, we find an ancestor which includes as many of the containers as possible, // then wrap the declaration with the remaining containers. int ancIndex = containers.GetMatchingAncestorIndex(context); Containers missing = containers.GetContainersNotInContext(context, ancIndex); stmts = Containers.WrapWithContainers(stmts, missing.outputs); context.AddStatementsBeforeAncestorIndex(ancIndex, stmts); context.InputAttributes.Set(newvd, containers); // convert into arrayExpr_indices[i] IExpression newExpr = Builder.ArrayIndex(Builder.VarRefExpr(newvd), innerIndex); newExpr = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy <PlaceHolder>), new Type[] { newExpr.GetExpressionType() }, newExpr); return(newExpr); } } } return(imie); }