public static CodegenExpression Codegen( ExprBetweenNodeForge forge, CodegenMethodScope codegenMethodScope, ExprForgeCodegenSymbol exprSymbol, CodegenClassScope codegenClassScope) { var nodes = forge.ForgeRenderable.ChildNodes; var value = nodes[0].Forge; var lower = nodes[1].Forge; var higher = nodes[2].Forge; var isNot = forge.ForgeRenderable.IsNotBetween; var methodNode = codegenMethodScope.MakeChild( typeof(bool?), typeof(ExprBetweenNodeForgeEval), codegenClassScope); var block = methodNode.Block; var valueType = value.EvaluationType.GetBoxedType(); block.DeclareVar( valueType, "value", value.EvaluateCodegen(valueType, methodNode, exprSymbol, codegenClassScope)); if (valueType.CanBeNull()) { block.IfRefNullReturnFalse("value"); } var lowerType = lower.EvaluationType.GetBoxedType(); block.DeclareVar( lowerType, "lower", lower.EvaluateCodegen(lowerType, methodNode, exprSymbol, codegenClassScope)); if (lowerType.CanBeNull()) { block.IfRefNull("lower").BlockReturn(Constant(isNot)); } var higherType = higher.EvaluationType.GetBoxedType(); block.DeclareVar( higherType, "higher", higher.EvaluateCodegen(higherType, methodNode, exprSymbol, codegenClassScope)); if (higher.EvaluationType.CanBeNull()) { block.IfRefNull("higher").BlockReturn(Constant(isNot)); } block.DeclareVar<bool>( "result", forge.Computer.CodegenNoNullCheck( Unbox(Ref("value"), valueType), value.EvaluationType, Unbox(Ref("lower"), lowerType), lower.EvaluationType, Unbox(Ref("higher"), higherType), higher.EvaluationType, methodNode, codegenClassScope)); block.MethodReturn(NotOptional(forge.ForgeRenderable.IsNotBetween, Ref("result"))); return LocalMethod(methodNode); }
public override ExprNode Validate(ExprValidationContext validationContext) { if (ChildNodes.Length != 3) { throw new ExprValidationException("The Between operator requires exactly 3 child expressions"); } // Must be either numeric or string var forges = ExprNodeUtilityQuery.GetForges(ChildNodes); var typeOne = forges[0].EvaluationType.GetBoxedType(); var typeTwo = forges[1].EvaluationType.GetBoxedType(); var typeThree = forges[2].EvaluationType.GetBoxedType(); if (typeOne == null) { throw new ExprValidationException("Null value not allowed in between-clause"); } Type compareType; var isAlwaysFalse = false; ExprBetweenComp computer = null; if (typeTwo == null || typeThree == null) { isAlwaysFalse = true; } else { if (typeOne != typeof(string) || typeTwo != typeof(string) || typeThree != typeof(string)) { if (!typeOne.IsNumeric()) { throw new ExprValidationException( "Implicit conversion from datatype '" + typeOne.CleanName() + "' to numeric is not allowed"); } if (!typeTwo.IsNumeric()) { throw new ExprValidationException( "Implicit conversion from datatype '" + typeTwo.CleanName() + "' to numeric is not allowed"); } if (!typeThree.IsNumeric()) { throw new ExprValidationException( "Implicit conversion from datatype '" + typeThree.CleanName() + "' to numeric is not allowed"); } } var intermedType = typeOne.GetCompareToCoercionType(typeTwo); compareType = intermedType.GetCompareToCoercionType(typeThree); computer = MakeComputer(compareType, typeOne, typeTwo, typeThree); } _forge = new ExprBetweenNodeForge(this, computer, isAlwaysFalse); return null; }
public ExprBetweenNodeForgeEval( ExprBetweenNodeForge forge, ExprEvaluator valueEval, ExprEvaluator lowerEval, ExprEvaluator higherEval) { _forge = forge; _valueEval = valueEval; _lowerEval = lowerEval; _higherEval = higherEval; }