Пример #1
0
 public ExprInNodeForgeEvalWColl(
     ExprInNodeForge forge,
     ExprEvaluator[] evaluators)
 {
     this._forge = forge;
     this._evaluators = evaluators;
 }
Пример #2
0
        public static CodegenExpression Codegen(
            ExprInNodeForge forge,
            CodegenMethodScope codegenMethodScope,
            ExprForgeCodegenSymbol exprSymbol,
            CodegenClassScope codegenClassScope)
        {
            var forges = ExprNodeUtilityQuery.GetForges(forge.ForgeRenderable.ChildNodes);
            var isNot = forge.ForgeRenderable.IsNotIn;
            var methodNode = codegenMethodScope.MakeChild(
                typeof(bool?),
                typeof(ExprInNodeForgeEvalWColl),
                codegenClassScope);

            var block = methodNode.Block
                .DeclareVar<bool>("hasNullRow", ConstantFalse());

            var leftTypeUncoerced = forges[0].EvaluationType.GetBoxedType();
            var leftTypeCoerced = forge.CoercionType.GetBoxedType();

            block.DeclareVar(
                leftTypeUncoerced,
                "left",
                forges[0].EvaluateCodegen(leftTypeUncoerced, methodNode, exprSymbol, codegenClassScope));
            block.DeclareVar(
                forge.CoercionType,
                "leftCoerced",
                !forge.IsMustCoerce
                    ? Ref("left")
                    : forge.Coercer.CoerceCodegenMayNullBoxed(
                        Ref("left"),
                        leftTypeUncoerced,
                        methodNode,
                        codegenClassScope));

            for (var i = 1; i < forges.Length; i++) {
                var reftype = forges[i].EvaluationType.GetBoxedType();
                var refforge = forges[i];
                var refname = "r" + i;

                if (reftype == null) {
                    block.AssignRef("hasNullRow", ConstantTrue());
                    continue;
                }

                block.DeclareVar(
                    reftype,
                    refname,
                    refforge.EvaluateCodegen(reftype, methodNode, exprSymbol, codegenClassScope));

                if (reftype.IsArray) {
                    var ifRightNotNull = block.IfCondition(NotEqualsNull(Ref(refname)));
                    {
                        if (leftTypeUncoerced.CanBeNull()) {
                            ifRightNotNull.IfCondition(
                                    And(
                                        Relational(ArrayLength(Ref(refname)), GT, Constant(0)),
                                        EqualsNull(Ref("left"))))
                                .BlockReturn(ConstantNull());
                        }

                        var forLoop = ifRightNotNull.ForLoopIntSimple("index", ArrayLength(Ref(refname)));
                        {
                            forLoop.DeclareVar(
                                reftype.GetElementType(),
                                "item",
                                ArrayAtIndex(Ref(refname), Ref("index")));
                            forLoop.DeclareVar<bool>(
                                "itemNull",
                                reftype.GetElementType().CanNotBeNull() ? ConstantFalse() : EqualsNull(Ref("item")));
                            var itemNotNull = forLoop.IfCondition(Ref("itemNull"))
                                .AssignRef("hasNullRow", ConstantTrue())
                                .IfElse();
                            {
                                if (!forge.IsMustCoerce) {
                                    itemNotNull.IfCondition(
                                            CodegenLegoCompareEquals.CodegenEqualsNonNullNoCoerce(
                                                Ref("leftCoerced"),
                                                leftTypeCoerced,
                                                Ref("item"),
                                                reftype.GetElementType()))
                                        .BlockReturn(!isNot ? ConstantTrue() : ConstantFalse());
                                }
                                else {
                                    if (TypeHelper.IsNumeric(reftype.GetElementType())) {
                                        itemNotNull.IfCondition(
                                                CodegenLegoCompareEquals.CodegenEqualsNonNullNoCoerce(
                                                    Ref("leftCoerced"),
                                                    leftTypeCoerced,
                                                    forge.Coercer.CoerceCodegen(Ref("item"), reftype.GetElementType()),
                                                    forge.CoercionType))
                                            .BlockReturn(!isNot ? ConstantTrue() : ConstantFalse());
                                    }
                                }
                            }
                        }
                    }
                }
                else if (reftype.IsGenericDictionary()) {
                    var ifRightNotNull = block.IfCondition(NotEqualsNull(Ref(refname)));
                    {
                        if (leftTypeUncoerced.CanBeNull()) {
                            ifRightNotNull.IfRefNullReturnNull("left");
                        }

                        var leftWithBoxing = ExprEqualsAllAnyNodeForgeHelper.ItemToCollectionUnboxing(
                            Ref("left"), leftTypeUncoerced, reftype.GetDictionaryKeyType());
                        
                        ifRightNotNull.IfCondition(ExprDotMethod(Ref(refname), "CheckedContainsKey", leftWithBoxing))
                            .BlockReturn(!isNot ? ConstantTrue() : ConstantFalse());
                    }
                }
                else if (reftype.IsGenericCollection()) {
                    var ifRightNotNull = block.IfCondition(NotEqualsNull(Ref(refname)));
                    {
                        if (leftTypeUncoerced.CanBeNull()) {
                            ifRightNotNull.IfRefNullReturnNull("left");
                        }

                        var leftWithBoxing = ExprEqualsAllAnyNodeForgeHelper.ItemToCollectionUnboxing(
                            Ref("left"), leftTypeUncoerced, reftype.GetCollectionItemType());
                        
                        ifRightNotNull
                            .IfCondition(StaticMethod(typeof(Collections), "CheckedContains", Ref(refname), leftWithBoxing))
                            .BlockReturn(!isNot ? ConstantTrue() : ConstantFalse());
                    }
                }
                else {
                    var ifRightNotNull = reftype.CanNotBeNull() ? block : block.IfRefNotNull(refname);
                    {
                        if (leftTypeUncoerced.CanBeNull()) {
                            ifRightNotNull.IfRefNullReturnNull("left");
                        }

                        if (!forge.IsMustCoerce) {
                            ifRightNotNull
                                .IfCondition(
                                    CodegenLegoCompareEquals.CodegenEqualsNonNullNoCoerce(
                                        Ref("leftCoerced"),
                                        leftTypeCoerced,
                                        Ref(refname),
                                        reftype))
                                .BlockReturn(!isNot ? ConstantTrue() : ConstantFalse());
                        }
                        else {
                            ifRightNotNull
                                .IfCondition(
                                    CodegenLegoCompareEquals.CodegenEqualsNonNullNoCoerce(
                                        Ref("leftCoerced"),
                                        leftTypeCoerced,
                                        forge.Coercer.CoerceCodegen(Ref(refname), reftype),
                                        forge.CoercionType))
                                .BlockReturn(!isNot ? ConstantTrue() : ConstantFalse());
                        }
                    }
                    if (reftype.CanBeNull()) {
                        block.IfRefNull(refname).AssignRef("hasNullRow", ConstantTrue());
                    }
                }
            }

            block.IfCondition(Ref("hasNullRow")).BlockReturn(ConstantNull());
            block.MethodReturn(isNot ? ConstantTrue() : ConstantFalse());
            return LocalMethod(methodNode);
        }