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); }
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)); }