예제 #1
0
 /// <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 iaie)
     {
         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);
 }
예제 #2
0
 private List <ConditionBinding> FilterConditionContext(GateBlock gateBlock, List <ConditionBinding> conditionContext)
 {
     return(conditionContext
            .Where(binding => !CodeRecognizer.IsStochastic(context, binding.lhs) &&
                   !ContainsLocalVars(gateBlock, binding.lhs) &&
                   !ContainsLocalVars(gateBlock, binding.rhs))
            .ToList());
 }
예제 #3
0
 protected override IVariableDeclaration ConvertVariableDecl(IVariableDeclaration ivd)
 {
     context.InputAttributes.Remove <GateBlock>(ivd);
     if (gateBlockContext.Count > 0)
     {
         GateBlock currentBlock = gateBlockContext[gateBlockContext.Count - 1];
         context.InputAttributes.Set(ivd, currentBlock);
     }
     RegisterDeclaration(ivd);
     return(ivd);
 }
예제 #4
0
 private int GetAncestorIndexOfGateBlock(GateBlock gateBlock)
 {
     for (int i = 0; i < context.InputStack.Count; i++)
     {
         if (context.InputStack[i].inputElement is IStatement st &&
             context.InputAttributes.Get <GateBlock>(st) == gateBlock)
         {
             return(i);
         }
     }
     return(-1);
 }
예제 #5
0
 private void RemoveUsesOfDefs(GateBlock gateBlock)
 {
     foreach (KeyValuePair <IVariableDeclaration, ExpressionWithBindings> entry in gateBlock.variablesDefined)
     {
         IVariableDeclaration   ivd = entry.Key;
         ExpressionWithBindings eb  = entry.Value;
         if (gateBlock.variablesUsed.TryGetValue(ivd, out List <ExpressionWithBindings> ebs))
         {
             List <ExpressionWithBindings> keep = new List <ExpressionWithBindings>();
             foreach (ExpressionWithBindings eb2 in ebs)
             {
                 if (!CouldOverlap(eb, eb2))
                 {
                     keep.Add(eb2);
                 }
             }
             gateBlock.variablesUsed[ivd] = keep;
         }
     }
 }
예제 #6
0
 private bool ContainsLocalVars(GateBlock gateBlock, IExpression expr)
 {
     return(Recognizer.GetVariables(expr).Any(ivd =>
                                              (context.InputAttributes.Get <GateBlock>(ivd) == gateBlock)
                                              ));
 }
예제 #7
0
        protected override IStatement ConvertCondition(IConditionStatement ics)
        {
            context.SetPrimaryOutput(ics);
            ConvertExpression(ics.Condition);
            ConditionBinding binding   = GateTransform.GetConditionBinding(ics.Condition, context, out IForStatement loop);
            IExpression      caseValue = binding.rhs;

            if (!GateTransform.IsLiteralOrLoopVar(context, caseValue, out loop))
            {
                Error("If statement condition must compare to a literal or loop counter, was: " + ics.Condition);
                return(ics);
            }
            bool        isStochastic = CodeRecognizer.IsStochastic(context, binding.lhs);
            IExpression gateBlockKey;

            if (isStochastic)
            {
                gateBlockKey = binding.lhs;
            }
            else
            {
                // definitions must not be unified across deterministic gate conditions
                gateBlockKey = binding.GetExpression();
            }
            GateBlock gateBlock             = null;
            Set <ConditionBinding> bindings = ConditionBinding.Copy(conditionContext);
            Dictionary <IExpression, GateBlock> blockMap;

            if (!gateBlocks.TryGetValue(bindings, out blockMap))
            {
                // first time seeing these bindings
                blockMap             = new Dictionary <IExpression, GateBlock>();
                gateBlocks[bindings] = blockMap;
            }
            if (!blockMap.TryGetValue(gateBlockKey, out gateBlock))
            {
                // first time seeing this lhs
                gateBlock = new GateBlock();
                blockMap[gateBlockKey] = gateBlock;
            }
            if (gateBlock.hasLoopCaseValue && loop == null)
            {
                Error("Cannot compare " + binding.lhs + " to a literal, since it was previously compared to a loop counter.  Put this test inside the loop.");
            }
            if (!gateBlock.hasLoopCaseValue && gateBlock.caseValues.Count > 0 && loop != null)
            {
                Error("Cannot compare " + binding.lhs + " to a loop counter, since it was previously compared to a literal.  Put the literal case inside the loop.");
            }
            gateBlock.caseValues.Add(caseValue);
            if (loop != null)
            {
                gateBlock.hasLoopCaseValue = true;
            }
            gateBlockContext.Add(gateBlock);
            context.OutputAttributes.Set(ics, gateBlock);
            int startIndex = conditionContext.Count;

            conditionContext.Add(binding);
            ConvertBlock(ics.Then);
            if (ics.Else != null)
            {
                conditionContext.RemoveRange(startIndex, conditionContext.Count - startIndex);
                binding = binding.FlipCondition();
                conditionContext.Add(binding);
                ConvertBlock(ics.Else);
            }
            conditionContext.RemoveRange(startIndex, conditionContext.Count - startIndex);
            gateBlockContext.RemoveAt(gateBlockContext.Count - 1);
            // remove any uses that match a def
            //RemoveUsesOfDefs(gateBlock);
            if (gateBlockContext.Count > 0)
            {
                GateBlock currentBlock = gateBlockContext[gateBlockContext.Count - 1];
                // all variables defined/used in the inner block must be processed by the outer block
                foreach (ExpressionWithBindings eb in gateBlock.variablesDefined.Values)
                {
                    if (eb.Bindings.Count > 0)
                    {
                        foreach (List <ConditionBinding> binding2 in eb.Bindings)
                        {
                            ProcessUse(eb.Expression, true, Union(conditionContext, binding2));
                        }
                    }
                    else
                    {
                        ProcessUse(eb.Expression, true, conditionContext);
                    }
                }
                foreach (List <ExpressionWithBindings> ebs in gateBlock.variablesUsed.Values)
                {
                    foreach (ExpressionWithBindings eb in ebs)
                    {
                        if (eb.Bindings.Count > 0)
                        {
                            foreach (ICollection <ConditionBinding> binding2 in eb.Bindings)
                            {
                                ProcessUse(eb.Expression, false, Union(conditionContext, binding2));
                            }
                        }
                        else
                        {
                            ProcessUse(eb.Expression, false, conditionContext);
                        }
                    }
                }
            }
            return(ics);
        }
예제 #8
0
        /// <summary>
        /// Add expr to currentBlock.variablesDefined or currentBlock.variablesUsed
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="isDef"></param>
        /// <param name="conditionContext"></param>
        protected void ProcessUse(IExpression expr, bool isDef, List <ConditionBinding> conditionContext)
        {
            IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(expr);

            if (ivd == null)
            {
                return;
            }
            if (!CodeRecognizer.IsStochastic(context, ivd))
            {
                return;
            }
            if (gateBlockContext.Count == 0)
            {
                return;
            }
            GateBlock currentBlock   = gateBlockContext[gateBlockContext.Count - 1];
            GateBlock gateBlockOfVar = context.InputAttributes.Get <GateBlock>(ivd);

            if (gateBlockOfVar == currentBlock)
            {
                return;                                 // local variable of the gateBlock
            }
            ExpressionWithBindings eb = new ExpressionWithBindings();

            eb.Expression = ReplaceLocalIndices(currentBlock, expr);
            List <ConditionBinding> bindings = FilterConditionContext(currentBlock, conditionContext);

            if (bindings.Count > 0)
            {
                eb.Bindings.Add(bindings);
            }
            //eb.Containers = Containers.InsideOf(context, GetAncestorIndexOfGateBlock(currentBlock));
            if (isDef)
            {
                ExpressionWithBindings eb2;
                if (!currentBlock.variablesDefined.TryGetValue(ivd, out eb2))
                {
                    currentBlock.variablesDefined[ivd] = eb;
                }
                else
                {
                    // all definitions of the same variable must have a common parent
                    currentBlock.variablesDefined[ivd] = GetCommonParent(eb, eb2);
                }
            }
            else
            {
                List <ExpressionWithBindings> ebs;
                if (!currentBlock.variablesUsed.TryGetValue(ivd, out ebs))
                {
                    ebs = new List <ExpressionWithBindings>();
                    ebs.Add(eb);
                    currentBlock.variablesUsed[ivd] = ebs;
                }
                else
                {
                    // collect all uses that overlap with eb, and replace with their common parent
                    List <ExpressionWithBindings> notOverlapping = new List <ExpressionWithBindings>();
                    while (true)
                    {
                        foreach (ExpressionWithBindings eb2 in ebs)
                        {
                            ExpressionWithBindings parent = GetCommonParent(eb, eb2);
                            if (CouldOverlap(eb, eb2))
                            {
                                eb = parent;
                            }
                            else
                            {
                                notOverlapping.Add(eb2);
                            }
                        }
                        if (notOverlapping.Count == ebs.Count)
                        {
                            break;                                    // nothing overlaps
                        }
                        // eb must have changed, so try again using the new eb
                        ebs.Clear();
                        ebs.AddRange(notOverlapping);
                        notOverlapping.Clear();
                    }
                    ebs.Add(eb);
                    currentBlock.variablesUsed[ivd] = ebs;
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Add expr to currentBlock.variablesDefined or currentBlock.variablesUsed
        /// </summary>
        /// <param name="expr"></param>
        /// <param name="isDef"></param>
        /// <param name="conditionContext"></param>
        protected void ProcessUse(IExpression expr, bool isDef, List <ConditionBinding> conditionContext)
        {
            IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(expr);

            if (ivd == null)
            {
                return;
            }
            if (!CodeRecognizer.IsStochastic(context, ivd))
            {
                return;
            }
            if (gateBlockContext.Count == 0)
            {
                return;
            }
            GateBlock currentBlock   = gateBlockContext[gateBlockContext.Count - 1];
            GateBlock gateBlockOfVar = context.InputAttributes.Get <GateBlock>(ivd);

            if (gateBlockOfVar == currentBlock)
            {
                return;                                 // local variable of the gateBlock
            }
            ExpressionWithBindings eb = new ExpressionWithBindings(ReplaceLocalIndices(currentBlock, expr), FilterConditionContext(currentBlock));

            if (isDef)
            {
                if (currentBlock.variablesDefined.TryGetValue(ivd, out ExpressionWithBindings eb2))
                {
                    // all definitions of the same variable must have a common parent
                    currentBlock.variablesDefined[ivd] = GetCommonParent(eb, eb2);
                }
                else
                {
                    currentBlock.variablesDefined[ivd] = eb;
                }
            }
            else
            {
                if (currentBlock.variablesUsed.TryGetValue(ivd, out List <ExpressionWithBindings> ebs))
                {
                    // collect all uses that overlap with eb, and replace with their common parent
                    List <ExpressionWithBindings> notOverlapping = new List <ExpressionWithBindings>();
                    while (true)
                    {
                        foreach (ExpressionWithBindings eb2 in ebs)
                        {
                            if (CouldOverlap(eb, eb2, ignoreBindings: GateTransform.DeterministicEnterExit))
                            {
                                eb = GetCommonParent(eb, eb2);
                            }
                            else
                            {
                                notOverlapping.Add(eb2);
                            }
                        }
                        if (notOverlapping.Count == ebs.Count)
                        {
                            break;                                    // nothing overlaps
                        }
                        // eb must have changed, so try again using the new eb
                        ebs.Clear();
                        ebs.AddRange(notOverlapping);
                        notOverlapping.Clear();
                    }
                    ebs.Add(eb);
                    currentBlock.variablesUsed[ivd] = ebs;
                }
                else
                {
                    currentBlock.variablesUsed[ivd] = new List <ExpressionWithBindings> {
                        eb
                    };
                }
            }

            List <ConditionBinding> FilterConditionContext(GateBlock gateBlock)
            {
                return(conditionContext
                       .Where(binding => !CodeRecognizer.IsStochastic(context, binding.lhs) &&
                              !ContainsLocalVars(gateBlock, binding.lhs) &&
                              !ContainsLocalVars(gateBlock, binding.rhs))
                       .ToList());
            }
        }