Пример #1
0
 private void CompileBoolean(XPathExpr expr, bool testValue)
 {
     if (this.compiler.nestingLevel == 1)
     {
         this.CompileBasicBoolean(expr, testValue);
     }
     else
     {
         OpcodeBlock block = new OpcodeBlock();
         Opcode      jump  = new BlockEndOpcode();
         block.Append(new PushBooleanOpcode(testValue));
         XPathExprList subExpr = expr.SubExpr;
         XPathExpr     expr2   = subExpr[0];
         block.Append(this.CompileBlock(expr2));
         if (expr2.ReturnType != ValueDataType.Boolean)
         {
             block.Append(new TypecastOpcode(ValueDataType.Boolean));
         }
         block.Append(new ApplyBooleanOpcode(jump, testValue));
         for (int i = 1; i < subExpr.Count; i++)
         {
             expr2 = subExpr[i];
             block.Append(new StartBooleanOpcode(testValue));
             block.Append(this.CompileBlock(expr2));
             if (expr2.ReturnType != ValueDataType.Boolean)
             {
                 block.Append(new TypecastOpcode(ValueDataType.Boolean));
             }
             block.Append(new EndBooleanOpcode(jump, testValue));
         }
         block.Append(jump);
         this.codeBlock.Append(block);
     }
 }
Пример #2
0
        internal static OpcodeBlock CompileForInternalEngine(string xpath, XmlNamespaceManager nsManager, QueryCompilerFlags flags, IFunctionLibrary[] functionLibs, out ValueDataType returnType)
        {
            OpcodeBlock codeBlock;

            returnType = ValueDataType.None;
            if (0 == xpath.Length)
            {
                // 0 length XPaths always match
                codeBlock = new OpcodeBlock();
                codeBlock.Append(new PushBooleanOpcode(true)); // Always match by pushing true on the eval stack
            }
            else
            {
                // Try to parse the xpath. Bind to default function libraries
                // The parser returns an expression tree
                XPathParser parser    = new XPathParser(xpath, nsManager, functionLibs);
                XPathExpr   parseTree = parser.Parse();

                if (null == parseTree)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.CouldNotParseExpression));
                }

                returnType = parseTree.ReturnType;

                // Compile the expression tree
                XPathCompiler compiler = new XPathCompiler(flags);

                codeBlock = compiler.Compile(parseTree);
            }

            return(codeBlock);
        }
Пример #3
0
            // Compiles expressions at nesting level == 1 -> boolean expressions that can be processed
            // with less complex opcodes because they will never track multiple sequences simultaneously
            void CompileBasicBoolean(XPathExpr expr, bool testValue)
            {
                // Boolean expressions must always have at least 2 sub expressions
                Fx.Assert(expr.SubExprCount > 1, "");
                Fx.Assert(this.compiler.nestingLevel == 1, "");

                OpcodeBlock   boolBlock   = new OpcodeBlock(); // struct
                Opcode        blockEnd    = new BlockEndOpcode();
                XPathExprList subExprList = expr.SubExpr;

                // Compile sub-expressions
                for (int i = 0; i < subExprList.Count; ++i)
                {
                    XPathExpr subExpr = subExprList[i];
                    boolBlock.Append(this.CompileBlock(subExpr));
                    // Make sure each sub-expression can produce a boolean result
                    if (subExpr.ReturnType != ValueDataType.Boolean)
                    {
                        boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                    }
                    if (i < (subExprList.Count - 1))
                    {
                        // No point jumping if this is the last expression
                        boolBlock.Append(new JumpIfOpcode(blockEnd, testValue));
                    }
                }
                boolBlock.Append(blockEnd);
                this.codeBlock.Append(boolBlock);
            }
 static XPathQueryMatcher()
 {
     ValueDataType type;
     matchAlwaysFilter = new PushBooleanOpcode(true);
     rootFilter = QueryMatcher.CompileForInternalEngine("/", null, QueryCompilerFlags.None, out type);
     rootFilter.Append(new MatchResultOpcode());
 }
 internal void CompileForInternal(string xpath, XmlNamespaceManager names)
 {
     base.query = null;
     xpath      = xpath.Trim();
     if (xpath.Length == 0)
     {
         base.query  = matchAlwaysFilter;
         this.flags |= XPathFilterFlags.AlwaysMatch;
     }
     else if ((1 == xpath.Length) && ('/' == xpath[0]))
     {
         base.query  = rootFilter.First;
         this.flags |= XPathFilterFlags.AlwaysMatch;
     }
     else
     {
         ValueDataType type;
         OpcodeBlock   block = QueryMatcher.CompileForInternalEngine(xpath, names, QueryCompilerFlags.None, out type);
         if (this.match)
         {
             block.Append(new MatchResultOpcode());
         }
         else
         {
             block.Append(new QueryResultOpcode());
         }
         base.query = block.First;
     }
     this.flags &= ~XPathFilterFlags.IsFxFilter;
 }
 private void CompileBoolean(XPathExpr expr, bool testValue)
 {
     if (this.compiler.nestingLevel == 1)
     {
         this.CompileBasicBoolean(expr, testValue);
     }
     else
     {
         OpcodeBlock block = new OpcodeBlock();
         Opcode jump = new BlockEndOpcode();
         block.Append(new PushBooleanOpcode(testValue));
         XPathExprList subExpr = expr.SubExpr;
         XPathExpr expr2 = subExpr[0];
         block.Append(this.CompileBlock(expr2));
         if (expr2.ReturnType != ValueDataType.Boolean)
         {
             block.Append(new TypecastOpcode(ValueDataType.Boolean));
         }
         block.Append(new ApplyBooleanOpcode(jump, testValue));
         for (int i = 1; i < subExpr.Count; i++)
         {
             expr2 = subExpr[i];
             block.Append(new StartBooleanOpcode(testValue));
             block.Append(this.CompileBlock(expr2));
             if (expr2.ReturnType != ValueDataType.Boolean)
             {
                 block.Append(new TypecastOpcode(ValueDataType.Boolean));
             }
             block.Append(new EndBooleanOpcode(jump, testValue));
         }
         block.Append(jump);
         this.codeBlock.Append(block);
     }
 }
        static XPathQueryMatcher()
        {
            ValueDataType type;

            matchAlwaysFilter = new PushBooleanOpcode(true);
            rootFilter        = QueryMatcher.CompileForInternalEngine("/", null, QueryCompilerFlags.None, out type);
            rootFilter.Append(new MatchResultOpcode());
        }
Пример #8
0
        internal void Add(string expression, XmlNamespaceManager names, object item, bool forceExternal)
        {
            Fx.Assert(null != item, "");

            // Compile the new filter

            bool        compiled  = false;
            OpcodeBlock codeBlock = new OpcodeBlock();

            codeBlock.Append(new NoOpOpcode(OpcodeID.QueryTree));
            if (!forceExternal)
            {
                try
                {
                    ValueDataType returnType = ValueDataType.None;

                    // Try to compile and merge the compiled query into the query tree
                    codeBlock.Append(QueryMatcher.CompileForInternalEngine(expression, names, QueryCompilerFlags.InverseQuery, out returnType));

                    MultipleResultOpcode opcode;

                    if (!this.match)
                    {
                        opcode = new QueryMultipleResultOpcode();
                    }
                    else
                    {
                        opcode = new MatchMultipleResultOpcode();
                    }

                    opcode.AddItem(item);
                    codeBlock.Append(opcode);
                    compiled = true;

                    // Perform SubExpression Elimination
                    codeBlock        = new OpcodeBlock(this.elim.Add(item, codeBlock.First));
                    this.subExprVars = this.elim.VariableCount;
                }
                catch (QueryCompileException)
                {
                    // If the filter couldn't be compiled, we drop down to the framework engine
                }
            }

            if (!compiled)
            {
                codeBlock.Append(QueryMatcher.CompileForExternalEngine(expression, names, item, this.match));
            }

            // Merge the compiled query into the query tree
            QueryTreeBuilder builder = new QueryTreeBuilder();

            this.query = builder.Build(this.query, codeBlock);
            // To de-merge this filter from the tree, we'll have to walk backwards up the tree... so we
            // have to remember the last opcode that is executed on behalf of this filter
            this.lastLookup[item] = builder.LastOpcode;
        }
Пример #9
0
        /// <summary>
        /// Compile the given filter to run on an external (fx) xpath engine
        /// </summary>
        internal static OpcodeBlock CompileForExternalEngine(string expression, XmlNamespaceManager namespaces, object item, bool match)
        {
            // Compile...
            XPathExpression xpathExpr = QueryMatcher.fxCompiler.Compile(expression);

            // Fx will bind prefixes and functions here.
            if (namespaces != null)
            {
                // There's a bug in System.Xml.XPath.  If we pass an XsltContext to SetContext it won't throw if there's
                // an undefined prefix.
                if (namespaces is XsltContext)
                {
                    // Lex the xpath to find all prefixes used
                    XPathLexer lexer = new XPathLexer(expression, false);
                    while (lexer.MoveNext())
                    {
                        string prefix = lexer.Token.Prefix;

                        if (prefix.Length > 0 && namespaces.LookupNamespace(prefix) == null)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XsltException(SR.GetString(SR.FilterUndefinedPrefix, prefix)));
                        }
                    }
                }

                xpathExpr.SetContext(namespaces);
            }

            //
            // FORCE the function to COMPILE - they won't bind namespaces unless we check the return type
            //
            if (XPathResultType.Error == xpathExpr.ReturnType)
            {
                // This should never be reached.  The above property should throw if there's an error
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XPathException(SR.GetString(SR.FilterCouldNotCompile, expression)));
            }

            OpcodeBlock codeBlock = new OpcodeBlock();
            SingleFxEngineResultOpcode op;

            if (!match)
            {
                op = new QuerySingleFxEngineResultOpcode();
            }
            else
            {
                op = new MatchSingleFxEngineResultOpcode();
            }

            op.XPath = xpathExpr;
            op.Item  = item;

            codeBlock.Append(op);
            return(codeBlock);
        }
 internal void Append(OpcodeBlock block)
 {
     if (this.last == null)
     {
         this.first = block.first;
         this.last  = block.last;
     }
     else
     {
         this.last.Attach(block.first);
         this.last = block.last;
     }
 }
 internal virtual OpcodeBlock Compile(XPathExpr expr)
 {
     this.nestingLevel = 1;
     this.pushInitialContext = false;
     OpcodeBlock block = new XPathExprCompiler(this).Compile(expr);
     if (this.pushInitialContext)
     {
         OpcodeBlock block2 = new OpcodeBlock();
         block2.Append(new PushContextNodeOpcode());
         block2.Append(block);
         block2.Append(new PopContextNodes());
         return block2;
     }
     return block;
 }
Пример #12
0
        internal virtual OpcodeBlock Compile(XPathExpr expr)
        {
            this.nestingLevel       = 1;
            this.pushInitialContext = false;
            OpcodeBlock block = new XPathExprCompiler(this).Compile(expr);

            if (this.pushInitialContext)
            {
                OpcodeBlock block2 = new OpcodeBlock();
                block2.Append(new PushContextNodeOpcode());
                block2.Append(block);
                block2.Append(new PopContextNodes());
                return(block2);
            }
            return(block);
        }
 internal Opcode Build(Opcode tree, OpcodeBlock newBlock)
 {
     if (tree == null)
     {
         this.lastOpcode = newBlock.Last;
         return newBlock.First;
     }
     this.diverger = new Diverger(tree, newBlock.First);
     if (!this.diverger.Find())
     {
         this.lastOpcode = this.diverger.TreePath[this.diverger.TreePath.Count - 1];
         return tree;
     }
     if (this.diverger.TreeOpcode == null)
     {
         this.diverger.TreePath[this.diverger.TreePath.Count - 1].Attach(this.diverger.InsertOpcode);
     }
     else
     {
         this.diverger.TreeOpcode.Add(this.diverger.InsertOpcode);
     }
     this.lastOpcode = newBlock.Last;
     if (this.diverger.InsertOpcode.IsMultipleResult())
     {
         if (OpcodeID.Branch == this.diverger.TreeOpcode.ID)
         {
             OpcodeList branches = ((BranchOpcode) this.diverger.TreeOpcode).Branches;
             int num = 0;
             int count = branches.Count;
             while (num < count)
             {
                 if (branches[num].IsMultipleResult())
                 {
                     this.lastOpcode = branches[num];
                     break;
                 }
                 num++;
             }
         }
         else if (this.diverger.TreeOpcode.IsMultipleResult())
         {
             this.lastOpcode = this.diverger.TreeOpcode;
         }
     }
     this.FixupJumps();
     return tree;
 }
Пример #14
0
 internal Opcode Build(Opcode tree, OpcodeBlock newBlock)
 {
     if (tree == null)
     {
         this.lastOpcode = newBlock.Last;
         return(newBlock.First);
     }
     this.diverger = new Diverger(tree, newBlock.First);
     if (!this.diverger.Find())
     {
         this.lastOpcode = this.diverger.TreePath[this.diverger.TreePath.Count - 1];
         return(tree);
     }
     if (this.diverger.TreeOpcode == null)
     {
         this.diverger.TreePath[this.diverger.TreePath.Count - 1].Attach(this.diverger.InsertOpcode);
     }
     else
     {
         this.diverger.TreeOpcode.Add(this.diverger.InsertOpcode);
     }
     this.lastOpcode = newBlock.Last;
     if (this.diverger.InsertOpcode.IsMultipleResult())
     {
         if (OpcodeID.Branch == this.diverger.TreeOpcode.ID)
         {
             OpcodeList branches = ((BranchOpcode)this.diverger.TreeOpcode).Branches;
             int        num      = 0;
             int        count    = branches.Count;
             while (num < count)
             {
                 if (branches[num].IsMultipleResult())
                 {
                     this.lastOpcode = branches[num];
                     break;
                 }
                 num++;
             }
         }
         else if (this.diverger.TreeOpcode.IsMultipleResult())
         {
             this.lastOpcode = this.diverger.TreeOpcode;
         }
     }
     this.FixupJumps();
     return(tree);
 }
Пример #15
0
            void CompileBoolean(XPathExpr expr, bool testValue)
            {
                // Boolean expressions must always have at least 2 sub expressions
                Fx.Assert(expr.SubExprCount > 1, "");

                if (this.compiler.nestingLevel == 1)
                {
                    this.CompileBasicBoolean(expr, testValue);
                    return;
                }

                OpcodeBlock boolBlock = new OpcodeBlock(); // struct
                Opcode      blockEnd  = new BlockEndOpcode();

                // Set up the result mask
                boolBlock.Append(new PushBooleanOpcode(testValue));
                XPathExprList subExprList = expr.SubExpr;
                XPathExpr     subExpr;

                // the first expression needs the least work..
                subExpr = subExprList[0];
                boolBlock.Append(this.CompileBlock(subExpr));
                if (subExpr.ReturnType != ValueDataType.Boolean)
                {
                    boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                }
                boolBlock.Append(new ApplyBooleanOpcode(blockEnd, testValue));

                // Compile remaining sub-expressions
                for (int i = 1; i < subExprList.Count; ++i)
                {
                    subExpr = subExprList[i];
                    boolBlock.Append(new StartBooleanOpcode(testValue));
                    boolBlock.Append(this.CompileBlock(subExpr));
                    // Make sure each sub-expression can produce a boolean result
                    if (subExpr.ReturnType != ValueDataType.Boolean)
                    {
                        boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                    }
                    boolBlock.Append(new EndBooleanOpcode(blockEnd, testValue));
                }
                boolBlock.Append(blockEnd);
                this.codeBlock.Append(boolBlock);
            }
Пример #16
0
        // Compiles top level expressions
        internal virtual OpcodeBlock Compile(XPathExpr expr)
        {
            Fx.Assert(null != expr, "");

            this.nestingLevel = 1;
            this.pushInitialContext = false;

            XPathExprCompiler exprCompiler = new XPathExprCompiler(this);
            OpcodeBlock mainBlock = exprCompiler.Compile(expr);
            if (this.pushInitialContext)
            {
                OpcodeBlock expandedBlock = new OpcodeBlock();
                expandedBlock.Append(new PushContextNodeOpcode());
                expandedBlock.Append(mainBlock);
                expandedBlock.Append(new PopContextNodes());
                return expandedBlock;
            }
            return mainBlock;
        }
Пример #17
0
        // Compiles top level expressions
        internal virtual OpcodeBlock Compile(XPathExpr expr)
        {
            Fx.Assert(null != expr, "");

            this.nestingLevel       = 1;
            this.pushInitialContext = false;

            XPathExprCompiler exprCompiler = new XPathExprCompiler(this);
            OpcodeBlock       mainBlock    = exprCompiler.Compile(expr);

            if (this.pushInitialContext)
            {
                OpcodeBlock expandedBlock = new OpcodeBlock();
                expandedBlock.Append(new PushContextNodeOpcode());
                expandedBlock.Append(mainBlock);
                expandedBlock.Append(new PopContextNodes());
                return(expandedBlock);
            }
            return(mainBlock);
        }
        internal static OpcodeBlock CompileForInternalEngine(string xpath, XmlNamespaceManager nsManager, QueryCompilerFlags flags, IFunctionLibrary[] functionLibs, out ValueDataType returnType)
        {
            returnType = ValueDataType.None;
            if (xpath.Length == 0)
            {
                OpcodeBlock block = new OpcodeBlock();
                block.Append(new PushBooleanOpcode(true));
                return(block);
            }
            XPathExpr expr = new XPathParser(xpath, nsManager, functionLibs).Parse();

            if (expr == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryCompileException(QueryCompileError.CouldNotParseExpression));
            }
            returnType = expr.ReturnType;
            XPathCompiler compiler = new XPathCompiler(flags);

            return(compiler.Compile(expr));
        }
        internal static OpcodeBlock CompileForExternalEngine(string expression, XmlNamespaceManager namespaces, object item, bool match)
        {
            SingleFxEngineResultOpcode opcode;
            XPathExpression            expression2 = fxCompiler.Compile(expression);

            if (namespaces != null)
            {
                if (namespaces is XsltContext)
                {
                    XPathLexer lexer = new XPathLexer(expression, false);
                    while (lexer.MoveNext())
                    {
                        string prefix = lexer.Token.Prefix;
                        if ((prefix.Length > 0) && (namespaces.LookupNamespace(prefix) == null))
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XsltException(System.ServiceModel.SR.GetString("FilterUndefinedPrefix", new object[] { prefix })));
                        }
                    }
                }
                expression2.SetContext(namespaces);
            }
            if (XPathResultType.Error == expression2.ReturnType)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XPathException(System.ServiceModel.SR.GetString("FilterCouldNotCompile", new object[] { expression })));
            }
            OpcodeBlock block = new OpcodeBlock();

            if (!match)
            {
                opcode = new QuerySingleFxEngineResultOpcode();
            }
            else
            {
                opcode = new MatchSingleFxEngineResultOpcode();
            }
            opcode.XPath = expression2;
            opcode.Item  = item;
            block.Append(opcode);
            return(block);
        }
        internal void Add(string expression, XmlNamespaceManager names, object item, bool forceExternal)
        {
            bool        flag     = false;
            OpcodeBlock newBlock = new OpcodeBlock();

            newBlock.Append(new NoOpOpcode(OpcodeID.QueryTree));
            if (!forceExternal)
            {
                try
                {
                    MultipleResultOpcode opcode;
                    ValueDataType        none = ValueDataType.None;
                    newBlock.Append(QueryMatcher.CompileForInternalEngine(expression, names, QueryCompilerFlags.InverseQuery, out none));
                    if (!this.match)
                    {
                        opcode = new QueryMultipleResultOpcode();
                    }
                    else
                    {
                        opcode = new MatchMultipleResultOpcode();
                    }
                    opcode.AddItem(item);
                    newBlock.Append(opcode);
                    flag             = true;
                    newBlock         = new OpcodeBlock(this.elim.Add(item, newBlock.First));
                    base.subExprVars = this.elim.VariableCount;
                }
                catch (QueryCompileException)
                {
                }
            }
            if (!flag)
            {
                newBlock.Append(QueryMatcher.CompileForExternalEngine(expression, names, item, this.match));
            }
            QueryTreeBuilder builder = new QueryTreeBuilder();

            base.query            = builder.Build(base.query, newBlock);
            this.lastLookup[item] = builder.LastOpcode;
        }
Пример #21
0
            private void CompileBasicBoolean(XPathExpr expr, bool testValue)
            {
                OpcodeBlock   block   = new OpcodeBlock();
                Opcode        jump    = new BlockEndOpcode();
                XPathExprList subExpr = expr.SubExpr;

                for (int i = 0; i < subExpr.Count; i++)
                {
                    XPathExpr expr2 = subExpr[i];
                    block.Append(this.CompileBlock(expr2));
                    if (expr2.ReturnType != ValueDataType.Boolean)
                    {
                        block.Append(new TypecastOpcode(ValueDataType.Boolean));
                    }
                    if (i < (subExpr.Count - 1))
                    {
                        block.Append(new JumpIfOpcode(jump, testValue));
                    }
                }
                block.Append(jump);
                this.codeBlock.Append(block);
            }
Пример #22
0
        /// <summary>
        /// Compile for the internal engine with default flags
        /// By defalt, we compile an xpath to run stand alone, with standard optimizations
        /// </summary>
        internal void CompileForInternal(string xpath, XmlNamespaceManager names)
        {
            this.query = null;
            xpath      = xpath.Trim();

            if (0 == xpath.Length)
            {
                // Empty xpaths always match. Same for xpaths that refer to the root only
                // We will evaluate such filters with minimal overhead. However, we
                // don't want a null value for this.query, so we stick a dummy value in there
                this.query  = XPathQueryMatcher.matchAlwaysFilter;
                this.flags |= (XPathFilterFlags.AlwaysMatch);
            }
            else if (1 == xpath.Length && '/' == xpath[0])
            {
                this.query  = XPathQueryMatcher.rootFilter.First;
                this.flags |= (XPathFilterFlags.AlwaysMatch);
            }
            else
            {
                ValueDataType returnType;
                OpcodeBlock   codeBlock = QueryMatcher.CompileForInternalEngine(xpath, names, QueryCompilerFlags.None, out returnType);
                // Inject a final opcode that will place the query result on the query context
                // This query is now ready for execution STAND ALONE
                if (this.match)
                {
                    codeBlock.Append(new MatchResultOpcode());
                }
                else
                {
                    codeBlock.Append(new QueryResultOpcode());
                }

                this.query = codeBlock.First;
            }

            this.flags &= ~XPathFilterFlags.IsFxFilter;
        }
 internal void Add(string expression, XmlNamespaceManager names, object item, bool forceExternal)
 {
     bool flag = false;
     OpcodeBlock newBlock = new OpcodeBlock();
     newBlock.Append(new NoOpOpcode(OpcodeID.QueryTree));
     if (!forceExternal)
     {
         try
         {
             MultipleResultOpcode opcode;
             ValueDataType none = ValueDataType.None;
             newBlock.Append(QueryMatcher.CompileForInternalEngine(expression, names, QueryCompilerFlags.InverseQuery, out none));
             if (!this.match)
             {
                 opcode = new QueryMultipleResultOpcode();
             }
             else
             {
                 opcode = new MatchMultipleResultOpcode();
             }
             opcode.AddItem(item);
             newBlock.Append(opcode);
             flag = true;
             newBlock = new OpcodeBlock(this.elim.Add(item, newBlock.First));
             base.subExprVars = this.elim.VariableCount;
         }
         catch (QueryCompileException)
         {
         }
     }
     if (!flag)
     {
         newBlock.Append(QueryMatcher.CompileForExternalEngine(expression, names, item, this.match));
     }
     QueryTreeBuilder builder = new QueryTreeBuilder();
     base.query = builder.Build(base.query, newBlock);
     this.lastLookup[item] = builder.LastOpcode;
 }
        internal Opcode Build(Opcode tree, OpcodeBlock newBlock)
        {
            if (null == tree)
            {
                this.lastOpcode = newBlock.Last;
                return newBlock.First;
            }

            this.diverger = new Diverger(tree, newBlock.First);

            if (!this.diverger.Find())
            {
                // The opcodes in newBlock already have equivalents or identical opcodes
                // in the query tree that can do the job
                Fx.Assert(this.diverger.TreePath.Count > 0, "");
                this.lastOpcode = this.diverger.TreePath[this.diverger.TreePath.Count - 1];
                return tree;
            }

            Fx.Assert(this.diverger.TreePath.Count == this.diverger.InsertPath.Count, "");

            // We can reuse opcodes upto this.diverger.TreePath[this.diverger.TreePath.Count - 1]
            // The remainder of the code in newBlock must be executed as is...
            if (null == this.diverger.TreeOpcode)
            {
                // We reached a leaf in the query tree
                // Simply add the remainder of the inserted code to the end of the tree path..
                this.diverger.TreePath[this.diverger.TreePath.Count - 1].Attach(this.diverger.InsertOpcode);
            }
            else
            {
                // Merge in the remaider of the new code block into the query tree
                // The first diverging opcodes follow the last entry in each path
                this.diverger.TreeOpcode.Add(this.diverger.InsertOpcode);
            }
            
            this.lastOpcode = newBlock.Last;
            if (this.diverger.InsertOpcode.IsMultipleResult())
            {
                // The complete new block was merged in, except for the the actual result opcode, which never
                // automatically merges. This means that the new block found all of its opcodes in common with 
                // the tree
                if (OpcodeID.Branch == this.diverger.TreeOpcode.ID)
                {
                    OpcodeList branches = (((BranchOpcode) this.diverger.TreeOpcode).Branches); 
                    for (int i = 0, count = branches.Count; i < count; ++i)
                    {
                        if (branches[i].IsMultipleResult())
                        {
                            this.lastOpcode = branches[i];
                            break;
                        }
                    }
                }
                else if (this.diverger.TreeOpcode.IsMultipleResult())
                {
                    this.lastOpcode = this.diverger.TreeOpcode;
                }
            }

            // Since we'll be diverging, any jumps that preceeded and leapt past the divergence point
            // will have to be branched
            this.FixupJumps();

            return tree;
        }
Пример #25
0
 internal OpcodeBlock Compile(XPathExpr expr)
 {
     this.codeBlock = new OpcodeBlock(); // struct
     this.CompileExpression(expr);
     return this.codeBlock;
 }
Пример #26
0
            void CompileBoolean(XPathExpr expr, bool testValue)
            {
                // Boolean expressions must always have at least 2 sub expressions
                Fx.Assert(expr.SubExprCount > 1, "");

                if (this.compiler.nestingLevel == 1)
                {
                    this.CompileBasicBoolean(expr, testValue);
                    return;
                }

                OpcodeBlock boolBlock = new OpcodeBlock(); // struct
                Opcode blockEnd = new BlockEndOpcode();
                // Set up the result mask
                boolBlock.Append(new PushBooleanOpcode(testValue));
                XPathExprList subExprList = expr.SubExpr;
                XPathExpr subExpr;

                // the first expression needs the least work..
                subExpr = subExprList[0];
                boolBlock.Append(this.CompileBlock(subExpr));
                if (subExpr.ReturnType != ValueDataType.Boolean)
                {
                    boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                }
                boolBlock.Append(new ApplyBooleanOpcode(blockEnd, testValue));

                // Compile remaining sub-expressions
                for (int i = 1; i < subExprList.Count; ++i)
                {
                    subExpr = subExprList[i];
                    boolBlock.Append(new StartBooleanOpcode(testValue));
                    boolBlock.Append(this.CompileBlock(subExpr));
                    // Make sure each sub-expression can produce a boolean result
                    if (subExpr.ReturnType != ValueDataType.Boolean)
                    {
                        boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                    }
                    boolBlock.Append(new EndBooleanOpcode(blockEnd, testValue));
                }
                boolBlock.Append(blockEnd);
                this.codeBlock.Append(boolBlock);
            }
Пример #27
0
 internal XPathExprCompiler(XPathCompiler compiler)
 {
     Fx.Assert(null != compiler, "");
     this.compiler = compiler;
     this.codeBlock = new OpcodeBlock();
 }
Пример #28
0
 XPathExprCompiler(XPathExprCompiler xpathCompiler)
 {
     this.compiler = xpathCompiler.compiler;
     this.codeBlock = new OpcodeBlock();
 }
Пример #29
0
            // Compiles expressions at nesting level == 1 -> boolean expressions that can be processed
            // with less complex opcodes because they will never track multiple sequences simultaneously
            void CompileBasicBoolean(XPathExpr expr, bool testValue)
            {
                // Boolean expressions must always have at least 2 sub expressions
                Fx.Assert(expr.SubExprCount > 1, "");
                Fx.Assert(this.compiler.nestingLevel == 1, "");

                OpcodeBlock boolBlock = new OpcodeBlock(); // struct
                Opcode blockEnd = new BlockEndOpcode();
                XPathExprList subExprList = expr.SubExpr;

                // Compile sub-expressions
                for (int i = 0; i < subExprList.Count; ++i)
                {
                    XPathExpr subExpr = subExprList[i];
                    boolBlock.Append(this.CompileBlock(subExpr));
                    // Make sure each sub-expression can produce a boolean result
                    if (subExpr.ReturnType != ValueDataType.Boolean)
                    {
                        boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean));
                    }
                    if (i < (subExprList.Count - 1))
                    {
                        // No point jumping if this is the last expression
                        boolBlock.Append(new JumpIfOpcode(blockEnd, testValue));
                    }
                }
                boolBlock.Append(blockEnd);
                this.codeBlock.Append(boolBlock);
            }
Пример #30
0
 internal XPathExprCompiler(XPathCompiler compiler)
 {
     Fx.Assert(null != compiler, "");
     this.compiler  = compiler;
     this.codeBlock = new OpcodeBlock();
 }
 private void CompileBasicBoolean(XPathExpr expr, bool testValue)
 {
     OpcodeBlock block = new OpcodeBlock();
     Opcode jump = new BlockEndOpcode();
     XPathExprList subExpr = expr.SubExpr;
     for (int i = 0; i < subExpr.Count; i++)
     {
         XPathExpr expr2 = subExpr[i];
         block.Append(this.CompileBlock(expr2));
         if (expr2.ReturnType != ValueDataType.Boolean)
         {
             block.Append(new TypecastOpcode(ValueDataType.Boolean));
         }
         if (i < (subExpr.Count - 1))
         {
             block.Append(new JumpIfOpcode(jump, testValue));
         }
     }
     block.Append(jump);
     this.codeBlock.Append(block);
 }
        internal Opcode Build(Opcode tree, OpcodeBlock newBlock)
        {
            if (null == tree)
            {
                this.lastOpcode = newBlock.Last;
                return(newBlock.First);
            }

            this.diverger = new Diverger(tree, newBlock.First);

            if (!this.diverger.Find())
            {
                // The opcodes in newBlock already have equivalents or identical opcodes
                // in the query tree that can do the job
                Fx.Assert(this.diverger.TreePath.Count > 0, "");
                this.lastOpcode = this.diverger.TreePath[this.diverger.TreePath.Count - 1];
                return(tree);
            }

            Fx.Assert(this.diverger.TreePath.Count == this.diverger.InsertPath.Count, "");

            // We can reuse opcodes upto this.diverger.TreePath[this.diverger.TreePath.Count - 1]
            // The remainder of the code in newBlock must be executed as is...
            if (null == this.diverger.TreeOpcode)
            {
                // We reached a leaf in the query tree
                // Simply add the remainder of the inserted code to the end of the tree path..
                this.diverger.TreePath[this.diverger.TreePath.Count - 1].Attach(this.diverger.InsertOpcode);
            }
            else
            {
                // Merge in the remaider of the new code block into the query tree
                // The first diverging opcodes follow the last entry in each path
                this.diverger.TreeOpcode.Add(this.diverger.InsertOpcode);
            }

            this.lastOpcode = newBlock.Last;
            if (this.diverger.InsertOpcode.IsMultipleResult())
            {
                // The complete new block was merged in, except for the the actual result opcode, which never
                // automatically merges. This means that the new block found all of its opcodes in common with
                // the tree
                if (OpcodeID.Branch == this.diverger.TreeOpcode.ID)
                {
                    OpcodeList branches = (((BranchOpcode)this.diverger.TreeOpcode).Branches);
                    for (int i = 0, count = branches.Count; i < count; ++i)
                    {
                        if (branches[i].IsMultipleResult())
                        {
                            this.lastOpcode = branches[i];
                            break;
                        }
                    }
                }
                else if (this.diverger.TreeOpcode.IsMultipleResult())
                {
                    this.lastOpcode = this.diverger.TreeOpcode;
                }
            }

            // Since we'll be diverging, any jumps that preceeded and leapt past the divergence point
            // will have to be branched
            this.FixupJumps();

            return(tree);
        }
 internal XPathExprCompiler(XPathCompiler compiler)
 {
     this.compiler = compiler;
     this.codeBlock = new OpcodeBlock();
 }
Пример #34
0
 internal void Append(OpcodeBlock block)
 {
     if (null == this.last)
     {
         this.first = block.first;
         this.last = block.last;
     }
     else
     {
         this.last.Attach(block.first);
         this.last = block.last;
     }
 }
Пример #35
0
 internal XPathExprCompiler(XPathCompiler compiler)
 {
     this.compiler  = compiler;
     this.codeBlock = new OpcodeBlock();
 }
Пример #36
0
 private XPathExprCompiler(XPathCompiler.XPathExprCompiler xpathCompiler)
 {
     this.compiler  = xpathCompiler.compiler;
     this.codeBlock = new OpcodeBlock();
 }
Пример #37
0
 internal OpcodeBlock Compile(XPathExpr expr)
 {
     this.codeBlock = new OpcodeBlock();
     this.CompileExpression(expr);
     return(this.codeBlock);
 }