Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        protected static IExpression GetCommonPrefix(IExpression expr, IExpression expr2)
        {
            List <IExpression> prefixes1 = Recognizer.GetAllPrefixes(expr);
            List <IExpression> prefixes2 = Recognizer.GetAllPrefixes(expr2);

            if (!prefixes1[0].Equals(prefixes2[0]))
            {
                throw new Exception($"Expressions have no overlap: {expr}, {expr2}");
            }
            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.Equals(prefix2))
                {
                    return(prefixes1[i - 1]);
                }
            }
            return(prefixes1[count - 1]);
        }
        /// <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 iaie1)
                {
                    if (prefix2 is IArrayIndexerExpression iaie2)
                    {
                        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);

            // Returns an expression equal to expr1 and expr2 under their respective bindings, or null if the expressions are not equal.
            IExpression Unify(
                IExpression expr1,
                IEnumerable <IReadOnlyCollection <ConditionBinding> > bindings1,
                IExpression expr2,
                IEnumerable <IReadOnlyCollection <ConditionBinding> > bindings2)
            {
                if (expr1.Equals(expr2))
                {
                    return(expr1);
                }
                foreach (IReadOnlyCollection <ConditionBinding> binding2 in bindings2)
                {
                    IExpression expr1b = ReplaceExpression(binding2, expr1);
                    if (expr1b.Equals(expr2))
                    {
                        return(expr1);
                    }
                }
                foreach (IReadOnlyCollection <ConditionBinding> binding1 in bindings1)
                {
                    IExpression expr2b = ReplaceExpression(binding1, expr2);
                    if (expr2b.Equals(expr1))
                    {
                        return(expr2);
                    }
                }
                bool lift = false;

                if (lift)
                {
                    IExpression lifted1 = GetLiftedExpression(expr1, bindings1);
                    IExpression lifted2 = GetLiftedExpression(expr2, bindings2);
                    if (lifted1 != null && lifted1.Equals(lifted2))
                    {
                        return(lifted1);
                    }
                }
                return(Builder.StaticMethod(new Func <int>(GateAnalysisTransform.AnyIndex)));

                IExpression GetLiftedExpression(IExpression expr, IEnumerable <IReadOnlyCollection <ConditionBinding> > bindings)
                {
                    IExpression lifted = null;

                    foreach (IReadOnlyCollection <ConditionBinding> binding in bindings)
                    {
                        IExpression lhs = null;
                        foreach (ConditionBinding b in binding)
                        {
                            if (b.rhs.Equals(expr))
                            {
                                lhs = b.lhs;
                            }
                        }
                        if (lifted == null)
                        {
                            lifted = lhs;
                        }
                        else if (lhs == null || !lifted.Equals(lhs))
                        {
                            return(null);
                        }
                    }
                    return(lifted);
                }
            }
        }