예제 #1
0
        /// <summary>
        /// Loop over all branches, trying to locate one that is equal to the given opcode
        /// If the branch is a branch itself, perform the locate recursively.
        /// </summary>
        /// <param name="opcode"></param>
        /// <returns></returns>
        internal override Opcode Locate(Opcode opcode)
        {
            Fx.Assert(!opcode.TestFlag(OpcodeFlags.Branch), "");

            for (int i = 0, count = this.branches.Count; i < count; ++i)
            {
                Opcode branch = this.branches[i];
                if (branch.TestFlag(OpcodeFlags.Branch))
                {
                    // The branch is itself a branch. Since branch opcodes serve as branches in the exection
                    // path for a query, but don't comprise one of the opcodes used to actually perform it, we
                    // recursively try to locate an equivalent opcode inside the branch
                    Opcode subBranch = branch.Locate(opcode);
                    if (null != subBranch)
                    {
                        return(subBranch);
                    }
                }
                else if (branch.Equals(opcode))
                {
                    return(branch);
                }
            }

            return(null);
        }
예제 #2
0
 void AddAlwaysBranch(QueryBranch literalBranch, Opcode next)
 {
     if (OpcodeID.Branch == next.ID)
     {
         BranchOpcode opcode   = (BranchOpcode)next;
         OpcodeList   branches = opcode.Branches;
         for (int i = 0; i < branches.Count; ++i)
         {
             Opcode branch = branches[i];
             if (this.IsAlwaysBranch(branch))
             {
                 this.AlwaysBranches.AddInOrder(new QueryBranch(branch, literalBranch.ID));
             }
             else
             {
                 branch.Flags |= OpcodeFlags.NoContextCopy;
             }
         }
     }
     else
     {
         Fx.Assert(!next.TestFlag(OpcodeFlags.Branch), "");
         if (this.IsAlwaysBranch(next))
         {
             this.AlwaysBranches.AddInOrder(new QueryBranch(next, literalBranch.ID));
         }
         else
         {
             next.Flags |= OpcodeFlags.NoContextCopy;
         }
     }
 }
        private void InvokeMultiMatch(ProcessingContext context)
        {
            int           counterMarker = context.Processor.CounterMarker;
            BranchContext context2      = new BranchContext(context);
            int           count         = this.resultTable.Count;
            int           num3          = 0;

            while (num3 < count)
            {
                ProcessingContext context3;
                QueryBranchResult result = this.resultTable[num3];
                QueryBranch       branch = result.Branch;
                Opcode            next   = branch.Branch.Next;
                if (next.TestFlag(OpcodeFlags.NoContextCopy))
                {
                    context3 = context;
                }
                else
                {
                    context3 = context2.Create();
                }
                this.InitResults(context3);
                context3.Values[context3.TopArg[result.ValIndex]].Boolean = true;
                while (++num3 < count)
                {
                    result = this.resultTable[num3];
                    if (branch.ID != result.Branch.ID)
                    {
                        break;
                    }
                    context3.Values[context3.TopArg[result.ValIndex]].Boolean = true;
                }
                try
                {
                    context3.EvalCodeBlock(next);
                }
                catch (XPathNavigatorException exception)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception.Process(next));
                }
                catch (NavigatorInvalidBodyAccessException exception2)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception2.Process(next));
                }
                context.Processor.CounterMarker = counterMarker;
            }
            context2.Release();
        }
 internal QueryBranch GetBranch(Opcode op)
 {
     if (op.TestFlag(OpcodeFlags.Literal))
     {
         LiteralRelationOpcode opcode = this.ValidateOpcode(op);
         if (opcode != null)
         {
             QueryBranch branch = this.branchIndex[opcode.Literal];
             if ((branch != null) && (branch.Branch.ID == op.ID))
             {
                 return(branch);
             }
         }
     }
     return(null);
 }
예제 #5
0
        internal QueryBranch GetBranch(Opcode op)
        {
            if (op.TestFlag(OpcodeFlags.Literal))
            {
                LiteralRelationOpcode relOp = this.ValidateOpcode(op);
                if (null != relOp)
                {
                    QueryBranch branch = this.branchIndex[relOp.Literal];
                    if (null != branch && branch.Branch.ID == op.ID)
                    {
                        return(branch);
                    }
                }
            }

            return(null);
        }
        private bool IsAlwaysBranch(Opcode next)
        {
            JumpIfOpcode opcode = next as JumpIfOpcode;

            if (opcode != null)
            {
                if (opcode.Test)
                {
                    Opcode opcode3;
                    Opcode jump = opcode.Jump;
                    if (jump == null)
                    {
                        return(false);
                    }
                    if (jump.TestFlag(OpcodeFlags.Branch))
                    {
                        OpcodeList branches = ((BranchOpcode)jump).Branches;
                        for (int i = 0; i < branches.Count; i++)
                        {
                            opcode3 = branches[i].Next;
                            if ((opcode3 != null) && !opcode3.TestFlag(OpcodeFlags.Result))
                            {
                                return(true);
                            }
                        }
                        return(false);
                    }
                    opcode3 = opcode.Jump.Next;
                    if ((opcode3 != null) && opcode3.TestFlag(OpcodeFlags.Result))
                    {
                        return(false);
                    }
                }
                return(true);
            }
            if (OpcodeID.BlockEnd == next.ID)
            {
                return(!next.Next.TestFlag(OpcodeFlags.Result));
            }
            return(!next.TestFlag(OpcodeFlags.Result));
        }
예제 #7
0
        internal override Opcode Locate(Opcode opcode)
        {
            int num   = 0;
            int count = this.branches.Count;

            while (num < count)
            {
                Opcode opcode2 = this.branches[num];
                if (opcode2.TestFlag(OpcodeFlags.Branch))
                {
                    Opcode opcode3 = opcode2.Locate(opcode);
                    if (opcode3 != null)
                    {
                        return(opcode3);
                    }
                }
                else if (opcode2.Equals(opcode))
                {
                    return(opcode2);
                }
                num++;
            }
            return(null);
        }
 private bool IsAlwaysBranch(Opcode next)
 {
     JumpIfOpcode opcode = next as JumpIfOpcode;
     if (opcode != null)
     {
         if (opcode.Test)
         {
             Opcode opcode3;
             Opcode jump = opcode.Jump;
             if (jump == null)
             {
                 return false;
             }
             if (jump.TestFlag(OpcodeFlags.Branch))
             {
                 OpcodeList branches = ((BranchOpcode) jump).Branches;
                 for (int i = 0; i < branches.Count; i++)
                 {
                     opcode3 = branches[i].Next;
                     if ((opcode3 != null) && !opcode3.TestFlag(OpcodeFlags.Result))
                     {
                         return true;
                     }
                 }
                 return false;
             }
             opcode3 = opcode.Jump.Next;
             if ((opcode3 != null) && opcode3.TestFlag(OpcodeFlags.Result))
             {
                 return false;
             }
         }
         return true;
     }
     if (OpcodeID.BlockEnd == next.ID)
     {
         return !next.Next.TestFlag(OpcodeFlags.Result);
     }
     return !next.TestFlag(OpcodeFlags.Result);
 }
 internal QueryBranch GetBranch(Opcode op)
 {
     if (op.TestFlag(OpcodeFlags.Literal))
     {
         LiteralRelationOpcode opcode = this.ValidateOpcode(op);
         if (opcode != null)
         {
             QueryBranch branch = this.branchIndex[opcode.Literal];
             if ((branch != null) && (branch.Branch.ID == op.ID))
             {
                 return branch;
             }
         }
     }
     return null;
 }
예제 #10
0
        bool IsAlwaysBranch(Opcode next)
        {
            Fx.Assert(null != next, "");

            // Opcodes subsequent to matching literals must obviously be branched to.
            // The question is whether we should branch to the opcodes following those literals that do *not* match.
            // Naturally, the answer depends on the sort of opcode that succeeds the literal.
            //
            // If the literal is within a boolean conjunction, the succeeding opcode will either be a JumpIfNot
            // Or a BlockEnd.
            //
            // -If the JumpIfNot is multiway, then always evaluate if it contains ANY non-result only opcodes.
            // -If JumpIfNot(False) -i.e. AND - only evaluate if the opcode succeeding the jump is NOT a result opcode.
            // -If JumpIfNot(True) - i.e. OR - always evaluate
            //
            // -If BlockEnd - evaluate only if not followed by a result
            //
            // When branching for matching literals, we push trues onto the ValueStack corresponding to the items that
            // matched. When branching for non-matching literals, we push ALL FALSE values... and then eval.

            // is it a the termination of a conditional?
            JumpIfOpcode jump = next as JumpIfOpcode;

            if (null != jump)
            {
                // Is the conditional JumpIfNot(False) = i.e. OR?
                if (!jump.Test)
                {
                    return(true);
                }

                // Does the conditional actually jump to anything? Should never be the case, but paranoia demands..
                Opcode jumpTo = jump.Jump;
                if (null == jumpTo)
                {
                    return(false);
                }

                // Lets see where the jump will take us
                Opcode postJump;
                if (jumpTo.TestFlag(OpcodeFlags.Branch))
                {
                    // Multiway jump
                    OpcodeList branches = ((BranchOpcode)jumpTo).Branches;
                    for (int i = 0; i < branches.Count; ++i)
                    {
                        postJump = branches[i].Next;
                        if (null != postJump && !postJump.TestFlag(OpcodeFlags.Result))
                        {
                            // There is at least one jump here that leads to a non-result.
                            // For now, this dooms everybody to being branched to, whether or not their respective literals
                            // matched
                            return(true);
                        }
                    }
                    return(false);
                }

                // single jump
                postJump = jump.Jump.Next;
                if (null != postJump && postJump.TestFlag(OpcodeFlags.Result))
                {
                    return(false);
                }

                return(true);
            }

            // If the next opcode is a BlockEnd, then only bother processing if what follows the block is not a result
            if (OpcodeID.BlockEnd == next.ID)
            {
                Fx.Assert(null != next.Next, "");
                return(!next.Next.TestFlag(OpcodeFlags.Result));
            }

            // The literal is not inside a boolean conjunction
            // If the literal is not followed by a result, then we must do further processing after the branch
            return(!next.TestFlag(OpcodeFlags.Result));
        }
예제 #11
0
        void InvokeMultiMatch(ProcessingContext context)
        {
            int           marker           = context.Processor.CounterMarker;
            BranchContext branchContext    = new BranchContext(context); // struct. quick.
            int           resultTableCount = this.resultTable.Count;

            for (int i = 0; i < resultTableCount;)
            {
                QueryBranchResult result = this.resultTable[i];
                QueryBranch       branch = result.Branch;
                // Branches can arbitrarily alter context stacks, rendering them unuseable to other branches.
                // Therefore, before following a branch, we have to clone the context. Cloning is relatively efficient because
                // can avoid allocating memory in most cases. We cannot, unfortunately, avoid Array copies.
                //
                // Optimization:
                // We can avoid cloning altogether when we can predict that the branch does NOT tamper with the stack,
                // or does so in a predictable way. If we are sure that we can restore the stack easily after the branch
                // completes, we have no reason to copy the stack.
                ProcessingContext newContext;
                Opcode            nextOpcode = branch.Branch.Next;
                if (nextOpcode.TestFlag(OpcodeFlags.NoContextCopy))
                {
                    newContext = context;
                }
                else
                {
                    newContext = branchContext.Create();
                }

                this.InitResults(newContext);

                //
                // Matches are sorted by their branch ID.
                // It is very possible that the a literal matches multiple times, especially when the value being
                // compared is a sequence. A literal may match multiple items in a single sequence
                // OR multiple items in multiple sequences. If there were 4 context sequences, the literal may have
                // matched one item each in 3 of them. The branchID for that literal will be present 3 times in the
                // resultTable.
                // Sorting the matches groups them by their branch Ids. We only want to take the branch ONCE, so now we
                // iterate over all the duplicate matches..
                // result.ValIndex will give us the index of the value that was matched. Thus if the 3rd sequence
                // matched, ValIndex == 2 (0 based)
                newContext.Values[newContext.TopArg[result.ValIndex]].Boolean = true;
                while (++i < resultTableCount)
                {
                    result = this.resultTable[i];
                    if (branch.ID == result.Branch.ID)
                    {
                        newContext.Values[newContext.TopArg[result.ValIndex]].Boolean = true;
                    }
                    else
                    {
                        break;
                    }
                }
                try
                {
                    newContext.EvalCodeBlock(nextOpcode);
                }
                catch (XPathNavigatorException e)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e.Process(nextOpcode));
                }
                catch (NavigatorInvalidBodyAccessException e)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e.Process(nextOpcode));
                }
                context.Processor.CounterMarker = marker;
            }
            branchContext.Release();
        }