コード例 #1
0
ファイル: IfExpr.cs プロジェクト: clojurians-org/clojure-clr
        private Expression GenCode(RHC rhc, ObjExpr objx, GenContext context, bool genUnboxed)
        {
            bool testIsBool = Compiler.MaybePrimitiveType(_testExpr) == typeof(bool);

            Expression testCode;

            if (testIsBool)
            {
                testCode = ((MaybePrimitiveExpr)_testExpr).GenCodeUnboxed(RHC.Expression, objx, context);
            }
            else
            {
                ParameterExpression testVar  = Expression.Parameter(typeof(object), "__test");
                Expression          assign   = Expression.Assign(testVar, Compiler.MaybeBox(_testExpr.GenCode(RHC.Expression, objx, context)));
                Expression          boolExpr =
                    Expression.Not(
                        Expression.OrElse(
                            Expression.Equal(testVar, Expression.Constant(null)),
                            Expression.AndAlso(Expression.TypeIs(testVar, typeof(bool)), Expression.IsFalse(Expression.Unbox(testVar, typeof(bool))))));
                testCode = Expression.Block(typeof(bool), new ParameterExpression[] { testVar }, assign, boolExpr);
            }

            Expression thenCode = genUnboxed ? ((MaybePrimitiveExpr)_thenExpr).GenCodeUnboxed(rhc, objx, context) : _thenExpr.GenCode(rhc, objx, context);

            Expression elseCode = genUnboxed ? ((MaybePrimitiveExpr)_elseExpr).GenCodeUnboxed(rhc, objx, context) : _elseExpr.GenCode(rhc, objx, context);

            Type targetType = typeof(object);

            if (this.HasClrType && this.ClrType != null)
            {
                // In this case, both _thenExpr and _elseExpr have types, and they are the same, or one is null.
                // TODO: Not sure if this works if one has a null value.
                targetType = this.ClrType;
            }

            if (thenCode.Type == typeof(void) && elseCode.Type != typeof(void))
            {
                thenCode = Expression.Block(thenCode, Expression.Default(elseCode.Type));
            }
            else if (elseCode.Type == typeof(void) && thenCode.Type != typeof(void))
            {
                elseCode = Expression.Block(elseCode, Expression.Default(thenCode.Type));
            }
            else if (!Reflector.AreReferenceAssignable(targetType, thenCode.Type) || !Reflector.AreReferenceAssignable(targetType, elseCode.Type))
            // Above: this is the test that Expression.Condition does.
            {
                // Try to reconcile
                if (thenCode.Type.IsAssignableFrom(elseCode.Type) && elseCode.Type != typeof(void))
                {
                    elseCode   = Expression.Convert(elseCode, thenCode.Type);
                    targetType = thenCode.Type;
                }
                else if (elseCode.Type.IsAssignableFrom(thenCode.Type) && thenCode.Type != typeof(void))
                {
                    thenCode   = Expression.Convert(thenCode, elseCode.Type);
                    targetType = elseCode.Type;
                }
                else
                {
                    //if (thenCode.Type == typeof(void))
                    //{
                    //    thenCode = Expression.Block(thenCode, Expression.Default(elseCode.Type));
                    //    targetType = elseCode.Type;
                    //}
                    //else if (elseCode.Type == typeof(void))
                    //{
                    //    elseCode = Expression.Block(elseCode, Expression.Default(thenCode.Type));
                    //    targetType = thenCode.Type;
                    //}
                    //else
                    //{
                    // TODO: Can we find a common ancestor?  probably not.
                    thenCode   = Expression.Convert(thenCode, typeof(object));
                    elseCode   = Expression.Convert(elseCode, typeof(object));
                    targetType = typeof(object);
                    //}
                }
            }

            Expression cond = Expression.Condition(testCode, thenCode, elseCode, targetType);

            cond = Compiler.MaybeAddDebugInfo(cond, _sourceSpan, context.IsDebuggable);
            return(cond);
        }
コード例 #2
0
        public override Expression GenDlr(GenContext context)
        {
            // Original code made a call to RT.IsTrue.
            // Now we inline the test.
            // Not clear if there is much speedup from this.

            //bool testIsBool = _testExpr is MaybePrimitiveExpr && _testExpr.HasClrType && _testExpr.ClrType == typeof(bool);

            //Expression testCode = testIsBool
            //    ? ((MaybePrimitiveExpr)_testExpr).GenDlrUnboxed(context)
            //    // TODO: Verify the call to MaybeBox is needed.
            //    // TODO: See if we can write the code more directly than calling RT.IsTrue.
            //    : Expression.Call(Compiler.Method_RT_IsTrue, Compiler.MaybeBox(_testExpr.GenDlr(context)));


            bool testIsBool = _testExpr is MaybePrimitiveExpr && _testExpr.HasClrType && _testExpr.ClrType == typeof(bool);

            Expression testCode;


            if (testIsBool)
            {
                testCode = ((MaybePrimitiveExpr)_testExpr).GenDlrUnboxed(context);
            }
            else
            {
                ParameterExpression testVar  = Expression.Parameter(typeof(object), "__test");
                Expression          assign   = Expression.Assign(testVar, Compiler.MaybeBox(_testExpr.GenDlr(context)));
                Expression          boolExpr =
                    Expression.Not(
                        Expression.OrElse(
                            Expression.Equal(testVar, Expression.Constant(null)),
                            Expression.AndAlso(Expression.TypeIs(testVar, typeof(bool)), Expression.IsFalse(Expression.Unbox(testVar, typeof(bool))))));
                //Expression.Not(Expression.AndAlso(Expression.TypeIs(testVar, typeof(bool)), Expression.IsFalse(Expression.Convert(testVar,typeof(bool))))));
                testCode = Expression.Block(typeof(bool), new ParameterExpression[] { testVar }, assign, boolExpr);
            }

            Expression thenCode = _thenExpr.GenDlr(context);
            Expression elseCode = _elseExpr == null
                ? Expression.Constant(null, typeof(object))
                : _elseExpr.GenDlr(context);

            Type targetType = typeof(object);

            if (this.HasClrType && this.ClrType != null)
            {
                // In this case, both _thenExpr and _elseExpr have types, and they are the same, or one is null.
                // TODO: Not sure if this works if one has a null value.
                targetType = this.ClrType;
            }

            if (thenCode.Type == typeof(void) && elseCode.Type != typeof(void))
            {
                thenCode = Expression.Block(thenCode, Expression.Default(elseCode.Type));
            }
            else if (elseCode.Type == typeof(void) && thenCode.Type != typeof(void))
            {
                elseCode = Expression.Block(elseCode, Expression.Default(thenCode.Type));
            }
            else if (!Reflector.AreReferenceAssignable(targetType, thenCode.Type) || !Reflector.AreReferenceAssignable(targetType, elseCode.Type))
            // Above: this is the test that Expression.Condition does.
            {
                // Try to reconcile
                if (thenCode.Type.IsAssignableFrom(elseCode.Type) && elseCode.Type != typeof(void))
                {
                    elseCode   = Expression.Convert(elseCode, thenCode.Type);
                    targetType = thenCode.Type;
                }
                else if (elseCode.Type.IsAssignableFrom(thenCode.Type) && thenCode.Type != typeof(void))
                {
                    thenCode   = Expression.Convert(thenCode, elseCode.Type);
                    targetType = elseCode.Type;
                }
                else
                {
                    //if (thenCode.Type == typeof(void))
                    //{
                    //    thenCode = Expression.Block(thenCode, Expression.Default(elseCode.Type));
                    //    targetType = elseCode.Type;
                    //}
                    //else if (elseCode.Type == typeof(void))
                    //{
                    //    elseCode = Expression.Block(elseCode, Expression.Default(thenCode.Type));
                    //    targetType = thenCode.Type;
                    //}
                    //else
                    //{
                    // TODO: Can we find a common ancestor?  probably not.
                    thenCode   = Expression.Convert(thenCode, typeof(object));
                    elseCode   = Expression.Convert(elseCode, typeof(object));
                    targetType = typeof(object);
                    //}
                }
            }

            return(Expression.Condition(testCode, thenCode, elseCode, targetType));
        }