Exemplo n.º 1
0
        private static CodegenExpression CodegenCompare(
            CodegenExpressionRef lhs,
            Type lhsType,
            CodegenExpressionRef rhs,
            Type rhsType,
            ExprCaseNodeForge forge,
            CodegenMethodScope codegenMethodScope,
            CodegenClassScope codegenClassScope)
        {
            if (lhsType == null) {
                return EqualsNull(rhs);
            }

            if (rhsType == null) {
                return EqualsNull(lhs);
            }

            if (lhsType.CanNotBeNull() && rhsType.CanNotBeNull() && !forge.IsMustCoerce) {
                return CodegenLegoCompareEquals.CodegenEqualsNonNullNoCoerce(lhs, lhsType, rhs, rhsType);
            }

            var block = codegenMethodScope
                .MakeChild(typeof(bool), typeof(ExprCaseNodeForgeEvalSyntax2), codegenClassScope)
                .AddParam(lhsType, "leftResult")
                .AddParam(rhsType, "rightResult")
                .Block;
            if (lhsType.CanBeNull()) {
                var ifBlock = block.IfCondition(EqualsNull(Ref("leftResult")));
                if (rhsType.CanNotBeNull()) {
                    ifBlock.BlockReturn(ConstantFalse());
                }
                else {
                    ifBlock.BlockReturn(EqualsNull(Ref("rightResult")));
                }
            }

            if (rhsType.CanBeNull()) {
                block.IfCondition(EqualsNull(Ref("rightResult"))).BlockReturn(ConstantFalse());
            }

            CodegenMethod method;
            if (!forge.IsMustCoerce) {
                method = block.MethodReturn(
                    CodegenLegoCompareEquals.CodegenEqualsNonNullNoCoerce(
                        Ref("leftResult"),
                        lhsType,
                        Ref("rightResult"),
                        rhsType));
            }
            else {
                block.DeclareVar<object>("left", forge.Coercer.CoerceCodegen(Ref("leftResult"), lhsType));
                block.DeclareVar<object>("right", forge.Coercer.CoerceCodegen(Ref("rightResult"), rhsType));
                method = block.MethodReturn(StaticMethod<object>("Equals", Ref("left"), Ref("right")));
            }

            return LocalMethodBuild(method).Pass(lhs).Pass(rhs).Call();
        }
Exemplo n.º 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);
        }