Type real_target_type = target_type;
- if (expr_type == TypeManager.sbyte_type){
+ if (target_type == TypeManager.bool_type) {
+
+ if (expr_type == TypeManager.decimal_type) {
+ return RTConversionExpression (ec, "System.Convert", ".ToBoolean" , expr, loc);
+ }
+ return new NumericToBoolCast (expr, expr.Type);
+ }
+
+ if (expr_type == TypeManager.bool_type){
+ //
+ if (real_target_type == TypeManager.sbyte_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+ if (real_target_type == TypeManager.byte_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+ if (real_target_type == TypeManager.int32_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+ if (real_target_type == TypeManager.int64_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+ if (real_target_type == TypeManager.double_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ if (real_target_type == TypeManager.float_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ if (real_target_type == TypeManager.short_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+ if (real_target_type == TypeManager.decimal_type)
+ return RTConversionExpression(ec, "System.Convert", ".ToDecimal", expr, loc);
+ } else if (expr_type == TypeManager.sbyte_type){
//
// From sbyte to short, int, long, float, double.
//
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (real_target_type == TypeManager.double_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ } else if (expr_type == TypeManager.string_type){
+
+ if (real_target_type == TypeManager.bool_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
+ if (real_target_type == TypeManager.decimal_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToDecimal" , expr, loc);
} else if (expr_type == TypeManager.float_type){
//
// float to double
//
+ if (real_target_type == TypeManager.decimal_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToDecimal" , expr, loc);
if (real_target_type == TypeManager.double_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
- }
+
+ } else if (expr_type == TypeManager.double_type){
+
+ if (real_target_type == TypeManager.decimal_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToDecimal" , expr, loc);
+ } else if (expr_type == TypeManager.decimal_type){
+
+ if (real_target_type == TypeManager.bool_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToBoolean" , expr, loc);
+ if (real_target_type == TypeManager.short_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToInt16" , expr, loc);
+ if (real_target_type == TypeManager.byte_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToByte" , expr, loc);
+ if (real_target_type == TypeManager.int32_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToInt32" , expr, loc);
+ if (real_target_type == TypeManager.int64_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToInt64" , expr, loc);
+ if (real_target_type == TypeManager.float_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToSingle" , expr, loc);
+ if (real_target_type == TypeManager.double_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToDouble" , expr, loc);
+ if (real_target_type == TypeManager.char_type)
+ return RTConversionExpression (ec, "System.Convert", ".ToString" , expr, loc);
+ }
return null;
}
// Tests whether an implicit reference conversion exists between expr_type
// and target_type
//
- public static bool ImplicitReferenceConversionExists (Expression expr, Type target_type)
+ public static bool ImplicitReferenceConversionExists (Expression expr, Type expr_type, Type target_type)
{
- Type expr_type = expr.Type;
-
//
// This is the boxed case.
//
if (StandardConversionExists (expr, target_type) == true)
return true;
+#if false
Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null);
if (dummy != null)
return true;
+#endif
return false;
}
/// </summary>
public static bool StandardConversionExists (Expression expr, Type target_type)
{
- Type expr_type = expr.Type;
+ return WideningConversionExists (expr, expr.type, target_type);
+ }
+
+ public static bool WideningConversionExists (Type expr_type, Type target_type)
+ {
+ return WideningConversionExists (null, expr_type, target_type);
+ }
+
+ public static bool WideningConversionExists (Expression expr, Type target_type)
+ {
+ return WideningConversionExists (expr, expr.Type, target_type);
+ }
+
+ public static bool WideningConversionExists (Expression expr, Type expr_type, Type target_type)
+ {
if (expr_type == null || expr_type == TypeManager.void_type)
return false;
return true;
// First numeric conversions
-
+
if (expr_type == TypeManager.sbyte_type){
//
// From sbyte to short, int, long, float, double.
// From byte to short, ushort, int, uint, long, ulong, float, double
//
if ((target_type == TypeManager.short_type) ||
+ (target_type == TypeManager.bool_type) ||
(target_type == TypeManager.ushort_type) ||
(target_type == TypeManager.int32_type) ||
(target_type == TypeManager.uint32_type) ||
// From short to int, long, float, double
//
if ((target_type == TypeManager.int32_type) ||
+ (target_type == TypeManager.bool_type) ||
(target_type == TypeManager.int64_type) ||
(target_type == TypeManager.double_type) ||
(target_type == TypeManager.float_type) ||
// From int to long, float, double
//
if ((target_type == TypeManager.int64_type) ||
+ (target_type == TypeManager.bool_type) ||
(target_type == TypeManager.double_type) ||
(target_type == TypeManager.float_type) ||
(target_type == TypeManager.decimal_type))
// From uint to long, ulong, float, double
//
if ((target_type == TypeManager.int64_type) ||
+ (target_type == TypeManager.bool_type) ||
(target_type == TypeManager.uint64_type) ||
(target_type == TypeManager.double_type) ||
(target_type == TypeManager.float_type) ||
// From long/ulong to float, double
//
if ((target_type == TypeManager.double_type) ||
+ (target_type == TypeManager.bool_type) ||
(target_type == TypeManager.float_type) ||
(target_type == TypeManager.decimal_type))
return true;
} else if (expr_type == TypeManager.float_type){
//
- // float to double
+ // float to double, decimal
//
if (target_type == TypeManager.double_type)
return true;
- }
+ } else if (expr_type == TypeManager.double_type){
+
+ if ((target_type == TypeManager.bool_type))
+ return true;
+ }
- if (ImplicitReferenceConversionExists (expr, target_type))
+ if (ImplicitReferenceConversionExists (expr, expr_type, target_type))
return true;
if (expr is IntConstant){
Type expr_type = expr.Type;
Expression e;
+
if (expr_type == target_type)
return expr;
e = ConvertImplicitStandard (ec, expr, target_type, loc);
if (e != null)
return e;
-
+
e = ImplicitUserConversion (ec, expr, target_type, loc);
+
if (e != null)
return e;
- e = RuntimeConversion (ec, expr, target_type, loc);
+ e = NarrowingConversion (ec, expr, target_type, loc);
if (e != null)
return e;
e = e.Resolve(ec);
return (e);
}
+
+ static private Expression RTConversionExpression (EmitContext ec, string ns, string method, Expression expr, Location loc)
+ {
+ Expression etmp, e;
+ ArrayList args;
+ Argument arg;
+
+ etmp = Mono.MonoBASIC.Parser.DecomposeQI(ns+method, loc);
+ args = new ArrayList();
+ arg = new Argument (expr, Argument.AType.Expression);
+ args.Add (arg);
+ e = (Expression) new Invocation (etmp, args, loc);
+ e = e.Resolve(ec);
+ return (e);
+ }
+
- static public bool RuntimeConversionExists (EmitContext ec, Expression expr, Type target_type)
+ static public bool NarrowingConversionExists (EmitContext ec, Expression expr, Type target_type)
{
- return (RuntimeConversion (ec, expr, target_type,Location.Null)) != null;
+ Type expr_type = expr.Type;
+
+ if (target_type == TypeManager.sbyte_type){
+ //
+ // To sbyte from short, int, long, float, double.
+ //
+ if ((expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.short_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return true;
+
+ } else if (target_type == TypeManager.byte_type){
+ //
+ // To byte from short, ushort, int, uint, long, ulong, float, double
+ //
+ if ((expr_type == TypeManager.short_type) ||
+ (expr_type == TypeManager.ushort_type) ||
+ (expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.uint32_type) ||
+ (expr_type == TypeManager.uint64_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return true;
+
+ } else if (target_type == TypeManager.short_type){
+ //
+ // To short from int, long, float, double
+ //
+ if ((expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return true;
+
+ } else if (target_type == TypeManager.ushort_type){
+ //
+ // To ushort from int, uint, long, ulong, float, double
+ //
+ if ((expr_type == TypeManager.uint32_type) ||
+ (expr_type == TypeManager.uint64_type) ||
+ (expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return true;
+
+ } else if (target_type == TypeManager.int32_type){
+ //
+ // To int from long, float, double
+ //
+ if ((expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return true;
+
+ } else if (target_type == TypeManager.uint32_type){
+ //
+ // To uint from long, ulong, float, double
+ //
+ if ((expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.uint64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return true;
+
+ } else if ((target_type == TypeManager.uint64_type) ||
+ (target_type == TypeManager.int64_type)) {
+ //
+ // To long/ulong from float, double
+ //
+ if ((expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return true;
+
+ } else if (target_type == TypeManager.char_type){
+ //
+ // To char from ushort, int, uint, long, ulong, float, double
+ //
+ if ((expr_type == TypeManager.ushort_type) ||
+ (expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.uint32_type) ||
+ (expr_type == TypeManager.uint64_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return true;
+
+ } else if (target_type == TypeManager.float_type){
+ //
+ // To float from double
+ //
+ if (expr_type == TypeManager.double_type)
+ return true;
+ }
+
+ return (NarrowingConversion (ec, expr, target_type,Location.Null)) != null;
}
- static public Expression RuntimeConversion (EmitContext ec, Expression expr,
+ static public Expression NarrowingConversion (EmitContext ec, Expression expr,
Type target_type, Location loc)
{
Type expr_type = expr.Type;
+
+ if (target_type == TypeManager.sbyte_type){
+ //
+ // To sbyte from short, int, long, float, double.
+ //
+ if ((expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.short_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
+
+ } else if (target_type == TypeManager.byte_type){
+ //
+ // To byte from short, ushort, int, uint, long, ulong, float, double
+ //
+ if ((expr_type == TypeManager.short_type) ||
+ (expr_type == TypeManager.ushort_type) ||
+ (expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.uint32_type) ||
+ (expr_type == TypeManager.uint64_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
+
+ } else if (target_type == TypeManager.short_type){
+ //
+ // To short from int, long, float, double
+ //
+ if ((expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+
+ } else if (target_type == TypeManager.ushort_type){
+ //
+ // To ushort from int, uint, long, ulong, float, double
+ //
+ if ((expr_type == TypeManager.uint32_type) ||
+ (expr_type == TypeManager.uint64_type) ||
+ (expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
+
+ } else if (target_type == TypeManager.int32_type){
+ //
+ // To int from long, float, double
+ //
+ if ((expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+
+ } else if (target_type == TypeManager.uint32_type){
+ //
+ // To uint from long, ulong, float, double
+ //
+ if ((expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.uint64_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
+
+ } else if ((target_type == TypeManager.uint64_type) ||
+ (target_type == TypeManager.int64_type)) {
+ //
+ // To long/ulong from float, double
+ //
+ if ((expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+
+ } else if (target_type == TypeManager.char_type){
+ //
+ // To char from ushort, int, uint, long, ulong, float, double
+ //
+ if ((expr_type == TypeManager.ushort_type) ||
+ (expr_type == TypeManager.int32_type) ||
+ (expr_type == TypeManager.uint32_type) ||
+ (expr_type == TypeManager.uint64_type) ||
+ (expr_type == TypeManager.int64_type) ||
+ (expr_type == TypeManager.float_type) ||
+ (expr_type == TypeManager.double_type) ||
+ (expr_type == TypeManager.decimal_type))
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
+
+ } else if (target_type == TypeManager.float_type){
+ //
+ // To float from double
+ //
+ if (expr_type == TypeManager.double_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ }
+
TypeCode dest_type = Type.GetTypeCode (target_type);
TypeCode src_type = Type.GetTypeCode (expr_type);
Expression e = null;
case TypeCode.Byte:
// Ok, this *is* broken
e = RTConversionExpression(ec, "ByteType.FromObject", expr, loc);
- break;
+ break;
+ case TypeCode.DateTime:
+ switch (src_type) {
+ case TypeCode.String:
+ e = RTConversionExpression(ec, "DateType.FromString", expr, loc);
+ break;
+ case TypeCode.Object:
+ e = RTConversionExpression(ec, "DateType.FromObject", expr, loc);
+ break;
+ }
+ break;
}
// We must examine separately some types that
return expr;
e = ImplicitNumericConversion (ec, expr, target_type, loc);
+
if (e != null)
return e;
TypeManager.MonoBASIC_Name (source) + "' to '" +
TypeManager.MonoBASIC_Name (target) + "'";
+ throw new Exception (msg);
+
Report.Error (29, loc, msg);
}
Expression e;
e = ConvertImplicit (ec, source, target_type, loc);
+
if (e != null)
return e;
+
if (source is DoubleLiteral && target_type == TypeManager.float_type){
Report.Error (664, loc,
"Double literal cannot be implicitly converted to " +
if (t != null)
return t;
- t = RuntimeConversion (ec, e, target_type, loc);
+ t = NarrowingConversion (ec, e, target_type, loc);
if (t != null)
return t;
return ne;
if (!(runtimeconv)) {
- ne = RuntimeConversion (ec, expr, target_type, loc);
+ ne = NarrowingConversion (ec, expr, target_type, loc);
if (ne != null)
return ne;
if (ne != null)
return ne;
- ne = RuntimeConversion (ec, expr, target_type, l);
+ ne = NarrowingConversion (ec, expr, target_type, l);
if (ne != null)
return ne;
: base (child, return_type)
{
+
this.op = op;
second_valid = false;
}
}
}
+
+ public class NumericToBoolCast : EmptyCast
+ {
+ Type src_type;
+
+ public NumericToBoolCast (Expression src, Type src_type)
+ : base (src, TypeManager.bool_type)
+
+ {
+ this.src_type = src_type;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ base.Emit (ec);
+
+ if (src_type == TypeManager.byte_type ||
+ src_type == TypeManager.short_type ||
+ src_type == TypeManager.int32_type) {
+
+ ec.ig.Emit (OpCodes.Ldc_I4_0);
+ ec.ig.Emit (OpCodes.Cgt_Un);
+ return;
+ }
+
+ if (src_type == TypeManager.int64_type) {
+ ec.ig.Emit (OpCodes.Ldc_I8, (long) 0);
+ ec.ig.Emit (OpCodes.Cgt_Un);
+ return;
+ }
+
+ if (src_type == TypeManager.float_type) {
+ ec.ig.Emit (OpCodes.Ldc_R4, (float) 0);
+ ec.ig.Emit (OpCodes.Ceq);
+ ec.ig.Emit (OpCodes.Ldc_I4_0);
+ ec.ig.Emit (OpCodes.Ceq);
+ return;
+ }
+
+ if (src_type == TypeManager.double_type) {
+ ec.ig.Emit (OpCodes.Ldc_R8, (double) 0);
+ ec.ig.Emit (OpCodes.Ceq);
+ ec.ig.Emit (OpCodes.Ldc_I4_0);
+ ec.ig.Emit (OpCodes.Ceq);
+ return;
+ }
+ }
+ }
+
/// <summary>
/// This kind of cast is used to encapsulate a child and cast it
/// to the class requested
override public Expression DoResolve (EmitContext ec)
{
if (getter == null){
- Report.Error (154, loc,
+ Report.Error (30524, loc,
"The property '" + PropertyInfo.Name +
"' can not be used in " +
"this context because it lacks a get accessor");
override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
if (setter == null){
- Report.Error (154, loc,
+ Report.Error (30526, loc,
"The property '" + PropertyInfo.Name +
"' can not be used in " +
"this context because it lacks a set accessor");
}
}
+ Expression field_expr = null;
+
public override Expression DoResolve (EmitContext ec)
{
if (instance_expr != null) {
return null;
}
+ if (this.DeclaringType == ec.ContainerType) {
+ MemberInfo mi = GetFieldFromEvent (this);
+ if (mi == null)
+ return null;
+ field_expr = ExprClassFromMemberInfo (ec, mi, loc);
+ ((FieldExpr) field_expr).InstanceExpression = instance_expr;
+ field_expr = field_expr.DoResolve (ec);
+ if (field_expr == null)
+ return null;
+ }
+
return this;
}
public override void Emit (EmitContext ec)
{
- Report.Error (70, loc, "The event '" + Name + "' can only appear on the left hand side of += or -= (except on the defining type)");
+ if (field_expr != null)
+ field_expr.Emit (ec);
}
public void EmitAddOrRemove (EmitContext ec, Expression source)