コード例 #1
0
 public ExprRelationalOpAllAnyNodeForgeEval(
     ExprRelationalOpAllAnyNodeForge forge,
     ExprEvaluator[] evaluators)
 {
     this.forge = forge;
     this.evaluators = evaluators;
 }
コード例 #2
0
        public static CodegenExpression Codegen(
            ExprRelationalOpAllAnyNodeForge forge,
            CodegenMethodScope codegenMethodScope,
            ExprForgeCodegenSymbol exprSymbol,
            CodegenClassScope codegenClassScope)
        {
            var forges = ExprNodeUtilityQuery.GetForges(forge.ForgeRenderable.ChildNodes);
            var valueLeftType = forges[0].EvaluationType;
            var isAll = forge.ForgeRenderable.IsAll;
            if (forges.Length == 1) {
                return Constant(isAll);
            }

            var methodNode = codegenMethodScope.MakeChild(
                typeof(bool?),
                typeof(ExprRelationalOpAllAnyNodeForgeEval),
                codegenClassScope);

            var block = methodNode.Block
                .DeclareVar<bool>("hasNonNullRow", ConstantFalse())
                .DeclareVar(
                    valueLeftType,
                    "valueLeft",
                    forges[0].EvaluateCodegen(valueLeftType, methodNode, exprSymbol, codegenClassScope));

            for (var i = 1; i < forges.Length; i++) {
                var refforge = forges[i];
                var refname = "r" + i;
                var reftype = refforge.EvaluationType;
                block.DeclareVar(
                    reftype,
                    refname,
                    refforge.EvaluateCodegen(reftype, methodNode, exprSymbol, codegenClassScope));

                if (reftype.IsArray) {
                    var blockIfNotNull = block.IfCondition(NotEqualsNull(Ref(refname)));
                    {
                        var forLoopArray = blockIfNotNull.ForLoopIntSimple("index", ArrayLength(Ref(refname)));
                        {
                            forLoopArray.DeclareVar(
                                Boxing.GetBoxedType(reftype.GetElementType()),
                                "item",
                                ArrayAtIndex(Ref(refname), Ref("index")));
                            var ifItemNull = forLoopArray.IfCondition(EqualsNull(Ref("item")));
                            {
                                if (isAll) {
                                    ifItemNull.IfReturn(ConstantNull());
                                }
                            }
                            var ifItemNotNull = ifItemNull.IfElse();
                            {
                                ifItemNotNull.AssignRef("hasNonNullRow", ConstantTrue());
                                var ifLeftNotNull = ifItemNotNull.IfCondition(NotEqualsNull(Ref("valueLeft")));
                                {
                                    ifLeftNotNull.IfCondition(
                                            NotOptional(
                                                isAll,
                                                forge.Computer.Codegen(
                                                    Ref("valueLeft"),
                                                    valueLeftType,
                                                    Ref("item"),
                                                    typeof(object))))
                                        .BlockReturn(isAll ? ConstantFalse() : ConstantTrue());
                                }
                            }
                        }
                    }
                }
                else if (reftype.IsGenericDictionary()) {
                    var blockIfNotNull = block.IfCondition(NotEqualsNull(Ref(refname)));
                    {
                        var forEach = blockIfNotNull.ForEach(
                            typeof(object),
                            "item",
                            ExprDotName(Ref(refname), "Keys"));
                        {
                            var ifNotNumber = forEach.IfCondition(Not(InstanceOf(Ref("item"), typeof(object))));
                            {
                                if (isAll) {
                                    ifNotNumber.IfRefNullReturnNull("item");
                                }
                            }
                            var ifNotNumberElse = ifNotNumber.IfElse();
                            {
                                ifNotNumberElse.AssignRef("hasNonNullRow", ConstantTrue());
                                var ifLeftNotNull = ifNotNumberElse.IfCondition(NotEqualsNull(Ref("valueLeft")));
                                {
                                    ifLeftNotNull.IfCondition(
                                            NotOptional(
                                                isAll,
                                                forge.Computer.Codegen(
                                                    Ref("valueLeft"),
                                                    valueLeftType,
                                                    Cast(typeof(object), Ref("item")),
                                                    typeof(object))))
                                        .BlockReturn(isAll ? ConstantFalse() : ConstantTrue());
                                }
                            }
                        }
                    }
                }
                else if (reftype.IsGenericCollection()) {
                    var blockIfNotNull = block.IfCondition(NotEqualsNull(Ref(refname)));
                    {
                        var forEach = blockIfNotNull.ForEach(typeof(object), "item", Ref(refname));
                        {
                            var ifNotNumber = forEach.IfCondition(Not(InstanceOf(Ref("item"), typeof(object))));
                            {
                                if (isAll) {
                                    ifNotNumber.IfRefNullReturnNull("item");
                                }
                            }
                            var ifNotNumberElse = ifNotNumber.IfElse();
                            {
                                ifNotNumberElse.AssignRef("hasNonNullRow", ConstantTrue());
                                var ifLeftNotNull = ifNotNumberElse.IfCondition(NotEqualsNull(Ref("valueLeft")));
                                {
                                    ifLeftNotNull.IfCondition(
                                            NotOptional(
                                                isAll,
                                                forge.Computer.Codegen(
                                                    Ref("valueLeft"),
                                                    valueLeftType,
                                                    Cast(typeof(object), Ref("item")),
                                                    typeof(object))))
                                        .BlockReturn(isAll ? ConstantFalse() : ConstantTrue());
                                }
                            }
                        }
                    }
                }
                else if (!TypeHelper.IsSubclassOrImplementsInterface(
                    Boxing.GetBoxedType(reftype),
                    typeof(object))) {
                    if (reftype.CanBeNull()) {
                        block.IfRefNullReturnNull(refname);
                    }

                    block.AssignRef("hasNonNullRow", ConstantTrue());
                    if (isAll) {
                        block.BlockReturn(ConstantNull());
                    }
                }
                else {
                    if (reftype.CanNotBeNull()) {
                        block.AssignRef("hasNonNullRow", ConstantTrue());
                        block.IfCondition(
                                NotOptional(
                                    isAll,
                                    forge.Computer.Codegen(Ref("valueLeft"), valueLeftType, Ref(refname), reftype)))
                            .BlockReturn(isAll ? ConstantFalse() : ConstantTrue());
                    }
                    else {
                        if (isAll) {
                            block.IfRefNullReturnNull(refname);
                        }

                        var ifRefNotNull = block.IfRefNotNull(refname);
                        {
                            ifRefNotNull.AssignRef("hasNonNullRow", ConstantTrue());
                            var ifLeftNotNull = ifRefNotNull.IfCondition(NotEqualsNull(Ref("valueLeft")));
                            ifLeftNotNull.IfCondition(
                                    NotOptional(
                                        isAll,
                                        forge.Computer.Codegen(
                                            Ref("valueLeft"),
                                            valueLeftType,
                                            Ref(refname),
                                            typeof(object))))
                                .BlockReturn(isAll ? ConstantFalse() : ConstantTrue());
                        }
                    }
                }
            }

            block.IfCondition(Not(Ref("hasNonNullRow")))
                .BlockReturn(ConstantNull());
            if (valueLeftType.CanBeNull()) {
                block.IfRefNullReturnNull("valueLeft");
            }

            block.MethodReturn(Constant(isAll));
            return LocalMethod(methodNode);
        }