public virtual Constant CreateConstantReference(Location loc) { if (value == null) { return(null); } return(Constant.CreateConstant(value.Type, value.GetValue(), loc)); }
public static CustomAttributeBuilder CreateDecimalConstantAttribute(Constant c) { PredefinedAttribute pa = PredefinedAttributes.Get.DecimalConstant; if (pa.Constructor == null && !pa.ResolveConstructor (c.Location, TypeManager.byte_type, TypeManager.byte_type, TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type)) return null; Decimal d = (Decimal) c.GetValue (); int [] bits = Decimal.GetBits (d); object [] args = new object [] { (byte) (bits [3] >> 16), (byte) (bits [3] >> 31), (uint) bits [2], (uint) bits [1], (uint) bits [0] }; return new CustomAttributeBuilder (pa.Constructor, args); }
public virtual void ApplyAttributes(MethodBuilder mb, ConstructorBuilder cb, int index) { if (mb == null) { builder = cb.DefineParameter(index, Attributes, Name); } else { builder = mb.DefineParameter(index, Attributes, Name); } if (OptAttributes != null) { OptAttributes.Emit(); } if (HasDefaultValue) { // // Emit constant values for true constants only, the other // constant-like expressions will rely on default value expression // Constant c = default_expr as Constant; if (c != null) { if (default_expr.Type == TypeManager.decimal_type) { builder.SetCustomAttribute(Const.CreateDecimalConstantAttribute(c)); } else { builder.SetConstant(c.GetValue()); } } } if (TypeManager.IsDynamicType(parameter_type)) { PredefinedAttributes.Get.Dynamic.EmitAttribute(builder, Location); } }
public static CustomAttributeBuilder CreateDecimalConstantAttribute(Constant c) { PredefinedAttribute pa = PredefinedAttributes.Get.DecimalConstant; if (pa.Constructor == null && !pa.ResolveConstructor(c.Location, TypeManager.byte_type, TypeManager.byte_type, TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type)) { return(null); } Decimal d = (Decimal)c.GetValue(); int [] bits = Decimal.GetBits(d); object [] args = new object [] { (byte)(bits [3] >> 16), (byte)(bits [3] >> 31), (uint)bits [2], (uint)bits [1], (uint)bits [0] }; return(new CustomAttributeBuilder(pa.Constructor, args)); }
public override object Visit (Constant constant) { var result = new PrimitiveExpression (constant.GetValue (), Convert (constant.Location), constant.AsString ().Length); return result; }
public override object Visit(Constant constant) { if (constant.GetValue() == null) return new NullReferenceExpression(Convert(constant.Location)); string literalValue; var literalConstant = constant as ILiteralConstant; literalValue = literalConstant != null ? new string(literalConstant.ParsedValue) : constant.GetValueAsLiteral(); object val = constant.GetValue(); if (val is bool) literalValue = (bool)val ? "true" : "false"; var result = new PrimitiveExpression(val, Convert(constant.Location), literalValue); return result; }
public override object Visit (Constant constant) { return new CodePrimitiveExpression (constant.GetValue ()); }
public virtual void ApplyAttributes(MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa) { if (builder != null) { throw new InternalErrorException("builder already exists"); } var pattrs = ParametersCompiled.GetParameterAttribute(modFlags); if (HasOptionalExpression) { pattrs |= ParameterAttributes.Optional; } if (mb == null) { builder = cb.DefineParameter(index, pattrs, Name); } else { builder = mb.DefineParameter(index, pattrs, Name); } if (OptAttributes != null) { OptAttributes.Emit(); } if (HasDefaultValue) { // // Emit constant values for true constants only, the other // constant-like expressions will rely on default value expression // var def_value = DefaultValue; Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant; if (c != null) { if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { pa.DecimalConstant.EmitAttribute(builder, (decimal)c.GetValue(), c.Location); } else { builder.SetConstant(c.GetValue()); } } else if (default_expr.Type.IsStruct) { // // Handles special case where default expression is used with value-type // // void Foo (S s = default (S)) {} // builder.SetConstant(null); } } if (parameter_type != null) { if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { pa.Dynamic.EmitAttribute(builder); } else if (parameter_type.HasDynamicElement) { pa.Dynamic.EmitAttribute(builder, parameter_type, Location); } } }
/// <summary> /// Constant expression folder for binary operations. /// /// Returns null if the expression can not be folded. /// </summary> static public Constant BinaryFold (ResolveContext ec, Binary.Operator oper, Constant left, Constant right, Location loc) { Constant result = null; if (left is EmptyConstantCast) return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc); if (left is SideEffectConstant) { result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc); if (result == null) return null; return new SideEffectConstant (result, left, loc); } if (right is EmptyConstantCast) return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc); if (right is SideEffectConstant) { result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc); if (result == null) return null; return new SideEffectConstant (result, right, loc); } TypeSpec lt = left.Type; TypeSpec rt = right.Type; bool bool_res; if (lt.BuiltinType == BuiltinTypeSpec.Type.Bool && lt == rt) { bool lv = (bool) left.GetValue (); bool rv = (bool) right.GetValue (); switch (oper) { case Binary.Operator.BitwiseAnd: case Binary.Operator.LogicalAnd: return new BoolConstant (ec.BuiltinTypes, lv && rv, left.Location); case Binary.Operator.BitwiseOr: case Binary.Operator.LogicalOr: return new BoolConstant (ec.BuiltinTypes, lv || rv, left.Location); case Binary.Operator.ExclusiveOr: return new BoolConstant (ec.BuiltinTypes, lv ^ rv, left.Location); case Binary.Operator.Equality: return new BoolConstant (ec.BuiltinTypes, lv == rv, left.Location); case Binary.Operator.Inequality: return new BoolConstant (ec.BuiltinTypes, lv != rv, left.Location); } return null; } // // During an enum evaluation, none of the rules are valid // Not sure whether it is bug in csc or in documentation // if (ec.HasSet (ResolveContext.Options.EnumScope)){ if (left is EnumConstant) left = ((EnumConstant) left).Child; if (right is EnumConstant) right = ((EnumConstant) right).Child; } else if (left is EnumConstant && rt == lt) { switch (oper){ /// /// E operator |(E x, E y); /// E operator &(E x, E y); /// E operator ^(E x, E y); /// case Binary.Operator.BitwiseOr: case Binary.Operator.BitwiseAnd: case Binary.Operator.ExclusiveOr: result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); if (result != null) result = result.TryReduce (ec, lt); return result; /// /// U operator -(E x, E y); /// case Binary.Operator.Subtraction: result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); if (result != null) result = result.TryReduce (ec, EnumSpec.GetUnderlyingType (lt)); return result; /// /// bool operator ==(E x, E y); /// bool operator !=(E x, E y); /// bool operator <(E x, E y); /// bool operator >(E x, E y); /// bool operator <=(E x, E y); /// bool operator >=(E x, E y); /// case Binary.Operator.Equality: case Binary.Operator.Inequality: case Binary.Operator.LessThan: case Binary.Operator.GreaterThan: case Binary.Operator.LessThanOrEqual: case Binary.Operator.GreaterThanOrEqual: return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); } return null; } switch (oper){ case Binary.Operator.BitwiseOr: // // bool? operator &(bool? x, bool? y); // if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) || (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) { var b = new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); // false | null => null // null | false => null if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue)) return Nullable.LiftedNull.CreateFromExpression (ec, b); // true | null => true // null | true => true return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, true, loc), b); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; if (left is IntConstant){ int res = ((IntConstant) left).Value | ((IntConstant) right).Value; return new IntConstant (ec.BuiltinTypes, res, left.Location); } if (left is UIntConstant){ uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value; return new UIntConstant (ec.BuiltinTypes, res, left.Location); } if (left is LongConstant){ long res = ((LongConstant)left).Value | ((LongConstant)right).Value; return new LongConstant (ec.BuiltinTypes, res, left.Location); } if (left is ULongConstant){ ulong res = ((ULongConstant)left).Value | ((ULongConstant)right).Value; return new ULongConstant (ec.BuiltinTypes, res, left.Location); } break; case Binary.Operator.BitwiseAnd: // // bool? operator &(bool? x, bool? y); // if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) || (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) { var b = new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); // false & null => false // null & false => false if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue)) return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, false, loc), b); // true & null => null // null & true => null return Nullable.LiftedNull.CreateFromExpression (ec, b); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; /// /// int operator &(int x, int y); /// uint operator &(uint x, uint y); /// long operator &(long x, long y); /// ulong operator &(ulong x, ulong y); /// if (left is IntConstant){ int res = ((IntConstant) left).Value & ((IntConstant) right).Value; return new IntConstant (ec.BuiltinTypes, res, left.Location); } if (left is UIntConstant){ uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value; return new UIntConstant (ec.BuiltinTypes, res, left.Location); } if (left is LongConstant){ long res = ((LongConstant)left).Value & ((LongConstant)right).Value; return new LongConstant (ec.BuiltinTypes, res, left.Location); } if (left is ULongConstant){ ulong res = ((ULongConstant)left).Value & ((ULongConstant)right).Value; return new ULongConstant (ec.BuiltinTypes, res, left.Location); } break; case Binary.Operator.ExclusiveOr: if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; if (left is IntConstant){ int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value; return new IntConstant (ec.BuiltinTypes, res, left.Location); } if (left is UIntConstant){ uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value; return new UIntConstant (ec.BuiltinTypes, res, left.Location); } if (left is LongConstant){ long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value; return new LongConstant (ec.BuiltinTypes, res, left.Location); } if (left is ULongConstant){ ulong res = ((ULongConstant)left).Value ^ ((ULongConstant)right).Value; return new ULongConstant (ec.BuiltinTypes, res, left.Location); } break; case Binary.Operator.Addition: if (lt == InternalType.NullLiteral) return right; if (rt == InternalType.NullLiteral) return left; // // If both sides are strings, then concatenate, if // one is a string, and the other is not, then defer // to runtime concatenation // if (lt.BuiltinType == BuiltinTypeSpec.Type.String || rt.BuiltinType == BuiltinTypeSpec.Type.String){ if (lt == rt) return new StringConstant (ec.BuiltinTypes, (string)left.GetValue () + (string)right.GetValue (), left.Location); return null; } // // handle "E operator + (E x, U y)" // handle "E operator + (Y y, E x)" // EnumConstant lc = left as EnumConstant; EnumConstant rc = right as EnumConstant; if (lc != null || rc != null){ if (lc == null) { lc = rc; lt = lc.Type; right = left; } // U has to be implicitly convetible to E.base right = right.ConvertImplicitly (lc.Child.Type); if (right == null) return null; result = BinaryFold (ec, oper, lc.Child, right, loc); if (result == null) return null; result = result.TryReduce (ec, lt); if (result == null) return null; return new EnumConstant (result, lt); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value + ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value + ((DoubleConstant) right).Value); return new DoubleConstant (ec.BuiltinTypes, res, left.Location); } if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value + ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value + ((FloatConstant) right).Value); result = new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value + ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value + ((ULongConstant) right).Value); result = new ULongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value + ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value + ((LongConstant) right).Value); result = new LongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value + ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value + ((UIntConstant) right).Value); result = new UIntConstant (ec.BuiltinTypes, res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value + ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value + ((IntConstant) right).Value); result = new IntConstant (ec.BuiltinTypes, res, left.Location); } else if (left is DecimalConstant) { decimal res; if (ec.ConstantCheckState) res = checked (((DecimalConstant) left).Value + ((DecimalConstant) right).Value); else res = unchecked (((DecimalConstant) left).Value + ((DecimalConstant) right).Value); result = new DecimalConstant (ec.BuiltinTypes, res, left.Location); } } catch (OverflowException){ Error_CompileTimeOverflow (ec, loc); } return result; case Binary.Operator.Subtraction: // // handle "E operator - (E x, U y)" // handle "E operator - (Y y, E x)" // lc = left as EnumConstant; rc = right as EnumConstant; if (lc != null || rc != null){ if (lc == null) { lc = rc; lt = lc.Type; right = left; } // U has to be implicitly convetible to E.base right = right.ConvertImplicitly (lc.Child.Type); if (right == null) return null; result = BinaryFold (ec, oper, lc.Child, right, loc); if (result == null) return null; result = result.TryReduce (ec, lt); if (result == null) return null; return new EnumConstant (result, lt); } if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value - ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value - ((DoubleConstant) right).Value); result = new DoubleConstant (ec.BuiltinTypes, res, left.Location); } else if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value - ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value - ((FloatConstant) right).Value); result = new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value - ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value - ((ULongConstant) right).Value); result = new ULongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value - ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value - ((LongConstant) right).Value); result = new LongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value - ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value - ((UIntConstant) right).Value); result = new UIntConstant (ec.BuiltinTypes, res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value - ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value - ((IntConstant) right).Value); result = new IntConstant (ec.BuiltinTypes, res, left.Location); } else if (left is DecimalConstant) { decimal res; if (ec.ConstantCheckState) res = checked (((DecimalConstant) left).Value - ((DecimalConstant) right).Value); else res = unchecked (((DecimalConstant) left).Value - ((DecimalConstant) right).Value); return new DecimalConstant (ec.BuiltinTypes, res, left.Location); } else { throw new Exception ( "Unexepected subtraction input: " + left); } } catch (OverflowException){ Error_CompileTimeOverflow (ec, loc); } return result; case Binary.Operator.Multiply: if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value * ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value * ((DoubleConstant) right).Value); return new DoubleConstant (ec.BuiltinTypes, res, left.Location); } else if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value * ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value * ((FloatConstant) right).Value); return new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value * ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value * ((ULongConstant) right).Value); return new ULongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value * ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value * ((LongConstant) right).Value); return new LongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value * ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value * ((UIntConstant) right).Value); return new UIntConstant (ec.BuiltinTypes, res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value * ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value * ((IntConstant) right).Value); return new IntConstant (ec.BuiltinTypes, res, left.Location); } else if (left is DecimalConstant) { decimal res; if (ec.ConstantCheckState) res = checked (((DecimalConstant) left).Value * ((DecimalConstant) right).Value); else res = unchecked (((DecimalConstant) left).Value * ((DecimalConstant) right).Value); return new DecimalConstant (ec.BuiltinTypes, res, left.Location); } else { throw new Exception ( "Unexepected multiply input: " + left); } } catch (OverflowException){ Error_CompileTimeOverflow (ec, loc); } break; case Binary.Operator.Division: if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value / ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value / ((DoubleConstant) right).Value); return new DoubleConstant (ec.BuiltinTypes, res, left.Location); } else if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value / ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value / ((FloatConstant) right).Value); return new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value / ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value / ((ULongConstant) right).Value); return new ULongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value / ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value / ((LongConstant) right).Value); return new LongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value / ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value / ((UIntConstant) right).Value); return new UIntConstant (ec.BuiltinTypes, res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value / ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value / ((IntConstant) right).Value); return new IntConstant (ec.BuiltinTypes, res, left.Location); } else if (left is DecimalConstant) { decimal res; if (ec.ConstantCheckState) res = checked (((DecimalConstant) left).Value / ((DecimalConstant) right).Value); else res = unchecked (((DecimalConstant) left).Value / ((DecimalConstant) right).Value); return new DecimalConstant (ec.BuiltinTypes, res, left.Location); } else { throw new Exception ( "Unexepected division input: " + left); } } catch (OverflowException){ Error_CompileTimeOverflow (ec, loc); } catch (DivideByZeroException) { ec.Report.Error (20, loc, "Division by constant zero"); } break; case Binary.Operator.Modulus: if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value % ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value % ((DoubleConstant) right).Value); return new DoubleConstant (ec.BuiltinTypes, res, left.Location); } else if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value % ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value % ((FloatConstant) right).Value); return new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value % ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value % ((ULongConstant) right).Value); return new ULongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value % ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value % ((LongConstant) right).Value); return new LongConstant (ec.BuiltinTypes, res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value % ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value % ((UIntConstant) right).Value); return new UIntConstant (ec.BuiltinTypes, res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value % ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value % ((IntConstant) right).Value); return new IntConstant (ec.BuiltinTypes, res, left.Location); } else { throw new Exception ( "Unexepected modulus input: " + left); } } catch (DivideByZeroException){ ec.Report.Error (20, loc, "Division by constant zero"); } catch (OverflowException){ Error_CompileTimeOverflow (ec, loc); } break; // // There is no overflow checking on left shift // case Binary.Operator.LeftShift: if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } IntConstant ic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant; if (ic == null){ Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); return null; } int lshift_val = ic.Value; switch (left.Type.BuiltinType) { case BuiltinTypeSpec.Type.ULong: return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value << lshift_val, left.Location); case BuiltinTypeSpec.Type.Long: return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value << lshift_val, left.Location); case BuiltinTypeSpec.Type.UInt: return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value << lshift_val, left.Location); } // null << value => null if (left is NullLiteral) return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); left = left.ConvertImplicitly (ec.BuiltinTypes.Int); if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int) return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value << lshift_val, left.Location); Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); break; // // There is no overflow checking on right shift // case Binary.Operator.RightShift: if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } IntConstant sic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant; if (sic == null){ Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ; return null; } int rshift_val = sic.Value; switch (left.Type.BuiltinType) { case BuiltinTypeSpec.Type.ULong: return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value >> rshift_val, left.Location); case BuiltinTypeSpec.Type.Long: return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value >> rshift_val, left.Location); case BuiltinTypeSpec.Type.UInt: return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value >> rshift_val, left.Location); } // null >> value => null if (left is NullLiteral) return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); left = left.ConvertImplicitly (ec.BuiltinTypes.Int); if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int) return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value >> rshift_val, left.Location); Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); break; case Binary.Operator.Equality: if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) || (left is Nullable.LiftedNull && right.IsNull) || (right is Nullable.LiftedNull && left.IsNull)) { if (left.IsNull || right.IsNull) { return ReducedExpression.Create ( new BoolConstant (ec.BuiltinTypes, left.IsNull == right.IsNull, left.Location), new Binary (oper, left, right)); } if (left is StringConstant && right is StringConstant) return new BoolConstant (ec.BuiltinTypes, ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location); return null; } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value == ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value == ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value == ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value == ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value == ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value == ((IntConstant) right).Value; else return null; return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); case Binary.Operator.Inequality: if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) || (left is Nullable.LiftedNull && right.IsNull) || (right is Nullable.LiftedNull && left.IsNull)) { if (left.IsNull || right.IsNull) { return ReducedExpression.Create ( new BoolConstant (ec.BuiltinTypes, left.IsNull != right.IsNull, left.Location), new Binary (oper, left, right)); } if (left is StringConstant && right is StringConstant) return new BoolConstant (ec.BuiltinTypes, ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location); return null; } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value != ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value != ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value != ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value != ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value != ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value != ((IntConstant) right).Value; else return null; return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); case Binary.Operator.LessThan: if (right is NullLiteral) { if (left is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } if (left is Nullable.LiftedNull) { return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); } } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value < ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value < ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value < ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value < ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value < ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value < ((IntConstant) right).Value; else return null; return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); case Binary.Operator.GreaterThan: if (right is NullLiteral) { if (left is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } if (left is Nullable.LiftedNull) { return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); } } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value > ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value > ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value > ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value > ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value > ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value > ((IntConstant) right).Value; else return null; return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); case Binary.Operator.GreaterThanOrEqual: if (right is NullLiteral) { if (left is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } if (left is Nullable.LiftedNull) { return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); } } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value >= ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value >= ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value >= ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value >= ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value >= ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value >= ((IntConstant) right).Value; else return null; return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); case Binary.Operator.LessThanOrEqual: if (right is NullLiteral) { if (left is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); } if (left is Nullable.LiftedNull) { return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); } } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value <= ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value <= ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value <= ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value <= ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value <= ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value <= ((IntConstant) right).Value; else return null; return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); } return null; }
public override object Visit (Constant constant) { if (constant.GetValue () == null) return new NullReferenceExpression (Convert (constant.Location)); string literalValue; if (constant is ILiteralConstant) { literalValue = new string (((ILiteralConstant)constant).ParsedValue); } else { literalValue = constant.GetValueAsLiteral (); } var result = new PrimitiveExpression (constant.GetValue (), Convert (constant.Location), literalValue); return result; }
public override object Visit (Constant constant) { if (constant.GetValue () == null) return new NullReferenceExpression (Convert (constant.Location)); var result = new PrimitiveExpression (constant.GetValue (), Convert (constant.Location), constant.GetValueAsLiteral ().Length); return result; }
// <summary> // This routine will attempt to simplify the unary expression when the // argument is a constant. // </summary> Constant TryReduceConstant (ResolveContext ec, Constant e) { if (e is EmptyConstantCast) return TryReduceConstant (ec, ((EmptyConstantCast) e).child); if (e is SideEffectConstant) { Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value); return r == null ? null : new SideEffectConstant (r, e, r.Location); } Type expr_type = e.Type; switch (Oper){ case Operator.UnaryPlus: // Unary numeric promotions if (expr_type == TypeManager.byte_type) return new IntConstant (((ByteConstant)e).Value, e.Location); if (expr_type == TypeManager.sbyte_type) return new IntConstant (((SByteConstant)e).Value, e.Location); if (expr_type == TypeManager.short_type) return new IntConstant (((ShortConstant)e).Value, e.Location); if (expr_type == TypeManager.ushort_type) return new IntConstant (((UShortConstant)e).Value, e.Location); if (expr_type == TypeManager.char_type) return new IntConstant (((CharConstant)e).Value, e.Location); // Predefined operators if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type || expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type || expr_type == TypeManager.float_type || expr_type == TypeManager.double_type || expr_type == TypeManager.decimal_type) { return e; } return null; case Operator.UnaryNegation: // Unary numeric promotions if (expr_type == TypeManager.byte_type) return new IntConstant (-((ByteConstant)e).Value, e.Location); if (expr_type == TypeManager.sbyte_type) return new IntConstant (-((SByteConstant)e).Value, e.Location); if (expr_type == TypeManager.short_type) return new IntConstant (-((ShortConstant)e).Value, e.Location); if (expr_type == TypeManager.ushort_type) return new IntConstant (-((UShortConstant)e).Value, e.Location); if (expr_type == TypeManager.char_type) return new IntConstant (-((CharConstant)e).Value, e.Location); // Predefined operators if (expr_type == TypeManager.int32_type) { int value = ((IntConstant)e).Value; if (value == int.MinValue) { if (ec.ConstantCheckState) { ConstantFold.Error_CompileTimeOverflow (ec, loc); return null; } return e; } return new IntConstant (-value, e.Location); } if (expr_type == TypeManager.int64_type) { long value = ((LongConstant)e).Value; if (value == long.MinValue) { if (ec.ConstantCheckState) { ConstantFold.Error_CompileTimeOverflow (ec, loc); return null; } return e; } return new LongConstant (-value, e.Location); } if (expr_type == TypeManager.uint32_type) { UIntLiteral uil = e as UIntLiteral; if (uil != null) { if (uil.Value == 2147483648) return new IntLiteral (int.MinValue, e.Location); return new LongLiteral (-uil.Value, e.Location); } return new LongConstant (-((UIntConstant)e).Value, e.Location); } if (expr_type == TypeManager.uint64_type) { ULongLiteral ull = e as ULongLiteral; if (ull != null && ull.Value == 9223372036854775808) return new LongLiteral (long.MinValue, e.Location); return null; } if (expr_type == TypeManager.float_type) { FloatLiteral fl = e as FloatLiteral; // For better error reporting if (fl != null) return new FloatLiteral (-fl.Value, e.Location); return new FloatConstant (-((FloatConstant)e).Value, e.Location); } if (expr_type == TypeManager.double_type) { DoubleLiteral dl = e as DoubleLiteral; // For better error reporting if (dl != null) return new DoubleLiteral (-dl.Value, e.Location); return new DoubleConstant (-((DoubleConstant)e).Value, e.Location); } if (expr_type == TypeManager.decimal_type) return new DecimalConstant (-((DecimalConstant)e).Value, e.Location); return null; case Operator.LogicalNot: if (expr_type != TypeManager.bool_type) return null; bool b = (bool)e.GetValue (); return new BoolConstant (!b, e.Location); case Operator.OnesComplement: // Unary numeric promotions if (expr_type == TypeManager.byte_type) return new IntConstant (~((ByteConstant)e).Value, e.Location); if (expr_type == TypeManager.sbyte_type) return new IntConstant (~((SByteConstant)e).Value, e.Location); if (expr_type == TypeManager.short_type) return new IntConstant (~((ShortConstant)e).Value, e.Location); if (expr_type == TypeManager.ushort_type) return new IntConstant (~((UShortConstant)e).Value, e.Location); if (expr_type == TypeManager.char_type) return new IntConstant (~((CharConstant)e).Value, e.Location); // Predefined operators if (expr_type == TypeManager.int32_type) return new IntConstant (~((IntConstant)e).Value, e.Location); if (expr_type == TypeManager.uint32_type) return new UIntConstant (~((UIntConstant)e).Value, e.Location); if (expr_type == TypeManager.int64_type) return new LongConstant (~((LongConstant)e).Value, e.Location); if (expr_type == TypeManager.uint64_type){ return new ULongConstant (~((ULongConstant)e).Value, e.Location); } if (e is EnumConstant) { e = TryReduceConstant (ec, ((EnumConstant)e).Child); if (e != null) e = new EnumConstant (e, expr_type); return e; } return null; } throw new Exception ("Can not constant fold: " + Oper.ToString()); }
// <summary> // Resolve is used in method definitions // </summary> public virtual Type Resolve(IMemberContext rc) { if (parameter_type != null) { return(parameter_type); } if (attributes != null) { attributes.AttachTo(this, rc); } TypeExpr texpr = TypeName.ResolveAsTypeTerminal(rc, false); if (texpr == null) { return(null); } parameter_type = texpr.Type; // Ignore all checks for dummy members AbstractPropertyEventMethod pem = rc as AbstractPropertyEventMethod; if (pem != null && pem.IsDummy) { return(parameter_type); } if (default_expr != null) { ResolveContext ec = new ResolveContext(rc); default_expr = default_expr.Resolve(ec); if (default_expr != null) { Constant value = default_expr as Constant; if (value == null) { if (default_expr != null) { bool is_valid = false; if (default_expr is DefaultValueExpression) { is_valid = true; } else if (default_expr is New && ((New)default_expr).IsDefaultValueType) { is_valid = TypeManager.IsEqual(parameter_type, default_expr.Type) || (TypeManager.IsNullableType(parameter_type) && Convert.ImplicitNulableConversion(ec, default_expr, parameter_type) != EmptyExpression.Null); } else { rc.Compiler.Report.Error(1736, default_expr.Location, "The expression being assigned to optional parameter `{0}' must be a constant or default value", Name); is_valid = true; } if (!is_valid) { default_expr = null; ec.Compiler.Report.Error(1763, Location, "Optional parameter `{0}' of type `{1}' can only be initialized with `null'", Name, GetSignatureForError()); } } } else { Constant c = value.ConvertImplicitly(parameter_type); if (c == null) { if (parameter_type == TypeManager.object_type) { rc.Compiler.Report.Error(1763, Location, "Optional parameter `{0}' of type `{1}' can only be initialized with `null'", Name, GetSignatureForError()); } else { rc.Compiler.Report.Error(1750, Location, "Optional parameter value `{0}' cannot be converted to parameter type `{1}'", value.GetValue(), GetSignatureForError()); } default_expr = null; } } } } if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && TypeManager.IsSpecialType(parameter_type)) { rc.Compiler.Report.Error(1601, Location, "Method or delegate parameter cannot be of type `{0}'", GetSignatureForError()); return(null); } TypeManager.CheckTypeVariance(parameter_type, (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant, rc); if (TypeManager.IsGenericParameter(parameter_type)) { return(parameter_type); } if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) { rc.Compiler.Report.Error(721, Location, "`{0}': static types cannot be used as parameters", texpr.GetSignatureForError()); return(parameter_type); } if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || TypeManager.IsDynamicType(parameter_type))) { rc.Compiler.Report.Error(1103, Location, "The extension method cannot be of type `{0}'", TypeManager.CSharpName(parameter_type)); } return(parameter_type); }
/// <summary> /// Constant expression folder for binary operations. /// /// Returns null if the expression can not be folded. /// </summary> static public Constant BinaryFold (EmitContext ec, Binary.Operator oper, Constant left, Constant right, Location loc) { Constant result = null; if (left is EmptyConstantCast) return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc); if (left is SideEffectConstant) { result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc); if (result == null) return null; return new SideEffectConstant (result, left, loc); } if (right is EmptyConstantCast) return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc); if (right is SideEffectConstant) { result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc); if (result == null) return null; return new SideEffectConstant (result, right, loc); } Type lt = left.Type; Type rt = right.Type; bool bool_res; if (lt == TypeManager.bool_type && lt == rt) { bool lv = (bool) left.GetValue (); bool rv = (bool) right.GetValue (); switch (oper) { case Binary.Operator.BitwiseAnd: case Binary.Operator.LogicalAnd: return new BoolConstant (lv && rv, left.Location); case Binary.Operator.BitwiseOr: case Binary.Operator.LogicalOr: return new BoolConstant (lv || rv, left.Location); case Binary.Operator.ExclusiveOr: return new BoolConstant (lv ^ rv, left.Location); case Binary.Operator.Equality: return new BoolConstant (lv == rv, left.Location); case Binary.Operator.Inequality: return new BoolConstant (lv != rv, left.Location); } return null; } // // During an enum evaluation, none of the rules are valid // Not sure whether it is bug in csc or in documentation // if (ec.InEnumContext){ if (left is EnumConstant) left = ((EnumConstant) left).Child; if (right is EnumConstant) right = ((EnumConstant) right).Child; } else if (left is EnumConstant && rt == lt) { switch (oper){ /// /// E operator |(E x, E y); /// E operator &(E x, E y); /// E operator ^(E x, E y); /// case Binary.Operator.BitwiseOr: case Binary.Operator.BitwiseAnd: case Binary.Operator.ExclusiveOr: return BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc).TryReduce (ec, lt, loc); /// /// U operator -(E x, E y); /// case Binary.Operator.Subtraction: result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); return result.TryReduce (ec, ((EnumConstant)left).Child.Type, loc); /// /// bool operator ==(E x, E y); /// bool operator !=(E x, E y); /// bool operator <(E x, E y); /// bool operator >(E x, E y); /// bool operator <=(E x, E y); /// bool operator >=(E x, E y); /// case Binary.Operator.Equality: case Binary.Operator.Inequality: case Binary.Operator.LessThan: case Binary.Operator.GreaterThan: case Binary.Operator.LessThanOrEqual: case Binary.Operator.GreaterThanOrEqual: return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); } return null; } switch (oper){ case Binary.Operator.BitwiseOr: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; if (left is IntConstant){ int res = ((IntConstant) left).Value | ((IntConstant) right).Value; return new IntConstant (res, left.Location); } if (left is UIntConstant){ uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value; return new UIntConstant (res, left.Location); } if (left is LongConstant){ long res = ((LongConstant)left).Value | ((LongConstant)right).Value; return new LongConstant (res, left.Location); } if (left is ULongConstant){ ulong res = ((ULongConstant)left).Value | ((ULongConstant)right).Value; return new ULongConstant (res, left.Location); } break; case Binary.Operator.BitwiseAnd: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; /// /// int operator &(int x, int y); /// uint operator &(uint x, uint y); /// long operator &(long x, long y); /// ulong operator &(ulong x, ulong y); /// if (left is IntConstant){ int res = ((IntConstant) left).Value & ((IntConstant) right).Value; return new IntConstant (res, left.Location); } if (left is UIntConstant){ uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value; return new UIntConstant (res, left.Location); } if (left is LongConstant){ long res = ((LongConstant)left).Value & ((LongConstant)right).Value; return new LongConstant (res, left.Location); } if (left is ULongConstant){ ulong res = ((ULongConstant)left).Value & ((ULongConstant)right).Value; return new ULongConstant (res, left.Location); } break; case Binary.Operator.ExclusiveOr: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; if (left is IntConstant){ int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value; return new IntConstant (res, left.Location); } if (left is UIntConstant){ uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value; return new UIntConstant (res, left.Location); } if (left is LongConstant){ long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value; return new LongConstant (res, left.Location); } if (left is ULongConstant){ ulong res = ((ULongConstant)left).Value ^ ((ULongConstant)right).Value; return new ULongConstant (res, left.Location); } break; case Binary.Operator.Addition: // // If both sides are strings, then concatenate, if // one is a string, and the other is not, then defer // to runtime concatenation // if (lt == TypeManager.string_type || rt == TypeManager.string_type){ if (lt == TypeManager.string_type && rt == TypeManager.string_type) return new StringConstant ( ((StringConstant) left).Value + ((StringConstant) right).Value, left.Location); return null; } if (lt == TypeManager.null_type && lt == rt) return left; // // handle "E operator + (E x, U y)" // handle "E operator + (Y y, E x)" // EnumConstant lc = left as EnumConstant; EnumConstant rc = right as EnumConstant; if (lc != null || rc != null){ if (lc == null) { lc = rc; lt = lc.Type; right = left; } // U has to be implicitly convetible to E.base right = right.ConvertImplicitly (lc.Child.Type); if (right == null) return null; result = BinaryFold (ec, oper, lc.Child, right, loc); if (result == null) return null; result = result.TryReduce (ec, lt, loc); if (result == null) return null; return new EnumConstant (result, lt); } if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value + ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value + ((DoubleConstant) right).Value); return new DoubleConstant (res, left.Location); } if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value + ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value + ((FloatConstant) right).Value); result = new FloatConstant (res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value + ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value + ((ULongConstant) right).Value); result = new ULongConstant (res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value + ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value + ((LongConstant) right).Value); result = new LongConstant (res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value + ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value + ((UIntConstant) right).Value); result = new UIntConstant (res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value + ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value + ((IntConstant) right).Value); result = new IntConstant (res, left.Location); } else if (left is DecimalConstant) { decimal res; if (ec.ConstantCheckState) res = checked (((DecimalConstant) left).Value + ((DecimalConstant) right).Value); else res = unchecked (((DecimalConstant) left).Value + ((DecimalConstant) right).Value); result = new DecimalConstant (res, left.Location); } else { throw new Exception ( "Unexepected addition input: " + left); } } catch (OverflowException){ Error_CompileTimeOverflow (loc); } return result; case Binary.Operator.Subtraction: // // handle "E operator - (E x, U y)" // handle "E operator - (Y y, E x)" // lc = left as EnumConstant; rc = right as EnumConstant; if (lc != null || rc != null){ if (lc == null) { lc = rc; lt = lc.Type; right = left; } // U has to be implicitly convetible to E.base right = right.ConvertImplicitly (lc.Child.Type); if (right == null) return null; result = BinaryFold (ec, oper, lc.Child, right, loc); if (result == null) return null; result = result.TryReduce (ec, lt, loc); if (result == null) return null; return new EnumConstant (result, lt); } if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value - ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value - ((DoubleConstant) right).Value); result = new DoubleConstant (res, left.Location); } else if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value - ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value - ((FloatConstant) right).Value); result = new FloatConstant (res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value - ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value - ((ULongConstant) right).Value); result = new ULongConstant (res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value - ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value - ((LongConstant) right).Value); result = new LongConstant (res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value - ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value - ((UIntConstant) right).Value); result = new UIntConstant (res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value - ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value - ((IntConstant) right).Value); result = new IntConstant (res, left.Location); } else if (left is DecimalConstant) { decimal res; if (ec.ConstantCheckState) res = checked (((DecimalConstant) left).Value - ((DecimalConstant) right).Value); else res = unchecked (((DecimalConstant) left).Value - ((DecimalConstant) right).Value); return new DecimalConstant (res, left.Location); } else { throw new Exception ( "Unexepected subtraction input: " + left); } } catch (OverflowException){ Error_CompileTimeOverflow (loc); } return result; case Binary.Operator.Multiply: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value * ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value * ((DoubleConstant) right).Value); return new DoubleConstant (res, left.Location); } else if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value * ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value * ((FloatConstant) right).Value); return new FloatConstant (res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value * ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value * ((ULongConstant) right).Value); return new ULongConstant (res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value * ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value * ((LongConstant) right).Value); return new LongConstant (res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value * ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value * ((UIntConstant) right).Value); return new UIntConstant (res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value * ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value * ((IntConstant) right).Value); return new IntConstant (res, left.Location); } else if (left is DecimalConstant) { decimal res; if (ec.ConstantCheckState) res = checked (((DecimalConstant) left).Value * ((DecimalConstant) right).Value); else res = unchecked (((DecimalConstant) left).Value * ((DecimalConstant) right).Value); return new DecimalConstant (res, left.Location); } else { throw new Exception ( "Unexepected multiply input: " + left); } } catch (OverflowException){ Error_CompileTimeOverflow (loc); } break; case Binary.Operator.Division: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value / ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value / ((DoubleConstant) right).Value); return new DoubleConstant (res, left.Location); } else if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value / ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value / ((FloatConstant) right).Value); return new FloatConstant (res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value / ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value / ((ULongConstant) right).Value); return new ULongConstant (res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value / ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value / ((LongConstant) right).Value); return new LongConstant (res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value / ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value / ((UIntConstant) right).Value); return new UIntConstant (res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value / ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value / ((IntConstant) right).Value); return new IntConstant (res, left.Location); } else if (left is DecimalConstant) { decimal res; if (ec.ConstantCheckState) res = checked (((DecimalConstant) left).Value / ((DecimalConstant) right).Value); else res = unchecked (((DecimalConstant) left).Value / ((DecimalConstant) right).Value); return new DecimalConstant (res, left.Location); } else { throw new Exception ( "Unexepected division input: " + left); } } catch (OverflowException){ Error_CompileTimeOverflow (loc); } catch (DivideByZeroException) { Report.Error (020, loc, "Division by constant zero"); } break; case Binary.Operator.Modulus: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { if (left is DoubleConstant){ double res; if (ec.ConstantCheckState) res = checked (((DoubleConstant) left).Value % ((DoubleConstant) right).Value); else res = unchecked (((DoubleConstant) left).Value % ((DoubleConstant) right).Value); return new DoubleConstant (res, left.Location); } else if (left is FloatConstant){ float res; if (ec.ConstantCheckState) res = checked (((FloatConstant) left).Value % ((FloatConstant) right).Value); else res = unchecked (((FloatConstant) left).Value % ((FloatConstant) right).Value); return new FloatConstant (res, left.Location); } else if (left is ULongConstant){ ulong res; if (ec.ConstantCheckState) res = checked (((ULongConstant) left).Value % ((ULongConstant) right).Value); else res = unchecked (((ULongConstant) left).Value % ((ULongConstant) right).Value); return new ULongConstant (res, left.Location); } else if (left is LongConstant){ long res; if (ec.ConstantCheckState) res = checked (((LongConstant) left).Value % ((LongConstant) right).Value); else res = unchecked (((LongConstant) left).Value % ((LongConstant) right).Value); return new LongConstant (res, left.Location); } else if (left is UIntConstant){ uint res; if (ec.ConstantCheckState) res = checked (((UIntConstant) left).Value % ((UIntConstant) right).Value); else res = unchecked (((UIntConstant) left).Value % ((UIntConstant) right).Value); return new UIntConstant (res, left.Location); } else if (left is IntConstant){ int res; if (ec.ConstantCheckState) res = checked (((IntConstant) left).Value % ((IntConstant) right).Value); else res = unchecked (((IntConstant) left).Value % ((IntConstant) right).Value); return new IntConstant (res, left.Location); } else { throw new Exception ( "Unexepected modulus input: " + left); } } catch (DivideByZeroException){ Report.Error (020, loc, "Division by constant zero"); } catch (OverflowException){ Error_CompileTimeOverflow (loc); } break; // // There is no overflow checking on left shift // case Binary.Operator.LeftShift: IntConstant ic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant; if (ic == null){ Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); return null; } int lshift_val = ic.Value; if (left.Type == TypeManager.uint64_type) return new ULongConstant (((ULongConstant)left).Value << lshift_val, left.Location); if (left.Type == TypeManager.int64_type) return new LongConstant (((LongConstant)left).Value << lshift_val, left.Location); if (left.Type == TypeManager.uint32_type) return new UIntConstant (((UIntConstant)left).Value << lshift_val, left.Location); left = left.ConvertImplicitly (TypeManager.int32_type); if (left.Type == TypeManager.int32_type) return new IntConstant (((IntConstant)left).Value << lshift_val, left.Location); Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); break; // // There is no overflow checking on right shift // case Binary.Operator.RightShift: IntConstant sic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant; if (sic == null){ Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); ; return null; } int rshift_val = sic.Value; if (left.Type == TypeManager.uint64_type) return new ULongConstant (((ULongConstant)left).Value >> rshift_val, left.Location); if (left.Type == TypeManager.int64_type) return new LongConstant (((LongConstant)left).Value >> rshift_val, left.Location); if (left.Type == TypeManager.uint32_type) return new UIntConstant (((UIntConstant)left).Value >> rshift_val, left.Location); left = left.ConvertImplicitly (TypeManager.int32_type); if (left.Type == TypeManager.int32_type) return new IntConstant (((IntConstant)left).Value >> rshift_val, left.Location); Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); break; case Binary.Operator.Equality: if (left is NullLiteral){ if (right is NullLiteral) return new BoolConstant (true, left.Location); else if (right is StringConstant) return new BoolConstant ( ((StringConstant) right).Value == null, left.Location); } else if (right is NullLiteral) { if (left is NullLiteral) return new BoolConstant (true, left.Location); else if (left is StringConstant) return new BoolConstant ( ((StringConstant) left).Value == null, left.Location); } if (left is StringConstant && right is StringConstant){ return new BoolConstant ( ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location); } if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value == ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value == ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value == ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value == ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value == ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value == ((IntConstant) right).Value; else return null; return new BoolConstant (bool_res, left.Location); case Binary.Operator.Inequality: if (left is NullLiteral) { if (right is NullLiteral) return new BoolConstant (false, left.Location); else if (right is StringConstant) return new BoolConstant ( ((StringConstant) right).Value != null, left.Location); } else if (right is NullLiteral) { if (left is NullLiteral) return new BoolConstant (false, left.Location); else if (left is StringConstant) return new BoolConstant ( ((StringConstant) left).Value != null, left.Location); } if (left is StringConstant && right is StringConstant){ return new BoolConstant ( ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location); } if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value != ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value != ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value != ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value != ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value != ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value != ((IntConstant) right).Value; else return null; return new BoolConstant (bool_res, left.Location); case Binary.Operator.LessThan: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value < ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value < ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value < ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value < ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value < ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value < ((IntConstant) right).Value; else return null; return new BoolConstant (bool_res, left.Location); case Binary.Operator.GreaterThan: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value > ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value > ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value > ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value > ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value > ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value > ((IntConstant) right).Value; else return null; return new BoolConstant (bool_res, left.Location); case Binary.Operator.GreaterThanOrEqual: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value >= ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value >= ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value >= ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value >= ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value >= ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value >= ((IntConstant) right).Value; else return null; return new BoolConstant (bool_res, left.Location); case Binary.Operator.LessThanOrEqual: if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; if (left is DoubleConstant) bool_res = ((DoubleConstant) left).Value <= ((DoubleConstant) right).Value; else if (left is FloatConstant) bool_res = ((FloatConstant) left).Value <= ((FloatConstant) right).Value; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value <= ((ULongConstant) right).Value; else if (left is LongConstant) bool_res = ((LongConstant) left).Value <= ((LongConstant) right).Value; else if (left is UIntConstant) bool_res = ((UIntConstant) left).Value <= ((UIntConstant) right).Value; else if (left is IntConstant) bool_res = ((IntConstant) left).Value <= ((IntConstant) right).Value; else return null; return new BoolConstant (bool_res, left.Location); } return null; }