private void CompileLiteralOrdinal(XPathExpr expr) { int ordinal = 0; try { XPathNumberExpr expr2 = (XPathNumberExpr)expr; ordinal = Convert.ToInt32(expr2.Number); if (expr2.Negate) { ordinal = -ordinal; expr2.Negate = false; } if (ordinal < 1) { this.ThrowError(QueryCompileError.InvalidOrdinal); } } catch (OverflowException) { this.ThrowError(QueryCompileError.InvalidOrdinal); } if ((this.compiler.flags & QueryCompilerFlags.InverseQuery) != QueryCompilerFlags.None) { this.codeBlock.Append(new PushContextPositionOpcode()); this.codeBlock.Append(new NumberEqualsOpcode((double)ordinal)); } else { this.codeBlock.Append(new LiteralOrdinalOpcode(ordinal)); } }
void CompileNumberRelation(XPathRelationExpr expr) { if (expr.Op == RelationOperator.Eq) { this.CompileNumberLiteralEquality(expr); return; } bool leftNumber = (XPathExprType.Number == expr.Left.Type); bool rightNumber = (XPathExprType.Number == expr.Right.Type); Fx.Assert(leftNumber || rightNumber, ""); Fx.Assert(!(leftNumber && rightNumber), ""); this.CompileExpression(leftNumber ? expr.Right : expr.Left); XPathNumberExpr litExpr = leftNumber ? (XPathNumberExpr)expr.Left : (XPathNumberExpr)expr.Right; double literal = litExpr.Number; if (litExpr.Negate) { litExpr.Negate = false; literal = -literal; } // To maximize code branch commonality, we canonacalize the relation expressions so that the non-literal // is always to the left and the literal to the right. If this makes us swap expressions, we must also flip // relation operators appropriately. if (leftNumber) { // Flip operators switch (expr.Op) { case RelationOperator.Gt: expr.Op = RelationOperator.Lt; break; case RelationOperator.Ge: expr.Op = RelationOperator.Le; break; case RelationOperator.Lt: expr.Op = RelationOperator.Gt; break; case RelationOperator.Le: expr.Op = RelationOperator.Ge; break; } } if (0 != (this.compiler.flags & QueryCompilerFlags.InverseQuery)) { this.codeBlock.Append(new NumberIntervalOpcode(literal, expr.Op)); } else { this.codeBlock.Append(new NumberRelationOpcode(literal, expr.Op)); } }
private void CompileNumberRelation(XPathRelationExpr expr) { if (expr.Op == RelationOperator.Eq) { this.CompileNumberLiteralEquality(expr); } else { bool flag = XPathExprType.Number == expr.Left.Type; XPathExprType type = expr.Right.Type; this.CompileExpression(flag ? expr.Right : expr.Left); XPathNumberExpr expr2 = flag ? ((XPathNumberExpr)expr.Left) : ((XPathNumberExpr)expr.Right); double number = expr2.Number; if (expr2.Negate) { expr2.Negate = false; number = -number; } if (flag) { switch (expr.Op) { case RelationOperator.Gt: expr.Op = RelationOperator.Lt; break; case RelationOperator.Ge: expr.Op = RelationOperator.Le; break; case RelationOperator.Lt: expr.Op = RelationOperator.Gt; break; case RelationOperator.Le: expr.Op = RelationOperator.Ge; break; } } if ((this.compiler.flags & QueryCompilerFlags.InverseQuery) != QueryCompilerFlags.None) { this.codeBlock.Append(new NumberIntervalOpcode(number, expr.Op)); } else { this.codeBlock.Append(new NumberRelationOpcode(number, expr.Op)); } } }
private void CompileNumberLiteralEquality(XPathRelationExpr expr) { bool flag = XPathExprType.Number == expr.Left.Type; XPathExprType type = expr.Right.Type; this.CompileExpression(flag ? expr.Right : expr.Left); XPathNumberExpr expr2 = flag ? ((XPathNumberExpr)expr.Left) : ((XPathNumberExpr)expr.Right); double number = expr2.Number; if (expr2.Negate) { expr2.Negate = false; number = -number; } this.codeBlock.Append(new NumberEqualsOpcode(number)); }
void CompileNumberLiteralEquality(XPathRelationExpr expr) { Fx.Assert(expr.Op == RelationOperator.Eq, ""); bool leftNumber = (XPathExprType.Number == expr.Left.Type); bool rightNumber = (XPathExprType.Number == expr.Right.Type); Fx.Assert(leftNumber || rightNumber, ""); Fx.Assert(!(leftNumber && rightNumber), ""); this.CompileExpression(leftNumber ? expr.Right : expr.Left); XPathNumberExpr litExpr = leftNumber ? (XPathNumberExpr)expr.Left : (XPathNumberExpr)expr.Right; double literal = litExpr.Number; if (litExpr.Negate) { litExpr.Negate = false; literal = -literal; } this.codeBlock.Append(new NumberEqualsOpcode(literal)); }
private void CompileExpression(XPathExpr expr) { switch (expr.Type) { case XPathExprType.Or: this.CompileBoolean(expr, false); break; case XPathExprType.And: this.CompileBoolean(expr, true); break; case XPathExprType.Relational: this.CompileRelational((XPathRelationExpr)expr); break; case XPathExprType.Union: { XPathConjunctExpr expr2 = (XPathConjunctExpr)expr; this.CompileExpression(expr2.Left); this.CompileExpression(expr2.Right); this.codeBlock.Append(new UnionOpcode()); break; } case XPathExprType.LocationPath: if (expr.SubExprCount > 0) { this.CompileLocationPath(expr); this.codeBlock.Append(new PopSequenceToValueStackOpcode()); } break; case XPathExprType.RelativePath: this.CompileRelativePath(expr, true); break; case XPathExprType.XsltVariable: this.CompileXsltVariable((XPathXsltVariableExpr)expr); break; case XPathExprType.String: this.codeBlock.Append(new PushStringOpcode(((XPathStringExpr)expr).String)); break; case XPathExprType.Number: { XPathNumberExpr expr3 = (XPathNumberExpr)expr; double number = expr3.Number; if (expr3.Negate) { expr3.Negate = false; number = -number; } this.codeBlock.Append(new PushNumberOpcode(number)); break; } case XPathExprType.Function: this.CompileFunction((XPathFunctionExpr)expr); break; case XPathExprType.XsltFunction: this.CompileXsltFunction((XPathXsltFunctionExpr)expr); break; case XPathExprType.Math: this.CompileMath((XPathMathExpr)expr); break; case XPathExprType.Filter: this.CompileFilter(expr); if (expr.ReturnType == ValueDataType.Sequence) { this.codeBlock.Append(new PopSequenceToValueStackOpcode()); } break; case XPathExprType.Path: this.CompilePath(expr); if ((expr.SubExprCount == 0) && (expr.ReturnType == ValueDataType.Sequence)) { this.codeBlock.Append(new PopSequenceToValueStackOpcode()); } break; default: this.ThrowError(QueryCompileError.UnsupportedExpression); break; } this.NegateIfRequired(expr); }
void CompileExpression(XPathExpr expr) { Fx.Assert(null != expr, ""); switch (expr.Type) { default: this.ThrowError(QueryCompileError.UnsupportedExpression); break; case XPathExprType.And: this.CompileBoolean(expr, true); break; case XPathExprType.Or: this.CompileBoolean(expr, false); break; case XPathExprType.Relational: this.CompileRelational((XPathRelationExpr)expr); break; case XPathExprType.Function: this.CompileFunction((XPathFunctionExpr)expr); break; case XPathExprType.Union: { XPathConjunctExpr unionExpr = (XPathConjunctExpr)expr; this.CompileExpression(unionExpr.Left); this.CompileExpression(unionExpr.Right); this.codeBlock.Append(new UnionOpcode()); } break; case XPathExprType.RelativePath: this.CompileRelativePath(expr, true); break; case XPathExprType.LocationPath: if (expr.SubExprCount > 0) { this.CompileLocationPath(expr); // Step complete. Transfer results onto the value stack this.codeBlock.Append(new PopSequenceToValueStackOpcode()); } break; case XPathExprType.Math: this.CompileMath((XPathMathExpr)expr); break; case XPathExprType.Number: XPathNumberExpr number = (XPathNumberExpr)expr; double literal = number.Number; if (number.Negate) { number.Negate = false; literal = -literal; } this.codeBlock.Append(new PushNumberOpcode(literal)); break; case XPathExprType.String: this.codeBlock.Append(new PushStringOpcode(((XPathStringExpr)expr).String)); break; case XPathExprType.Filter: this.CompileFilter(expr); if (expr.ReturnType == ValueDataType.Sequence) { this.codeBlock.Append(new PopSequenceToValueStackOpcode()); } break; case XPathExprType.Path: this.CompilePath(expr); if (expr.SubExprCount == 0 && expr.ReturnType == ValueDataType.Sequence) { this.codeBlock.Append(new PopSequenceToValueStackOpcode()); } break; case XPathExprType.XsltFunction: this.CompileXsltFunction((XPathXsltFunctionExpr)expr); break; case XPathExprType.XsltVariable: this.CompileXsltVariable((XPathXsltVariableExpr)expr); break; } NegateIfRequired(expr); }