void CompileRelational(XPathRelationExpr expr) { // Are we comparing two literals? if (expr.Left.IsLiteral && expr.Right.IsLiteral) { // Do the comparison at compile time this.CompileLiteralRelation(expr); return; } // != is not optimized in M5 if (expr.Op != RelationOperator.Ne) { // Number relations are handled in a special way if (XPathExprType.Number == expr.Left.Type || XPathExprType.Number == expr.Right.Type) { this.CompileNumberRelation(expr); return; } // Equality tests with string literals are handled in a special way if (expr.Op == RelationOperator.Eq && (XPathExprType.String == expr.Left.Type || XPathExprType.String == expr.Right.Type)) { this.CompileStringLiteralEquality(expr); return; } } // Can't optimize. Use a general purpose relation opcode this.CompileExpression(expr.Left); this.CompileExpression(expr.Right); this.codeBlock.Append(new RelationOpcode(expr.Op)); }
private void CompileRelational(XPathRelationExpr expr) { if (expr.Left.IsLiteral && expr.Right.IsLiteral) { this.CompileLiteralRelation(expr); } else { if (expr.Op != RelationOperator.Ne) { if ((XPathExprType.Number == expr.Left.Type) || (XPathExprType.Number == expr.Right.Type)) { this.CompileNumberRelation(expr); return; } if ((expr.Op == RelationOperator.Eq) && ((XPathExprType.String == expr.Left.Type) || (XPathExprType.String == expr.Right.Type))) { this.CompileStringLiteralEquality(expr); return; } } this.CompileExpression(expr.Left); this.CompileExpression(expr.Right); this.codeBlock.Append(new RelationOpcode(expr.Op)); } }
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 CompileLiteralRelation(XPathRelationExpr expr) { XPathLiteralExpr left = (XPathLiteralExpr)expr.Left; XPathLiteralExpr right = (XPathLiteralExpr)expr.Right; bool literal = QueryValueModel.CompileTimeCompare(left.Literal, right.Literal, expr.Op); this.codeBlock.Append(new PushBooleanOpcode(literal)); }
private void CompileStringLiteralEquality(XPathRelationExpr expr) { bool flag = XPathExprType.String == expr.Left.Type; XPathExprType type = expr.Right.Type; this.CompileExpression(flag ? expr.Right : expr.Left); string literal = flag ? ((XPathStringExpr)expr.Left).String : ((XPathStringExpr)expr.Right).String; this.codeBlock.Append(new StringEqualsOpcode(literal)); }
XPathExpr ParseRelationalExpression() { XPathExpr leftExpr = this.ParseAdditiveExpression(); if (null != leftExpr) { RelationOperator op; do { op = RelationOperator.None; XPathToken token = this.NextToken(); if (null != token) { switch (token.TokenID) { default: this.PushToken(token); break; case XPathTokenID.Lt: op = RelationOperator.Lt; break; case XPathTokenID.Lte: op = RelationOperator.Le; break; case XPathTokenID.Gt: op = RelationOperator.Gt; break; case XPathTokenID.Gte: op = RelationOperator.Ge; break; } if (RelationOperator.None != op) { XPathExpr rightExpr = this.ParseAdditiveExpression(); if (null == rightExpr) { this.ThrowError(QueryCompileError.InvalidExpression); } leftExpr = new XPathRelationExpr(op, leftExpr, rightExpr); } } } while (RelationOperator.None != op); } return(leftExpr); }
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 XPathExpr ParseRelationalExpression() { XPathExpr left = this.ParseAdditiveExpression(); if (left != null) { RelationOperator none; do { none = RelationOperator.None; XPathToken token = this.NextToken(); if (token != null) { switch (token.TokenID) { case XPathTokenID.Gt: none = RelationOperator.Gt; break; case XPathTokenID.Gte: none = RelationOperator.Ge; break; case XPathTokenID.Lt: none = RelationOperator.Lt; break; case XPathTokenID.Lte: none = RelationOperator.Le; break; default: this.PushToken(token); break; } if (none != RelationOperator.None) { XPathExpr right = this.ParseAdditiveExpression(); if (right == null) { this.ThrowError(QueryCompileError.InvalidExpression); } left = new XPathRelationExpr(none, left, right); } } }while (none != RelationOperator.None); } return(left); }
void CompileStringLiteralEquality(XPathRelationExpr expr) { Fx.Assert(expr.Op == RelationOperator.Eq, ""); bool leftString = (XPathExprType.String == expr.Left.Type); bool rightString = (XPathExprType.String == expr.Right.Type); Fx.Assert(leftString || rightString, ""); Fx.Assert(!(leftString && rightString), ""); this.CompileExpression(leftString ? expr.Right : expr.Left); string literal = leftString ? ((XPathStringExpr)expr.Left).String : ((XPathStringExpr)expr.Right).String; this.codeBlock.Append(new StringEqualsOpcode(literal)); }
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 XPathExpr ParseRelationalExpression() { XPathExpr left = this.ParseAdditiveExpression(); if (left != null) { RelationOperator none; do { none = RelationOperator.None; XPathToken token = this.NextToken(); if (token != null) { switch (token.TokenID) { case XPathTokenID.Gt: none = RelationOperator.Gt; break; case XPathTokenID.Gte: none = RelationOperator.Ge; break; case XPathTokenID.Lt: none = RelationOperator.Lt; break; case XPathTokenID.Lte: none = RelationOperator.Le; break; default: this.PushToken(token); break; } if (none != RelationOperator.None) { XPathExpr right = this.ParseAdditiveExpression(); if (right == null) { this.ThrowError(QueryCompileError.InvalidExpression); } left = new XPathRelationExpr(none, left, right); } } } while (none != RelationOperator.None); } return left; }
void CompileStringLiteralEquality(XPathRelationExpr expr) { Fx.Assert(expr.Op == RelationOperator.Eq, ""); bool leftString = (XPathExprType.String == expr.Left.Type); bool rightString = (XPathExprType.String == expr.Right.Type); Fx.Assert(leftString || rightString, ""); Fx.Assert(!(leftString && rightString), ""); this.CompileExpression(leftString ? expr.Right : expr.Left); string literal = leftString ? ((XPathStringExpr)expr.Left).String : ((XPathStringExpr)expr.Right).String; this.codeBlock.Append(new StringEqualsOpcode(literal)); }
void CompileRelational(XPathRelationExpr expr) { // Are we comparing two literals? if (expr.Left.IsLiteral && expr.Right.IsLiteral) { // Do the comparison at compile time this.CompileLiteralRelation(expr); return; } // != is not optimized in M5 if (expr.Op != RelationOperator.Ne) { // Number relations are handled in a special way if (XPathExprType.Number == expr.Left.Type || XPathExprType.Number == expr.Right.Type) { this.CompileNumberRelation(expr); return; } // Equality tests with string literals are handled in a special way if (expr.Op == RelationOperator.Eq && (XPathExprType.String == expr.Left.Type || XPathExprType.String == expr.Right.Type)) { this.CompileStringLiteralEquality(expr); return; } } // Can't optimize. Use a general purpose relation opcode this.CompileExpression(expr.Left); this.CompileExpression(expr.Right); this.codeBlock.Append(new RelationOpcode(expr.Op)); }
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)); } }
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)); }
void CompileLiteralRelation(XPathRelationExpr expr) { XPathLiteralExpr left = (XPathLiteralExpr)expr.Left; XPathLiteralExpr right = (XPathLiteralExpr)expr.Right; bool result = QueryValueModel.CompileTimeCompare(left.Literal, right.Literal, expr.Op); this.codeBlock.Append(new PushBooleanOpcode(result)); }
XPathExpr ParseRelationalExpression() { XPathExpr leftExpr = this.ParseAdditiveExpression(); if (null != leftExpr) { RelationOperator op; do { op = RelationOperator.None; XPathToken token = this.NextToken(); if (null != token) { switch (token.TokenID) { default: this.PushToken(token); break; case XPathTokenID.Lt: op = RelationOperator.Lt; break; case XPathTokenID.Lte: op = RelationOperator.Le; break; case XPathTokenID.Gt: op = RelationOperator.Gt; break; case XPathTokenID.Gte: op = RelationOperator.Ge; break; } if (RelationOperator.None != op) { XPathExpr rightExpr = this.ParseAdditiveExpression(); if (null == rightExpr) { this.ThrowError(QueryCompileError.InvalidExpression); } leftExpr = new XPathRelationExpr(op, leftExpr, rightExpr); } } } while (RelationOperator.None != op); } return leftExpr; }
private void CompileStringLiteralEquality(XPathRelationExpr expr) { bool flag = XPathExprType.String == expr.Left.Type; XPathExprType type = expr.Right.Type; this.CompileExpression(flag ? expr.Right : expr.Left); string literal = flag ? ((XPathStringExpr) expr.Left).String : ((XPathStringExpr) expr.Right).String; this.codeBlock.Append(new StringEqualsOpcode(literal)); }
private void CompileRelational(XPathRelationExpr expr) { if (expr.Left.IsLiteral && expr.Right.IsLiteral) { this.CompileLiteralRelation(expr); } else { if (expr.Op != RelationOperator.Ne) { if ((XPathExprType.Number == expr.Left.Type) || (XPathExprType.Number == expr.Right.Type)) { this.CompileNumberRelation(expr); return; } if ((expr.Op == RelationOperator.Eq) && ((XPathExprType.String == expr.Left.Type) || (XPathExprType.String == expr.Right.Type))) { this.CompileStringLiteralEquality(expr); return; } } this.CompileExpression(expr.Left); this.CompileExpression(expr.Right); this.codeBlock.Append(new RelationOpcode(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)); }