public ExprEqualsAllAnyNodeForgeEvalAllNoColl( ExprEqualsAllAnyNodeForge forge, ExprEvaluator[] evaluators) { this.forge = forge; this.evaluators = evaluators; }
public static CodegenExpression Codegen( ExprEqualsAllAnyNodeForge forge, CodegenMethodScope codegenMethodScope, ExprForgeCodegenSymbol exprSymbol, CodegenClassScope codegenClassScope) { var forges = ExprNodeUtilityQuery.GetForges(forge.ForgeRenderable.ChildNodes); var isNot = forge.ForgeRenderable.IsNot; var methodNode = codegenMethodScope.MakeChild( typeof(bool?), typeof(ExprEqualsAllAnyNodeForgeEvalAllWColl), codegenClassScope); var block = methodNode.Block; var leftTypeUncoerced = forges[0].EvaluationType; block.DeclareVar( leftTypeUncoerced, "left", forges[0].EvaluateCodegen(leftTypeUncoerced, methodNode, exprSymbol, codegenClassScope)); block.DeclareVar( forge.CoercionTypeBoxed, "leftCoerced", !forge.IsMustCoerce ? Ref("left") : forge.Coercer.CoerceCodegenMayNullBoxed( Ref("left"), leftTypeUncoerced, methodNode, codegenClassScope)); block.DeclareVar<bool>("hasNonNullRow", ConstantFalse()); block.DeclareVar<bool>("hasNullRow", ConstantFalse()); for (var i = 1; i < forges.Length; i++) { var refforge = forges[i]; var refname = "r" + i; var reftype = forges[i].EvaluationType; if (reftype.IsArray) { var arrayBlock = block.IfRefNullReturnNull("left") .DeclareVar( reftype, refname, refforge.EvaluateCodegen(reftype, methodNode, exprSymbol, codegenClassScope)) .IfCondition(EqualsNull(Ref(refname))) .AssignRef("hasNullRow", ConstantTrue()) .IfElse(); var forLoop = arrayBlock.ForLoopIntSimple("i", ArrayLength(Ref(refname))); var arrayAtIndex = ArrayAtIndex(Ref(refname), Ref("i")); forLoop.DeclareVar( forge.CoercionTypeBoxed, "item", forge.Coercer == null ? arrayAtIndex : forge.Coercer.CoerceCodegenMayNullBoxed( arrayAtIndex, reftype.GetElementType(), methodNode, codegenClassScope)); var forLoopElse = forLoop.IfCondition(EqualsNull(Ref("item"))) .AssignRef("hasNullRow", ConstantTrue()) .IfElse(); forLoopElse.AssignRef("hasNonNullRow", ConstantTrue()); forLoopElse.IfCondition( NotOptional(!isNot, StaticMethod<object>("Equals", Ref("leftCoerced"), Ref("item")))) .BlockReturn(ConstantFalse()); } else if (reftype.IsGenericDictionary()) { var dictionaryType = typeof(IDictionary<,>) .MakeGenericType( reftype.GetGenericArguments()[0], reftype.GetGenericArguments()[1]); var leftWithBoxing = ExprEqualsAllAnyNodeForgeHelper.ItemToCollectionUnboxing( Ref("left"), leftTypeUncoerced, reftype.GetDictionaryKeyType()); block.IfRefNullReturnNull("left") .DeclareVar( dictionaryType, refname, refforge.EvaluateCodegen( dictionaryType, methodNode, exprSymbol, codegenClassScope)) .IfCondition(EqualsNull(Ref(refname))) .AssignRef("hasNullRow", ConstantTrue()) .IfElse() .AssignRef("hasNonNullRow", ConstantTrue()) .IfCondition(NotOptional(!isNot, ExprDotMethod(Ref(refname), "CheckedContainsKey", leftWithBoxing))) .BlockReturn(ConstantFalse()); } else if (reftype.IsGenericCollection()) { var collectionType = typeof(ICollection<>) .MakeGenericType(reftype.GetGenericArguments()[0]); var leftWithBoxing = ExprEqualsAllAnyNodeForgeHelper.ItemToCollectionUnboxing( Ref("left"), leftTypeUncoerced, reftype.GetCollectionItemType()); block.IfRefNullReturnNull("left") .DeclareVar( collectionType, refname, refforge.EvaluateCodegen( collectionType, methodNode, exprSymbol, codegenClassScope)) .IfCondition(EqualsNull(Ref(refname))) .AssignRef("hasNullRow", ConstantTrue()) .IfElse() .AssignRef("hasNonNullRow", ConstantTrue()) .IfCondition(NotOptional(!isNot, ExprDotMethod(Ref(refname), "CheckedContains", leftWithBoxing))) .BlockReturn(ConstantFalse()); } else { block.IfRefNullReturnNull("leftCoerced"); block.DeclareVar( forge.CoercionTypeBoxed, refname, forge.Coercer == null ? refforge.EvaluateCodegen( forge.CoercionTypeBoxed, methodNode, exprSymbol, codegenClassScope) : forge.Coercer.CoerceCodegenMayNullBoxed( refforge.EvaluateCodegen( forge.CoercionTypeBoxed, methodNode, exprSymbol, codegenClassScope), reftype, methodNode, codegenClassScope)); var ifRightNotNull = block.IfRefNotNull(refname); { ifRightNotNull.AssignRef("hasNonNullRow", ConstantTrue()); ifRightNotNull .IfCondition(NotOptional(!isNot, StaticMethod<object>("Equals", Ref("leftCoerced"), Ref(refname)))) .BlockReturn(ConstantFalse()); } ifRightNotNull.IfElse() .AssignRef("hasNullRow", ConstantTrue()); } } block.IfCondition(Or(Not(Ref("hasNonNullRow")), Ref("hasNullRow"))).BlockReturn(ConstantNull()); block.MethodReturn(ConstantTrue()); return LocalMethod(methodNode); }
public override ExprNode Validate(ExprValidationContext validationContext) { // Must have 2 child nodes if (ChildNodes.Length < 1) { throw new IllegalStateException("Equals group node does not have 1 or more parameters"); } // Must be the same boxed type returned by expressions under this Type typeOne = ChildNodes[0].Forge.EvaluationType.GetBoxedType(); // collections, array or map not supported if (typeOne.IsArray || typeOne.IsGenericCollection() || typeOne.IsGenericStringDictionary()) { throw new ExprValidationException( "Collection or array comparison is not allowed for the IN, ANY, SOME or ALL keywords"); } IList<Type> comparedTypes = new List<Type>(); comparedTypes.Add(typeOne); var hasCollectionOrArray = false; for (var i = 0; i < ChildNodes.Length - 1; i++) { var propType = ChildNodes[i + 1].Forge.EvaluationType; if (propType == null) { // no action } else if (propType.IsArray) { hasCollectionOrArray = true; if (propType.GetElementType() != typeof(object)) { comparedTypes.Add(propType.GetElementType()); } } else if (propType.IsGenericCollection()) { hasCollectionOrArray = true; } else if (propType.IsGenericStringDictionary()) { hasCollectionOrArray = true; } else { comparedTypes.Add(propType); } } // Determine common denominator type Type coercionTypeBoxed; try { coercionTypeBoxed = TypeHelper.GetCommonCoercionType(comparedTypes.ToArray()); } catch (CoercionException ex) { throw new ExprValidationException("Implicit conversion not allowed: " + ex.Message); } // Check if we need to coerce var mustCoerce = false; Coercer coercer = null; if (coercionTypeBoxed.IsNumeric()) { foreach (var compareType in comparedTypes) { if (coercionTypeBoxed != compareType.GetBoxedType()) { mustCoerce = true; } } if (mustCoerce) { coercer = SimpleNumberCoercerFactory.GetCoercer(null, coercionTypeBoxed.GetBoxedType()); } } _forge = new ExprEqualsAllAnyNodeForge(this, mustCoerce, coercer, coercionTypeBoxed, hasCollectionOrArray); return null; }