/// <summary> /// Tries to return the literal obtained from constant folding the binary expression whose literal arguments are given /// by opnd1 and opnd2. If any of these are null, the result is null. If the binary expression cannot be constant folded /// the result is also null. /// </summary> /// <param name="opnd1">null or literal corresponding to binary expression's 1st constant folded argument</param> /// <param name="opnd2">null or literal corresponding to binary expression's 2nd constant folded argument</param> /// <param name="binaryExpression">the original binary expression</param> /// <returns>null, or constant folded literal</returns> public static Literal EvalBinaryExpression(Literal opnd1, Literal opnd2, BinaryExpression binaryExpression, TypeSystem typeSystem){ if (binaryExpression == null) return null; if (opnd1 == null) return null; if (opnd2 == null) return null; IConvertible ic1 = opnd1.Value as IConvertible; IConvertible ic2 = opnd2.Value as IConvertible; TypeCode code1 = ic1 == null ? TypeCode.Object : ic1.GetTypeCode(); TypeCode code2 = ic2 == null ? TypeCode.Object : ic2.GetTypeCode(); TypeNode type = SystemTypes.Object; object val = null; switch (binaryExpression.NodeType){ case NodeType.Add : if (typeSystem != null && typeSystem.checkOverflow) goto case NodeType.Add_Ovf; return PureEvaluator.DoAdd(ic1, ic2, code1, code2, binaryExpression); case NodeType.Add_Ovf : case NodeType.Add_Ovf_Un : return PureEvaluator.DoAddOvf(ic1, ic2, code1, code2, binaryExpression); case NodeType.AddEventHandler : return null; case NodeType.And : return PureEvaluator.DoAnd(ic1, ic2, code1, code2, binaryExpression); case NodeType.As : return null; case NodeType.Box : case NodeType.Castclass : case NodeType.ExplicitCoercion : type = (TypeNode)opnd2.Value; TypeNode t = type; EnumNode en = type as EnumNode; if (en != null) t = en.UnderlyingType; if (t == null || !t.IsPrimitive) return null; if (typeSystem != null && binaryExpression.NodeType == NodeType.ExplicitCoercion){ ErrorHandler savedErrorHandler = typeSystem.ErrorHandler; typeSystem.ErrorHandler = null; Expression result; try { result = typeSystem.ExplicitLiteralCoercion(opnd1, opnd1.Type, t, null); } finally { typeSystem.ErrorHandler = savedErrorHandler; }; return result as Literal; } Type rt = t.GetRuntimeType(); if (rt != null) val = Convert.ChangeType(opnd1.Value, rt, null); else val = opnd1.Value; break; case NodeType.Ceq : case NodeType.Cgt : case NodeType.Cgt_Un : case NodeType.Clt : case NodeType.Clt_Un : return null; case NodeType.Comma: return opnd2; case NodeType.Div : case NodeType.Div_Un : return PureEvaluator.DoDiv(ic1, ic2, code1, code2, binaryExpression); case NodeType.Eq : return PureEvaluator.DoEq(ic1, ic2, code1, code2, binaryExpression); case NodeType.Ge : return PureEvaluator.DoGe(ic1, ic2, code1, code2, binaryExpression); case NodeType.Gt : return PureEvaluator.DoGt(ic1, ic2, code1, code2, binaryExpression); case NodeType.Is : case NodeType.Isinst : case NodeType.Ldvirtftn : return null; case NodeType.Le : return PureEvaluator.DoLe(ic1, ic2, code1, code2, binaryExpression); case NodeType.LogicalAnd : return PureEvaluator.DoLogicalAnd(ic1, ic2, code1, code2, binaryExpression); case NodeType.LogicalOr : return PureEvaluator.DoLogicalOr(ic1, ic2, code1, code2, binaryExpression); case NodeType.Lt : return PureEvaluator.DoLt(ic1, ic2, code1, code2, binaryExpression); case NodeType.Mkrefany : return null; case NodeType.Mul : if (typeSystem != null && typeSystem.checkOverflow) goto case NodeType.Mul_Ovf; return PureEvaluator.DoMul(ic1, ic2, code1, code2, binaryExpression); case NodeType.Mul_Ovf : case NodeType.Mul_Ovf_Un : return PureEvaluator.DoMulOvf(ic1, ic2, code1, code2, binaryExpression); case NodeType.Ne : return PureEvaluator.DoNe(ic1, ic2, code1, code2, binaryExpression); case NodeType.Or : return PureEvaluator.DoOr(ic1, ic2, code1, code2, binaryExpression); case NodeType.Refanyval : return null; case NodeType.Rem : case NodeType.Rem_Un : return PureEvaluator.DoRem(ic1, ic2, code1, code2, binaryExpression); case NodeType.RemoveEventHandler : return null; case NodeType.Shl : return PureEvaluator.DoLeftShift(ic1, ic2, code1, code2, binaryExpression); case NodeType.Shr : case NodeType.Shr_Un : return PureEvaluator.DoRightShift(ic1, ic2, code1, code2, binaryExpression); case NodeType.Sub : if (typeSystem != null && typeSystem.checkOverflow) goto case NodeType.Sub_Ovf; return PureEvaluator.DoSub(ic1, ic2, code1, code2, binaryExpression); case NodeType.Sub_Ovf : case NodeType.Sub_Ovf_Un : return PureEvaluator.DoSubOvf(ic1, ic2, code1, code2, binaryExpression); case NodeType.Unbox : case NodeType.Xor : default: return null; } return new Literal(val, type, binaryExpression.SourceContext); }